# Hello World, We’re CryptoCustoms 👋

Introducing CryptoLegacy: predefined on-chain execution rules that define what happens to your crypto when you cannot act.

Nice to meet you — we’ll keep this brief.

We’re web3 builders who’ve been around since the early days: GPUs overheating, Bitcoin forks, Mt. Gox collapses, Ethereum ICOs. It’s been a long ride, with enough failures to learn where systems break in practice.

From ICO booms and DeFi summers to NFTs, rollups, RWAs, DePin, and even meme coins — we’ve seen cycles come and go. Since 2017, we’ve built projects for experimentation, for learning, and sometimes for profit. But always with a focus on fundamentals, user responsibility, and long-term thinking.

In 2024, we decided to build something different — not another DEX, lending protocol, or infrastructure layer — but something we felt was missing even after all these years: a way to define what happens to crypto assets **when the owner cannot act.**

That idea became CryptoLegacy.

CryptoLegacy does not store your funds and does not replace self-custody. Assets remain in your own wallets during normal operation. What it adds is a predefined execution layer: on-chain rules that determine how recovery or transfer can occur **when the owner cannot act**, according to conditions set in advance.

These rules are defined upfront, enforced on-chain, and designed to work without ad-hoc coordination, discretionary decisions, or reliance on legal processes at the moment they matter most.

Because in crypto, the hardest problem isn’t access.\
It’s execution **when the owner cannot act**.

CryptoLegacy exists to address that problem — quietly, predictably, and without hype.

Because it’s not just about earning crypto.\
It’s about making sure your rules still apply when execution can’t depend on you.

Have questions?\
Ask our Custom GPT — [CryptoLegacy AI](https://chatgpt.com/g/g-68c9f2e3d5ec8191a86f75068462c886-cryptolegacy-ai). It explains how the protocol works, without marketing or oversimplification.

Follow us for updates on [X](https://x.com/0xCust).\
Some more details [here](https://cryptolegacy.app/).


# Status

The current status of the CryptoLegacy project as of January 31, 2026, is:

* Smart contract code is finalized and has successfully passed audits by [Mixbytes](https://github.com/mixbytes/audits_public/tree/master/CryptoLegacy/CryptoLegacy), [Decurity](https://github.com/Decurity/audits/blob/master/Cryptolegacy/cryptolegacy-audit-report-2025-1.1.pdf), [Pessimistic](https://github.com/pessimistic-io/audits/blob/main/CryptoLegacy%20Security%20Analysis%20by%20Pessimistic.pdf), and [Kamensec](https://github.com/kamensec/solo-audits-public/blob/main/crypto-legacy-report-1.pdf).
* Contracts are deployed on Ethereum, Arbitrum, Base, Optimism, and Linea.
* The interface is fully launched and live at [my.cryptolegacy.app](https://my.cryptolegacy.app/).
* The full platform is live and operational across all supported networks.


# Read This First

The following articles explain the problem CryptoLegacy addresses, the solution it provides, and a real-life example — using simple, non-technical language.

[The Problem: When Self-Custody Fail](/start-here/the-problem-when-self-custody-fail)

[The Solution: How CryptoLegacy Works](/start-here/the-solution-how-cryptolegacy-works)

[A Real Example](/start-here/a-real-example)

***

#### Want to go deeper?

* Ask our Custom GPT — [CryptoLegacy AI](https://chatgpt.com/g/g-68c9f2e3d5ec8191a86f75068462c886-cryptolegacy-ai). It explains how the protocol works, without marketing or oversimplification.
* If you’re looking for **execution scenarios** that examine CryptoLegacy from multiple perspectives — privacy under pressure, security failures, long-term flexibility, automation without coordination, reliability, legal uncertainty, and cost — go to the [Execution Scenario Articles section](/execution-scenarios/execution-scenarios-introduction).
* If you’re looking for **protocol-level mechanics**, you can skip directly to the [detailed documentation](/protocol-mechanics/read-this-first).


# The Problem: When Self-Custody Fail

### The Problem: When Self-Custody Fails

Self-custody works well **as long as the owner can act**.

As long as you can:

* access your wallets
* sign transactions
* coordinate with others

everything works.

The problem starts when **you cannot act**, temporarily or permanently.

In practice, this usually happens in three distinct ways.

***

#### 1. Loss of access

You may:

* lose devices or backups
* forget, destroy, or misplace keys
* be unable to reach your setup

In self-custody, there is no fallback.

If the owner cannot sign, **nothing can happen**.

Funds do not move.\
Execution depends entirely on whether someone else already has control.

***

#### 2. Coordination failure

Many existing solutions assume that **people will coordinate at the right moment**.

In real life, coordination often fails:

* someone is unavailable
* someone hesitates
* someone refuses to act
* someone is legally or technically blocked

When execution requires people to cooperate in real time,\
execution can stall indefinitely.

These systems assume coordination will succeed\
**exactly when execution is required**.

Over long time horizons, this assumption often breaks.

***

#### 3. Splitting or sharing mnemonics

Another common workaround is to:

* split a seed phrase
* share parts of a mnemonic
* store fragments with different people

This is often presented as a safety measure,\
but in practice it **transfers control away from the owner**.

Once a mnemonic is split or shared:

* control is no longer exclusive
* access depends on other people
* execution depends on their coordination

This is effectively a **hidden multisig**,\
but without clear rules, thresholds, or enforcement.

It introduces serious risks:

* fragments can be lost or copied
* people may act too early or too late
* reconstruction may fail years later
* intent cannot be verified or enforced

Instead of defining execution rules,\
this approach **hands control to humans in advance**\
and relies on long-term discipline and trust.

Over long time horizons, this model breaks easily.

***

### Why existing solutions are not enough

When the owner cannot act, most existing approaches fail in predictable ways.

#### **Multisig and MPC**

Multisig and MPC require **active coordination at execution time**.

If one participant cannot or will not act,\
execution may never complete.

These systems work for shared control,\
but fail when coordination breaks.

***

#### **Custodial and institutional solutions**

Custodians solve execution by **holding keys**.

This introduces other risks:

* loss of self-custody
* discretionary control by third parties
* jurisdictional exposure
* dependence on the custodian’s continued operation

You gain execution, but lose sovereignty.

***

#### **Legal inheritance and trusts**

Legal structures define **who should receive assets**,\
but they do not execute blockchain transactions.

They rely on:

* courts and trustees
* paperwork and procedures
* cross-border coordination

Even when legal intent is clear,\
on-chain execution can be delayed or blocked.

***

### The core issue

All existing approaches fail for the same reason:

> **They depend on keys or human coordination at execution time.**

Self-custody has no native mechanism\
for situations where the owner cannot act\
or coordination fails.

That is the problem CryptoLegacy is designed to solve.


# The Solution: How CryptoLegacy Works

### The Solution: How CryptoLegacy Works

CryptoLegacy is **not a wallet** and **does not store your funds**.

It is an on-chain execution system that you configure **in advance**,\
so execution does not depend on human decisions later.

Below is how the system works in simple, practical terms.

***

#### 1. You create a CryptoLegacy contract

You create a personal CryptoLegacy contract.

During setup, you define:

* who should receive assets (beneficiaries)
* how assets should be transferred and distributed
* timing rules that control when execution is allowed

The contract does not hold funds.\
It only stores **rules and permissions**.

***

#### 2. You approve assets for future execution

Your assets remain in your own wallets.

You approve the CryptoLegacy contract\
to transfer specific assets **only if execution is triggered later**.

Nothing moves at this stage.\
Approval only makes future execution possible.

***

#### 3. (Optional) You configure guardians and recovery

You can optionally configure two additional roles.\
They serve different purposes and are activated under different conditions.

***

**Guardians**

Guardians exist to **avoid waiting for the inactivity timer**.

If something happens to you:

* guardians can collectively signal that execution should begin
* this allows the system to proceed **without waiting for inactivity**

Guardians:

* do not hold your keys
* do not control your funds
* cannot act individually
* can only trigger predefined execution paths

Guardians reduce **coordination delays**,\
but they do not introduce custody or discretion.

***

**Recovery**

Recovery is a stronger fallback mechanism.

Recovery addresses can:

* cancel an execution before final transfer
* stop guardian-triggered execution
* recover remaining assets if execution must be halted

Recovery exists for situations where:

* guardians fail or disagree
* execution must be stopped before finality
* remaining funds need to be secured

Recovery does not grant control in advance.\
It becomes active only under strict, predefined on-chain rules.

***

#### 4. During normal use, nothing happens

As long as you:

* interact on-chain
* update the activity timer as required

CryptoLegacy does nothing.

Your assets stay in your wallets.\
There is no custody and no execution.

***

#### 5. If you stop acting, a waiting period begins

If you do not update the activity timer:

* the system detects inactivity
* a waiting (Challenge) period begins

During this period:

* you can cancel execution if you regain access
* recovery roles can stop the process

No assets are transferred yet.

***

#### 6. How execution can begin

Execution can start in one of two ways.

1. **Inactivity path**
   * the owner stops acting
   * the waiting period completes
   * execution is allowed
2. **Guardian path**
   * guardians reach the required threshold
   * execution is allowed **without waiting for inactivity**

In both cases, the same predefined rules apply.

***

#### 7. Execution and distribution

Once execution begins:

* approved assets are transferred
* distribution follows the rules you defined
* claims proceed deterministically

At this stage:

* no human decisions are made
* no coordination is required
* execution cannot be reinterpreted

CryptoLegacy executes exactly what was defined in advance.


# A Real Example

You create a CryptoLegacy contract.

During setup, you:

* define beneficiaries and transfer rules
* approve specific wallets and tokens for future execution
* intentionally allocate **only a limited portion of your assets**, not everything
* add guardians to avoid long delays
* add recovery as a safety fallback

CryptoLegacy governs a **dedicated execution pool** —\
assets you explicitly choose to cover situations where you cannot act.

Your remaining assets stay fully outside the system\
and remain under your direct control.

You continue using crypto normally\
and periodically update the activity timer.

Nothing happens.\
Your assets stay in your wallets.

***

#### A situation where you cannot act

You are traveling for work across regions\
with unstable or unavailable internet access.

Your primary device is lost or damaged.\
Backups are not immediately reachable.

For an extended period of time, you **cannot**:

* access your wallets
* sign transactions
* cancel or update anything on-chain

You are safe, but completely unable to act.

At the same time, your family needs funds:

* for regular living expenses
* to handle an unexpected situation
* without waiting weeks or months

No one has your private keys.\
No mnemonic fragments can be reconstructed.\
People who could help cannot coordinate or act on your behalf.

***

#### What the system does

CryptoLegacy detects that required activity has stopped\
and starts a waiting (Challenge) period.

Nothing is transferred yet.

***

If guardians are configured,\
they can act earlier so execution does not need to wait\
for the inactivity timer to complete.

This allows execution to begin\
even while the owner is temporarily unreachable.

***

#### Two possible outcomes

**Outcome 1 — Access is restored**

You regain access before execution is finalized.

Or a recovery address acts on your behalf.

In this case:

* execution is canceled
* guardian actions are reset
* no assets are transferred

The dedicated execution pool remains untouched.

CryptoLegacy returns to normal operation.

***

**Outcome 2 — Execution proceeds**

If no one intervenes before the waiting period ends:

* execution is allowed
* **only the pre-approved assets** are transferred
* distribution follows the rules you defined

Funds reach the intended recipients\
without reconstructing keys\
and without requiring coordination.

Your other assets remain unaffected.

***

#### The key point

CryptoLegacy does not assume\
that all assets should be governed by one mechanism.

It allows you to:

* segment capital
* define different risk profiles
* limit execution scope intentionally

Nothing is decided at execution time.

The system does not ask *why* you were unavailable.\
It does not try to interpret intent or circumstances.

It checks only one thing:

> **Were the predefined on-chain conditions met or not?**

CryptoLegacy executes exactly\
what you defined in advance.


# Execution Scenarios: Introduction

This section presents a series of execution-scenario articles that examine **CryptoLegacy** from multiple perspectives.

Each chapter explores a specific condition under **owner inability to act** — including privacy under pressure, security failures, long-term flexibility, automation without coordination, reliability, legal uncertainty, and cost. Together, they show how the **same underlying execution model** behaves as real-world assumptions break down.

These are **not separate features or isolated solutions**.\
They are different views of a **single execution system** designed for situations where the owner cannot act on-chain.

Rather than describing what CryptoLegacy *can* do, these articles explain:

* **why the model exists**,
* **which failure cases it addresses**, and
* **how predefined on-chain rules behave** when human coordination, availability, or legal certainty fails.

Taken together, the section forms a coherent narrative about **self-custody beyond key management**  — focused on execution, limits, and continuity over time.

***

#### Want to go deeper?

* If you’re looking for **protocol-level mechanics**, you can skip directly to the [detailed documentation](/protocol-mechanics/read-this-first).
* Or ask [**CryptoLegacy AI** ](https://chatgpt.com/g/g-68c9f2e3d5ec8191a86f75068462c886-cryptolegacy-ai)— our custom GPT — to explain how the protocol works, **without marketing or oversimplification**.


# Prologue: Why Absence Changes Everything

Self-custody breaks when you can’t act. CryptoLegacy defines how assets are transferred and recovered in that moment — with inheritance as a final execution case, not the starting point.

Most crypto holders don’t like to think about it — but they absolutely should: What happens to your assets **when you cannot act**?

It’s uncomfortable to consider worst-case scenarios. Yet over long time horizons, the inability to act is not an edge case. Illness, device loss, legal or geopolitical constraints — these are not theoretical risks, but real conditions that eventually affect many long-term holders.

From the start, our belief has been simple: **Your keys, your crypto.** True self-custody is powerful — but it also carries responsibility beyond key management.

The hardest problem in decentralized finance isn’t technology. It’s **execution when the owner cannot act**.

Self-custody works perfectly while you can sign transactions. When you can’t, it provides no execution path on its own.

CryptoLegacy does not remove all risk. It replaces undefined execution with predefined assumptions.

If something goes wrong:

* who can act?
* under which conditions?
* and can that action be stopped if the situation changes?

We’ve been working around this problem since 2017. Back then, the stakes felt lower. Today, with larger portfolios and longer horizons, the inability-to-act problem is impossible to ignore.

CryptoLegacy is built for this exact moment — not by replacing self-custody, but by extending it with predefined, on-chain rules for recovery and, if necessary, inheritance.

Hidden. Secure. Transferable.

Because ultimately, it’s not just about controlling assets while you are present — it’s about defining how execution works **when the owner cannot act**.

**Your keys. Your crypto. Your legacy.**


# Chapter 0: Choosing the Right Path for Your Crypto Legacy

Why predefined on-chain execution rules are necessary when the owner cannot act — and how CryptoLegacy differs from common approaches.

Most crypto holders prioritize security — but often overlook one critical question:

What happens to your crypto if you cannot act?

The decision you make today determines whether you retain control while you are present — and whether predefined rules exist for how your crypto is handled when you are not — or whether your assets risk confusion, irreversible loss, or human conflict at the worst possible moment.

Here are the common approaches, and why they often fail:

* **Multisig Wallets:**\
  Popular, but coordination-dependent. If one participant is unavailable, execution may be blocked indefinitely. Balances are visible, increasing security and social pressure risks.
* **Mnemonic Sharing (Seed Phrases):**\
  Simple, but fragile. A single leaked, lost, or misused fragment can result in permanent and immediate loss, with no reversibility or control.
* **Custodial Exchanges:**\
  Convenient, yet discretionary. Assets depend on third parties, exposed to hacks, insolvency, or regulatory intervention.
* **Traditional Legal Inheritance:**\
  Slow, expensive, and jurisdiction-bound. Courts and lawyers cannot execute on-chain transactions and often introduce long delays and loss of privacy.
* **Social Recovery Wallets:**\
  Appealing in theory, but dependent on long-term human trust and coordination, which degrades over time.
* **Multi-Party Computation (MPC):**\
  Technically advanced but brittle. If enough key shares are lost or compromised, access is permanently gone. MPC does not provide native on-chain execution logic for delays, recovery, or staged distribution.
* **DIY Solutions (Custom Smart Contracts):**\
  Attractive for advanced users, but complex and risky. A single mistake can permanently lock assets, and individual implementations rarely match battle-tested systems.

And then there is CryptoLegacy.

CryptoLegacy is not a replacement for self-custody.\
It is a system designed to define what happens **when self-custody alone is no longer sufficient**.

Hidden. Secure. Transferable.

* **Hidden Privacy:**\
  Assets, balances, and role relationships remain private until predefined on-chain conditions allow execution.
* **Trusted Guardians:**\
  Guardians are individuals you select in advance. They do not control assets and cannot access funds directly. Their role is limited to confirming owner unavailability according to predefined thresholds, enabling execution without discretionary decisions.
* **Assets Remain Under Owner Control:**\
  CryptoLegacy contracts do not hold assets during normal operation. Assets remain in the owner’s wallets until predefined conditions permit transfer.
* **Built-in Recovery:**\
  Recovery addresses provide a predefined override mechanism, allowing remaining contract-held assets to be withdrawn if circumstances change, without rewriting history or reversing completed transfers.
* **Deterministic Execution:**\
  Transfers follow predefined rules and timing. Execution is automated at the rule level, not through discretionary intervention.
* **Flexible by Design:**\
  Beneficiaries, wallets, and distribution parameters can be updated over time, while the core execution model remains stable across assets and chains.

CryptoLegacy does not promise outcomes.\
It defines and enforces execution rules in advance.

Your crypto deserves more than secure storage.\
It deserves a defined execution path when the owner cannot act.

**Your keys. Your crypto. Your legacy.**


# Chapter 1 – Privacy: How CryptoLegacy Shields You from Coercion

Privacy-by-design prevents coercion by hiding asset information until execution conditions are met.

Imagine Bob, traveling abroad, suddenly detained without explanation. Authorities seize his laptop and phone, leaving him unable to access or control his crypto assets. Pressure shifts to his family, where past tensions — sibling rivalries, unresolved conflicts — become leverage.

With multisig wallets, Bob’s family must urgently coordinate signatures. In doing so, his full balances are immediately exposed. Under pressure and uncertainty, conflicts escalate, increasing the risk of coercion and manipulation.

With shared mnemonics, the situation is even more direct: beneficiaries instantly gain visibility into Bob’s entire holdings, concentrating both power and pressure at the worst possible moment.

Traditional legal approaches offer little relief. They are slow, jurisdiction-bound, and ineffective in situations involving immediate on-chain control — especially across borders.

CryptoLegacy approaches the problem differently, by reducing leverage created through premature disclosure:

* **Trusted Guardians:**\
  Guardians are selected in advance and operate under predefined thresholds. They do not access funds or control assets. Their role is limited to confirming owner unavailability according to on-chain rules, enabling execution without discretionary decisions.
* **Encrypted Asset Data:**\
  Information about wallets and assets is encrypted per role and remains inaccessible until predefined conditions are met. Neither guardians nor beneficiaries have visibility into balances or asset structure before execution is permitted.
* **Gradual Beneficiary Access:**\
  Once assets are transferred into the CryptoLegacy contract, beneficiaries can claim only what the predefined schedule allows. This staged access limits sudden concentration of control and reduces external pressure.
* **Hidden Recovery Mechanism:**\
  Recovery addresses are stored as cryptographic hashes and remain unlinkable until used. They provide a predefined recovery path for remaining contract-held assets if circumstances change, without exposing control paths in advance.

By separating visibility from authority, CryptoLegacy limits the leverage that third parties can exert during moments of uncertainty.

Bob’s family can act within predefined boundaries, without exposing full balances, concentrating power, or escalating pressure — exactly when restraint matters most.

**Your keys. Your crypto. Your privacy.**


# Chapter 2 – Security: Keeping Your Assets Safe in Any Situation

Assets stay under owner control until strict on-chain conditions allow execution.

Alice always took crypto security seriously. She protected her wallets, maintained backups, and followed best practices — yet she remained uncertain about what would happen if she could no longer act herself:

* **Multisig wallets or MPC:**\
  Coordination failure is a real risk. If one key is lost or compromised, assets may be locked or exposed. Relying on multiple signers also introduces human conflict and availability risks.
* **Mnemonic sharing:**\
  Simple, but brittle. A single leaked or lost fragment can lead to immediate and irreversible loss.
* **Traditional legal custody (lawyers, notaries, trust companies):**\
  Handing over backups or keys to intermediaries creates new attack surfaces. Documents can be copied, lost, or misused, and legal processes cannot execute on-chain actions.

That is why Alice chose CryptoLegacy.

With CryptoLegacy, Alice retained full control while she was active. Her assets stayed in her own wallets and were never deposited into third-party contracts. The system operated as a predefined state machine: as long as Alice remained active, no one else could initiate transfers or move assets.

She designated Guardians in advance — family members, friends, or advisors — who could act only within strict protocol-defined limits. No single Guardian could trigger execution alone. A predefined threshold of confirmations was required, followed by a mandatory challenge period before any transfer became possible.

Guardians had no direct access to funds and no visibility into balances. Even if a Guardian’s account were compromised, it could not result in immediate execution. Their role was limited to contributing a confirmation toward a state transition, not granting control.

Beneficiaries were also constrained by design. Even if a beneficiary account were compromised, assets could not be withdrawn all at once. Claims were only possible after the system entered the distribution state and followed Alice’s predefined schedule, releasing assets gradually.

When Alice suffered a serious accident and remained unconscious for weeks, uncertainty spread among those around her. Despite this, her assets remained inaccessible to unauthorized action. No one could bypass thresholds, skip the challenge period, or accelerate execution. Only after the required confirmations and time-based checks were satisfied did the system transition states and allow predefined distribution rules to execute.

Alice later recovered. Using the predefined recovery mechanism, she regained control over the remaining contract-held assets. Transfers that had already occurred were final, but no additional assets were exposed or moved prematurely.

CryptoLegacy did not eliminate risk.\
It reduced critical failure modes by design:

* **Assets remained under owner control** until thresholds and time-based conditions were met.
* **Execution required multiple confirmations**, not a single compromised actor.
* **Challenge periods prevented rushed or mistaken execution.**
* **Recovery applied only to remaining assets**, without rewriting history.

CryptoLegacy gave Alice something other approaches could not: a security model that continues to function correctly even when the owner cannot act.

**Your keys. Your crypto. Your security.**


# Chapter 3 – Flexibility: Rapidly Changing Investments

Change assets and strategies freely without breaking recovery or execution logic.

Bob loved exploring new blockchain opportunities — minting NFTs, staking tokens, providing liquidity on different chains, and experimenting with emerging DeFi protocols. As his portfolio expanded, the challenge was not access, but continuity: how to keep investing freely while preserving a consistent transfer, recovery and inheritance (if needed) model across assets, chains, and strategies.

* **Multisig wallets or MPC:**\
  Bob experimented with multisig setups for backup and inheritance. Each new chain or protocol required a new configuration and renewed coordination. Losing access meant depending on others at exactly the wrong moment. Over time, everyday activity turned into operational friction.
* **Mnemonic sharing:**\
  Splitting a seed phrase seemed simple at first. As the portfolio grew, it became fragile. Each new wallet, protocol, or chain required updates, explanations, and manual coordination. Small omissions accumulated into real risk.
* **Traditional legal custody (lawyers, notaries, trust companies):**\
  Updating legal documents for each new investment was slow and expensive. Paper-based processes failed to keep up with on-chain activity and introduced additional security concerns.
* **Custodial platforms:**\
  At first, custodial services appeared flexible. They abstracted complexity, offered unified interfaces, and simplified cross-chain activity. But that flexibility depended on external policies, jurisdictions, and operational decisions beyond Bob’s control. When conditions changed, access could change with them — without on-chain guarantees or predefined recovery paths.

That is why Bob chose CryptoLegacy.

With CryptoLegacy, Bob continued to invest without locking his assets or changing how he used them day to day. His funds remained in his own wallets. CryptoLegacy contracts did not hold assets — they only defined permissions and execution rules. New wallets could be added simply by approving transfers under the same predefined conditions.

As Bob expanded to new blockchains, he reused the same beneficiary and recovery configuration. Contracts were deployed with identical logic, not by moving assets, but by copying rules. This allowed Bob to protect new investments immediately, without renegotiating trust or redesigning inheritance each time.

CryptoLegacy’s plugin system supported this flexibility within clear boundaries. During the distribution phase, beneficiaries could interact with assets only through actions Bob had explicitly allowed — staking, swapping, or closing positions — without gaining control over timing, thresholds, or execution rules. Plugins extended what could be done, not who could decide.

Planned cross-chain tooling follows the same principle. Assets may move between environments only when protocol conditions are met, preserving state transitions, thresholds, and time-based constraints across chains.

If Bob ever lost access, recovery addresses provided a predefined path to regain control over remaining assets — without freezing funds in advance or restricting how his portfolio was structured.

CryptoLegacy did not optimize investments.\
It ensured that investment freedom did not come at the cost of continuity.

Bob could change strategies, chains, and protocols without locking assets, rebuilding custody, or expanding trust assumptions beyond what he had already defined.

**Your keys. Your crypto. Your flexibility.**


# Chapter 4 – Automation: Rules That Manage Execution

Rules enforce execution when the owner cannot act, reducing coordination; actions still require authorized on-chain transactions.

Alice’s crypto journey expanded rapidly — NFTs, DeFi ventures, Layer-2 innovations. As her investments multiplied, the challenge was not activity, but reliability: how to ensure transfer, recovery — and only if necessary, inheritance — would execute correctly if she could no longer act, without relying on coordination at the worst possible moment.

* **Shared Mnemonics — Endless Manual Checks**: Initially, Alice distributed parts of her seed phrase among trusted friends. Maintaining this approach required constant manual oversight to ensure each fragment remained secure and accessible. Any single failure introduced the risk of permanent loss, replacing certainty with ongoing vigilance.
* **Multisig Wallets - Continuous Signer Dependence**: Multisig wallets offered shared control but no automation. If Alice lost access, recovery depended entirely on signer availability and willingness to act. In practice, emergency recovery meant urgent coordination precisely when coordination was hardest.
* **Traditional Legal Approach - Constantly Behind Reality**: Traditional legal methods required repeated updates as Alice’s portfolio changed. Each new blockchain or asset meant additional paperwork, legal review, and human involvement. These processes could not keep pace with on-chain activity or guarantee timely execution.

CryptoLegacy removed the need for ad-hoc coordination by automating rule enforcement, not the actions themselves. Alice defined timeouts, roles, and thresholds in advance. Once set, the system enforced these conditions deterministically on-chain.

If Alice cannot act, Guardians could confirm that state through on-chain transactions. Their confirmations did not grant control over assets — they triggered predefined state transitions. Asset transfers were possible only after protocol conditions were satisfied.

If Guardians were unreachable, the same time-based rules allowed execution to proceed without requiring discretionary decisions. Beneficiaries could act only within the boundaries Alice had defined, and only after the system entered the appropriate state.

Recovery followed the same logic. Alice maintained predefined recovery addresses that allowed remaining contract-held assets to be reclaimed if circumstances changed, without reversing completed transfers or rewriting history.

With CryptoLegacy, nothing “managed itself” in the background.\
What changed was that execution no longer depended on coordination, interpretation, or manual intervention at the moment it mattered.

Rules were defined once.\
Execution followed deterministically within predefined rules, once the required on-chain actions were submitted.

**Your keys. Your crypto. Your rules.**


# Chapter 5 – Reliability: Ensuring Your Execution Plan Works as Intended

Reliability comes from deterministic on-chain execution, not human availability.

Bob valued reliability when planning for situations where he might not be able to act. He knew that situations change over time, and wanted execution to remain predictable even if he couldn’t personally manage every step.

From experience, he saw that many common approaches fail not because of attacks, but because execution breaks down over time:

* **Shared Mnemonics:**\
  Losing, withholding, or mishandling even one fragment can permanently block access or trigger disputes among intended recipients or trusted parties.
* **Shamir’s Secret Sharing:**\
  While more structured, missing or uncooperative participants can still delay or prevent recovery.
* **Multisig Wallets:**\
  A single unavailable signer can block execution indefinitely, turning availability into a critical failure point.
* **Traditional Legal Processes:**\
  Expensive and slow, often delayed by disputes, bureaucracy, or third-party errors. Legal procedures cannot guarantee timely on-chain execution.

Bob chose CryptoLegacy to reduce these failure modes.

With CryptoLegacy, Bob’s assets remained in his own wallets during normal operation. Reliability came not from human coordination, but from predefined execution rules enforced on-chain:

* **Blockchain-enforced timeouts** ensured that execution could not remain stalled indefinitely once inactivity conditions were met.
* **Guardian confirmations** acted as a verification layer, not a control mechanism. Guardians did not access assets; they confirmed Bob’s unavailability according to predefined thresholds.
* **Recovery addresses** provided a predefined path to reclaim remaining contract-held assets if circumstances changed, without rewriting history or depending on ad-hoc intervention.

When Bob temporarily lost access, the system behaved predictably. Guardians confirmed his unavailability on-chain, allowing execution to proceed according to the defined rules. At the same time, recovery remained available as a fallback for remaining assets that had not yet been distributed.

CryptoLegacy did not remove uncertainty from life.\
It removed uncertainty from execution.

Reliability came from the fact that once conditions were met, the system behaved consistently — without delays caused by coordination failures, disputes, or unavailable participants.

**Your keys. Your crypto. Your reliability.**


# Chapter 6 – Complexity: Why Simplicity Is the Key to Security

Fewer assumptions mean fewer failures when execution matters most.

Alice valued simplicity. From experience, she knew that solutions which seem simple at setup often become complex later — when execution depends on human coordination and assumptions rather than predefined rules, and the owner is no longer available to intervene.

* **Shared Mnemonics:**\
  Splitting a mnemonic phrase often looks like the simplest solution. In practice, it introduces hidden complexity. Individual fragments can be lost, forgotten, or mishandled. Participants must know each other, understand instructions, trust one another, and coordinate at the right moment. They must also reconstruct context — where assets are held, how they should be accessed, and in what order. At the same time, keeping a mnemonic in a single set of hands concentrates full control in one person, turning trust into absolute authority and creating a permanent risk of loss in case of conflict, pressure, or mistake. When the owner cannot act, both models rely on human behavior rather than defined execution, making coordination the weakest link.
* **Multisig Wallets:**\
  Multisig setups are usually straightforward to configure, but difficult to execute when the owner cannot act. Quorums require timely participation and cooperation. Conflicts between signers, unavailable participants, or misaligned incentives can stall execution indefinitely or lead to outcomes that differ from the original intent. If the quorum is configured to allow execution without the owner, control is effectively delegated to other signers, creating the same concentration-of-power risk as sharing a mnemonic — where assets can be moved due to conflict, pressure, or mistake, without the owner’s involvement.
* **Traditional Legal Approach:**\
  Legal documents may appear simple on paper, but introduce different forms of complexity in practice. Third parties can gain access, disputes may arise, and court processes are slow and jurisdiction-dependent. Even in cases of clear wrongdoing — such as unauthorized access following a mnemonic leak — legal action may lead to criminal proceedings, but not to asset recovery. Courts cannot reverse on-chain transactions, and legal interpretations of digital assets vary widely across jurisdictions, often resulting in years of uncertainty without a practical execution path. Most importantly, legal systems cannot directly execute on-chain actions, leaving enforcement detached from the moment when clarity is needed most.
* **DIY Smart Contracts:** Custom smart contracts may appear flexible, but they concentrate execution risk in unreviewed or insufficiently tested code. When the owner cannot act, bugs, edge cases, or unmaintained logic can permanently block or misroute assets, with no practical path to correction or recovery.

CryptoLegacy was not effortless to configure. It required a deliberate, one-time setup of roles, thresholds, and time-based rules. But once defined, these rules replaced ongoing human coordination with a fixed execution model that did not depend on the owner’s continued involvement.

Guardians acted only as a verification layer. They could not see balances or access assets. Their role was limited to confirming Alice’s unavailability through on-chain transactions, contributing to predefined state transitions rather than exercising discretion.

Recovery addresses provided a predefined fallback for remaining assets if circumstances changed. They did not rewrite history or override completed transfers, but ensured that the owner’s inability to act did not result in permanent loss of remaining contract-held assets.

When Alice became temporarily unavailable due to a serious medical condition, the system behaved as designed. Guardians confirmed her unavailability, and execution followed predefined rules — without interpretation, coordination, or legal intervention.

During this period, part of the assets was claimed by her family and transferred to their designated accounts according to the predefined distribution rules.

When Alice later regained access, she was able to reclaim control over the remaining assets through her recovery configuration. The same predefined rules allowed execution to halt and ownership to be restored without disputes or manual intervention.

CryptoLegacy did not simplify life. It simplified execution when you can’t act.

By reducing coordination requirements and hidden assumptions where the owner cannot act, the system minimized the risk that recovery or execution of asset transfers would fail.

**Your keys. Your crypto. Your simplicity.**


# Chapter 7 – Jurisdictional Risks: Navigating Legal Uncertainty Under Absence

On-chain execution reduces dependence on courts and jurisdictions.

Bob understood that crypto itself was borderless — but the moment an owner cannot act on their own, everything around it stops being so. Laws differed between countries, interpretations shifted over time, and legal processes moved slowly. What concerned Bob was not inheritance as a legal outcome, but whether transfer and recovery would continue to execute in a defined and predictable way, with inheritance only as a terminal case if execution progressed that far.

If he could no longer act on his own, would execution depend on courts, jurisdictions, and paperwork — or on rules defined in advance?

* **Shared Mnemonics:** Initially, Bob shared his seed phrases directly with family members. While simple and independent of any jurisdiction, this approach relied entirely on personal trust. If Bob cannot act on his own, any disagreement, misuse, or conflict would no longer be resolvable through predefined execution, making transfer and recovery dependent on human discretion rather than rules. In theory, courts might intervene after the fact. In practice, such processes are slow, costly, and jurisdiction-dependent. They cannot guarantee timely recovery or restoration of control, leaving outcomes dependent on relationships rather than enforceable execution rules.
* **Multisig Wallets:** Multisig wallets appeared more structured and less tied to a single legal system. But Bob realized that once the owner cannot act on his own, signers located in different jurisdictions introduced new uncertainty. Conflicts, unavailability, or regulatory pressure on individual signers could stall execution indefinitely. Courts could not reliably resolve such deadlocks across borders or enforce timely on-chain action.
* **MPC and Custodial Models:** Bob also looked at MPC-based wallets and custodial services, including exchanges. These models appeared convenient and, in some cases, aligned with local regulations. However, they ultimately shifted execution outside the blockchain. Access and recovery depended on service providers, internal policies, or legal orders tied to specific jurisdictions. When the owner cannot act, any transfer or recovery required off-chain intervention — customer support processes, compliance reviews, or legal claims — all subject to local law, changing regulations, and discretionary decisions. In practice, execution remained jurisdiction-dependent, even though the assets themselves were digital.
* **Traditional Legal Approach:** Bob also considered wills and trusts. These mechanisms were designed to operate when the owner cannot act, but they depended entirely on jurisdiction. Each country imposed different requirements, and evolving crypto regulations made long-term planning fragile. Even when courts eventually acted, they could not directly execute on-chain transfers. In practice, the owner’s inability to act translated into delay, cost, and uncertainty around transfer and recovery.

With **CryptoLegacy**, Bob approached the inability to act differently. Instead of relying on legal enforcement after the fact, he defined execution rules in advance and placed them on-chain. When he could no longer act, recovery or distribution could proceed only after predefined conditions were met — either through time-based rules or Guardian confirmations — without requiring court orders or cross-border legal coordination.

Guardians did not access or control assets. Their role was limited to confirming that Bob cannot act on his own, allowing the system to transition states according to rules Bob had defined.

Bob also configured recovery addresses that remained separate from the transfer flow. These addresses allowed him to regain control over remaining assets if circumstances changed, ensuring that a temporary inability to act did not automatically result in irreversible transfer of all assets.

Inheritance, in this model, was not the starting point — it was a terminal outcome, reached only if the owner’s inability to act became irreversible and recovery was no longer exercised.

With CryptoLegacy, Bob did not eliminate legal uncertainty.\
He limited its impact by separating execution from jurisdiction.

CryptoLegacy does not replace the law.\
It defines what happens when the law cannot act in time.

**Your keys. Your crypto. Your code.**


# Chapter 8 – Costs: Balancing Security and Your Bottom Line

Predictable on-chain costs replace hidden costs of failed execution.

Alice knew that protecting her crypto wasn’t just about the initial setup — it was about minimizing hidden costs and reducing the chance that execution would break down later. She compared each option carefully, realizing that certain “free” methods could become extremely expensive when she cannot act on her own and uncertainty turned into real outcomes.

* **Shared Mnemonics:** Splitting a seed phrase among friends looked free at first. But Alice saw the hidden cost: a single lost shard, a misunderstanding, or a conflict could lead to irreversible loss. Even if legal action was possible afterward, it would be slow, costly, and uncertain — and it could not reverse on-chain execution.
* **Multisig Wallets:** In a multisig setup, the visible cost was gas. But the hidden cost was coordination: more signers meant more future transactions, more availability risk, and more opportunities for delays or deadlocks. Over time, those operational frictions could become more expensive than the fees themselves.
* **Traditional Legal Approach:** A will or trust seemed familiar. Yet legal fees, notaries, cross-border procedures, and court timelines could inflate costs quickly. With crypto still evolving legally across jurisdictions, Alice also saw uncertainty: additional consultations, translations, delays, and unpredictable outcomes — all while courts still could not directly execute on-chain transfers.

With CryptoLegacy, Alice could pay for a predefined execution model rather than for ad-hoc coordination:

* **Contract Creation Fee:** A one-time payment to create her personal CryptoLegacy contract.
* **Periodic Updates (every six months):** A predictable on-chain check-in that maintains normal operation and reduces reliance on manual coordination later.
* **Lifetime NFT Option:** A one-time NFT pass that can reduce recurring update fees and simplify long-term usage across supported chains.

CryptoLegacy did not make execution free.\
It made costs explicit.

Instead of “free” setups that can fail unpredictably when the owner cannot act, or legal processes that can expand into years of uncertainty, Alice preferred a model where she could understand the trade-offs and plan around them. The goal was not to minimize fees at all costs, but to avoid the far greater cost of undefined execution.

**Your keys. Your crypto. No hidden costs.**


# Read This First

This section is intentionally **technical and formal**.

It defines **how the CryptoLegacy protocol actually behaves on-chain**, not how it is explained or presented elsewhere.

The goal of this document is to be:

* precise rather than intuitive,
* exhaustive rather than friendly,
* authoritative rather than illustrative.

If you are new to CryptoLegacy, we recommend starting with [**Start Here**](/start-here/read-this-first).

This section is meant for readers who need exact guarantees, limits, and invariants.

***

Have questions?\
Ask our Custom GPT — [CryptoLegacy AI](https://chatgpt.com/g/g-68c9f2e3d5ec8191a86f75068462c886-cryptolegacy-ai). It explains how the protocol works, without marketing or oversimplification.

If you’re looking for **execution scenarios** that examine CryptoLegacy from multiple perspectives — privacy under pressure, security failures, long-term flexibility, automation without coordination, reliability, legal uncertainty, and cost — go to the [Execution Scenario Articles section](/execution-scenarios/execution-scenarios-introduction).


# Our Vision

CryptoLegacy focuses on long-term value, security, and deterministic on-chain execution — without speculation, discretion, or dependency on human coordination.

CryptoLegacy is built on a pragmatic belief:\
systems that matter over decades must continue to operate not only when everything goes right, but when the owner cannot act, coordination fails, and assumptions break.

Market cycles, speculative trends, and platforms come and go.\
Inability to act is different: it is an execution condition that can arise unexpectedly and persist for an unknown duration.

Throughout this document, *“cannot act”* refers strictly to the inability to submit required on-chain transactions.\
It does not imply death, legal status, or any specific real-world event.

The protocol does not predict outcomes, interpret intent, or distinguish between temporary and permanent causes.\
All execution is defined in advance and enforced on-chain under strict, predefined rules.

We believe self-custody is meaningful only if execution remains possible during periods of owner inability to act — regardless of whether that condition is temporary or permanent.\
Ownership without an execution model for such periods is incomplete.

Inheritance exists within CryptoLegacy only as a terminal execution outcome.\
It is not the primary framing of the system, but the final state reached if temporary execution paths are not resolved.

This document describes the principles that guide CryptoLegacy at the protocol level.\
It is not a marketing statement and does not imply or promise any specific outcome.

CryptoLegacy exists to define and constrain execution during owner inability to act — deliberately, predictably, and without discretion.

#### Core Principle

If an execution outcome is not explicitly allowed by protocol rules, it cannot occur.

#### Key Principles

* **Inability to act as the primary execution condition**\
  CryptoLegacy is designed around a single on-chain condition:\
  *the owner cannot act*.\
  This condition is agnostic to cause and does not assume death, permanence, or intent — only the absence of required on-chain actions.
* **Temporary before terminal**\
  Execution paths prioritize reversibility and recovery during temporary inability to act.\
  Inheritance exists only as a terminal execution outcome if the condition becomes permanent and earlier paths are not resolved.
* **Execution before narratives**\
  UX, features, growth, and tooling exist only to support predefined execution paths under inability to act — not to infer real-world situations.
* **Users first**\
  We build CryptoLegacy for ourselves, the people we care about, and for you and those you trust.\
  Real execution constraints matter more than metrics, storytelling, or adoption curves.
* **Security as enforced constraints**\
  Security is not a promise and not a guarantee.\
  It is achieved by limiting execution paths, enforcing role boundaries, and designing failure modes that are predictable rather than catastrophic.
* **Tokens can fail — execution must persist**\
  Token prices are temporary.\
  Inability to act — temporary or permanent — is a long-term execution risk.\
  CryptoLegacy is designed to function independently of market conditions, sustained by real usage and a transparent donation-based funding model.
* **Decentralization with strict boundaries**\
  No governance process, operator, plugin, or upgrade mechanism may override execution rules, shorten protocol-defined periods, or reverse finalized outcomes.
* **No investor pressure**\
  Execution integrity is never traded for growth, speed, or visibility.
* **Simplicity as a security property**\
  Complexity increases failure modes.\
  CryptoLegacy is designed to remain understandable and auditable because execution must work during extended periods of owner inability to act.

#### What CryptoLegacy Is Not

* Not a death-triggered mechanism
* Not an inheritance-first system
* Not a custodial service
* Not a recovery hotline
* Not a discretionary governance system
* Not a coordination-dependent mechanism
* Not a promise of safety or outcome
* Not a system that interprets intent or real-world events

CryptoLegacy defines execution during inability to act — and nothing beyond it.


# Canonical Definitions

#### Protocol

The **CryptoLegacy Protocol** is the complete set of on-chain rules, state transitions, and execution constraints enforced by the CryptoLegacy smart contracts.

The protocol defines:

* valid execution paths,
* allowed state transitions,
* authority boundaries between roles,
* conditions under which asset movement is permitted.

The protocol does not interpret off-chain intent and does not perform discretionary decision-making.

***

#### Personal CryptoLegacy Contract

An owner-specific smart contract instance that:

* stores configuration, roles, and execution state,
* enforces protocol invariants,
* may temporarily hold assets during Distribution,
* holds no assets during the Normal Period.

Each personal contract operates independently and deterministically.

***

#### Asset Holder

\
An Asset Holder is an external address that holds assets governed by a personal CryptoLegacy contract.

An Asset Holder:

* is an **externally owned account (EOA)** or a **smart contract wallet** (for example, a multisig),
* holds assets **outside** the personal CryptoLegacy contract,
* grants approval for specific assets to be transferred by the protocol when execution conditions are met.

During Normal and Challenge Periods:

* assets remain in Asset Holder addresses,
* no assets are moved into the personal contract.

During Distribution Period (or via recovery execution paths):

* **pre-approved assets** may be transferred from Asset Holder addresses into the personal CryptoLegacy contract,
* transfers are executed strictly via protocol-defined execution paths and conditions.

Asset Holders are **not execution roles** and do not possess protocol authority.

***

#### Execution Path

A **protocol-defined, on-chain execution route** that specifies:

* required on-chain state conditions,
* authorized roles that may submit transactions,
* permitted state transitions,
* allowed asset movements and destinations (if any).

Execution paths are fixed by protocol logic.\
Roles may only **trigger the conditions** for an execution path and cannot modify, combine, or create new ones.

***

#### Execution Period

A **high-level protocol state** that defines which execution paths are available.

CryptoLegacy defines exactly three execution periods:

* **Normal Period**
* **Challenge Period**
* **Distribution Period**

Execution periods are mutually exclusive and ordered.

***

#### Normal Period

The default execution period in which:

* assets remain in Asset Holder addresses (external owner-controlled wallets),
* the personal contract holds no assets,
* configuration and maintenance actions are allowed,
* inactivity-based and guardian-based execution paths that move assets are disabled,
* recovery-specific execution paths may remain available, subject to recovery conditions.

***

#### Challenge Period

A transitional execution period preceding Distribution.

Entered via:

* **Beneficiary-Initiated Challenge** (fixed 3 months), or
* **Guardian-Initiated Challenge** (bounded 0–30 days).

During this period:

* no asset transfer into the personal contract is permitted,
* execution proceeds to Distribution only if the challenge completes uncancelled.

***

#### Distribution Period

The execution period in which:

* protocol-defined execution paths that move assets are enabled,
* **pre-approved assets** may be transferred into the personal contract,
* beneficiaries may claim assets,
* recovery execution paths may withdraw remaining contract-held assets.

Distribution introduces **asset-level finality**.

***

#### Roles

**Owner**\
Configures and maintains the personal contract during Normal Period.\
Once Distribution begins, owner-only operational actions are disabled.

**Beneficiary**\
May initiate a Beneficiary Challenge and claim assets during Distribution.\
Never has custody before Distribution.

**Guardian**\
May collectively trigger a guardian execution path before inactivity expires.\
Never gains custody and cannot transfer assets to arbitrary addresses.

**Recovery Address**\
Enables a recovery-specific execution path.\
Under recovery-specific thresholds, Recovery addresses may (1) transfer **pre-approved assets** from Asset Holder addresses (external owner-controlled wallets) into the personal contract without waiting for beneficiary or guardian challenge periods, and (2) withdraw contract-held assets to **arbitrary new recipient addresses** according to the recovery execution rules.\
Recovery cannot reverse, modify, or invalidate finalized beneficiary claims.

***

#### Asset-Level Finality

Finality applies independently to each asset.\
Once a transfer or claim is finalized, it cannot be reversed by any role, plugin, or governance mechanism.


# Protocol Execution Invariants

The following properties **must always hold** and cannot be bypassed.

#### Asset Custody and Movement

* Assets may be moved **from external Asset Holder addresses into the personal CryptoLegacy contract** only via **protocol-defined execution paths** and only if:
  * all required on-chain state conditions for that execution path are satisfied, and
  * the relevant assets were **pre-approved** for protocol-defined transfer.
* During the **Normal Period**, assets are **not** moved into the personal contract via inactivity-based or guardian-based execution paths. Asset movement during the Normal Period is possible **only** via **recovery-specific execution paths**, subject to recovery thresholds and recovery-specific on-chain conditions.
* Assets may be moved **from the personal CryptoLegacy contract to external addresses** only via **protocol-defined execution paths** and in accordance with the rules of that path. In particular, recovery execution paths may withdraw contract-held assets to **arbitrary new recipient addresses** according to recovery execution rules.
* **Recovery execution is a distinct protocol-defined execution path** and **cannot reverse, modify, or invalidate** finalized beneficiary claims.
* Any assets sent directly to the personal contract **outside protocol-defined execution paths** are **out of scope** and do not affect protocol guarantees.

***

#### Deterministic Execution and Finality

* All execution is deterministic and based exclusively on on-chain state and timestamps.
* Execution finality is asset-level, not contract-level.
* Finalized execution cannot be rolled back.

***

#### Authority Boundaries

* Beneficiaries, Guardians, and Recovery addresses are execution roles, not custodians.
* No role may bypass execution conditions, shorten protocol-defined challenge periods, or override protocol-defined state transitions.

***

#### Ownership and Control

* Once Distribution begins, owner-only operational actions are disabled by protocol checks.
* Ownership transfer does not re-enable disabled authority or grant discretionary control.

***

#### Plugins and Extensibility

* Plugins may extend execution actions **only within existing execution paths**.
* Plugins cannot modify:
  * protocol timing parameters,
  * role classes,
  * execution finality guarantees.

***

#### Governance and Operators

* Governance, build managers, registries, and operators:
  * cannot move assets,
  * cannot trigger execution paths,
  * cannot alter finalized outcomes.

***

#### Time Assumptions

* All time-based logic relies on blockchain timestamps.
* Network delays may delay execution but cannot change rules or authority.

***

### Protocol vs Interface Semantics

The protocol operates purely on-chain.

Encryption, backups, asset lists, wallet management, and decrypt/import flows are **off-chain coordination tools** and do not affect protocol execution or authority.

Visibility of encrypted metadata does not grant authority.


# How CryptoLegacy Works

CryptoLegacy defines on-chain execution rules for asset transfer and recovery when the owner cannot act. Execution is configured in advance and triggered by timeouts or guardian confirmations.

### **General Overview**

CryptoLegacy is built around a single protocol-defined execution lifecycle that governs what happens to assets when the owner cannot act. The process starts with contract creation and configuration, but assets always remain in Asset Holder addresses (external owner-controlled wallets) until predefined execution conditions are met. Asset movement during the Normal Period is possible only via recovery-specific execution paths.

First, the owner creates a personal contract, configures beneficiaries, guardians, and recovery options, approves specific assets for transfer, and encrypts asset metadata. This information remains hidden — beneficiaries and guardians cannot see balances, wallets, or asset details prior to the applicable execution phase. Beneficiaries cannot trigger asset transfers while the owner remains active. Guardians may initiate the guardian execution path under predefined on-chain conditions.

As long as the owner periodically updates the inactivity timeout on-chain, the protocol remains in Normal operation. If the timeout expires, a Beneficiary-Initiated Challenge applies. If guardians initiate execution under predefined conditions before inactivity expires, a Guardian-Initiated Challenge applies, bounded by a guardian challenge period (0–30 days). If this process completes without interruption, approved assets may be transferred into the CryptoLegacy contract via the inactivity-based or guardian-based execution paths after the applicable challenge period completes uncancelled, according to protocol-defined execution rules.

Once assets are inside the contract, beneficiaries claim them according to predefined rules. Claims execute independently and are final at the asset level. Recovery remains available as a separate protocol-defined execution path that may (a) transfer pre-approved assets from Asset Holder addresses (external owner-controlled wallets) into the contract and (b) withdraw contract-held assets to new recipient addresses, without reversing or modifying finalized transfers or claims.

The sections below describe each part of this lifecycle in detail — transfer, recovery, execution extensions, and customization — and how they interact within the same execution model.

### **Transfer**

#### **Step 1: Setup**

Create a personal smart contract and pay the required protocol fee (DAO donation in the interface). Configure beneficiaries as part of the execution parameters, including their shares, delays, and distribution schedules.

Approve asset transfers and encrypt asset metadata for each beneficiary via the interface for later protocol execution. Every six months, the inactivity timeout is extended via an on-chain transaction.

Assets remain in Asset Holder addresses (external owner-controlled wallets) during normal operation. Asset movement during the Normal Period is possible only via recovery-specific execution paths. Transfer via inactivity-based or guardian-based execution paths becomes possible only after predefined protocol execution conditions are met: either the inactivity timeout expires and the subsequent challenge period completes, or guardians (if configured) reach the required confirmation threshold and the guardian challenge period (up to 30 days) completes. Recovery addresses (if configured) provide an independent execution path that can (a) transfer pre-approved assets from Asset Holder addresses (external owner-controlled wallets) into the contract and (b) withdraw contract-held assets to new recipient addresses according to predefined rules, without reversing or modifying completed or finalized claims.

#### **Step 2: Challenge**

If the inactivity timeout expires, a beneficiary may initiate a fixed three-month challenge period. During this period, the owner may reset the timeout and cancel the beneficiary-initiated challenge.

If the challenge period completes without interruption, the contract enters the **Distribution** phase. After Distribution has begun, any single beneficiary — and, if guardians are configured, any single guardian — may decrypt the asset metadata and initiate transfer of only the pre-approved assets from Asset Holder addresses (external owner-controlled wallets) into the CryptoLegacy contract, as permitted by the active execution path.

#### **Step 3: Distribution**

Beneficiaries claim assets according to their configured shares and schedules. Once distribution begins, individual claims execute independently and cannot be reversed or modified by the owner, and assets cannot be withdrawn using owner-only operational authority.

During the distribution period, beneficiaries may switch their beneficiary address (beneficiary hash) used for claiming, as permitted by the protocol. Assets remain held in the CryptoLegacy contract until claimed.

Recovery remains available via pre-configured recovery addresses and may apply both to (1) transferring pre-approved assets from Asset Holder addresses (external owner-controlled wallets) into the contract and (2) withdrawing remaining contract-held assets to new recipient addresses, without interrupting, reversing, or modifying claims that have already finalized.

### **Recovery**

#### **Step 1: Add Guardians and Recovery**

Guardian and recovery plugins may be enabled during contract creation or added later during the Normal Period. By default, if no explicit guardians are set, beneficiaries act as guardians with a majority-based approval threshold (for example, 2-of-3) and a default guardian challenge period of 30 days. The owner may replace the guardian set, adjust confirmation thresholds, and configure the guardian challenge period within protocol-defined limits.

Recovery addresses are configured separately and may require multiple approvals according to the selected recovery threshold. All recovery addresses are stored on-chain as hashes and cannot be linked to a specific CryptoLegacy contract until they are used in a transaction.

#### **Step 2: Guardian-Initiated Transfer**

Guardians may perform an emergency transfer under predefined conditions as an alternative protocol-defined execution path, without waiting for the six-month inactivity timeout. Once the required guardian confirmation threshold is reached, the guardian challenge period (up to 30 days, as configured by the owner) begins. During this period, the owner or a recovery execution path may cancel the guardian execution path, subject to protocol-defined authority checks.

If the guardian challenge period completes without interruption, any single guardian may decrypt the encrypted asset metadata and initiate transfer of only the pre-approved assets from Asset Holder addresses (external owner-controlled wallets) into the CryptoLegacy contract, as defined by the protocol. Guardians never have direct access to assets and cannot withdraw funds to arbitrary recipient addresses or perform transfers outside protocol-defined destinations.

#### **Step 3: Distribution and Recovery**

Beneficiaries claim assets according to the configured shares and schedules. Once distribution begins, individual claims execute independently and cannot be reversed or modified by the owner. Once Distribution has begun, the owner no longer has authority to perform owner-only operational actions.

Recovery remains available only via pre-configured recovery addresses and may (a) transfer pre-approved assets from Asset Holder addresses (external owner-controlled wallets) into the contract and (b) withdraw remaining contract-held assets to new recipient addresses, without interrupting, reversing, or modifying claims that have already finalized. Recovery addresses are stored as hashes and become linkable to a specific CryptoLegacy contract only when used on-chain.

### **Execution Extensions**

#### **Step 1: Add Execution Plugins**

While assets remain in the owner’s wallets during normal operation, the owner retains full control over those assets outside the CryptoLegacy contract. Asset management during this phase is entirely off-contract and unrestricted.

The contract owner may add protocol-approved execution plugins to the CryptoLegacy contract during the Normal Period. These plugins do not grant custody and may only operate on assets once they are held by the CryptoLegacy contract, and only within protocol-defined execution paths. They define which execution actions may be performed later once assets are transferred into the CryptoLegacy contract, within protocol-defined constraints.

Examples of supported actions include token swaps, staking (e.g. Lido), and protocol-specific actions exposed through approved execution plugins.

#### **Step 2: Allow Beneficiaries to Add Plugins**

The owner may add a dedicated plugin that allows beneficiaries to add additional execution plugins during the distribution phase. This capability is governed by predefined confirmation rules set in advance by the owner.

For example, the owner may initially require a 3-of-5 beneficiary confirmation threshold to approve changes to plugin installation rules. Beneficiaries may then, using that same 3-of-5 threshold, approve a rule change that sets a new confirmation threshold of 2-of-5 for future plugin additions, within the same protocol-defined execution path. Once approved, the 2-of-5 threshold becomes the active execution rule for adding plugins.

Beneficiaries cannot remove existing plugins and cannot exceed protocol-defined execution constraints.

#### **Step 3: Execute Actions During Distribution**

During the distribution phase, beneficiaries may use authorized execution plugins to perform allowed actions on assets held in the CryptoLegacy contract. Each action is subject to the confirmation thresholds defined for that plugin.

Asset claims continue independently according to predefined shares and schedules. Execution plugins extend what actions may be executed, not who controls assets or how distribution proceeds.

### **Customization**

#### **Step 1: Enable Extended Execution Logic via Plugins**

CryptoLegacy supports customization through execution plugins that extend the set of allowed actions without modifying the core execution model. These plugins do not introduce arbitrary logic and cannot grant new owner powers, alter fixed protocol timing parameters, or affect execution finality. They cannot modify fixed protocol timing parameters or execution finality, and may modify thresholds or distribution-related rules only where explicitly permitted by the protocol.

Examples of supported extensions include NFT transfers, closing Uniswap NFT positions, fixed-amount distributions alongside share-based claims, or protocol-specific execution logic exposed through audited plugins.

#### **Step 2: Allow Beneficiaries to Enable Additional Logic**

The contract owner may preconfigure a plugin that allows beneficiaries to enable additional execution plugins during the distribution phase. This capability is subject to predefined confirmation thresholds and execution constraints.

Beneficiaries cannot introduce new execution paths beyond those allowed by the protocol, cannot modify core execution rules, and cannot add or remove beneficiaries or recovery addresses.

#### **Step 3: Plugin Verification and Security**

All execution plugins must be registered in the on-chain Plugin Registry. The registry enforces allowlist-based admission of protocol-approved plugins.

This model ensures that customization expands execution capabilities without introducing discretionary control or unapproved code paths outside the predefined protocol boundaries.


# Secure Asset Data Transfer with CryptoLegacy

CryptoLegacy encrypts asset metadata client-side with wallet-derived keys and records it on-chain. Data is usable only through protocol-defined execution paths, preserving privacy and self-custody.

CryptoLegacy provides confidentiality by never storing sensitive asset-holder information — such as wallet addresses or token specifics — in plaintext within the smart contract state. Instead, asset-related metadata is encrypted client-side and recorded on-chain as encrypted payloads in transaction events, while asset movement itself relies strictly on protocol-defined execution paths and required on-chain approvals.

Encryption keys are derived directly from the user’s Ethereum wallet through a signature-based mechanism. This ensures that encryption and decryption capabilities remain fully under user control and never require exposing private keys or relying on custodial services.

### **Encrypted On-chain Data**

CryptoLegacy uses a signature-derived asymmetric encryption system based on modern elliptic curve cryptography (X25519 with authenticated encryption).\
The encryption process works as follows:

* A user signs a fixed, domain-specific message with their Ethereum wallet.
* The signature deterministically derives a virtual encryption key pair.
* The public encryption key may be shared or recorded.
* The private key is never stored or transmitted and can be recreated only by re-signing the same message.

Encrypted payloads are stored on-chain as hexadecimal-encoded data in transaction events. Although publicly visible, they cannot be decrypted without recreating the corresponding encryption key pair via the original wallet signature.

CryptoLegacy uses **two distinct types of encrypted messages**, each with a clearly defined purpose.

#### **Message Type 1: Asset Transfer Data (Role-Specific)**

The first message type contains only the information required to **transfer assets from external wallets into the CryptoLegacy contract**.\
These messages include:

* Asset-holder wallet addresses
* Token contract addresses

This data is required by:

* Beneficiaries
* Guardians
* Recovery addresses

Each message of this type is encrypted **individually for the recipient role**, using that role’s public encryption key.\
This ensures that each beneficiary, guardian, or recovery address can decrypt only the asset transfer data intended for them and only when the relevant protocol-defined execution conditions are satisfied.

These messages do **not** include:

* Other beneficiaries or roles
* Nicknames or labels
* Full contract configuration

Their sole purpose is enabling protocol-defined asset transfer execution.

#### **Message Type 2: Owner Backup Data**

The second message type is intended **exclusively for the contract owner** and serves as an encrypted backup of the full contract configuration.

This message may include:

* Beneficiary, guardian, and recovery addresses
* Public encryption keys for all roles
* Optional nicknames or labels
* Asset-holder wallet addresses
* Token contract addresses

This data is encrypted using **the owner’s own public encryption key** and can only be decrypted by the owner through recreating the corresponding encryption key pair.

Owner backup data does not grant execution authority and does not affect protocol behavior. Its purpose is recoverability, continuity across devices, and protection against local data loss.

### **Data Access and Availability**

Encrypted asset data remains inaccessible to roles without the appropriate encryption keys; protocol conditions restrict how decrypted data may be used.

* Beneficiaries can decrypt asset transfer data only after the applicable challenge period has completed and Distribution has begun.
* Guardians can decrypt asset transfer data only after reaching the required confirmation threshold and completion of the guardian challenge period.
* Recovery addresses may decrypt asset transfer data at any time, while asset movement remains restricted to recovery-specific protocol-defined execution paths under the defined recovery thresholds.
* The owner may decrypt owner backup data at any time by recreating the encryption key through wallet signature.

To ensure correctness, CryptoLegacy provides a mechanism for verifying encryption through test messages, allowing users to confirm decryption capability in advance without exposing asset data or granting execution authority.

### **Compatibility with Previous Encryption Formats**

CryptoLegacy supports backward compatibility with previously encrypted data formats. Legacy payloads generated using deprecated wallet encryption methods can be distinguished by their encoding format and are handled using the appropriate decryption logic.

Newly encrypted data includes an explicit version marker, allowing the system to reliably detect the encryption method and apply the correct cryptographic procedure.

### **Security Considerations**

It is safe to publicly disclose:

* Public encryption keys
* Ephemeral public keys
* Nonces and encrypted payloads

Critical security assumptions rely on:

* The integrity of the wallet signature used to derive encryption keys
* The user’s responsibility not to sign the encryption message on untrusted websites

Encrypted data alone does not grant asset access, execution authority, or custody, and decryption does not modify protocol state. Asset transfers remain strictly governed by on-chain approvals and protocol-defined execution paths.

CryptoLegacy combines deterministic on-chain execution with client-side encryption to ensure privacy, self-custody, and long-term reliability in managing and transferring digital assets.


# How CryptoLegacy Contract Periods and Guardian Controls Work

Explains the fixed 6-month check-in, 3-month challenge, and distribution phases. Guardians trigger protocol-defined execution paths when the owner cannot act, while recovery handles remaining assets.

### **CryptoLegacy Contract Statuses**

* **Normal (Active Status)**
  * The contract is deployed and active but holds no assets.
  * Every 6 months, the contract owner confirms activity by sending an on-chain transaction.
  * This 6-month check-in interval is fixed and cannot be changed, ensuring a predictable execution schedule.
  * During Normal status, assets remain in Asset Holder addresses (external owner-controlled wallets).
  * While the owner remains active, no inactivity-based or guardian-based asset transfer execution can occur.\
    Recovery-specific execution paths may remain available.
* **Challenge Period (Fixed 3-Month Window)**
  * If the owner misses the required 6-month check-in, any beneficiary may initiate a fixed 3-month challenge period.
  * During this period, the owner may restore normal operation by updating the inactivity timeout on-chain.
  * During the Challenge Period, no asset transfer into the CryptoLegacy contract is permitted via the inactivity-based or guardian-based execution paths. Execution proceeds to Distribution only if the challenge completes without being canceled.
  * If guardians are configured, a guardian-initiated execution path may be triggered via guardian confirmations, followed by a guardian challenge period (0–30 days), only if guardians act before the inactivity timeout expires.
  * The duration of the beneficiary challenge period is fixed and cannot be modified.
* **Distribution Period**
  * If the applicable challenge period completes without interruption, the contract enters Distribution.
  * During Distribution, pre-approved assets may be transferred from Asset Holder addresses into the CryptoLegacy contract via protocol-defined execution paths.
  * Any single beneficiary — or any single guardian, if guardians are configured and the guardian execution path has completed — may decrypt asset metadata and initiate transfers as permitted by the active execution path, and only for assets that were explicitly approved in advance.
  * Once assets are held by the contract, beneficiaries claim them according to predefined parameters:
    * **Delay:** The waiting period after distribution begins before a beneficiary can start claiming.
    * **Duration:** The time over which assets unlock gradually and can be claimed incrementally.

### **Guardians and Recovery Controls**

#### **Guardians**

Guardians are on-chain verification roles used to trigger a protocol-defined execution path when the contract owner cannot act. They do not control assets, make discretionary decisions, or receive custody at any point.

The contract owner selects guardians and defines a confirmation threshold (e.g., 1-of-3, 2-of-3, 3-of-5). By default, beneficiaries act as guardians with a **majority-based confirmation threshold** (for example, 2-of-3). If fewer than two beneficiaries are configured, the threshold equals the number of beneficiaries.

The guardian challenge period is set to 30 days by default and may be adjusted by the owner within protocol-defined limits (0–30 days).

Guardian addresses are stored on-chain as hashes and are not directly linkable to a specific CryptoLegacy contract until they participate in a transaction.

Once the guardian confirmation threshold is reached and the guardian challenge period completes without interruption, any single guardian may decrypt the encrypted asset metadata and initiate transfer of pre-approved assets into the CryptoLegacy contract via the guardian execution path. Guardians never withdraw assets to their own addresses and never gain custody.

#### **Recovery Addresses**

Recovery addresses provide an always-available, separate protocol-defined execution path that allows control over remaining assets under protocol control to be restored if circumstances change. Recovery availability is not tied to contract periods, but its effects remain constrained by protocol execution rules and asset-level finality.

Recovery addresses are always able to decrypt encrypted asset metadata. They may, without waiting for beneficiary or guardian challenge periods, initiate transfers of pre-approved assets from Asset Holder addresses into the CryptoLegacy contract via the recovery execution path, and subsequently withdraw remaining contract-held assets to new addresses according to predefined recovery thresholds and rules.

Recovery does not interrupt, reverse, or modify transfers or claims that have already finalized. It applies only to assets that remain under contract control at the time of recovery execution.

Recovery addresses are stored on-chain as hashes and are not linkable to a specific CryptoLegacy contract until used.\
Optionally, a recovery password (secret) may be configured and cryptographically combined with the recovery address before hashing. In this case, knowledge of the private key alone is insufficient to associate the address with the CryptoLegacy contract or to execute recovery actions without the corresponding password.

When a recovery action is executed, the recovery address necessarily becomes visible on-chain as part of that transaction.

#### **Additional Security Notes**

Beneficiaries and guardians can decrypt encrypted asset metadata only after the relevant protocol-defined execution conditions are met, such as completion of a challenge period or satisfaction of guardian confirmation thresholds.

Recovery addresses are not subject to these timing constraints and may decrypt asset metadata at any time, while asset movement remains restricted to recovery-specific protocol-defined execution paths.

Encryption keys and metadata are validated in advance using test messages to ensure that execution can proceed correctly when required.

CryptoLegacy enforces clear role separation, deterministic execution rules, and on-chain verification, reducing reliance on coordination, discretion, or off-chain enforcement.


# Cross-chain Integration for Lifetime NFTs and Referral Program

Lifetime NFTs and referral codes work across multiple blockchains via deBridge. NFTs are minted once and locked cross-chain, while referral codes are created once and reused across supported networks.

When designing **CryptoLegacy**, we needed a way to avoid repeating contract setup and periodic payments on every blockchain.

CryptoLegacy contracts are sustained through transparent DAO donations. A fixed donation is required when a contract is created and periodically to keep it active. Without a pass, this donation applies separately on each blockchain where a contract is deployed.

The **Unlimited NFT Pass** solves this by allowing users to pay once and reuse that right across all supported blockchains. Instead of making recurring donations for every contract on every chain, the pass can be locked cross-chain and used to create and update contracts without additional payments on those networks.

The **Referral Program** is an optional protocol mechanism for trusted introductions. Referral codes are created on Arbitrum to minimize costs and are then propagated to other supported blockchains. When a referral code is used, the invitee receives a discount, and a portion of the donation is allocated to the code holder. Referral codes are intended for private use in trusted contexts, not for public promotion or growth campaigns.

Both mechanisms rely on the **deBridge protocol** to synchronize state across blockchains. deBridge is used strictly as a messaging layer to propagate NFT lock status, NFT ownership updates, and referral code data across networks. deBridge does not hold assets, does not execute protocol logic, and does not make discretionary decisions.

#### Cross-chain Lifetime NFT (Unlimited Pass)

A **Lifetime NFT** (Unlimited Pass) can be used to waive DAO donation payments on chains where its lock status is active. The typical flow is:

**1. Mint on Ethereum Mainnet**

Lifetime NFTs are minted on **Ethereum Mainnet**. Ethereum acts as the originating chain from which lock and ownership updates are propagated to other supported networks.

**2. Lock and propagate to other chains (deBridge)**

To use the NFT on a target network, the lock state is propagated cross-chain:

* Submit a transaction on Ethereum to send the lock data to the target chain.
* deBridge delivers the cross-chain message.
* On the target chain, the lock state is confirmed automatically upon successful message delivery.\
  If automatic confirmation does not occur, the lock can be confirmed through an explicit on-chain confirmation transaction.

Once confirmed, the same Unlimited NFT Pass permissions apply on that chain (for example, contract creation and updates without additional DAO donations).

**3. Unlocking**

Unlocking is constrained by protocol-defined timing and cross-chain lock state:

* The **lock period** is a protocol parameter enforced on-chain.\
  **Current lock period: 150 days.**
* An NFT cannot be unlocked on any chain while it is still recorded as locked on other chains.
* Unlocking requires removing remote locks first via cross-chain unlock messages, and then confirming the final unlock on the originating chain.

Lock timing parameters (including the lock period) are enforced by the LockChainGate logic and may be adjusted through protocol administration or governance over time.

**4. Transferring a locked NFT**

A Lifetime NFT behaves like a standard ERC-721 when it is not locked. When it is locked, transfers are constrained:

* Transfers of a locked NFT are subject to a protocol-defined **transfer timeout** (cooldown).\
  **Current transfer timeout: 14 days.**
* If the NFT lock status exists on multiple chains, ownership changes on the originating chain are propagated to the other chains where the lock is active via protocol-defined cross-chain owner update messages.

The transfer timeout is enforced by the LockChainGate logic and may be adjusted through protocol administration or governance over time.

#### Cross-chain Referral Program

Referral codes are a protocol mechanism used for DAO donation discounts and reward routing.

**1. Create a code (typically on Arbitrum)**

To reduce costs, referral codes are typically created on **Arbitrum**, which currently acts as the canonical chain for the referral program, and then propagated to other supported chains.

Each code has:

* an **owner** (admin address),
* a **payout address** (where referral rewards are sent),
* **discount** and **referral share** values.

Discount and referral share are defined on the canonical chain and may be propagated to other supported chains as part of referral code synchronization.\
If a referral code has explicit discount/share values, those values override local defaults on destination chains.\
If no explicit values are propagated for a given field, destination chains apply their locally configured defaults for that field.

A key constraint is that a referral code owner cannot already own another referral code (one-code-per-owner).

**2. Activate / propagate to other chains**

Referral code data is propagated using deBridge:

* Submit a transaction on the source chain specifying destination chains.
* deBridge delivers the cross-chain messages.
* On destination chains, referral codes are activated automatically once the messages are confirmed.\
  If automatic activation does not occur, activation can be completed via an explicit on-chain confirmation transaction.

Once activated, the same referral code, owner, payout address, and any propagated discount/share values apply on those networks.

**3. Updating owner / payout address**

Referral code configuration can be updated on the canonical source chain.

Updates to the referral code owner and/or payout address are performed by submitting an on-chain update on that chain. As part of the same operation, the updated referral code data can be propagated to other supported chains by specifying the target networks and covering the required cross-chain messaging fees.

On destination chains, the updated fields are applied through a protocol-defined cross-chain update delivered by deBridge.

If propagation to a specific chain is not finalized automatically, the update can be completed by confirming it on that target chain.

**4. Updating discount and referral share**

In addition to ownership and payout address, referral discount and referral share can be changed.

This is a two-step process:

1. **Change the values on the canonical chain**\
   Discount/share values are stored on-chain and can be updated through the canonical chain configuration. This updates the values used on the canonical chain.
2. **Propagate updated values to other chains**\
   To apply updated discount/share values on other supported networks, the referral code data must be propagated cross-chain via a protocol-defined deBridge update. On destination chains, only the fields included in the update are modified; any fields not included remain unchanged.

As with other referral code updates, if propagation to a specific chain is not finalized automatically, the update can be completed by confirming it on that target chain.

#### Cross-chain Asset Transfer

CryptoLegacy does not currently support direct cross-chain transfers for assets held inside a personal contract. Asset execution (transfer, claim, recovery) is always performed on the chain where the personal contract is deployed.

If cross-chain asset transfer is introduced in the future, it would be implemented via a dedicated execution plugin and would only be available if explicitly enabled under protocol-defined execution rules.

#### Cross-chain Contract Copy

CryptoLegacy supports a contract copy flow across networks in the interface. The goal is to deploy a contract on another network while preserving the same beneficiary configuration and execution assumptions, and then re-add assets and encrypted backups on the target chain.

Each copied contract is an independent on-chain instance on its respective network and follows the same protocol-defined execution model.


# CryptoLegacy Plugins Extend Contract Functionality

CryptoLegacy contracts use modular, audited execution plugins registered on-chain to extend allowed actions without changing core execution rules or authority boundaries.

CryptoLegacy contracts use the Diamond standard (EIP-2535) so that all personal contracts execute the same core protocol logic. Instead of deploying a unique smart contract with custom code for each user, CryptoLegacy deploys a standardized contract shell and attaches audited plugins that implement specific execution actions.

In practice, this means that the rules governing execution periods, role authority, timing, and asset movement are identical across all personal contracts and are enforced by the same underlying logic. No personal contract can introduce custom execution paths, shortcuts, or special-case behavior through custom code.

Differences between personal contracts arise only from configuration set by the owner — such as which plugins are enabled, which roles are assigned, what confirmation thresholds apply, and which execution actions are permitted during Distribution. These differences affect *what actions are allowed*, not *how the protocol itself behaves*.

This model avoids the risks of bespoke contract logic while making the system easier to audit, upgrade, and reason about. All security-critical behavior remains consistent and predictable, while plugins provide controlled extensibility within protocol-defined execution paths.

### **Adding and Managing Execution Plugins**

Contract owners may add or replace execution plugins by submitting on-chain transactions to their personal CryptoLegacy contract during the Normal Period. Each requested plugin is validated against the on-chain Plugin Registry before it can be enabled.

Plugins are registered through protocol-defined governance and security review processes. The registry enforces that only approved plugins can be activated, without discretionary intervention at execution time.

**Execution plugins operate under explicit confirmation thresholds.**\
Each plugin defines the number of confirmations required for its actions to execute within existing protocol-defined execution paths (for example, 1-of-N or M-of-N beneficiary confirmations). These thresholds are part of the execution constraints and are enforced on-chain.

Some plugins require a locked Lifetime NFT to be enabled, depending on the permissions they introduce.

### **Plugin Governance and Thresholds**

In addition to execution plugins, CryptoLegacy supports protocol-defined meta-plugins that govern how other plugins may be added within existing execution paths.

A contract owner may enable a dedicated plugin during the Normal Period that allows beneficiaries to add new execution plugins during the Distribution phase. This capability exists only if such a plugin was explicitly configured in advance and is strictly constrained by predefined confirmation rules.

For example, a contract owner may initially require a 3-of-5 beneficiary confirmation threshold to approve changes to plugin installation rules. Using that same threshold, beneficiaries may approve a rule change that lowers the threshold for future plugin additions (e.g., to 2-of-5). Once approved, the new threshold becomes the active execution rule for adding plugins.

Beneficiaries cannot remove existing plugins and cannot exceed protocol-defined execution constraints set during the Normal Period.

### **Plugin Security Model**

* All plugins must be registered in the on-chain Plugin Registry.
* Plugins are reviewed and audited by independent security firms before registration.
* Plugins follow a minimal execution-scope design to reduce complexity and attack surface.
* Users interact only with their personal contracts when enabling plugins; no shared custody or external control is introduced.
* The Plugin Registry is designed to be progressively decentralized. Registry participation does not grant execution authority or discretionary control over personal contracts.

### **Available Plugins**

* **Base Plugin**\
  Provides the core execution logic shared by all CryptoLegacy contracts.
* **Trusted Guardians Plugin**\
  Implements guardian-specific execution logic within existing protocol-defined guardian execution paths, allowing transfers to proceed under predefined conditions without waiting for inactivity timeouts.
* **Recovery Plugin**\
  Implements recovery-specific execution paths using hashed recovery addresses to withdraw remaining contract-held assets according to predefined recovery rules.

### **Future Plugins**

* **Lido Plugin**\
  Enables protocol-specific staking actions during distribution.
* **Aave Plugin**\
  Enables protocol-specific lending and withdrawal actions during distribution.
* **Uniswap Position Closure Plugin**\
  Allows authorized closure of Uniswap NFT positions held by the contract.
* **Uniswap Swap Plugin**\
  Enables token swaps within predefined execution constraints.
* **Beneficiary Execution Plugin**\
  Allows beneficiaries to perform additional execution actions, including enabling further plugins, only if explicitly permitted by a preconfigured plugin and subject to predefined confirmation thresholds.
* **NFT Legacy Plugin**\
  Enables NFT-specific transfer and handling logic during distribution.

Plugins extend which execution actions are permitted within protocol-defined execution paths. They do not grant custody, discretionary authority, or the ability to override core execution rules, timing, or finality.


# CryptoLegacy NFT: Lifetime Access and DAO Rights

A single Lifetime NFT replaces recurring DAO donations, enables cross-chain access, and provides tier-based DAO governance rights.

CryptoLegacy uses an NFT-based access model to simplify long-term participation across blockchains.\
Instead of making repeated DAO donations for every contract creation or periodic timeout update on each network, users may mint a single **Lifetime NFT** and reuse it wherever CryptoLegacy is deployed.

The NFT can be locked across multiple blockchains using the **deBridge messaging protocol**. While locked, it grants the right to create and update CryptoLegacy contracts without additional DAO donations on those networks.

Each NFT lock is subject to a **protocol-defined lock period** (currently 150 days). The NFT can only be unlocked after this period has elapsed. Lock parameters are part of the protocol configuration and may be adjusted through governance.

### **NFT Tiers**

CryptoLegacy Lifetime NFTs include **on-chain tiers** based on mint order. These tiers are inspired by rare-earth metals that underpin modern digital infrastructure and are recorded directly on-chain.

The tiers include:

* **Silicon (1–100)**\
  Foundational tier representing the core of modern computing and semiconductors.
* **Gallium (101–300)**\
  Associated with high-speed electronics, LEDs, and wireless technologies.
* **Indium (301–700)**\
  Linked to touchscreens, displays, and modern user interfaces.
* **Tantalum (701–1500)**\
  Represents advanced electronic components and miniaturization.
* **Base Tier (1501 and above)**\
  Standard NFT tier with baseline protocol access.

NFT tiers do **not** affect contract execution, security rules, transfer logic, or recovery paths. They are used exclusively for governance, community, and incentive mechanisms.

### **DAO Rights**

CryptoLegacy Lifetime NFTs form the foundation of DAO participation:

* Each NFT provides **voting power proportional to its tier**, as defined by protocol rules.
* **DAO voting is currently conducted off-chain using Snapshot.** Voting affects governance only and does not change contract execution, roles, or asset control.
* Governance decisions may be migrated on-chain in the future through dedicated governance contracts.
* If a DAO-issued ERC20 token is introduced, NFT tiers are expected to serve as one of the inputs for airdrop allocation.

The current voting weights per NFT tier are:

* **Silicon** — **20 votes per NFT**
* **Gallium** — **9 votes per NFT**
* **Indium** — **4 votes per NFT**
* **Tantalum** — **2 votes per NFT**
* **Base Tier** — **1 vote per NFT**

NFT tiers influence governance and incentives only; they do not grant additional execution privileges, affect contract behavior, or modify asset control.

### **CryptoLegacy NFT Pricing**

At launch, each CryptoLegacy Lifetime NFT is priced at **1 ETH**.\
Pricing is a protocol parameter initially set by the team and expected to transition to DAO governance over time. Referral discounts may apply.

### **CryptoLegacy NFT Groups**

Lifetime NFT holders may access private community channels, such as an exclusive Telegram group.\
Access is verified **off-chain** by signing a message to prove NFT ownership. Community access does not affect protocol execution or contract behavior.


# CryptoLegacy Governance and Path to True Decentralization

CryptoLegacy governance evolves from NFT-based DAO voting and multisig control toward fully decentralized, on-chain governance.

This section describes protocol-adjacent infrastructure. It does not modify or extend core execution guarantees.

CryptoLegacy is designed with decentralization as a long-term goal, not a marketing promise. While the system is self-custodial, governance requires a careful transition to avoid introducing new risks.

In the initial phase, governance is formed by early users and supporters holding **CryptoLegacy Lifetime NFTs**. DAO participation and voting are currently conducted **off-chain using Snapshot**, with voting power derived from NFT tiers. This phase allows the community to define core principles, including the **Manifesto**, **Mission**, and governance **rules**, without introducing execution risk into smart contracts.

During early decentralization, critical protocol-adjacent components — most notably the **Plugin Registry** — may be managed via **DAO-controlled multisig wallets**. This approach balances decentralization with security, ensuring that plugin approvals and updates remain auditable and conservative while the ecosystem matures. Security firms and partner protocols may participate in this process to provide additional review and oversight.

Most core CryptoLegacy smart contracts are non-proxied, and do not require ongoing governance intervention. Governance is intentionally limited to areas where flexibility is necessary, such as plugin approval, fee/configuration parameters, and cross-chain configuration.

In the future, the DAO may choose to introduce an **ERC20 governance or utility token**, but no such decision has been made. If introduced, it would be governed by the community and designed to complement — not replace — the existing NFT-based governance model.

Decentralization in CryptoLegacy is treated as a process, not a milestone. Each governance step is intended to reduce trust assumptions while preserving the security and predictability of execution.


# CryptoLegacy: Security-First Approach to Asset Transfer and Recovery

CryptoLegacy secures assets by defining deterministic execution paths for transfer and recovery, without custody, manual intervention, or trust-based controls.

CryptoLegacy was designed from the start around the assumption that **owner inability to act and execution failures are primary risks in self-custody systems**. As a result, security is enforced through deterministic execution rules rather than reliance on trusted intermediaries or emergency controls.

#### CryptoLegacy Smart Contract Security

* CryptoLegacy smart contracts have undergone **multiple independent security audits**, with additional reviews and audits ongoing as the protocol evolves.
* A DAO-managed **bug bounty program** is planned to complement audits.
* You remain the **sole owner of your personal CryptoLegacy contract**. Control is limited to execution-relevant configuration only. There are no privileged backdoors or discretionary recovery mechanisms.
* Personal contracts **do not custody assets**. Assets remain in your own wallets during normal operation and are transferred only after:
  * inactivity timeouts and challenge periods complete, or
  * guardian confirmation thresholds and challenge periods are satisfied, or
  * recovery execution paths are used.
  * Note: the 6-month inactivity check-in and the 90-day Beneficiary Challenge are protocol-defined and fixed; the Guardians Challenge is configurable only within 0–30 days.
* **Guardians do not have custody** and cannot withdraw assets to arbitrary addresses.\
  **Recovery addresses provide a separate execution path and may, subject to predefined recovery thresholds and rules, transfer assets into the contract and withdraw remaining contract-held assets to new addresses, without reversing or modifying finalized transfers or claims.**
* Personal contracts follow the **Diamond Standard (EIP-2535)** to allow modular execution extensions. Only approved execution plugins may be enabled, and core execution rules remain immutable.
* All plugins must be registered in the **on-chain Plugin Registry** and reviewed before activation. Plugin approval is governed through DAO-controlled processes rather than discretionary execution-time decisions.
* Core execution contracts are **non-proxied**, reducing upgrade-related risk. The Fee Registry is upgradeable due to its governance-linked role.
* Some external calls during execution are designed to use bounded gas and defensive patterns (for example via gas budgeting and try/catch) to reduce the risk of execution being blocked by hostile or misconfigured external contracts.
* Beneficiary claims do not rely on fees for correctness: the claim fee is treated as a voluntary donation and can be zero; fee settings do not change the beneficiary’s entitlement.

#### Threat Model

CryptoLegacy is designed to mitigate the following classes of risk:

* Loss of access or inability of the owner to act.
* Human coordination failures during recovery or transfer.
* Premature disclosure of asset information.
* Execution deadlocks caused by unavailable participants.

CryptoLegacy does **not** attempt to mitigate:

* Loss of all private keys, guardians, and recovery access simultaneously.
* Global blockchain halts or permanent network failures.
* Protocol-level failures of underlying blockchains or cross-chain infrastructure.

#### Execution Finality

Once an execution step completes on-chain, it is final:

* Completed transfers cannot be reversed.
* Completed claims cannot be canceled.
* Recovery applies only to assets that remain under contract control at the time of recovery execution.

CryptoLegacy intentionally avoids rollback or override mechanisms to preserve determinism and auditability.

#### Time-Based Assumptions

CryptoLegacy relies on blockchain timestamps for time-based execution, including inactivity timeouts, challenge periods, and lock durations.\
Minor timestamp variance does not affect correctness, but extreme reorgs or prolonged chain instability may delay execution.

#### Known Execution Failure Conditions

Execution will not proceed if any of the following conditions are met:

* Required confirmations or thresholds are not reached.
* A challenge period is still active.
* Assets were not approved for transfer in advance.
* (Fee/Access only) Lifetime NFT lock state and cross-chain messages (for NFT lock / referral sync) may delay fee-free updates or cross-chain synchronization. They do not change personal contract execution rules for asset transfer, claim, or recovery on the chain where the personal contract is deployed.

These conditions do not alter execution rules; they may only delay execution.

#### Configuration Risks

CryptoLegacy does not attempt to prevent all misconfiguration.\
Incorrect thresholds, unreachable guardians, missing recovery addresses, or insufficient approvals may result in execution paths that cannot complete. Users are responsible for validating their configuration before assets are at risk.

#### Guardian and Recovery Risks

Guardians and recovery addresses are powerful execution roles.\
Incorrect selection, loss of access, or collusion may result in delayed or unintended execution.

CryptoLegacy enforces technical limits but cannot evaluate human trust decisions.

#### Governance Scope and Limits

DAO governance **cannot**:

* Move user assets.
* Override execution rules.
* Cancel finalized transfers or claims.
* Access guardian or recovery execution paths.

Governance is intentionally limited to protocol parameters and critical infrastructure such as the Plugin Registry.

#### Upgrade Scope

The **Fee Registry** is upgradeable due to its governance-linked role.

The **Plugin Registry contract itself is not upgradeable**; governance controls only which plugins are added to or removed from the registry.

Personal CryptoLegacy contracts and their core execution logic are **not upgradeable**.\
Execution capabilities may be extended only through explicitly enabled plugins, without modifying core contract code.

#### Gas and Fee Responsibility

Users are responsible for providing sufficient gas and fees for execution.\
Failed or reverted transactions do not modify execution state.

#### Cross-Chain Messaging Limitations

Cross-chain execution depends on successful message delivery. Network congestion, bridge downtime, or misconfiguration may delay execution but cannot alter predefined rules or grant additional authority.

#### CryptoLegacy UI Security

* The CryptoLegacy interface is protected by Cloudflare to mitigate DNS spoofing, cache poisoning, and man-in-the-middle attacks.
* For maximum assurance, users can run the interface **self-hosted**, removing reliance on hosted frontends.
* A mirrored deployment is available on **Arweave** for censorship-resistant access.

#### CryptoLegacy Infrastructure Dependencies

* CryptoLegacy relies on RPC providers, SubQuery indexers, and APIs for usability, all of which can be **overridden or replaced** by the user.
* The interface is designed to be deployable on **decentralized hosting platforms** such as IPFS and Arweave.
* Infrastructure services **do not participate in execution logic** and cannot move assets or alter contract behavior.

#### Support Limitations

CryptoLegacy support cannot:

* Modify contract state.
* Recover lost keys.
* Change execution rules.
* Reverse on-chain actions.

Support assistance is limited to guidance and documentation.

#### Security Invariants

The following invariants are enforced by design:

* Assets are never held by the protocol during normal operation.
* No role has unilateral authority over execution.
* Execution cannot proceed without predefined conditions.
* Recovery cannot affect finalized execution.

#### Key Security Principle

CryptoLegacy does not attempt to “secure funds” through custody or intervention.\
Instead, it secures **execution paths** by ensuring that:

* rules are defined in advance,
* execution is deterministic,
* recovery does not rewrite history,
* and no actor can bypass protocol-defined conditions.


# CryptoLegacy: Privacy Is Important for Execution When the Owner Cannot Act

CryptoLegacy protects privacy by encrypting sensitive data locally and recording it on-chain. Decrypted data is usable only within protocol-defined execution paths when the owner cannot act.

We believe privacy is crucial for execution in situations where the owner cannot act. CryptoLegacy operates within an architecture where assets are approved from external wallets to a personal CryptoLegacy contract, while the protocol is designed so that sensitive information is not exposed through standard interfaces and remains encrypted unless protocol-defined execution conditions are satisfied.

Privacy in CryptoLegacy is achieved by separating **data visibility** from **execution authority**. Encrypted data may exist on-chain, but it does not grant custody, control, or execution rights. Asset movement remains strictly governed by predefined on-chain execution paths and required approvals.

As a result, sensitive data is not revealed prematurely in the interface, and asset-related information remains encrypted until the protocol reaches a state where the conditions required for a specific execution path are satisfied.

**Key Privacy Principles**

* Names, Beneficiaries, Guardians, Recovery addresses, Asset Holders (wallet addresses), ERC20 token addresses, and public encryption keys are stored locally in the user’s browser.
* Owner backups are encrypted using the owner’s public encryption key and recorded on-chain as encrypted transaction events in a separate backup contract.
* Asset-holder wallet addresses and token addresses required for asset transfer are encrypted individually for each Beneficiary, Guardian, and Recovery address using their respective public encryption keys and recorded on-chain as encrypted transaction events in the CryptoLegacy contract.
* All encryption is performed client-side using wallet-derived encryption keys. Private keys and encryption seeds are never transmitted or stored on-chain.

Encrypted data recorded on-chain is publicly visible but cannot be decrypted without recreating the corresponding encryption key through a wallet signature. Visibility of encrypted data does not grant execution authority.

**Data Availability by Role**

Encrypted asset data becomes usable only within protocol-defined execution paths and never grants authority by itself:

* **Beneficiaries** can decrypt asset transfer data only after the applicable challenge period has completed and Distribution has begun.
* **Guardians** can decrypt asset transfer data only after reaching the required confirmation threshold and completion of the guardian challenge period.
* **Recovery addresses** may decrypt asset transfer data at any time, while asset movement remains restricted to recovery-specific protocol-defined execution paths under the defined recovery thresholds.
* **The owner** may decrypt owner backup data at any time by recreating the encryption key through wallet signature.

Decryption is an off-chain operation and does not modify protocol state or grant execution authority.

To ensure correctness, CryptoLegacy provides a mechanism for verifying encryption through test messages, allowing users to confirm decryption capability in advance without exposing asset data or granting execution authority.

**Execution Routing and Privacy**

CryptoLegacy enforces execution strictly through protocol-defined on-chain execution paths.\
In the current architecture, assets are approved directly to the personal CryptoLegacy contract and transferred according to the active execution period and role permissions.

In addition to this direct model, the protocol defines an **intent-based execution mechanism** implemented via a shared execution router and a dedicated plugin.\
This mechanism allows the owner to predefine permitted asset transfers as hashed execution intents, without revealing wallet or token relationships in plaintext on-chain.

Execution intents:

* do not grant execution authority,
* do not bypass challenge periods, thresholds, or role checks,
* serve only as deterministic constraints evaluated during execution.

Under this model:

* The owner registers hashed execution intents in the personal CryptoLegacy contract.
* Detailed transfer parameters (wallet addresses, tokens, signatures, and related metadata) are delivered to the relevant roles through encrypted on-chain messages.
* When execution is permitted by the protocol, Beneficiaries, Guardians, or Recovery roles execute transfers via the plugin, which forwards validated executions to the shared router.
* The router verifies intent digests, validates signatures, and performs transfers strictly according to protocol-defined rules.

This routing mechanism does not grant additional authority and does not bypass execution constraints. It exists to reduce on-chain linkability between wallets and contracts while preserving deterministic execution and auditability.

**Compatibility with Previous Encryption Formats**

CryptoLegacy supports backward compatibility with previously encrypted data formats. Legacy payloads generated using deprecated wallet encryption methods can be distinguished by their encoding format and are handled using the appropriate decryption logic.

Newly encrypted data includes an explicit version marker, allowing the system to reliably detect the encryption method and apply the correct cryptographic procedure.

**Security Considerations**

Privacy in CryptoLegacy is achieved through protocol design, not through obscurity or trust assumptions.

* Encrypted data may be publicly visible but does not grant asset access or execution authority.
* Decryption is performed off-chain and does not affect protocol execution logic.
* Asset transfers remain strictly constrained by on-chain approvals, thresholds, and execution paths.

By combining client-side encryption, local data storage, and deterministic on-chain execution, CryptoLegacy provides practical privacy for execution and recovery in situations where the owner cannot act, without compromising self-custody or protocol safety.


# CryptoLegacy: Protocol Integrations for Flexibility

CryptoLegacy integrates with external protocols through execution plugins, allowing predefined actions during Distribution without changing custody, authority, or core execution rules.

CryptoLegacy integrations are designed to extend **what actions may be executed**, not who controls assets or how execution decisions are made. All integrations operate within the same execution model: predefined rules, explicit permissions, and on-chain enforcement.

Integrations are available either as native interfaces or as execution plugins that can be enabled by the contract owner and, where permitted, by beneficiaries under predefined confirmation thresholds.

### **dApp Integration**

CryptoLegacy is available as a **Safe App**, allowing users who custody assets in Safe wallets to interact with CryptoLegacy directly.

In practice, this integration is primarily used to **manage token approvals** — granting, reviewing, and revoking allowances required for execution — without changing custody models or moving assets. The Safe App provides a familiar and secure interface for preparing assets for execution while keeping full control within the Safe.

### **Execution Plugins and Future Integrations**

Additional protocol integrations are implemented or planned as **execution plugins**. These plugins allow specific, predefined actions to be executed during the Distribution phase, subject to protocol rules and confirmation thresholds.

Planned integrations include:

* **Aave Plugin**\
  Enables predefined lending, withdrawal, and position management actions during Distribution.
* **Uniswap Plugin**\
  Enables token swaps and position closure within predefined execution constraints.
* **1inch Plugin**\
  Enables token swaps through aggregated liquidity, subject to execution permissions.
* **Lido Plugin**\
  Enables staking and unstaking actions (ETH/WETH ↔ stETH/wstETH) as predefined execution steps.
* **DeBridge Plugin (Cross-Chain Swaps)**\
  A dedicated execution plugin planned to enable **explicit cross-chain swaps** between CryptoLegacy contracts deployed on different blockchains that share the same address. Cross-chain swaps will only be possible if this plugin is explicitly enabled and executed under predefined execution rules and confirmation thresholds.

All integrations operate strictly within the CryptoLegacy execution model. They do not introduce custody, discretionary control, or automatic asset movement beyond what is explicitly defined and approved in advance.


# CryptoLegacy Example Flow Overview

This section provides detailed example scenarios for using the CryptoLegacy contract. All parameters - such as the number of beneficiaries, guardians, recovery addresses, approval thresholds, delays, and distribution periods - are for illustration purposes only.&#x20;

You can adjust these settings based on your preferences, requirements, or desired security level.

These examples illustrate how to:

• Set up beneficiaries and securely encrypt their data.

• Assign guardians and manage emergency approvals.

• Use recovery addresses for additional security.

• Trigger asset distributions securely and predictably.

Feel free to customize the parameters to suit your specific needs.


# Detailed Contract Setup Flow

CryptoLegacy sets beneficiaries, secures asset distribution, encrypts data, and stores backups safely on blockchain.

## **Create CryptoLegacy Contract**&#x20;

* **Beneficiaries**:
  * Beneficiaries provide their addresses and public encryption keys.
  * Add 5 beneficiaries (provide their addresses and public encryption keys).
  * Set a 1-month delay per beneficiary (of course, you can choose any period).
  * Distribute equal shares (20% each) over 10 years. You can customize any parameter.
* **Deployment**:
  * Pay DAO donation and deploy the contract via the Factory.
  * Guardians and Recovery plugins are automatically added.
* **Data Storage**:
  * Beneficiary addresses are stored as hashes.
  * Original addresses and encryption keys are saved locally in your browser.

## **Token Approval**

* You have:
  * 3 multisig wallets holding assets.
  * 4 regular wallet addresses.
* Approve all tokens from all wallets to the new CryptoLegacy contract.
* Wallet and ERC20 token addresses are automatically saved locally in your browser.

## **Backup Encryption**

* Your backup is automatically encrypted with your public encryption key.
* Send a transaction to store the encrypted backup within a smart contract event.

## **Beneficiary Data Encryption**

* Wallet and asset addresses are automatically encrypted for each beneficiary using their public encryption keys.
* Send a transaction to store the encrypted data within a smart contract event.

## **Beneficiary Access and Testing**

* Beneficiaries do **not** have direct access to encrypted messages.
* Request beneficiaries verify encryption by testing with a provided test message.

## **Update timeout on CryptoLegacy Contract**

* Each 6 months send transaction to update timeout.


# Detailed Guardians Setup Flow

CryptoLegacy assigns guardians, sets approval thresholds, encrypts guardian data, stores backups, and tests access securely on-chain.

## **Guardians Setup for CryptoLegacy Contract**

* **Default Guardians**:
  * Beneficiaries automatically become Guardians (this can be modified).
  * Default approval threshold: **2 of 3** Guardians required for emergency withdrawals.
  * Emergency withdrawals trigger a **30-day challenge period** before distribution.
* **Adding Additional Guardians**:
  * Invite two friends to serve as additional guardians. There’s no limit - this is just an example.
  * Collect their addresses and public encryption keys.
  * Set the approval threshold to **4-of-7 guardians**. You can choose any number from 1 up to the total number of guardians.
  * Set Guardians' challenge timeout to **5 days**.
  * Confirm these settings by sending a transaction.
* **Data Storage**:
  * Guardian addresses are stored as hashes on-chain.
  * Original Guardian addresses and encryption keys are stored locally in your browser.

## **Backup Encryption**

* Backup is automatically encrypted using your public encryption key.
* Store encrypted backup by sending a transaction to the smart contract event.

## **Guardian Data Encryption**

* Automatically encrypt wallet and asset addresses for each Guardian using their public encryption keys.
* Store this encrypted data by sending a transaction to the smart contract event.

## **Guardian Access and Testing**

* Guardians do **not** have direct access to encrypted messages.
* Request Guardians verify encryption by testing with a provided test message.


# Detailed Challenge Period Start and Cancel Flow

CryptoLegacy lets beneficiaries start challenges, transfer assets securely after owner timeout, and claim their shares.

## Detailed Challenge Period Start and Cancel Flow

* You missed sending the transaction to update the **6-month timeout**.
* Any beneficiary can send a transaction to **start the 3-month challenge period**.
* As the contract owner, you can send a transaction to **cancel the challenge period**.

## Detailed Distribution Period and Asset Transfer Flow

* You did **not** cancel the challenge period.
* Any beneficiary automatically retrieves wallet and ERC20 token address data, decrypting it with their private encryption key.
* Any beneficiary initiates a transaction to transfer **all assets** from the wallets to the CryptoLegacy contract.
* Beneficiaries can send transactions to **claim assets** according to their share (20%), delay (1 month), and distribution schedule (over 10 years).


# Detailed Recovery Setup Flow

CryptoLegacy sets recovery addresses with encryption, stores hashed data securely on-chain, and grants direct emergency access if needed.

## **Recovery Setup for CryptoLegacy Contract**

* Create **3 recovery addresses** and provide their public encryption keys.
* Send a transaction to set these recovery addresses with a **2 of 3 threshold**.
* Recovery addresses are stored as hashes on-chain.
* Original recovery addresses and encryption keys are saved locally in your browser.

## **Recovery Data Encryption**

* Automatically encrypt wallet and asset addresses for each recovery address using their public encryption keys.
* Store the encrypted data by sending a transaction to a smart contract event.

## **Recovery Access**

* **Recovery addresses** have direct access to encrypted messages.


# Detailed Guardians Emergency Asset Withdrawal and Distribution Start

Guardians initiate emergency withdrawal; if owner doesn’t cancel in 5 days, guardians decrypt wallet data and transfer all assets on-chain.

* Guardian **#1** sends a transaction initiating an emergency withdrawal and distribution.
* Guardians **#2, #3, and #4** send transactions confirming the emergency withdrawal.
* **4 of 7 Guardians threshold** reached; a **5-day timeout** begins.
* As the contract Owner, you may send a transaction to **cancel** during this 5-day period.
* Alternatively, **2 of 3 Recovery addresses** may also send transactions to cancel during this period.
* You **do not cancel** within the 5-day timeout.
* After the 5-day timeout expires, neither the Owner nor Recovery addresses can cancel.
* After expiration, any Guardian automatically retrieves wallet and ERC20 address data, decrypting it with their private encryption keys.
* Any Guardian sends a transaction transferring **all assets** from wallets to the CryptoLegacy contract.


# Detailed Recovery Emergency Asset Withdrawal

CryptoLegacy allows emergency recovery; two recovery addresses confirm transactions, automatically withdrawing all assets securely.

* Initiate emergency asset recovery by sending a transaction from **Recovery Address #1**.
* Confirm recovery by sending a transaction from **Recovery Address #2**.
* Once the **2-out-of-3 threshold** is reached, **all currently supported assets** are automatically withdrawn from the CryptoLegacy contract to another address.


# Detailed Cross-chain Contract Copy Flow

Create and replicate CryptoLegacy contracts across chains with identical settings, and set up Guardians and Recovery per chain.

* **Create Contracts:**\
  On each supported chain, you can create any number of CryptoLegacy contracts for each owner with a unique address.
* **Replicate Contracts:**\
  You can replicate each contract on other chains using the same address, beneficiaries, shares, delay, and distribution settings.
* **Setup Guardians and Recovery:**\
  On each new chain, you must set up Guardians and Recovery settings.


# Detailed Cross-chain NFT Mint, Lock, and Unlock Flow

Mint an NFT to skip DAO donations cross-chain; auto-locks 5 months per action; unlock via Ethereum after confirming on all chains.

* **Mint and Lock NFT:**
  * Mint and lock an Unlimited NFT Pass by paying a DAO donation during contract creation, timeout updates, or challenge period cancellations.
* **Benefits of Locked NFT:**
  * Skip regular DAO donations for contract creation and timeout updates on all supported chains.
* **Ethereum Automatic NFT Minting:**
  * When creating a contract or updating a timeout on Ethereum without owning an NFT, the NFT can automatically mint and lock if you select that option.
* **Cross-chain NFT Minting via Ethereum:**
  * For contract creation or timeout updates on other chains without owning an NFT:
    1. Switch to Ethereum to mint and lock the NFT, automatically propagating the lock data to other chains via deBridge.
    2. After receiving bridge confirmations, switch back to the target chain and confirm the transaction.
  * Once confirmed, future contract creations and timeout updates on that chain become free for existing and new contracts.
* **Cross-chain NFT Unlock via Ethereum:**
  * The locked NFT has a 5-month lock period on each chain, starting from the moment of locking.
  * Each contract timeout update or new contract creation automatically extends the NFT lock by an additional 5 months if the previous lock period has expired.
  * To unlock the NFT after the lock period ends:
    1. Send an unlock transaction on the target chain. This transaction automatically sends a cross-chain message to Ethereum via deBridge.
    2. Wait for bridge confirmations, then switch to Ethereum and confirm the unlock transaction.
* **NFT Unlock on Ethereum:**
  * To unlock the NFT on Ethereum, it must first be unlocked on all other chains.
  * After unlocking on all other chains and once the Ethereum lock period expires, send an unlock transaction on Ethereum. The NFT will then be withdrawn directly to your address.
* **Multiple NFT Mint on Ethereum:**
  * DAO multisig can set an NFT total supply threshold, after which it becomes possible to mint NFTs without locking to multiple recipients.
  * Useful for gifting NFTs or obtaining better tiers and IDs for your own or friends' future contracts.
  * To mint, send a transaction including recipient addresses and NFT amounts, along with the DAO donation.
  * Initially, this threshold is set to 500.


# Detailed Admin Functions Flow

Transfer ownership, pause/unpause contracts, manage token approvals, and securely move locked NFTs cross-chain via Ethereum.

* As the contract Owner, you have full administrative rights for your personal CryptoLegacy contract.
* **Ownership Transfer:**
  * Transfer contract ownership anytime by sending a transaction for each contract on each chain.
* **Pause Contract:**
  * Pause the contract at any time, preventing asset withdrawals from your main wallets.
  * Optionally, remove token approvals during this state.
* **Unpause Contract:**
  * Unpause the contract anytime.
  * After unpausing, update the timeout if necessary by sending another transaction.
* **NFT Transfer on Ethereum:**
  * Transfer your locked NFT on Ethereum anytime by sending a single transaction.
* **NFT Transfer on Other Chains:**
  * To transfer a locked NFT on another chain:
    1. Switch to Ethereum and send a transaction to update the locked NFT owner, propagating the update via deBridge.
    2. Wait for bridge confirmations.
    3. Switch to the target chain and send a transaction to confirm the transfer.


# Detailed Beneficiary Claim Flow

Beneficiaries claim tokens per shares/delays; claims auto-adjust if token balances change via rebase or plugin logic.

* You **did not** cancel the challenge period.
* Beneficiaries automatically retrieve your wallet and ERC20 token address data, decrypting it with their private encryption keys.
* After distribution begins, any Beneficiary can initiate a transaction to transfer all assets from your main wallets to the CryptoLegacy personal contract. This transaction also records the block number of the transfer in the CryptoLegacy contract and logs transfer details in the transaction event.
* Beneficiaries can submit transactions to claim assets according to their share (in this example, 20%), delay (in this example, 1 month), and distribution schedule (in this example, 10 years).
* Initial token distribution amounts are recorded in the contract at the time of transfer.
* Each Beneficiary’s claimed token amounts are tracked and recorded within the contract.
* Beneficiaries can claim all available tokens at once or individually per token by submitting transactions.
* If token balances change due to rebases (e.g., stETH) or custom claim logic added via a plugin, initial distribution amounts automatically adjust based on the current contract balance and previously claimed amounts.


# Detailed Plugin Management Flow

Manage CryptoLegacy plugins securely; owner adds/removes before distribution; beneficiaries can manage plugins with approvals.

Your CryptoLegacy contract uses the Diamond Standard pattern, enabling easy addition of functionalities and integration with various protocols - such as NFT support, fixed-amount distribution, asset swapping via Uniswap, lending via Aave, or staking/unstaking in Lido during distribution.

* **Owner Plugin Management:**
  * During the Normal period, as the contract owner, you can add, remove, or replace plugins at any time.
  * Plugins being added or replaced are verified through a Plugin Registry managed by the DAO Multisig, consisting of the core team, partnered protocols, and leading security firms. Plugins are added only after several independent security audits.
  * To add, remove, or replace plugins, send a transaction to your CryptoLegacy contract.
  * You lose these rights during the distribution period.
* **Beneficiary Plugin Management:**
  * You can add a plugin granting beneficiaries the right to manage plugins during the distribution period.
  * This is useful for keeping protocol integrations up-to-date.
  * By default, there’s a 2-of-3 approval threshold, meaning two out of three Beneficiaries must approve a plugin addition.
  * You can adjust this threshold via transaction.
  * DAO will never approve plugins that alter distribution rules.


# Detailed DAO Donation Flow

DAO donations support lifetime NFT access or per-contract payments, unlocking features and ensuring project sustainability.

We are building a product designed to live and evolve indefinitely. Short-term crypto market cycles - dominated by VCs, centralized exchanges, and speculative token valuations - aren’t suitable for this purpose. To overcome this, we use a DAO donation model focused on real value, rather than speculation or reliance on future token price increases.

You can choose to make a donation for each contract creation and update or donate once to receive a lifetime-access NFT. Alternatively, you can create a contract without a DAO donation, but your CryptoLegacy contract will remain paused until you make one.

***

**Donation When Contract is Created Without a Donation (Paused State)**

* During initial contract creation without a donation, a one-time DAO donation amount is recorded in your CryptoLegacy contract.
* To activate the paused contract, submit a transaction with the required DAO donation.
* Alternatively, you can make a larger DAO donation to mint and lock an NFT (described below).

***

**Donation During Contract Creation on Ethereum**

* When creating a contract on Ethereum, you pay a DAO donation specified in the `FeeRegistry` contract unless you already have a locked NFT.
* Alternatively, you can make a larger DAO donation during contract creation to automatically mint and lock an NFT.
* After minting and locking the NFT, all future Ethereum contract creations and updates become free of charge.

***

**Donation During Contract Creation on Other Chains**

* When creating a contract on other chains, you pay a DAO donation specified in the `FeeRegistry` contract for that chain unless you already have a locked NFT there.

**To Lock an NFT on Ethereum and Use It on Another Chain:**

1. Switch to Ethereum.
2. Submit a transaction with the DAO donation to mint and lock the NFT. Lock data is automatically sent to the target chain via **deBridge**.
3. Wait for bridge confirmations.
4. Switch to the target chain.
5. Submit a transaction to confirm the bridged lock data.
6. After confirmation, you can create new contracts without additional donations.

**If You Already Have an NFT Locked on Ethereum but Not on the Target Chain:**

1. Switch to Ethereum.
2. Submit a transaction to send existing lock data to the target chain via **deBridge**.
3. Wait for bridge confirmations.
4. Switch to the target chain.
5. Submit a transaction to confirm lock data on the target chain.
6. After confirmation, you can create new contracts without additional donations.

***

**Donation During Contract Updates on Ethereum**

* When updating the 6-month timeout, you pay a DAO donation specified in the `FeeRegistry` contract unless you already have a locked NFT.
* If the standard function retrieving the donation amount fails for any reason, a fallback view function is used. This function automatically updates the recorded amount in your contract if there is a mismatch.
* Alternatively, you can make a larger DAO donation during contract creation or update to automatically mint and lock an NFT.
* After minting and locking the NFT, all future Ethereum contract creations and updates become free of charge.

***

**Donation During Contract Updates on Other Chains**

* When updating the 6-month timeout, you pay a DAO donation specified in the `FeeRegistry` contract unless you already have a locked NFT on that chain.
* If the standard function retrieving the donation amount fails for any reason, a fallback view function is used. This function automatically updates the recorded amount in your contract if there is a mismatch.
* Alternatively, you can make a larger DAO donation during the update to automatically mint and lock an NFT.

**NFT Locking Process (if no NFT exists or it’s locked only on Ethereum):**

1. Switch to Ethereum.
2. Submit a transaction with the DAO donation to mint and lock an NFT or send existing NFT lock data via **deBridge** to the target chain.
3. Wait for bridge confirmations.
4. Switch to the target chain.
5. Submit a transaction to confirm lock data on the target chain.
6. After confirmation, future contract creations and updates on this chain become free of charge.

***

**Donation During Beneficiary Claim**

* Beneficiary claims are free of charge if there is a locked NFT on that chain.
* If no locked NFT exists on the chain, the claim transaction automatically includes a DAO donation along with a referrer commission.
* For security reasons, donation and referrer data are **not** retrieved from `FeeRegistry`; instead, they are provided directly via the UI at the time of transaction submission.
* This approach ensures Beneficiary claims remain independent of `FeeRegistry` or any other contract operations.

***

**DAO Donation Management**

* DAO donation amounts, both one-time and lifetime NFT, are managed by the DAO and multisig.
* In the future, this management will be decentralized.


# Detailed Referral Program Flow

Cross-chain referral codes let users earn commissions and offer discounts on DAO donations, promoting growth without speculation.

To achieve a network effect without speculative tokenomics, we use a fair referral program for DAO donations. Anyone can create a cross-chain referral code and earn commissions. In this model, the referrer receives a percentage, and the referral gains a discount.

* All referral codes are cross-chain, allowing the same code to be used for contract creation on every supported chain.
* To minimize gas expenses, codes are initially created on Arbitrum and then transferred to other supported chains.
* Each referral code has an owner (admin) and a payment address where commissions are automatically transferred.

**Referral Code Creation**

* Switch to Arbitrum to create a referral code.
* Submit a transaction specifying all chains where you want the code created. You can provide your own code or have one generated automatically.
* Wait for bridge confirmations.
* Switch to each target chain and confirm code creation. Once confirmed, you can share the referral link and earn commissions.

**Referral Code Cross-Chain Update**

* If you did not initially send your referral code to a particular chain, you can do so anytime - for example, when a new chain is supported.
* Switch to Arbitrum.
* Submit a transaction to send the code to the target chain.
* Wait for bridge confirmations, switch to the target network, and submit a transaction to confirm.

**DAO Donation with Referral Code**

* When a referral uses a link containing a referral code, it is automatically stored in their browser.
* When creating a contract with a one-time DAO donation, the referral code is recorded in their personal CryptoLegacy contract. The contract automatically retrieves the payment address and sends ETH to it.
* All future timeout updates will automatically send commissions to the current payment address.
* If the referral makes a lifetime NFT DAO donation, the commission also goes directly to the payment address.

**Changing Owner and Payment Address**

* You can change the owner and payment address for your referral code on each chain at any time. Payments always route through the permanent referral code.
* Submit a transaction on each chain where you want to update the owner or payment address.

**Custom Discount and Commission**

* The DAO can assign increased discounts and commission rates to specific referral codes on each chain.
* The DAO typically does this for valuable community members.

**Default Discount and Commission Management**

* The DAO, along with its multisig, manages default discounts and commission rates.


# Ownership and Roles

You control your personal contract. Other protocol contracts use roles assigned to DAO multisigs composed of the core team, partner protocols, and security firms.

Although you - and only you - are the Owner of your CryptoLegacy personal contract, there are other contracts within the protocol.

We use a flexible yet reliable role-based approach to manage these contracts. Various DAO multisigs include signers from the Core team, Protocol partners, and Top Security Firms.

Role names are simplified as:

* Msig 1.
* Msig 2.
* Msig 3.&#x20;

Detailed information about their associated multisig wallets can be found in separate articles.

The table below lists the contracts, their functions, and the roles assigned to each. Every function is protected by a **personal timelock for execution**.

<table><thead><tr><th width="239.64453125">Contract</th><th width="376.015625">Function</th><th width="304.703125">Purpose</th><th width="86.5703125">Role</th><th width="112.9453125">Timelock</th></tr></thead><tbody><tr><td>BuildManagerOwnable</td><td>setBuildManager()</td><td>Adds or removes a build manager address. Only the owner can call.</td><td>Msig 3</td><td>5 days</td></tr><tr><td>CryptoLegacyBuildManager</td><td>setRegistries()</td><td>Sets references to the fee registry, plugins registry, and beneficiary registry.</td><td>Msig 3</td><td>5 days</td></tr><tr><td>CryptoLegacyBuildManager</td><td>setFactory()</td><td>Sets the factory contract.</td><td>Msig 3</td><td>5 days</td></tr><tr><td>CryptoLegacyBuildManager</td><td>setSupplyLimit()</td><td>Sets the supply limit for lifetime NFTs, after which multiple mints without a lock become possible.</td><td>Msig 2</td><td>5 days</td></tr><tr><td>CryptoLegacyBuildManager</td><td>setExternalLens()</td><td>Sets the external lens contract address.</td><td>Msig 2</td><td>5 days</td></tr><tr><td>CryptoLegacyBuildManager</td><td>withdrawFee()</td><td>Withdraws fee from the contract to a recipient.</td><td>Msig 2</td><td>5 days</td></tr><tr><td>CryptoLegacyFactory</td><td>setBuildOperator()</td><td>Adds or removes an allowed operator to build CryptoLegacy contracts.</td><td>Msig 3</td><td>5 days</td></tr><tr><td>FeeRegistry</td><td>setCodeOperator()</td><td>Sets a operator address, that can manage referral codes.</td><td>Msig 2</td><td>5 days</td></tr><tr><td>FeeRegistry</td><td>setSupportedRefCodeInChains()</td><td>Adds or removes supported chain IDs for referral codes.</td><td>Msig 2</td><td>5 days</td></tr><tr><td>FeeRegistry</td><td>setFeeBeneficiaries()</td><td>Sets the custom fee beneficiaries for the registry.</td><td>Msig 2</td><td>5 days</td></tr><tr><td>FeeRegistry</td><td>setDefaultPct()</td><td>Sets the default discount and share percentages.</td><td>Msig 2</td><td>5 days</td></tr><tr><td>FeeRegistry</td><td>setRefererSpecificPct()</td><td>Sets referral-specific discount and share percentages.</td><td>Msig 2</td><td>0 days</td></tr><tr><td>FeeRegistry</td><td>setContractCaseFee()</td><td>Sets the fee for a particular contract case.</td><td>Msig 2</td><td>5 days</td></tr><tr><td>LifetimeNft</td><td>setBaseUri()</td><td>Sets a new base URI for the tokens.</td><td>Msig 2</td><td>0 days</td></tr><tr><td>LifetimeNft</td><td>setMinterOperator()</td><td>Grants or revokes permission to mint new tokens.</td><td>Msig 3</td><td>5 days</td></tr><tr><td>LockChainGate</td><td>setDebridgeGate()</td><td>Sets the deBridgeGate contract.</td><td>Msig 3</td><td>5 days</td></tr><tr><td>LockChainGate</td><td>setDebridgeNativeFee()</td><td>Sets the native fee for a specific chain.</td><td>Msig 2</td><td>5 days</td></tr><tr><td>LockChainGate</td><td>setDestinationChainContract()</td><td>Sets the destination chain contract.</td><td>Msig 2</td><td>5 days</td></tr><tr><td>LockChainGate</td><td>setSourceChainContract()</td><td>Sets the source chain contract.</td><td>Msig 2</td><td>5 days</td></tr><tr><td>LockChainGate</td><td>setSourceAndDestinationChainContract()</td><td>Sets both the source and destination chain contracts to the same address.</td><td>Msig 2</td><td>5 days</td></tr><tr><td>LockChainGate</td><td>setLockPeriod()</td><td>Sets the NFT lock period.</td><td>Msig 2</td><td>5 days</td></tr><tr><td>LockChainGate</td><td>setReferralCode()</td><td>Sets the referral code for deBridge.</td><td>Msig 2</td><td>0 days</td></tr><tr><td>LockChainGate</td><td>setCustomChainId()</td><td>Sets a custom chain ID.</td><td>Msig 2</td><td>5 days</td></tr><tr><td>PluginsRegistry</td><td>addPlugin()</td><td>Registers a plugin and logs a description block number.</td><td>Msig 3</td><td>5 days</td></tr><tr><td>PluginsRegistry</td><td>addPluginDescription()</td><td>Adds a new descriptive note for an already-registered plugin.</td><td>Msig 3</td><td>5 days</td></tr><tr><td>PluginsRegistry</td><td>removePlugin()</td><td>Deregisters a plugin.</td><td>Msig 3</td><td>5 days</td></tr><tr><td>SignatureRoleTimelock</td><td>setMaxExecutionPeriod()</td><td>Sets the maximum allowable execution period for scheduled calls.</td><td>Msig 1.</td><td>0 days</td></tr><tr><td>SignatureRoleTimelock</td><td>setRoleAccounts()</td><td>Manages role-account associations by adding, removing, or updating accounts for specified roles.</td><td>Msig 1.</td><td>0 days</td></tr><tr><td>SignatureRoleTimelock</td><td>cancelCallList()</td><td>Cancels scheduled contract calls.</td><td>Msig 1.</td><td>0 days</td></tr></tbody></table>


# Frequently Asked Questions

Clear answers on Recovery, Guardians, Beneficiaries, privacy, security, fees, NFTs, flexibility, and more - CryptoLegacy FAQ.

## What are Recovery Addresses?

Recovery addresses are one or more addresses configured by the owner to execute recovery actions under an owner-defined approval threshold. Recovery can optionally include additional password-based authentication. Recovery addresses are hashed together with the password and remain unlinkable to a specific CryptoLegacy contract until they are used on-chain.

Recovery-related asset metadata is encrypted per recovery role. Recovery addresses can decrypt this metadata at any time to prepare recovery transactions. Decryption alone does not grant access to assets or allow transfers.

Recovery addresses can cancel active Guardian voting and Challenge periods, and can initiate the predefined on-chain recovery process. This process first moves assets into the CryptoLegacy contract and then transfers them to any specified address, strictly according to the configured rules.

***

## Who are the Beneficiaries?

Beneficiaries are addresses designated by the owner to receive assets during the Distribution period. For each Beneficiary, the owner defines a share, an optional delay, and a distribution period, which together determine how and when assets become claimable.

Beneficiary-related asset metadata is encrypted individually per Beneficiary. Beneficiaries have no visibility into wallets balances, asset metadata, or contract state until distribution conditions are met.

If the 6-month inactivity timeout expires, any Beneficiary may initiate a 3-month Challenge period. If the Challenge period is not canceled, Beneficiaries can decrypt the encrypted metadata, trigger the on-chain process that moves assets into the CryptoLegacy contract, and claim assets gradually according to their configured schedules.

If approved plugins are enabled, Beneficiaries may also use the predefined plugin logic during Distribution. All Beneficiary actions are executed strictly according to on-chain rules and do not grant direct access to private keys or unrestricted control over assets.

***

## Who are the Guardians?

Guardians are addresses authorized to bypass the 6-month inactivity timeout and initiate distribution by voting according to a predefined approval threshold.

Once the threshold is reached, an owner-configured Challenge period (up to 30 days) may apply. During this period, the owner or a recovery address can cancel the process.

After the Challenge period, any Guardian may trigger the on-chain process that moves assets into the CryptoLegacy contract for distribution. Guardians cannot withdraw assets to their own addresses or redirect them.

By default, Beneficiaries act as Guardians with a 3-of-5 approval threshold and a 30-day Challenge period.

***

## What do Normal, Challenge, and Distribution periods mean?

They represent the states of a CryptoLegacy contract:

* Normal — The contract is active, holds no assets, and requires a periodic on-chain transaction every 6 months to confirm owner activity. During this period, the owner retains full control and manages assets directly in their wallets.
* Challenge — Triggered when the 6-month inactivity timeout expires or when Guardians vote to bypass the timeout according to the configured approval threshold. This period lasts up to 3 months and may be canceled by the owner or a recovery address.
* Distribution — Asset metadata becomes decryptable, and Guardians or Beneficiaries may trigger the on-chain process that moves assets into the CryptoLegacy contract. Beneficiaries then claim their shares gradually according to the configured distribution schedule. Recovery addresses may also execute the recovery flow to transfer all assets according to the contract rules.

***

## My Beneficiaries aren't familiar with web3, crypto, and blockchain. Is this a requirement?

No.

Beneficiaries do not need prior Web3 or blockchain experience to participate in the Distribution process. They interact only with predefined contract flows, such as decrypting metadata and claiming assets according to the configured schedule.

Documentation and interface guidance are available to explain required steps. All asset-related actions are executed autonomously by the protocol according to on-chain rules.

***

## What are the advantages of CryptoLegacy over multi-sig wallets for recovery and inheritance?

Multi-signature wallets are designed for shared control, not for inheritance. They require beneficiaries to hold signing keys in advance, which can expose balances early and make key management critical over long periods.

CryptoLegacy uses a different approach:

* Assets remain in the owner’s wallets until distribution conditions are met, avoiding early balance exposure and shared custody.
* Distribution rules are defined in advance and enforced on-chain, providing clear, deterministic execution when distribution begins.
* Funds are not locked in a shared wallet, reducing permanent lock-out risks caused by lost, inactive, or unavailable keys.
* Recovery is handled through a separate, predefined recovery flow, allowing recovery addresses to execute a full recovery according to contract rules, without requiring shared access to funds during normal operation.

The two models serve different purposes: multisig focuses on shared access and coordination, while CryptoLegacy focuses on time-based distribution, recovery, and strict role separation between owner, guardians, recovery addresses, and beneficiaries.

***

## How is CryptoLegacy different from physical mnemonic sharing?

Physical mnemonic sharing involves splitting a wallet’s recovery phrase and distributing parts of it to multiple people for long-term storage. This approach requires all participants to coordinate correctly, understand their role, retain their fragment securely over long periods, and act honestly when the time comes. Any mistake, loss, misunderstanding, or lack of cooperation can permanently block access to assets.

CryptoLegacy follows a different model:

* No physical or digital sharing of mnemonics — recovery phrases and private keys are never split, copied, or distributed.
* No long-term coordination requirements — beneficiaries, guardians, and recovery addresses do not need to store secrets, remember procedures, or coordinate actions outside predefined rules.
* Rule-based execution instead of trust-based assembly — asset transfers and recovery actions are executed through predefined on-chain processes, not by reconstructing a private key through human agreement.
* Dedicated recovery flow — recovery is handled through explicit contract logic, removing the need for manual decision-making or trust at the time of execution.

The two approaches address different risks: physical mnemonic sharing relies on long-term secrecy, coordination, and trust between participants, while CryptoLegacy removes secret distribution entirely and enforces recovery and distribution through on-chain rules.

***

## How does CryptoLegacy compare to legal inheritance?

Traditional legal inheritance transfers legal ownership, but in self-custody it does not solve two practical problems. First, private keys or hardware wallets must eventually be stored, transported, or disclosed to someone, which introduces unavoidable risks of loss, copying, or misuse. Second, execution depends on jurisdiction-specific procedures—courts, intermediaries, and timelines—which can be slow, disputed, or hard to coordinate across countries.

CryptoLegacy uses a different model: it does not rely on intermediaries to handle keys. Instead, recovery and distribution are executed on-chain according to predefined rules, independent of court processes at the moment of transfer. Legal inheritance and CryptoLegacy address different layers: legal systems define rights, while CryptoLegacy provides a deterministic mechanism for executing transfers without exposing private keys.

***

## How does CryptoLegacy compare to MPC-based inheritance or recovery?

In MPC-based setups, control over assets is split across multiple participants who collectively authorize actions. When MPC is used for inheritance, beneficiaries effectively become part of the MPC group responsible for approving transfers.

In practice, this creates ambiguity. It is often unclear who initiates recovery, how many participants must cooperate, what happens if some beneficiaries are unavailable, or how disagreements are resolved. Execution depends on off-chain coordination, participant availability, and correct behavior at the exact moment assets need to be transferred.

CryptoLegacy follows a different model. Beneficiaries are not required to coordinate key usage or participate in off-chain approval flows. Instead, recovery and distribution are executed on-chain according to predefined rules, with clear roles, thresholds, and time-based conditions defined in advance.

The two approaches address different assumptions: MPC relies on active coordination between participants, while CryptoLegacy assumes that coordination may fail and encodes execution rules directly into the protocol.

***

## How does CryptoLegacy compare to Shamir’s Secret Sharing?

Shamir’s Secret Sharing splits a private key or mnemonic into multiple fragments, requiring a threshold of fragments to reconstruct the original secret. In inheritance scenarios, these fragments are typically distributed to beneficiaries or trusted parties for long-term storage.

In practice, this creates similar challenges to physical mnemonic sharing. Fragments must be stored securely for long periods, participants must remain available, and someone must eventually coordinate the reconstruction process. If fragments are lost, withheld, or combined incorrectly, assets can become permanently inaccessible. Execution depends on human coordination at the exact moment recovery is needed.

CryptoLegacy follows a different model. Private keys and mnemonics are never reconstructed or revealed. Instead of reassembling a secret, recovery and distribution are executed on-chain according to predefined rules, thresholds, and time-based conditions. Beneficiaries do not need to hold or combine secret fragments, and no off-chain coordination is required at execution time.

The two approaches address different assumptions: Shamir’s Secret Sharing assumes long-term availability and cooperation of participants, while CryptoLegacy assumes that coordination may fail and encodes execution logic directly into the protocol.

***

## How does CryptoLegacy ensure the smart contract security?

CryptoLegacy uses personal smart contracts that are fundless during normal operation, reducing the attack surface before any distribution or recovery conditions are met.

Contract logic is intentionally minimal and executes only predefined actions. The protocol has undergone independent security audits, and all asset-related operations are gated by explicit on-chain conditions rather than discretionary logic.

Assets remain in the owner’s wallets until distribution or recovery is triggered according to the contract rules. No assets are held or managed by the protocol outside these predefined execution flows.

***

## How does CryptoLegacy ensure the security of UI?

CryptoLegacy’s interface does not store private keys or sensitive asset data and does not participate in asset execution. All critical logic is enforced by smart contracts on-chain, not by the frontend.

The hosted interface is delivered using standard web security practices and protections against common network-level attacks. For users who require additional control, the frontend can be self-hosted, reducing reliance on third-party infrastructure without changing contract behavior.

***

## What happens if I don’t send the required transaction every six months?

If the 6-month inactivity timeout expires, a 3-month Challenge period may be initiated. The Challenge can be started by Beneficiaries or Guardians according to the configured approval threshold.

During the Challenge period, the process may be canceled by the owner or a recovery address. If the Challenge period completes without cancellation, Distribution begins according to the predefined contract rules.

At that point, Guardians or Beneficiaries may trigger the on-chain process that moves assets into the CryptoLegacy contract. Beneficiaries then claim their shares gradually according to the configured distribution schedule, while recovery addresses may execute the recovery flow to transfer all assets as defined by the contract.

***

## Can I host the CryptoLegacy frontend myself?

Yes.

The CryptoLegacy frontend can be self-hosted using the published repository. Self-hosting allows users to run the interface on their own infrastructure, such as IPFS, Arweave, or a private server, without relying on the hosted frontend.

Self-hosting does not change contract behavior or execution logic. All critical actions remain enforced by on-chain smart contracts, independent of where the interface is served.

***

## How does CryptoLegacy protect the privacy of Beneficiaries and assets?

CryptoLegacy is designed to limit information disclosure and delay visibility until distribution or recovery conditions are met.

* Each CryptoLegacy contract uses its own unique address, which is not directly linked to the owner’s wallet or to other contracts.
* Beneficiary, Guardian, and Recovery addresses are stored as hashes, preventing early association with a specific contract until they are used on-chain.
* Asset-related metadata is encrypted per role and can be decrypted only when the corresponding on-chain conditions are satisfied.
* During normal operation, assets remain in the owner’s wallets. The contract holds no funds and does not expose balances or asset data prior to execution.

Privacy in CryptoLegacy is enforced through role separation, hashed identities, encrypted metadata, and rule-based execution, rather than through custodial obfuscation or off-chain secrecy.

***

## Can Beneficiaries or Guardians access encrypted data early by inspecting the blockchain or code?

Encrypted metadata is publicly visible on-chain and can be analyzed off-chain.

However, encrypted metadata cannot be meaningfully decrypted without the corresponding private keys, and decryption alone does not grant the ability to move assets. All asset transfers remain gated by on-chain conditions, approval thresholds, and contract-defined execution flows.

Inspecting the frontend, self-hosting the interface, or reviewing the source code does not provide additional access beyond what is already publicly visible on-chain. The interface does not store private keys or plaintext asset data, and it does not bypass cryptographic or contract-level enforcement.

CryptoLegacy does not rely on obscurity or frontend restrictions for privacy. It relies on encryption, role separation, and rule-based on-chain execution, accepting that blockchain data is public by design.

***

## But approvals and encrypted data are stored on-chain — isn’t it technically accessible?

Yes. Encrypted metadata and approval data are publicly visible on-chain and can be analyzed off-chain.

However, technical availability does not imply practical access or control. Encrypted data cannot be meaningfully decrypted without private keys, and even successful decryption does not allow assets to be moved outside predefined execution paths.

CryptoLegacy assumes that blockchain data is public by default and focuses on ensuring that visibility does not translate into authority. Recovery and distribution can only be executed through predefined on-chain rules, regardless of off-chain analysis or reverse engineering.

***

## Can CryptoLegacy support NFTs and other protocols?

CryptoLegacy is designed to be extensible via a plugin system based on the Diamond Standard (EIP-2535).

The plugin architecture allows additional execution logic to be introduced without modifying core contract behavior. This includes support for asset types and protocol interactions beyond basic token transfers.

At launch, the plugin system is in place, while support for NFTs and additional protocol integrations is planned to be introduced through approved plugins over time. Plugin registration and execution remain subject to predefined rules and do not alter distribution logic.

***

## What happens if a private key is compromised?

If a private key is compromised during the Normal period, the owner can update contract configuration according to the predefined rules. This may include changing the owner address, updating Beneficiary or Guardian addresses, or adjusting recovery configuration.

Once the Distribution period begins, owner control is suspended and cannot be used to alter execution. At this stage, asset transfers proceed strictly according to the predefined distribution or recovery rules, independent of the compromised key.

Beneficiaries may update their receiving addresses during Distribution, as allowed by the contract logic. No role can use a compromised key to bypass on-chain conditions or alter execution flows.

***

## What can I do if my keys are potentially compromised and I don't have access to my devices or backups?

During the Normal period, predefined recovery mechanisms may be used according to the contract configuration.

Guardians can initiate the predefined on-chain process to move assets into the CryptoLegacy contract, subject to approval thresholds and the configured Challenge period. During the Challenge period, the process may be canceled by the owner or a recovery address.

Recovery addresses can also execute the recovery flow according to the predefined rules. This flow moves assets into the CryptoLegacy contract and allows them to be transferred as defined by the recovery configuration.

All actions are executed strictly according to on-chain rules. No role can bypass approval thresholds, time delays, or execution conditions.

***

## Can I pause or unpause the contract?

The CryptoLegacy contract includes a pause mechanism that prevents asset transfers and other execution actions.

While the contract is paused, assets cannot be moved, and Challenge initiation is blocked. The owner may still update contract configuration, including Beneficiary settings, Guardian configuration, recovery parameters, and other non-execution options according to the protocol rules.

The inactivity timeout continues to elapse while the contract is paused. To avoid entering the Challenge state, the owner must refresh the 6-month inactivity timeout by submitting the required on-chain update transaction (and DAO donation, if applicable).

If the inactivity timeout has already expired, a Challenge period cannot be initiated while the contract is paused, but may be initiated immediately after the contract is unpaused.

Unpausing restores execution under the same on-chain conditions. Token approvals can be revoked independently at any time, outside of the pause mechanism.

***

## Can I customize Beneficiary distribution schedules?

Yes.

For each Beneficiary, the owner defines a share, an optional delay, and a distribution period. These parameters determine when asset claiming begins and how assets become claimable over time.

* Delay — the waiting period before a Beneficiary can start claiming assets.
* Distribution period — the duration over which assets become claimable gradually according to the configured schedule.

Distribution parameters can be updated by the owner during the Normal period. Once Distribution begins, these parameters are fixed and enforced on-chain according to the configured rules.

***

## What fees does CryptoLegacy require?

CryptoLegacy is sustained through DAO donations.

A fixed donation is required when deploying a personal contract and when refreshing the inactivity timeout at the required interval.

An alternative unlimited-access option may be used according to the protocol configuration, covering contract deployments and timeout updates across supported chains.

***

## What is the referral mechanism, and how does it work?

CryptoLegacy includes an optional referral mechanism intended to account for trusted introductions.

When a referral code is used, a predefined discount is applied to the deploying party, and a predefined allocation is attributed to the referral code holder according to the protocol rules.

Referral codes are intended for private use and trusted contexts, not for public distribution or growth campaigns. Payout addresses associated with referral codes can be updated according to the protocol configuration.

***

## What happens if the core team is unable to support the product?

CryptoLegacy does not rely on continuous involvement of a core team for contract execution.

Once deployed, CryptoLegacy contracts operate autonomously on-chain and do not depend on centralized services to execute recovery or distribution logic. The frontend can be self-hosted, and contracts can be interacted with directly on-chain, independent of any hosted interface.

Code availability and maintenance may evolve over time according to the project’s governance, but deployed contracts remain functional and enforce their predefined rules regardless of ongoing team support.

***

## Why is the contract code open, but under copyright and not released under an open-source license?

The CryptoLegacy contract code is publicly readable to allow independent review and auditing.

At the same time, the code is distributed under copyright to limit unverified reuse, cloning, or deployment in misleading or unsafe contexts. This approach is intended to reduce the risk of scams, misconfigured forks, or unauthorized deployments that could harm users.

Licensing and code availability may evolve over time according to the project’s governance and maturity. Regardless of licensing, deployed contracts continue to operate autonomously and enforce their rules on-chain.

***

## Why is the UI code closed and obfuscated?

The CryptoLegacy interface is not a security boundary. It does not store private keys, decrypted asset metadata, or execution authority. All critical logic is enforced by on-chain smart contracts.

The UI code is distributed in an obfuscated form to reduce the risk of phishing, spoofed frontends, and misleading replicas that could prompt users to sign unintended transactions. Obfuscation is used to limit trivial reuse or modification of the interface in unsafe contexts, not as a substitute for cryptographic or contract-level security.

Users may self-host the interface or interact with the contracts directly on-chain. UI code availability and licensing may evolve over time according to the project’s governance, but deployed contracts remain fully auditable and enforce their rules independently of the frontend.


# Contracts

Below is a clear overview of each major CryptoLegacy smart contract: its purpose, inheritance, key methods, events, and external interactions.

## Table of Contents

1. [BeneficiaryRegistry](#beneficiaryregistry)
2. [BuildManagerOwnable](#buildmanagerownable)
3. [Create3Factory](#create3factory)
4. [CryptoLegacy](#cryptolegacy)
5. [CryptoLegacyBuildManager](#cryptolegacybuildmanager)
6. [CryptoLegacyDiamondBase](#cryptolegacydiamondbase)
7. [CryptoLegacyExternalLens](#cryptolegacyexternallens)
8. [CryptoLegacyFactory](#cryptolegacyfactory)
9. [CryptoLegacyOwnable](#cryptolegacyownable)
10. [FeeRegistry](#feeregistry)
11. [LegacyMessenger](#legacymessenger)
12. [LifetimeNft](#lifetimenft)
13. [LockChainGate](#lockchaingate)
14. [MultiPermit](#multipermit)
15. [PluginsRegistry](#pluginsregistry)
16. [ProxyBuilder](#proxybuilder)
17. [ProxyBuilderAdmin](#proxybuilderadmin)
18. [SignatureRoleTimelock](#signatureroletimelock)
19. [WethUnwrapIWETH (Interface)](#wethunwrapiweth-interface)
20. [WethUnwrap](#wethunwrap)
21. [ArbSys (Interface)](#arbsys-interface)
22. [Flags (Library)](#flags-library)
23. [IAaveV3Pool (Interface)](#iaavev3pool-interface)
24. [IAaveV3PoolDataProvider (Interface)](#iaavev3pooldataprovider-interface)
25. [IBeneficiaryRegistry (Interface)](#ibeneficiaryregistry-interface)
26. [IBuildManagerOwnable (Interface)](#ibuildmanagerownable-interface)
27. [ICallProxy (Interface)](#icallproxy-interface)
28. [ICryptoLegacy (Interface)](#icryptolegacy-interface)
29. [ICryptoLegacyBuildManager (Interface)](#icryptolegacybuildmanager-interface)
30. [ICryptoLegacyDiamondBase (Interface)](#icryptolegacydiamondbase-interface)
31. [ICryptoLegacyFactory (Interface)](#icryptolegacyfactory-interface)
32. [ICryptoLegacyLens (Interface)](#icryptolegacylens-interface)
33. [ICryptoLegacyOwnable (Interface)](#icryptolegacyownable-interface)
34. [ICryptoLegacyPlugin (Interface)](#icryptolegacyplugin-interface)
35. [ICryptoLegacyUpdaterPlugin (Interface)](#icryptolegacyupdaterplugin-interface)
36. [IDeBridgeGate (Interface)](#idebridgegate-interface)
37. [IDiamondCut (Interface)](#idiamondcut-interface)
38. [IDiamondLoupe (Interface)](#idiamondloupe-interface)
39. [IFeeRegistry (Interface)](#ifeeregistry-interface)
40. [ILockChainGate (Interface)](#ilockchaingate-interface)
41. [ILegacyMessenger (Interface)](#ilegacymessenger-interface)
42. [ILido (Interface)](#ilido-interface)
43. [ILidoWithdrawalQueue (Interface)](#ilidowithdrawalqueue-interface)
44. [ILifetimeNft (Interface)](#ilifetimenft-interface)
45. [IPermit2 (Interface)](#ipermit2-interface)
46. [IPluginsRegistry (Interface)](#ipluginsregistry-interface)
47. [ISafeMinimalMultisig (Interface)](#isafeminimalmultisig-interface)
48. [ISignatureRoleTimelock (Interface)](#isignatureroletimelock-interface)
49. [IStataToken (Interface)](#istatatoken-interface)
50. [IStataTokenFactory (Interface)](#istatatokenfactory-interface)
51. [ITrustedGuardiansPlugin (Interface)](#itrustedguardiansplugin-interface)
52. [IUniversalRouter (Interface)](#iuniversalrouter-interface)
53. [IWETH (Interface)](#iweth-interface)
54. [IWstETH (Interface)](#iwsteth-interface)
55. [DiamondLoupeFacet](#diamondloupefacet)
56. [LibCLUtils (Library)](#libclutils-library)
57. [LibClaimMigrationCore (Library)](#libclaimmigrationcore-library)
58. [LibOneStepClaimMigration (Library)](#libonestepclaimmigration-library)
59. [LibTwoStepClaimMigration (Library)](#libtwostepclaimmigration-library)
60. [LibCreate3 (Library)](#libcreate3-library)
61. [LibCryptoLegacy (Library)](#libcryptolegacy-library)
62. [LibCryptoLegacyDeploy (Library)](#libcryptolegacydeploy-library)
63. [LibCryptoLegacyPlugins (Library)](#libcryptolegacyplugins-library)
64. [LibDiamond (Library)](#libdiamond-library)
65. [LibSafeMinimalBeneficiaryMultisig (Library)](#libsafeminimalbeneficiarymultisig-library)
66. [LibSafeMinimalMultisig (Library)](#libsafeminimalmultisig-library)
67. [LibTrustedGuardiansPlugin (Library)](#libtrustedguardiansplugin-library)
68. [BeneficiaryAaveV3SupplyPlugin](#beneficiaryaavev3supplyplugin)
69. [BeneficiaryLidoStakingPlugin](#beneficiarylidostakingplugin)
70. [BeneficiaryPluginAddRights](#beneficiarypluginaddrights)
71. [BeneficiaryUniswapV4SwapPlugin](#beneficiaryuniswapv4swapplugin)
72. [CryptoLegacyBasePlugin](#cryptolegacybaseplugin)
73. [LegacyRecoveryPlugin](#legacyrecoveryplugin)
74. [LensPlugin](#lensplugin)
75. [NftLegacyPlugin](#nftlegacyplugin)
76. [ReceiveEthPlugin](#receiveethplugin)
77. [TrustedGuardiansPlugin](#trustedguardiansplugin)
78. [UpdateRolePlugin](#updateroleplugin)

## BeneficiaryRegistry

### Purpose

BeneficiaryRegistry maintains role-indexed registries that map hashed participant identifiers to CryptoLegacy contract addresses.

### Inheritance

* `IBeneficiaryRegistry`
* `BuildManagerOwnable`

### Key Methods

* [setCryptoLegacyBeneficiary(...)](https://docs.cryptolegacy.app/documentation/functions-reference#setcryptolegacybeneficiary-br1) - Adds or removes the calling CryptoLegacy from a beneficiary hash index.
* [setCryptoLegacyGuardian(...)](https://docs.cryptolegacy.app/documentation/functions-reference#setcryptolegacyguardian-br1) - Adds or removes the calling CryptoLegacy from a guardian hash index.
* [setCryptoLegacyOwner(...)](https://docs.cryptolegacy.app/documentation/functions-reference#setcryptolegacyowner-br1) - Adds or removes the calling CryptoLegacy from an owner hash index.
* [setCryptoLegacyRecoveryAddresses(...)](https://docs.cryptolegacy.app/documentation/functions-reference#setcryptolegacyrecoveryaddresses-br1) - Updates recovery-hash indexes for the calling CryptoLegacy by removing old and adding new hashes.
* [getCryptoLegacyListByBeneficiary(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getcryptolegacylistbybeneficiary-br1) - Returns CryptoLegacy addresses indexed by a beneficiary hash.
* [getCryptoLegacyListByOwner(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getcryptolegacylistbyowner-br1) - Returns CryptoLegacy addresses indexed by an owner hash.
* [getCryptoLegacyListByGuardian(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getcryptolegacylistbyguardian-br1) - Returns CryptoLegacy addresses indexed by a guardian hash.
* [getCryptoLegacyListByRecovery(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getcryptolegacylistbyrecovery-br1) - Returns CryptoLegacy addresses indexed by a recovery hash.

### All Functions

* [constructor(...)](https://docs.cryptolegacy.app/documentation/functions-reference#constructor-br1) - Initializes the registry and transfers ownership to `owner`.
* [\_setBlockNumberChange(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_setblocknumberchange-br1) - Records the current L1/L2 block number for the given CryptoLegacy contract.
* [setCryptoLegacyBeneficiary(...)](https://docs.cryptolegacy.app/documentation/functions-reference#setcryptolegacybeneficiary-br1) - Adds or removes the calling CryptoLegacy from a beneficiary hash index.
* [setCryptoLegacyGuardian(...)](https://docs.cryptolegacy.app/documentation/functions-reference#setcryptolegacyguardian-br1) - Adds or removes the calling CryptoLegacy from a guardian hash index.
* [setCryptoLegacyOwner(...)](https://docs.cryptolegacy.app/documentation/functions-reference#setcryptolegacyowner-br1) - Adds or removes the calling CryptoLegacy from an owner hash index.
* [setCryptoLegacyRecoveryAddresses(...)](https://docs.cryptolegacy.app/documentation/functions-reference#setcryptolegacyrecoveryaddresses-br1) - Updates recovery-hash indexes for the calling CryptoLegacy by removing old and adding new hashes.
* [getCryptoLegacyListByBeneficiary(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getcryptolegacylistbybeneficiary-br1) - Returns CryptoLegacy addresses indexed by a beneficiary hash.
* [getCryptoLegacyListByOwner(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getcryptolegacylistbyowner-br1) - Returns CryptoLegacy addresses indexed by an owner hash.
* [getCryptoLegacyListByGuardian(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getcryptolegacylistbyguardian-br1) - Returns CryptoLegacy addresses indexed by a guardian hash.
* [getCryptoLegacyListByRecovery(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getcryptolegacylistbyrecovery-br1) - Returns CryptoLegacy addresses indexed by a recovery hash.
* [getCryptoLegacyBlockNumberChanges(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getcryptolegacyblocknumberchanges-br1) - Returns recorded block numbers when the given CryptoLegacy triggered registry update calls.
* [getAllCryptoLegacyListByRoles(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getallcryptolegacylistbyroles-br1) - Returns all CryptoLegacy lists for a given hash across beneficiary, owner, guardian, and recovery roles.

### Events

* [AddCryptoLegacyForBeneficiary](https://docs.cryptolegacy.app/documentation/events-reference#addcryptolegacyforbeneficiary-ibr1)
* [RemoveCryptoLegacyForBeneficiary](https://docs.cryptolegacy.app/documentation/events-reference#removecryptolegacyforbeneficiary-ibr1)
* [AddCryptoLegacyForGuardian](https://docs.cryptolegacy.app/documentation/events-reference#addcryptolegacyforguardian-ibr1)
* [RemoveCryptoLegacyForGuardian](https://docs.cryptolegacy.app/documentation/events-reference#removecryptolegacyforguardian-ibr1)
* [AddCryptoLegacyForRecovery](https://docs.cryptolegacy.app/documentation/events-reference#addcryptolegacyforrecovery-ibr1)
* [RemoveCryptoLegacyForRecovery](https://docs.cryptolegacy.app/documentation/events-reference#removecryptolegacyforrecovery-ibr1)
* [AddCryptoLegacyForOwner](https://docs.cryptolegacy.app/documentation/events-reference#addcryptolegacyforowner-ibr1)
* [RemoveCryptoLegacyForOwner](https://docs.cryptolegacy.app/documentation/events-reference#removecryptolegacyforowner-ibr1)
* [AddBuildManager](https://docs.cryptolegacy.app/documentation/events-reference#addbuildmanager-ibmo1)
* [RemoveBuildManager](https://docs.cryptolegacy.app/documentation/events-reference#removebuildmanager-ibmo1)

### Errors

* [NotTheOwnerOfCryptoLegacy](https://docs.cryptolegacy.app/documentation/errors-reference#nottheownerofcryptolegacy-ibmo1)
* [CryptoLegacyNotRegistered](https://docs.cryptolegacy.app/documentation/errors-reference#cryptolegacynotregistered-ibmo1)
* [BuildManagerNotAdded](https://docs.cryptolegacy.app/documentation/errors-reference#buildmanagernotadded-ibmo1)

### Access / Roles

* `setCryptoLegacyBeneficiary`: registered CryptoLegacy caller with approved build manager (`_checkBuildManagerValid`)
* `setCryptoLegacyGuardian`: registered CryptoLegacy caller with approved build manager (`_checkBuildManagerValid`)
* `setCryptoLegacyOwner`: registered CryptoLegacy caller with approved build manager (`_checkBuildManagerValid`)
* `setCryptoLegacyRecoveryAddresses`: registered CryptoLegacy caller with approved build manager (`_checkBuildManagerValid`)

### Interacts With

* `ArbSys`

### Missing Links

None.

## BuildManagerOwnable

### Purpose

BuildManagerOwnable governs the allowlist of build-manager accounts used to authorize maintenance actions on CryptoLegacy contracts.

### Inheritance

* `IBuildManagerOwnable`
* `Ownable`

### Key Methods

* [setBuildManager(...)](https://docs.cryptolegacy.app/documentation/functions-reference#setbuildmanager-bmo1) - Adds or removes a build manager address from the allowed set.
* [getBuildManagerAdded(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getbuildmanageradded-bmo1) - Returns the list of all added build manager addresses.

### All Functions

* [constructor()](https://docs.cryptolegacy.app/documentation/functions-reference#constructor-bmo1) - Initializes ownership state via OpenZeppelin’s `Ownable` base.
* [setBuildManager(...)](https://docs.cryptolegacy.app/documentation/functions-reference#setbuildmanager-bmo1) - Adds or removes a build manager address from the allowed set.
* [\_checkBuildManagerValid(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_checkbuildmanagervalid-bmo1) - Verifies that a given CryptoLegacy contract was built by an added build manager and (optionally) that it has a specific owner.
* [getBuildManagerAdded()](https://docs.cryptolegacy.app/documentation/functions-reference#getbuildmanageradded-bmo1) - Returns the list of all added build manager addresses.

### Events

* [AddBuildManager](https://docs.cryptolegacy.app/documentation/events-reference#addbuildmanager-ibmo1)
* [RemoveBuildManager](https://docs.cryptolegacy.app/documentation/events-reference#removebuildmanager-ibmo1)

### Errors

* [NotTheOwnerOfCryptoLegacy](https://docs.cryptolegacy.app/documentation/errors-reference#nottheownerofcryptolegacy-ibmo1)
* [CryptoLegacyNotRegistered](https://docs.cryptolegacy.app/documentation/errors-reference#cryptolegacynotregistered-ibmo1)
* [BuildManagerNotAdded](https://docs.cryptolegacy.app/documentation/errors-reference#buildmanagernotadded-ibmo1)

### Access / Roles

* `setBuildManager`: `onlyOwner`

### Interacts With

* `ICryptoLegacy`
* `ICryptoLegacyBuildManager`

### Missing Links

None.

## Create3Factory

### Purpose

Create3Factory provides deterministic contract deployment using CREATE3 salts with predictable target addresses.

### Inheritance

* `Ownable`

### Key Methods

* [build(...)](https://docs.cryptolegacy.app/documentation/functions-reference#build-c3f1) - Deploys a contract deterministically via CREATE3 using a salt and raw bytecode.
* [computeAddress(...)](https://docs.cryptolegacy.app/documentation/functions-reference#computeaddress-c3f1) - Predicts the deterministic CREATE3 address for a given salt without deploying.

### All Functions

* [constructor(...)](https://docs.cryptolegacy.app/documentation/functions-reference#constructor-c3f1) - Initializes the factory and assigns ownership to the provided `owner`.
* [build(...)](https://docs.cryptolegacy.app/documentation/functions-reference#build-c3f1) - Deploys a contract deterministically via CREATE3 using a salt and raw bytecode.
* [computeAddress(...)](https://docs.cryptolegacy.app/documentation/functions-reference#computeaddress-c3f1) - Predicts the deterministic CREATE3 address for a given salt without deploying.

### Events

* [Create3Contract](https://docs.cryptolegacy.app/documentation/events-reference#create3contract-c3f1)

### Errors

None.

### Access / Roles

* `build`: `onlyOwner`

### Interacts With

* `LibCreate3`

### Missing Links

None.

## CryptoLegacy

### Purpose

CryptoLegacy is the primary protocol contract that composes protocol plugins and exposes the diamond-based extension surface.

### Inheritance

* `CryptoLegacyDiamondBase`
* `CryptoLegacyOwnable`

### Key Methods

* [replacePlugin(...)](https://docs.cryptolegacy.app/documentation/functions-reference#replaceplugin-cl1) - Replaces an existing set of plugins with a new set.
* [addPluginList(...)](https://docs.cryptolegacy.app/documentation/functions-reference#addpluginlist-cl1) - Adds a list of plugins to the contract.
* [removePluginList(...)](https://docs.cryptolegacy.app/documentation/functions-reference#removepluginlist-cl1) - Removes a list of plugins from the contract.
* [externalLens(...)](https://docs.cryptolegacy.app/documentation/functions-reference#externallens-cl1) - Returns the address of the external lens configured in the build manager.

### All Functions

* [constructor(...)](https://docs.cryptolegacy.app/documentation/functions-reference#constructor-cl1) - Initializes core Diamond storage, sets the build manager and owner, timestamps the deployment, and installs initial plugins.
* [replacePlugin(...)](https://docs.cryptolegacy.app/documentation/functions-reference#replaceplugin-cl1) - Replaces an existing set of plugins with a new set.
* [addPluginList(...)](https://docs.cryptolegacy.app/documentation/functions-reference#addpluginlist-cl1) - Adds a list of plugins to the contract.
* [removePluginList(...)](https://docs.cryptolegacy.app/documentation/functions-reference#removepluginlist-cl1) - Removes a list of plugins from the contract.
* [externalLens()](https://docs.cryptolegacy.app/documentation/functions-reference#externallens-cl1) - Returns the address of the external lens configured in the build manager.

### Events

* [StaticCallCheck](https://docs.cryptolegacy.app/documentation/events-reference#staticcallcheck-icldb1)
* [OwnershipTransferStarted](https://docs.cryptolegacy.app/documentation/events-reference#ownershiptransferstarted-iclo1)
* [OwnershipTransferred](https://docs.cryptolegacy.app/documentation/events-reference#ownershiptransferred-iclo1)

### Errors

* [FunctionNotExists](https://docs.cryptolegacy.app/documentation/errors-reference#functionnotexists-icldb1)
* [NotSelfCall](https://docs.cryptolegacy.app/documentation/errors-reference#notselfcall-icldb1)
* [OwnableUnauthorizedAccount](https://docs.cryptolegacy.app/documentation/errors-reference#ownableunauthorizedaccount-iclo1)

### Access / Roles

* `replacePlugin`: `onlyOwner`
* `addPluginList`: `onlyOwner`
* `removePluginList`: `onlyOwner`

### Interacts With

* `ICryptoLegacy`
* `ICryptoLegacyBuildManager`
* `ICryptoLegacyPlugin`
* `LibCryptoLegacy`
* `LibCryptoLegacyPlugins`
* `LibDiamond`

### Missing Links

None.

## CryptoLegacyBuildManager

### Purpose

CryptoLegacyBuildManager orchestrates protocol-instance deployment, fee collection, and registry wiring for new protocol instances.

### Inheritance

* `ICryptoLegacyBuildManager`
* `IERC721Receiver`
* `Ownable`

### Key Methods

* [setRegistries(...)](https://docs.cryptolegacy.app/documentation/functions-reference#setregistries-clbm1) - Owner setter that updates Fee/Plugins/Beneficiary registries.
* [setFactory(...)](https://docs.cryptolegacy.app/documentation/functions-reference#setfactory-clbm1) - Owner setter that updates the deployment factory.
* [setSupplyLimit(...)](https://docs.cryptolegacy.app/documentation/functions-reference#setsupplylimit-clbm1) - Owner setter for the minimum Lifetime NFT supply required to allow mass minting.
* [setExternalLens(...)](https://docs.cryptolegacy.app/documentation/functions-reference#setexternallens-clbm1) - Owner setter for a helper "lens" address.
* [withdrawFee(...)](https://docs.cryptolegacy.app/documentation/functions-reference#withdrawfee-clbm1) - Owner can withdraw ETH from the contract to a recipient.
* [payFee(...)](https://docs.cryptolegacy.app/documentation/functions-reference#payfee-clbm1) - Pays an update fee or, if sufficient, auto-switches to lifetime fee and mints/locks an NFT.
* [payInitialFee(...)](https://docs.cryptolegacy.app/documentation/functions-reference#payinitialfee-clbm1) - Pays the initial build fee (or lifetime) and optionally locks a Lifetime NFT.
* [payForMultipleLifetimeNft(...)](https://docs.cryptolegacy.app/documentation/functions-reference#payformultiplelifetimenft-clbm1) - Mass mints Lifetime NFTs when supply threshold is met.

### All Functions

* [receive()](https://docs.cryptolegacy.app/documentation/functions-reference#receive-clbm1) - Accepts plain ETH transfers to the build manager.
* [constructor(...)](https://docs.cryptolegacy.app/documentation/functions-reference#constructor-clbm1) - Initializes registries and factory, stores the Lifetime NFT contract, and transfers ownership.
* [setRegistries(...)](https://docs.cryptolegacy.app/documentation/functions-reference#setregistries-clbm1) - Owner setter that updates Fee/Plugins/Beneficiary registries.
* [\_setRegistries(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_setregistries-clbm1) - Internal storage setter for main registries.
* [setFactory(...)](https://docs.cryptolegacy.app/documentation/functions-reference#setfactory-clbm1) - Owner setter that updates the deployment factory.
* [\_setFactory(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_setfactory-clbm1) - Internal storage setter for the factory contract.
* [setSupplyLimit(...)](https://docs.cryptolegacy.app/documentation/functions-reference#setsupplylimit-clbm1) - Owner setter for the minimum Lifetime NFT supply required to allow mass minting.
* [setExternalLens(...)](https://docs.cryptolegacy.app/documentation/functions-reference#setexternallens-clbm1) - Owner setter for a helper "lens" address.
* [withdrawFee(...)](https://docs.cryptolegacy.app/documentation/functions-reference#withdrawfee-clbm1) - Owner can withdraw ETH from the contract to a recipient.
* [payFee(...)](https://docs.cryptolegacy.app/documentation/functions-reference#payfee-clbm1) - Pays an update fee or, if sufficient, auto-switches to lifetime fee and mints/locks an NFT.
* [\_payFee(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_payfee-clbm1) - Internal fee engine for build/update/lifetime fees, handling payment and optional NFT mint/lock.
* [\_returnFee(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_returnfee-clbm1) - Refund helper to return surplus ETH to the caller.
* [\_checkFee(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_checkfee-clbm1) - Validates that `value` covers `fee`.
* [\_mintAndLockLifetimeNft(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_mintandlocklifetimenft-clbm1) - Mints a Lifetime NFT to this contract, approves the registry, and locks it cross-chain.
* [payInitialFee(...)](https://docs.cryptolegacy.app/documentation/functions-reference#payinitialfee-clbm1) - Pays the initial build fee (or lifetime) and optionally locks a Lifetime NFT.
* [payForMultipleLifetimeNft(...)](https://docs.cryptolegacy.app/documentation/functions-reference#payformultiplelifetimenft-clbm1) - Mass mints Lifetime NFTs when supply threshold is met.
* [createCustomRef(...)](https://docs.cryptolegacy.app/documentation/functions-reference#createcustomref-clbm1) - Creates a custom referral code and optionally locks it cross-chain; refunds any surplus.
* [\_createCustomRef(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_createcustomref-clbm1) - Internal custom-ref creation with cross-chain fee handling.
* [createRef(...)](https://docs.cryptolegacy.app/documentation/functions-reference#createref-clbm1) - Creates a short referral code and optionally locks it cross-chain; refunds surplus.
* [\_createRef(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_createref-clbm1) - Internal short-ref creation with cross-chain fee handling.
* [updateCrossChainsRef(...)](https://docs.cryptolegacy.app/documentation/functions-reference#updatecrosschainsref-clbm1) - Updates chain coverage for the caller’s referral code.
* [\_createRefAndPayForBuild(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_createrefandpayforbuild-clbm1) - Internal helper to optionally create a referral and then obtain/pay the build fee.
* [buildCryptoLegacy(...)](https://docs.cryptolegacy.app/documentation/functions-reference#buildcryptolegacy-clbm1) - Deploys and initializes a new CryptoLegacy instance after handling referral creation and fees.
* [\_checkBuildArgs(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_checkbuildargs-clbm1) - Validates required default timeouts in build arguments.
* [\_getAndPayBuildFee(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_getandpaybuildfee-clbm1) - Retrieves (and optionally pays) the initial build fee and always returns the update fee.
* [getUpdateFee(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getupdatefee-clbm1) - Returns the configured update fee for a referral code.
* [getAndPayBuildFee(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getandpaybuildfee-clbm1) - Convenience entry point to fetch build/update fees and optionally pay if ETH is sent.
* [transferStuckNft(...)](https://docs.cryptolegacy.app/documentation/functions-reference#transferstucknft-clbm1) - Owner rescue function to transfer out an ERC721 token held by this contract.
* [onERC721Received(...)](https://docs.cryptolegacy.app/documentation/functions-reference#onerc721received-clbm1) - ERC721 safe-transfer hook confirming receipt.
* [calculateCrossChainCreateRefFee(...)](https://docs.cryptolegacy.app/documentation/functions-reference#calculatecrosschaincreatereffee-clbm1) - Computes the total native fee needed to create/lock a referral across chains.
* [getFactoryAddress()](https://docs.cryptolegacy.app/documentation/functions-reference#getfactoryaddress-clbm1) - Returns the currently configured factory address.
* [isLifetimeNftLocked(...)](https://docs.cryptolegacy.app/documentation/functions-reference#islifetimenftlocked-clbm1) - Checks whether a Lifetime NFT is locked for `owner`.
* [isLifetimeNftLockedAndUpdate(...)](https://docs.cryptolegacy.app/documentation/functions-reference#islifetimenftlockedandupdate-clbm1) - For a calling CryptoLegacy, verifies ownership and then checks/updates the Lifetime NFT lock status.
* [isPluginRegistered(...)](https://docs.cryptolegacy.app/documentation/functions-reference#ispluginregistered-clbm1) - Checks if a plugin is registered in the plugin registry.
* [isCryptoLegacyBuilt(...)](https://docs.cryptolegacy.app/documentation/functions-reference#iscryptolegacybuilt-clbm1) - Returns whether a given CryptoLegacy address was deployed by this manager.

### Events

* [SetRegistries](https://docs.cryptolegacy.app/documentation/events-reference#setregistries-iclbm1)
* [SetFactory](https://docs.cryptolegacy.app/documentation/events-reference#setfactory-iclbm1)
* [SetSupplyLimit](https://docs.cryptolegacy.app/documentation/events-reference#setsupplylimit-iclbm1)
* [SetExternalLens](https://docs.cryptolegacy.app/documentation/events-reference#setexternallens-iclbm1)
* [WithdrawFee](https://docs.cryptolegacy.app/documentation/events-reference#withdrawfee-iclbm1)
* [PaidForMint](https://docs.cryptolegacy.app/documentation/events-reference#paidformint-iclbm1)
* [PaidForMultipleNft](https://docs.cryptolegacy.app/documentation/events-reference#paidformultiplenft-iclbm1)
* [CreateCustomRef](https://docs.cryptolegacy.app/documentation/events-reference#createcustomref-iclbm1)
* [CreateRef](https://docs.cryptolegacy.app/documentation/events-reference#createref-iclbm1)
* [SetCrossChainsRef](https://docs.cryptolegacy.app/documentation/events-reference#setcrosschainsref-iclbm1)
* [Build](https://docs.cryptolegacy.app/documentation/events-reference#build-iclbm1)

### Errors

* [AlreadyLifetime](https://docs.cryptolegacy.app/documentation/errors-reference#alreadylifetime-iclbm1)
* [WithdrawFeeFailed](https://docs.cryptolegacy.app/documentation/errors-reference#withdrawfeefailed-iclbm1)
* [TransferFeeFailed](https://docs.cryptolegacy.app/documentation/errors-reference#transferfeefailed-iclbm1)
* [IncorrectFee](https://docs.cryptolegacy.app/documentation/errors-reference#incorrectfee-iclbm1)
* [BelowMinimumSupply](https://docs.cryptolegacy.app/documentation/errors-reference#belowminimumsupply-iclbm1)
* [NotValidTimeout](https://docs.cryptolegacy.app/documentation/errors-reference#notvalidtimeout-iclbm1)
* [NotRegisteredCryptoLegacy](https://docs.cryptolegacy.app/documentation/errors-reference#notregisteredcryptolegacy-iclbm1)
* [NotOwnerOfCryptoLegacy](https://docs.cryptolegacy.app/documentation/errors-reference#notownerofcryptolegacy-iclbm1)

### Access / Roles

* `setRegistries`: `onlyOwner`
* `setFactory`: `onlyOwner`
* `setSupplyLimit`: `onlyOwner`
* `setExternalLens`: `onlyOwner`
* `withdrawFee`: `onlyOwner`
* `transferStuckNft`: `onlyOwner`

### Interacts With

* `IBeneficiaryRegistry`
* `ICryptoLegacy`
* `ICryptoLegacyFactory`
* `IFeeRegistry`
* `ILockChainGate`
* `ILifetimeNft`
* `IPluginsRegistry`
* `CryptoLegacyBasePlugin`

### Missing Links

None.

## CryptoLegacyDiamondBase

### Purpose

CryptoLegacyDiamondBase provides shared diamond base behavior, including selector checks and static-call validation helpers.

### Inheritance

* `ICryptoLegacyDiamondBase`
* `DiamondLoupeFacet`

### Key Methods

* [staticCallChecker(...)](https://docs.cryptolegacy.app/documentation/functions-reference#staticcallchecker-cldb1) - Self-call probe used by the fallback to detect whether the current context is a static call.

### All Functions

* [staticCallChecker()](https://docs.cryptolegacy.app/documentation/functions-reference#staticcallchecker-cldb1) - Self-call probe used by the fallback to detect whether the current context is a static call.
* [fallback()](https://docs.cryptolegacy.app/documentation/functions-reference#fallback-cldb1) - Diamond fallback that routes unknown selectors to the correct facet via `delegatecall`, caching the facet address on non-static calls.

### Events

* [StaticCallCheck](https://docs.cryptolegacy.app/documentation/events-reference#staticcallcheck-icldb1)

### Errors

* [NotSelfCall](https://docs.cryptolegacy.app/documentation/errors-reference#notselfcall-icldb1)
* [FunctionNotExists](https://docs.cryptolegacy.app/documentation/errors-reference#functionnotexists-icldb1)

### Access / Roles

* `staticCallChecker`: self-call only (`msg.sender == address(this)`)

### Interacts With

* `ICryptoLegacy`
* `LibCryptoLegacy`
* `LibCryptoLegacyPlugins`
* `LibDiamond`

### Missing Links

None.

## CryptoLegacyExternalLens

### Purpose

CryptoLegacyExternalLens aggregates read-only status and portfolio views across CryptoLegacy-related components.

### Inheritance

None.

### Key Methods

* [isLifetimeActive(...)](https://docs.cryptolegacy.app/documentation/functions-reference#islifetimeactive-clexl1) - Forwarder that reports whether lifetime mode is active on a target CryptoLegacy.
* [isPaused(...)](https://docs.cryptolegacy.app/documentation/functions-reference#ispaused-clexl1) - Forwarder that reports whether the target CryptoLegacy is paused.
* [buildManager(...)](https://docs.cryptolegacy.app/documentation/functions-reference#buildmanager-clexl1) - Returns the build manager address of the target CryptoLegacy.
* [owner(...)](https://docs.cryptolegacy.app/documentation/functions-reference#owner-clexl1) - Returns the owner of the target CryptoLegacy.
* [updateInterval(...)](https://docs.cryptolegacy.app/documentation/functions-reference#updateinterval-clexl1) - Returns the update interval of the target.
* [challengeTimeout(...)](https://docs.cryptolegacy.app/documentation/functions-reference#challengetimeout-clexl1) - Returns the challenge timeout of the target.
* [distributionStartAt(...)](https://docs.cryptolegacy.app/documentation/functions-reference#distributionstartat-clexl1) - Returns the distribution start timestamp.
* [lastFeePaidAt(...)](https://docs.cryptolegacy.app/documentation/functions-reference#lastfeepaidat-clexl1) - Returns the timestamp of the last fee payment.

### All Functions

* [isLifetimeActive(...)](https://docs.cryptolegacy.app/documentation/functions-reference#islifetimeactive-clexl1) - Forwarder that reports whether lifetime mode is active on a target CryptoLegacy.
* [isPaused(...)](https://docs.cryptolegacy.app/documentation/functions-reference#ispaused-clexl1) - Forwarder that reports whether the target CryptoLegacy is paused.
* [buildManager(...)](https://docs.cryptolegacy.app/documentation/functions-reference#buildmanager-clexl1) - Returns the build manager address of the target CryptoLegacy.
* [owner(...)](https://docs.cryptolegacy.app/documentation/functions-reference#owner-clexl1) - Returns the owner of the target CryptoLegacy.
* [\_baseData(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_basedata-clexl1) - Internal helper that fetches base lens data from the target.
* [\_listTokensData(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_listtokensdata-clexl1) - Internal helper that fetches list data for specified tokens.
* [updateInterval(...)](https://docs.cryptolegacy.app/documentation/functions-reference#updateinterval-clexl1) - Returns the update interval of the target.
* [challengeTimeout(...)](https://docs.cryptolegacy.app/documentation/functions-reference#challengetimeout-clexl1) - Returns the challenge timeout of the target.
* [distributionStartAt(...)](https://docs.cryptolegacy.app/documentation/functions-reference#distributionstartat-clexl1) - Returns the distribution start timestamp.
* [lastFeePaidAt(...)](https://docs.cryptolegacy.app/documentation/functions-reference#lastfeepaidat-clexl1) - Returns the timestamp of the last fee payment.
* [lastUpdateAt(...)](https://docs.cryptolegacy.app/documentation/functions-reference#lastupdateat-clexl1) - Returns the timestamp of the last update.
* [initialFeeToPay(...)](https://docs.cryptolegacy.app/documentation/functions-reference#initialfeetopay-clexl1) - Returns the initial fee required by the target.
* [updateFee(...)](https://docs.cryptolegacy.app/documentation/functions-reference#updatefee-clexl1) - Returns the update fee required by the target.
* [invitedByRefCode(...)](https://docs.cryptolegacy.app/documentation/functions-reference#invitedbyrefcode-clexl1) - Returns the referral code associated with the target.
* [getBeneficiaries(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getbeneficiaries-clexl1) - Returns beneficiaries and their configs from the target.
* [getTokensDistribution(...)](https://docs.cryptolegacy.app/documentation/functions-reference#gettokensdistribution-clexl1) - Returns token distribution info for a token list.
* [getCryptoLegacyBaseData(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getcryptolegacybasedata-clexl1) - Returns consolidated base data for the target.
* [getCryptoLegacyListData(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getcryptolegacylistdata-clexl1) - Returns aggregated list data for specified tokens.
* [getMessagesBlockNumbersByRecipient(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getmessagesblocknumbersbyrecipient-clexl1) - Returns message block numbers for a recipient hash.
* [getTransferBlockNumbers(...)](https://docs.cryptolegacy.app/documentation/functions-reference#gettransferblocknumbers-clexl1) - Returns block numbers where transfers occurred.
* [getVestedAndClaimedData(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getvestedandclaimeddata-clexl1) - Returns vesting/claimed data for a beneficiary across tokens.
* [getPluginInfoList(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getplugininfolist-clexl1) - Returns plugin metadata installed on the target.
* [getCryptoLegacyListWithStatuses(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getcryptolegacylistwithstatuses-clexl1) - Returns CryptoLegacy addresses for all roles tied to a hash plus default-guardian status per beneficiary entry.

### Events

None.

### Errors

None.

### Access / Roles

None.

### Interacts With

* `IBeneficiaryRegistry`
* `ICryptoLegacy`
* `ICryptoLegacyLens`
* `ITrustedGuardiansPlugin`
* `CryptoLegacyBasePlugin`
* `LensPlugin`

### Missing Links

None.

## CryptoLegacyFactory

### Purpose

CryptoLegacyFactory creates new CryptoLegacy instances and controls which operators can trigger deployments.

### Inheritance

* `ICryptoLegacyFactory`
* `Ownable`

### Key Methods

* [setBuildOperator(...)](https://docs.cryptolegacy.app/documentation/functions-reference#setbuildoperator-clf1) - Adds or removes an authorized build operator.
* [createCryptoLegacy(...)](https://docs.cryptolegacy.app/documentation/functions-reference#createcryptolegacy-clf1) - Deploys a new `CryptoLegacy` contract at a deterministic address using CREATE3.
* [cryptoLegacyBytecode(...)](https://docs.cryptolegacy.app/documentation/functions-reference#cryptolegacybytecode-clf1) - Returns the full constructor bytecode for a `CryptoLegacy` deployment.
* [computeAddress(...)](https://docs.cryptolegacy.app/documentation/functions-reference#computeaddress-clf1) - Computes the deterministic address for a future `CryptoLegacy` deployment.

### All Functions

* [constructor(...)](https://docs.cryptolegacy.app/documentation/functions-reference#constructor-clf1) - Initializes the factory and sets the initial owner.
* [setBuildOperator(...)](https://docs.cryptolegacy.app/documentation/functions-reference#setbuildoperator-clf1) - Adds or removes an authorized build operator.
* [createCryptoLegacy(...)](https://docs.cryptolegacy.app/documentation/functions-reference#createcryptolegacy-clf1) - Deploys a new `CryptoLegacy` contract at a deterministic address using CREATE3.
* [cryptoLegacyBytecode(...)](https://docs.cryptolegacy.app/documentation/functions-reference#cryptolegacybytecode-clf1) - Returns the full constructor bytecode for a `CryptoLegacy` deployment.
* [computeAddress(...)](https://docs.cryptolegacy.app/documentation/functions-reference#computeaddress-clf1) - Computes the deterministic address for a future `CryptoLegacy` deployment.

### Events

* [AddBuildOperator](https://docs.cryptolegacy.app/documentation/events-reference#addbuildoperator-iclf1)
* [RemoveBuildOperator](https://docs.cryptolegacy.app/documentation/events-reference#removebuildoperator-iclf1)

### Errors

* [NotBuildOperator](https://docs.cryptolegacy.app/documentation/errors-reference#notbuildoperator-iclf1)

### Access / Roles

* `setBuildOperator`: `onlyOwner`

### Interacts With

* `LibCryptoLegacyDeploy`

### Missing Links

None.

## CryptoLegacyOwnable

### Purpose

CryptoLegacyOwnable implements ownership-transfer and pause controls shared by protocol contracts.

### Inheritance

* `ICryptoLegacyOwnable`

### Key Methods

* [acceptOwnership(...)](https://docs.cryptolegacy.app/documentation/functions-reference#acceptownership-clo1) - Completes the two-step ownership transfer by moving ownership to `msg.sender`.
* [setPause(...)](https://docs.cryptolegacy.app/documentation/functions-reference#setpause-clo1) - Sets the pause flag for the CryptoLegacy contract.
* [pendingOwner(...)](https://docs.cryptolegacy.app/documentation/functions-reference#pendingowner-clo1) - Returns the current `pendingOwner`.

### All Functions

* [\_transferOwnership(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_transferownership-clo1) - Starts a two-step ownership transfer by setting `pendingOwner` and emitting the start event.
* [acceptOwnership()](https://docs.cryptolegacy.app/documentation/functions-reference#acceptownership-clo1) - Completes the two-step ownership transfer by moving ownership to `msg.sender`.
* [setPause(...)](https://docs.cryptolegacy.app/documentation/functions-reference#setpause-clo1) - Sets the pause flag for the CryptoLegacy contract.
* [pendingOwner()](https://docs.cryptolegacy.app/documentation/functions-reference#pendingowner-clo1) - Returns the current `pendingOwner`.

### Events

* [OwnershipTransferStarted](https://docs.cryptolegacy.app/documentation/events-reference#ownershiptransferstarted-iclo1)
* [OwnershipTransferred](https://docs.cryptolegacy.app/documentation/events-reference#ownershiptransferred-iclo1)

### Errors

* [OwnableUnauthorizedAccount](https://docs.cryptolegacy.app/documentation/errors-reference#ownableunauthorizedaccount-iclo1)
* [ZeroAddress](https://docs.cryptolegacy.app/documentation/errors-reference#zeroaddress-icl1)

### Access / Roles

* `setPause`: `onlyOwner`
* `acceptOwnership`: `pendingOwner` only

### Interacts With

* `ICryptoLegacy`
* `LibCryptoLegacy`
* `LibDiamond`

### Missing Links

None.

## FeeRegistry

### Purpose

FeeRegistry stores referral code metadata, fee percentages, and beneficiary split configuration for payment flows.

### Inheritance

* `LockChainGate`
* `IFeeRegistry`

### Key Methods

* [initialize(...)](https://docs.cryptolegacy.app/documentation/functions-reference#initialize-fr1) - Initializes default percentages and the cross-chain gate configuration.
* [setCodeOperator(...)](https://docs.cryptolegacy.app/documentation/functions-reference#setcodeoperator-fr1) - Adds or removes an authorized referral-code operator.
* [setSupportedRefCodeInChains(...)](https://docs.cryptolegacy.app/documentation/functions-reference#setsupportedrefcodeinchains-fr1) - Adds or removes supported chain IDs for referral codes.
* [setFeeBeneficiaries(...)](https://docs.cryptolegacy.app/documentation/functions-reference#setfeebeneficiaries-fr1) - Sets protocol fee beneficiaries and their shares.
* [setDefaultPct(...)](https://docs.cryptolegacy.app/documentation/functions-reference#setdefaultpct-fr1) - Updates global default discount/share percentages.
* [setRefererSpecificPct(...)](https://docs.cryptolegacy.app/documentation/functions-reference#setrefererspecificpct-fr1) - Sets custom discount/share percentages for a referrer’s code.
* [setContractCaseFee(...)](https://docs.cryptolegacy.app/documentation/functions-reference#setcontractcasefee-fr1) - Sets the fee amount for a (contract, case) pair.
* [takeFee(...)](https://docs.cryptolegacy.app/documentation/functions-reference#takefee-fr1) - Charges a fee for a contract case and distributes referrer share.

### All Functions

* [constructor()](https://docs.cryptolegacy.app/documentation/functions-reference#constructor-fr1) - Deploy-time constructor that disables initializers and sets the initial owner.
* [lockFeeRegistryStorage()](https://docs.cryptolegacy.app/documentation/functions-reference#lockfeeregistrystorage-fr1) - Returns a namespaced storage pointer for FeeRegistry state.
* [initialize(...)](https://docs.cryptolegacy.app/documentation/functions-reference#initialize-fr1) - Initializes default percentages and the cross-chain gate configuration.
* [setCodeOperator(...)](https://docs.cryptolegacy.app/documentation/functions-reference#setcodeoperator-fr1) - Adds or removes an authorized referral-code operator.
* [setSupportedRefCodeInChains(...)](https://docs.cryptolegacy.app/documentation/functions-reference#setsupportedrefcodeinchains-fr1) - Adds or removes supported chain IDs for referral codes.
* [setFeeBeneficiaries(...)](https://docs.cryptolegacy.app/documentation/functions-reference#setfeebeneficiaries-fr1) - Sets protocol fee beneficiaries and their shares.
* [setDefaultPct(...)](https://docs.cryptolegacy.app/documentation/functions-reference#setdefaultpct-fr1) - Updates global default discount/share percentages.
* [\_setDefaultPct(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_setdefaultpct-fr1) - Internal setter for default discount/share percentages.
* [setRefererSpecificPct(...)](https://docs.cryptolegacy.app/documentation/functions-reference#setrefererspecificpct-fr1) - Sets custom discount/share percentages for a referrer’s code.
* [setContractCaseFee(...)](https://docs.cryptolegacy.app/documentation/functions-reference#setcontractcasefee-fr1) - Sets the fee amount for a (contract, case) pair.
* [takeFee(...)](https://docs.cryptolegacy.app/documentation/functions-reference#takefee-fr1) - Charges a fee for a contract case and distributes referrer share.
* [withdrawAccumulatedFee()](https://docs.cryptolegacy.app/documentation/functions-reference#withdrawaccumulatedfee-fr1) - Distributes accumulated protocol fees to configured beneficiaries.
* [withdrawReferralAccumulatedFee(...)](https://docs.cryptolegacy.app/documentation/functions-reference#withdrawreferralaccumulatedfee-fr1) - Pays out a referrer’s accumulated unpaid share.
* [\_setCustomCode(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_setcustomcode-fr1) - Internal writer for a custom referral code’s ownership, recipient, and percentages.
* [\_createCustomCode(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_createcustomcode-fr1) - Internal creator for a new custom referral code.
* [\_checkCodeNotZero(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_checkcodenotzero-fr1) - Validates that a referral code is non-zero.
* [\_checkSenderIsOperator(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_checksenderisoperator-fr1) - Ensures caller is an authorized code operator.
* [createCustomCode(...)](https://docs.cryptolegacy.app/documentation/functions-reference#createcustomcode-fr1) - Creates a **custom** referral code and optionally propagates it cross‑chain.
* [createCode(...)](https://docs.cryptolegacy.app/documentation/functions-reference#createcode-fr1) - Creates a **generated** referral code and optionally propagates it cross‑chain.
* [\_setCrossChainsRef(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_setcrosschainsref-fr1) - Internal helper to (create/update) code data across chains.
* [updateCrossChainsRef(...)](https://docs.cryptolegacy.app/documentation/functions-reference#updatecrosschainsref-fr1) - Updates cross-chain parameters for an existing referrer's code.
* [crossCreateCustomCode(...)](https://docs.cryptolegacy.app/documentation/functions-reference#crosscreatecustomcode-fr1) - Cross-chain entry to create a custom code.
* [crossUpdateCustomCode(...)](https://docs.cryptolegacy.app/documentation/functions-reference#crossupdatecustomcode-fr1) - Cross-chain entry to update code data.
* [\_encodeCrossCreateCustomCodeCommand(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_encodecrosscreatecustomcodecommand-fr1) - Encodes the cross-chain create code command payload.
* [\_encodeCrossUpdateCustomCodeCommand(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_encodecrossupdatecustomcodecommand-fr1) - Encodes the cross-chain update code command payload.
* [\_checkSenderIsReferrer(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_checksenderisreferrer-fr1) - Ensures the caller owns the specified referral code.
* [\_checkNewOwnerIsNotReferrer(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_checknewownerisnotreferrer-fr1) - Prevents assigning a code to an address that already has one.
* [changeCodeReferrer(...)](https://docs.cryptolegacy.app/documentation/functions-reference#changecodereferrer-fr1) - Transfers code ownership to a new referrer and optionally updates cross‑chain.
* [changeRecipientReferrer(...)](https://docs.cryptolegacy.app/documentation/functions-reference#changerecipientreferrer-fr1) - Updates the payout recipient for a referral code and optionally propagates cross-chain.
* [getCodeOperatorsList()](https://docs.cryptolegacy.app/documentation/functions-reference#getcodeoperatorslist-fr1) - Returns the list of authorized code operators.
* [isCodeOperator(...)](https://docs.cryptolegacy.app/documentation/functions-reference#iscodeoperator-fr1) - Checks whether an address is an authorized code operator.
* [getSupportedRefInChainsList()](https://docs.cryptolegacy.app/documentation/functions-reference#getsupportedrefinchainslist-fr1) - Lists chain IDs where referral codes are supported.
* [isSupportedRefInChain(...)](https://docs.cryptolegacy.app/documentation/functions-reference#issupportedrefinchain-fr1) - Checks whether a chain ID supports referral codes.
* [getFeeBeneficiaries()](https://docs.cryptolegacy.app/documentation/functions-reference#getfeebeneficiaries-fr1) - Returns protocol fee beneficiaries.
* [getCodePct(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getcodepct-fr1) - Returns effective discount/share percentages for a code.
* [\_getCodePct(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_getcodepct-fr1) - Internal resolver for a code’s effective percentages.
* [calculateFee(...)](https://docs.cryptolegacy.app/documentation/functions-reference#calculatefee-fr1) - Computes discount, share, and final fee for a code and base fee.
* [\_calculateFee(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_calculatefee-fr1) - Internal computation of discount/share/fee for a code and base amount.
* [getContractCaseFee(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getcontractcasefee-fr1) - Retrieves the stored fee for a (contract, case) pair.
* [getContractCaseFeeForCode(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getcontractcasefeeforcode-fr1) - Retrieves the effective fee for a (contract, case) after applying a code’s discount.
* [getReferrerByAddress(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getreferrerbyaddress-fr1) - Returns referrer metadata by referrer address.
* [\_getReferrerByAddress(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_getreferrerbyaddress-fr1) - Internal resolver for referrer by address.
* [getReferrerByCode(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getreferrerbycode-fr1) - Returns referrer metadata by code.
* [\_getReferrerByCode(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_getreferrerbycode-fr1) - Internal resolver for referrer by code.
* [defaultSharePct()](https://docs.cryptolegacy.app/documentation/functions-reference#defaultsharepct-fr1) - Returns the default share percentage.
* [defaultDiscountPct()](https://docs.cryptolegacy.app/documentation/functions-reference#defaultdiscountpct-fr1) - Returns the default discount percentage.
* [refererByCode(...)](https://docs.cryptolegacy.app/documentation/functions-reference#refererbycode-fr1) - Returns raw referrer record for a code (without effective pcts).
* [codeByReferrer(...)](https://docs.cryptolegacy.app/documentation/functions-reference#codebyreferrer-fr1) - Returns the code associated with a referrer address.
* [accumulatedFee()](https://docs.cryptolegacy.app/documentation/functions-reference#accumulatedfee-fr1) - Returns the accumulated protocol fee balance.

### Events

* [AddLockOperator](https://docs.cryptolegacy.app/documentation/events-reference#addlockoperator-ilcg1)
* [RemoveLockOperator](https://docs.cryptolegacy.app/documentation/events-reference#removelockoperator-ilcg1)
* [SetDestinationChainContract](https://docs.cryptolegacy.app/documentation/events-reference#setdestinationchaincontract-ilcg1)
* [SetSourceChainContract](https://docs.cryptolegacy.app/documentation/events-reference#setsourcechaincontract-ilcg1)
* [SetDeBridgeGate](https://docs.cryptolegacy.app/documentation/events-reference#setdebridgegate-ilcg1)
* [SetDeBridgeNativeFee](https://docs.cryptolegacy.app/documentation/events-reference#setdebridgenativefee-ilcg1)
* [SetLockPeriodConfig](https://docs.cryptolegacy.app/documentation/events-reference#setlockperiodconfig-ilcg1)
* [SendToChain](https://docs.cryptolegacy.app/documentation/events-reference#sendtochain-ilcg1)
* [LockNft](https://docs.cryptolegacy.app/documentation/events-reference#locknft-ilcg1)
* [UnlockNft](https://docs.cryptolegacy.app/documentation/events-reference#unlocknft-ilcg1)
* [ApproveNft](https://docs.cryptolegacy.app/documentation/events-reference#approvenft-ilcg1)
* [TransferNft](https://docs.cryptolegacy.app/documentation/events-reference#transfernft-ilcg1)
* [LockToChain](https://docs.cryptolegacy.app/documentation/events-reference#locktochain-ilcg1)
* [UpdateLockToChain](https://docs.cryptolegacy.app/documentation/events-reference#updatelocktochain-ilcg1)
* [Update](https://docs.cryptolegacy.app/documentation/events-reference#update-ilcg1)
* [UnlockFromChain](https://docs.cryptolegacy.app/documentation/events-reference#unlockfromchain-ilcg1)
* [CrossLockNft](https://docs.cryptolegacy.app/documentation/events-reference#crosslocknft-ilcg1)
* [CrossUnlockNft](https://docs.cryptolegacy.app/documentation/events-reference#crossunlocknft-ilcg1)
* [CrossUpdateNftOwner](https://docs.cryptolegacy.app/documentation/events-reference#crossupdatenftowner-ilcg1)
* [SetReferralCode](https://docs.cryptolegacy.app/documentation/events-reference#setreferralcode-ilcg1)
* [SetCustomChainId](https://docs.cryptolegacy.app/documentation/events-reference#setcustomchainid-ilcg1)
* [AddCodeOperator](https://docs.cryptolegacy.app/documentation/events-reference#addcodeoperator-ifr1)
* [RemoveCodeOperator](https://docs.cryptolegacy.app/documentation/events-reference#removecodeoperator-ifr1)
* [SetDefaultPct](https://docs.cryptolegacy.app/documentation/events-reference#setdefaultpct-ifr1)
* [SetRefererSpecificPct](https://docs.cryptolegacy.app/documentation/events-reference#setrefererspecificpct-ifr1)
* [SetContractCaseFee](https://docs.cryptolegacy.app/documentation/events-reference#setcontractcasefee-ifr1)
* [TakeFee](https://docs.cryptolegacy.app/documentation/events-reference#takefee-ifr1)
* [SentFee](https://docs.cryptolegacy.app/documentation/events-reference#sentfee-ifr1)
* [AccumulateFee](https://docs.cryptolegacy.app/documentation/events-reference#accumulatefee-ifr1)
* [CreateCode](https://docs.cryptolegacy.app/documentation/events-reference#createcode-ifr1)
* [UpdateCode](https://docs.cryptolegacy.app/documentation/events-reference#updatecode-ifr1)
* [ChangeCode](https://docs.cryptolegacy.app/documentation/events-reference#changecode-ifr1)
* [ChangeRecipient](https://docs.cryptolegacy.app/documentation/events-reference#changerecipient-ifr1)
* [SetCrossChainsRef](https://docs.cryptolegacy.app/documentation/events-reference#setcrosschainsref-ifr1)
* [SetFeeBeneficiaries](https://docs.cryptolegacy.app/documentation/events-reference#setfeebeneficiaries-ifr1)
* [AddSupportedRefCodeInChain](https://docs.cryptolegacy.app/documentation/events-reference#addsupportedrefcodeinchain-ifr1)
* [RemoveSupportedRefCodeInChain](https://docs.cryptolegacy.app/documentation/events-reference#removesupportedrefcodeinchain-ifr1)
* [WithdrawFee](https://docs.cryptolegacy.app/documentation/events-reference#withdrawfee-ifr1)
* [WithdrawRefFee](https://docs.cryptolegacy.app/documentation/events-reference#withdrawreffee-ifr1)

### Errors

* [ArrayLengthMismatch](https://docs.cryptolegacy.app/documentation/errors-reference#arraylengthmismatch-ilcg1)
* [AlreadyLocked](https://docs.cryptolegacy.app/documentation/errors-reference#alreadylocked-ilcg1)
* [LockedToChains](https://docs.cryptolegacy.app/documentation/errors-reference#lockedtochains-ilcg1)
* [CrossChainLock](https://docs.cryptolegacy.app/documentation/errors-reference#crosschainlock-ilcg1)
* [TooEarly](https://docs.cryptolegacy.app/documentation/errors-reference#tooearly-ilcg1)
* [DestinationChainNotSpecified](https://docs.cryptolegacy.app/documentation/errors-reference#destinationchainnotspecified-ilcg1)
* [TokenNotLocked](https://docs.cryptolegacy.app/documentation/errors-reference#tokennotlocked-ilcg1)
* [TokenIdMismatch](https://docs.cryptolegacy.app/documentation/errors-reference#tokenidmismatch-ilcg1)
* [AlreadyLockedToChain](https://docs.cryptolegacy.app/documentation/errors-reference#alreadylockedtochain-ilcg1)
* [SourceNotSpecified](https://docs.cryptolegacy.app/documentation/errors-reference#sourcenotspecified-ilcg1)
* [NotLockedByChain](https://docs.cryptolegacy.app/documentation/errors-reference#notlockedbychain-ilcg1)
* [DestinationNotSpecified](https://docs.cryptolegacy.app/documentation/errors-reference#destinationnotspecified-ilcg1)
* [NotAvailable](https://docs.cryptolegacy.app/documentation/errors-reference#notavailable-ilcg1)
* [IncorrectFee](https://docs.cryptolegacy.app/documentation/errors-reference#incorrectfee-ilcg1)
* [SameAddress](https://docs.cryptolegacy.app/documentation/errors-reference#sameaddress-ilcg1)
* [RecipientLocked](https://docs.cryptolegacy.app/documentation/errors-reference#recipientlocked-ilcg1)
* [TransferLockTimeout](https://docs.cryptolegacy.app/documentation/errors-reference#transferlocktimeout-ilcg1)
* [NotCallProxy](https://docs.cryptolegacy.app/documentation/errors-reference#notcallproxy-ilcg1)
* [ChainIdMismatch](https://docs.cryptolegacy.app/documentation/errors-reference#chainidmismatch-ilcg1)
* [NotValidSender](https://docs.cryptolegacy.app/documentation/errors-reference#notvalidsender-ilcg1)
* [NotAllowed](https://docs.cryptolegacy.app/documentation/errors-reference#notallowed-ilcg1)
* [TransferFeeFailed](https://docs.cryptolegacy.app/documentation/errors-reference#transferfeefailed-ilcg1)
* [WithdrawAccumulatedFeeFailed](https://docs.cryptolegacy.app/documentation/errors-reference#withdrawaccumulatedfeefailed-ifr1)
* [PctSumDoesntMatchBase](https://docs.cryptolegacy.app/documentation/errors-reference#pctsumdoesntmatchbase-ifr1)
* [TooBigPct](https://docs.cryptolegacy.app/documentation/errors-reference#toobigpct-ifr1)
* [RefAlreadyCreated](https://docs.cryptolegacy.app/documentation/errors-reference#refalreadycreated-ifr1)
* [ZeroCode](https://docs.cryptolegacy.app/documentation/errors-reference#zerocode-ifr1)
* [NotOperator](https://docs.cryptolegacy.app/documentation/errors-reference#notoperator-ifr1)
* [NotReferrer](https://docs.cryptolegacy.app/documentation/errors-reference#notreferrer-ifr1)
* [AlreadyReferrer](https://docs.cryptolegacy.app/documentation/errors-reference#alreadyreferrer-ifr1)
* [CodeNotCreated](https://docs.cryptolegacy.app/documentation/errors-reference#codenotcreated-ifr1)

### Access / Roles

* `initialize`: `initializer`
* `setCodeOperator`: `onlyOwner`
* `setSupportedRefCodeInChains`: `onlyOwner`
* `setFeeBeneficiaries`: `onlyOwner`
* `setDefaultPct`: `onlyOwner`
* `setRefererSpecificPct`: `onlyOwner`
* `setContractCaseFee`: `onlyOwner`
* `takeFee`: `nonReentrant`
* `withdrawAccumulatedFee`: `nonReentrant`
* `withdrawReferralAccumulatedFee`: `nonReentrant`
* `createCustomCode`: `nonReentrant`
* `createCode`: `nonReentrant`
* `updateCrossChainsRef`: `nonReentrant`
* `crossCreateCustomCode`: `nonReentrant`
* `crossUpdateCustomCode`: `nonReentrant`
* `changeCodeReferrer`: `nonReentrant`
* `changeRecipientReferrer`: `nonReentrant`

### Interacts With

* `ILifetimeNft`

### Missing Links

None.

## LegacyMessenger

### Purpose

LegacyMessenger records recipient-linked legacy messages and emits block-indexed message events for off-chain tracking.

### Inheritance

* `ILegacyMessenger`
* `BuildManagerOwnable`

### Key Methods

* [sendMessagesTo(...)](https://docs.cryptolegacy.app/documentation/functions-reference#sendmessagesto-lm1) - Emits per‑recipient message events and records the block number for each recipient.
* [getMessagesBlockNumbersByRecipient(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getmessagesblocknumbersbyrecipient-lm1) - Returns the list of block numbers when a given recipient received messages.

### All Functions

* [constructor(...)](https://docs.cryptolegacy.app/documentation/functions-reference#constructor-lm1) - Initializes the messenger and sets the contract owner.
* [sendMessagesTo(...)](https://docs.cryptolegacy.app/documentation/functions-reference#sendmessagesto-lm1) - Emits per‑recipient message events and records the block number for each recipient.
* [getMessagesBlockNumbersByRecipient(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getmessagesblocknumbersbyrecipient-lm1) - Returns the list of block numbers when a given recipient received messages.

### Events

* [LegacyMessage](https://docs.cryptolegacy.app/documentation/events-reference#legacymessage-ilm1)
* [LegacyMessageCheck](https://docs.cryptolegacy.app/documentation/events-reference#legacymessagecheck-ilm1)
* [AddBuildManager](https://docs.cryptolegacy.app/documentation/events-reference#addbuildmanager-ibmo1)
* [RemoveBuildManager](https://docs.cryptolegacy.app/documentation/events-reference#removebuildmanager-ibmo1)

### Errors

* [NotTheOwnerOfCryptoLegacy](https://docs.cryptolegacy.app/documentation/errors-reference#nottheownerofcryptolegacy-ibmo1)
* [CryptoLegacyNotRegistered](https://docs.cryptolegacy.app/documentation/errors-reference#cryptolegacynotregistered-ibmo1)
* [BuildManagerNotAdded](https://docs.cryptolegacy.app/documentation/errors-reference#buildmanagernotadded-ibmo1)

### Access / Roles

* `sendMessagesTo`: registered CryptoLegacy caller with approved build manager (`_checkBuildManagerValid`)

### Interacts With

* `ArbSys`

### Missing Links

None.

## LifetimeNft

### Purpose

LifetimeNft implements the protocol NFT with controlled minting and configurable metadata base URI.

### Inheritance

* `ILifetimeNft`
* `ERC721Enumerable`
* `Ownable`

### Key Methods

* [setBaseUri(...)](https://docs.cryptolegacy.app/documentation/functions-reference#setbaseuri-ln1) - Updates the collection-wide base URI.
* [setMinterOperator(...)](https://docs.cryptolegacy.app/documentation/functions-reference#setminteroperator-ln1) - Grants or revokes minting permission for an address.
* [mint(...)](https://docs.cryptolegacy.app/documentation/functions-reference#mint-ln1) - Mints a new token to the specified owner.
* [tokensOfOwner(...)](https://docs.cryptolegacy.app/documentation/functions-reference#tokensofowner-ln1) - Enumerates all token IDs owned by the given address.
* [getTier(...)](https://docs.cryptolegacy.app/documentation/functions-reference#gettier-ln1) - Computes the tier for a given token ID.

### All Functions

* [constructor(...)](https://docs.cryptolegacy.app/documentation/functions-reference#constructor-ln1) - Initializes the ERC721 token with name, symbol, base URI, and owner.
* [setBaseUri(...)](https://docs.cryptolegacy.app/documentation/functions-reference#setbaseuri-ln1) - Updates the collection-wide base URI.
* [\_setBaseUri(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_setbaseuri-ln1) - Internal helper to set the base URI and emit an event.
* [setMinterOperator(...)](https://docs.cryptolegacy.app/documentation/functions-reference#setminteroperator-ln1) - Grants or revokes minting permission for an address.
* [mint(...)](https://docs.cryptolegacy.app/documentation/functions-reference#mint-ln1) - Mints a new token to the specified owner.
* [\_baseURI()](https://docs.cryptolegacy.app/documentation/functions-reference#_baseuri-ln1) - Returns the stored base URI for metadata composition.
* [tokensOfOwner(...)](https://docs.cryptolegacy.app/documentation/functions-reference#tokensofowner-ln1) - Enumerates all token IDs owned by the given address.
* [getTier(...)](https://docs.cryptolegacy.app/documentation/functions-reference#gettier-ln1) - Computes the tier for a given token ID.

### Events

* [SetBaseURI](https://docs.cryptolegacy.app/documentation/events-reference#setbaseuri-ln1)
* [SetMinterOperator](https://docs.cryptolegacy.app/documentation/events-reference#setminteroperator-ln1)

### Errors

* [NotTheMinter](https://docs.cryptolegacy.app/documentation/errors-reference#nottheminter-iln1)

### Access / Roles

* `setBaseUri`: `onlyOwner`
* `setMinterOperator`: `onlyOwner`

### Interacts With

None.

### Missing Links

None.

## LockChainGate

### Purpose

LockChainGate manages lifetime-NFT lock/unlock flows and cross-chain routing parameters for bridge operations.

### Inheritance

* `Ownable`
* `ReentrancyGuardUpgradeable`
* `ILockChainGate`

### Key Methods

* [setLockOperator(...)](https://docs.cryptolegacy.app/documentation/functions-reference#setlockoperator-lcg1) - Adds or removes an address from the lock operators set.
* [setDebridgeGate(...)](https://docs.cryptolegacy.app/documentation/functions-reference#setdebridgegate-lcg1) - Sets the deBridgeGate contract used for cross-chain messages.
* [setDebridgeNativeFee(...)](https://docs.cryptolegacy.app/documentation/functions-reference#setdebridgenativefee-lcg1) - Sets the per-chain native fee used when sending cross-chain messages.
* [setDestinationChainContract(...)](https://docs.cryptolegacy.app/documentation/functions-reference#setdestinationchaincontract-lcg1) - Public setter for the destination chain contract mapping.
* [setSourceChainContract(...)](https://docs.cryptolegacy.app/documentation/functions-reference#setsourcechaincontract-lcg1) - Public setter for the source chain contract mapping.
* [setSourceAndDestinationChainContract(...)](https://docs.cryptolegacy.app/documentation/functions-reference#setsourceanddestinationchaincontract-lcg1) - Sets both source and destination contract addresses for a chain.
* [setLockPeriod(...)](https://docs.cryptolegacy.app/documentation/functions-reference#setlockperiod-lcg1) - Updates the NFT lock period and transfer timeout.
* [setReferralCode(...)](https://docs.cryptolegacy.app/documentation/functions-reference#setreferralcode-lcg1) - Sets deBridge referral code used in messages.

### All Functions

* [constructor()](https://docs.cryptolegacy.app/documentation/functions-reference#constructor-lcg1) - Deploy-time constructor that disables initializers and sets the Ownable owner.
* [lockChainGateStorage()](https://docs.cryptolegacy.app/documentation/functions-reference#lockchaingatestorage-lcg1) - Returns the storage pointer for the LockChainGate storage struct.
* [\_initializeLockChainGate(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_initializelockchaingate-lcg1) - Internal initializer to set Lifetime NFT address, lock config, owner, and reentrancy guard.
* [setLockOperator(...)](https://docs.cryptolegacy.app/documentation/functions-reference#setlockoperator-lcg1) - Adds or removes an address from the lock operators set.
* [setDebridgeGate(...)](https://docs.cryptolegacy.app/documentation/functions-reference#setdebridgegate-lcg1) - Sets the deBridgeGate contract used for cross-chain messages.
* [setDebridgeNativeFee(...)](https://docs.cryptolegacy.app/documentation/functions-reference#setdebridgenativefee-lcg1) - Sets the per-chain native fee used when sending cross-chain messages.
* [\_setDestinationChainContract(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_setdestinationchaincontract-lcg1) - Internal setter for the destination chain contract mapping.
* [setDestinationChainContract(...)](https://docs.cryptolegacy.app/documentation/functions-reference#setdestinationchaincontract-lcg1) - Public setter for the destination chain contract mapping.
* [\_setSourceChainContract(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_setsourcechaincontract-lcg1) - Internal setter for source chain contract mapping.
* [setSourceChainContract(...)](https://docs.cryptolegacy.app/documentation/functions-reference#setsourcechaincontract-lcg1) - Public setter for the source chain contract mapping.
* [setSourceAndDestinationChainContract(...)](https://docs.cryptolegacy.app/documentation/functions-reference#setsourceanddestinationchaincontract-lcg1) - Sets both source and destination contract addresses for a chain.
* [setLockPeriod(...)](https://docs.cryptolegacy.app/documentation/functions-reference#setlockperiod-lcg1) - Updates the NFT lock period and transfer timeout.
* [setReferralCode(...)](https://docs.cryptolegacy.app/documentation/functions-reference#setreferralcode-lcg1) - Sets deBridge referral code used in messages.
* [setCustomChainId(...)](https://docs.cryptolegacy.app/documentation/functions-reference#setcustomchainid-lcg1) - Overrides the auto-detected chainId with a custom value.
* [\_writeLockLifetimeNft(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_writelocklifetimenft-lcg1) - Records a newly locked NFT for a holder.
* [lockLifetimeNft(...)](https://docs.cryptolegacy.app/documentation/functions-reference#locklifetimenft-lcg1) - Locks a Lifetime NFT and optionally mirrors the lock on specified chains.
* [\_calcAndReturnFee(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_calcandreturnfee-lcg1) - Computes surplus ETH after fees and returns it to caller.
* [\_returnFee(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_returnfee-lcg1) - Sends ETH back to `msg.sender` if `_returnValue > 0`.
* [crossLockLifetimeNft(...)](https://docs.cryptolegacy.app/documentation/functions-reference#crosslocklifetimenft-lcg1) - Handles cross-chain lock message to record a lock from a source chain.
* [\_lockLifetimeNftToChains(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_locklifetimenfttochains-lcg1) - Locks a token to multiple chains by sending cross-chain messages.
* [\_checkFee(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_checkfee-lcg1) - Validates that `msg.value` matches the required fee within tolerance.
* [lockLifetimeNftToChains(...)](https://docs.cryptolegacy.app/documentation/functions-reference#locklifetimenfttochains-lcg1) - Mirrors the caller’s existing lock to additional chains.
* [\_lockLifetimeNftToChain(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_locklifetimenfttochain-lcg1) - Sends a cross-chain lock message to a single chain and records mirroring.
* [unlockLifetimeNft(...)](https://docs.cryptolegacy.app/documentation/functions-reference#unlocklifetimenft-lcg1) - Unlocks a locally locked NFT back to the caller if conditions are satisfied.
* [unlockLifetimeNftFromChain(...)](https://docs.cryptolegacy.app/documentation/functions-reference#unlocklifetimenftfromchain-lcg1) - Initiates cross-chain unlock to the source chain and clears local lock.
* [crossUnlockLifetimeNft(...)](https://docs.cryptolegacy.app/documentation/functions-reference#crossunlocklifetimenft-lcg1) - Handles cross-chain unlock completion from a source chain.
* [crossUpdateNftOwner(...)](https://docs.cryptolegacy.app/documentation/functions-reference#crossupdatenftowner-lcg1) - Updates owner mapping based on cross-chain transfer message.
* [\_deleteTokenData(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_deletetokendata-lcg1) - Clears all lock-related mappings for a token and holder.
* [\_onlyCrossChain(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_onlycrosschain-lcg1) - Ensures the function is called by deBridge CallProxy from the expected source chain and contract.
* [\_send(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_send-lcg1) - Sends a cross-chain message via deBridge with flags set.
* [approveLifetimeNftTo(...)](https://docs.cryptolegacy.app/documentation/functions-reference#approvelifetimenftto-lcg1) - Approves an address to unlock or transfer a locked NFT.
* [\_transferLifetimeNftTo(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_transferlifetimenftto-lcg1) - Internal mapping-only transfer of a locked NFT between holders.
* [transferLifetimeNftTo(...)](https://docs.cryptolegacy.app/documentation/functions-reference#transferlifetimenftto-lcg1) - Transfers a locked NFT to a new holder locally and updates remote chains.
* [updateNftOwnerOnChainList(...)](https://docs.cryptolegacy.app/documentation/functions-reference#updatenftowneronchainlist-lcg1) - Sends owner-update messages for the caller’s locked NFT to specified chains.
* [\_updateNftOwnerOnChainList(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_updatenftowneronchainlist-lcg1) - Internal routine to update NFT owner on a list of chains.
* [\_updateLifetimeNftOwnerOnChain(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_updatelifetimenftowneronchain-lcg1) - Sends owner-update for a single chain and records mirroring.
* [\_encodeCrossLockCommand(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_encodecrosslockcommand-lcg1) - Encodes the cross-chain lock command calldata.
* [\_encodeCrossUnlockCommand(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_encodecrossunlockcommand-lcg1) - Encodes the cross-chain unlock command calldata.
* [\_encodeCrossUpdateOwnerCommand(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_encodecrossupdateownercommand-lcg1) - Encodes the cross-chain update-owner command calldata.
* [\_checkDestinationLockedChain(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_checkdestinationlockedchain-lcg1) - Ensures destination chain contract is configured.
* [\_checkTokenLocked(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_checktokenlocked-lcg1) - Validates that a holder currently has a locked token and returns its id.
* [\_checkCrossChainLock(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_checkcrosschainlock-lcg1) - Ensures the token is not currently locked via cross-chain lock source id.
* [\_checkTooEarly(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_checktooearly-lcg1) - Enforces that the lock period has elapsed for a holder.
* [\_checkSource(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_checksource-lcg1) - Ensures source chain contract is configured.
* [\_checkHolderTokenLock(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_checkholdertokenlock-lcg1) - Verifies that `_holder` is recorded as the holder of `_tokenId`.
* [getLockedToChainsIdsOfAccount(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getlockedtochainsidsofaccount-lcg1) - Returns destination chain ids where the account’s token is mirrored.
* [\_getLockedToChainsIdsOfAccount(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_getlockedtochainsidsofaccount-lcg1) - Internal getter for mirrored chain IDs of `_holder`.
* [getLockedUntil(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getlockeduntil-lcg1) - Returns the timestamp when `_holder` can unlock.
* [\_getLockedUntil(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_getlockeduntil-lcg1) - Internal computation of unlock timestamp.
* [getLockedToChainsIds(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getlockedtochainsids-lcg1) - Returns mirrored chain ids for a given token id.
* [lockPeriod()](https://docs.cryptolegacy.app/documentation/functions-reference#lockperiod-lcg1) - Getter for current lock period.
* [transferTimeout()](https://docs.cryptolegacy.app/documentation/functions-reference#transfertimeout-lcg1) - Getter for transfer timeout.
* [referralCode()](https://docs.cryptolegacy.app/documentation/functions-reference#referralcode-lcg1) - Getter for deBridge referral code.
* [ownerOfTokenId(...)](https://docs.cryptolegacy.app/documentation/functions-reference#owneroftokenid-lcg1) - Returns owner address recorded for a locked token.
* [lockedNftFromChainId(...)](https://docs.cryptolegacy.app/documentation/functions-reference#lockednftfromchainid-lcg1) - Returns the source chain id that locked a token, if any.
* [lockedNftApprovedTo(...)](https://docs.cryptolegacy.app/documentation/functions-reference#lockednftapprovedto-lcg1) - Returns the address approved for a locked NFT.
* [lockedNft(...)](https://docs.cryptolegacy.app/documentation/functions-reference#lockednft-lcg1) - Returns the [`LockedNft`](https://docs.cryptolegacy.app/documentation/data-structures-reference#lockednft-ilcg1-s2) record for a holder.
* [getDeBridgeChainNativeFeeAndCheck(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getdebridgechainnativefeeandcheck-lcg1) - Returns required native fee for a chain and verifies `msg.value` matches policy.
* [\_getDeBridgeChainNativeFeeAndCheck(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_getdebridgechainnativefeeandcheck-lcg1) - Internal compute-and-check fee helper.
* [getDeBridgeChainNativeFee(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getdebridgechainnativefee-lcg1) - View function to compute native fee for a chain.
* [\_getDeBridgeChainNativeFee(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_getdebridgechainnativefee-lcg1) - Internal fee computation for a chain.
* [deBridgeGate()](https://docs.cryptolegacy.app/documentation/functions-reference#debridgegate-lcg1) - Returns the configured deBridgeGate address.
* [lifetimeNft()](https://docs.cryptolegacy.app/documentation/functions-reference#lifetimenft-lcg1) - Returns the associated LifetimeNft address.
* [deBridgeChainConfig(...)](https://docs.cryptolegacy.app/documentation/functions-reference#debridgechainconfig-lcg1) - Returns cross-chain configuration for a chain id.
* [getLockOperatorsList()](https://docs.cryptolegacy.app/documentation/functions-reference#getlockoperatorslist-lcg1) - Returns all lock operator addresses.
* [isLockOperator(...)](https://docs.cryptolegacy.app/documentation/functions-reference#islockoperator-lcg1) - Checks whether an address is a lock operator.
* [calculateCrossChainCreateRefNativeFee(...)](https://docs.cryptolegacy.app/documentation/functions-reference#calculatecrosschaincreaterefnativefee-lcg1) - Computes total native fee for cross-chain referral creation.
* [isNftLocked(...)](https://docs.cryptolegacy.app/documentation/functions-reference#isnftlocked-lcg1) - Returns whether a holder has a locked NFT.
* [\_isNftLocked(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_isnftlocked-lcg1) - Internal check if a holder has a locked token id.
* [isNftLockedAndUpdate(...)](https://docs.cryptolegacy.app/documentation/functions-reference#isnftlockedandupdate-lcg1) - Returns whether the holder has a locked NFT and refreshes lock time if expired.
* [getChainId()](https://docs.cryptolegacy.app/documentation/functions-reference#getchainid-lcg1) - Returns the effective chain id (custom or EVM).
* [\_getChainId(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_getchainid-lcg1) - Internal effective chain id getter.

### Events

* [SetLockPeriodConfig](https://docs.cryptolegacy.app/documentation/events-reference#setlockperiodconfig-ilcg1)
* [AddLockOperator](https://docs.cryptolegacy.app/documentation/events-reference#addlockoperator-ilcg1)
* [RemoveLockOperator](https://docs.cryptolegacy.app/documentation/events-reference#removelockoperator-ilcg1)
* [SetDeBridgeGate](https://docs.cryptolegacy.app/documentation/events-reference#setdebridgegate-ilcg1)
* [SetDeBridgeNativeFee](https://docs.cryptolegacy.app/documentation/events-reference#setdebridgenativefee-ilcg1)
* [SetDestinationChainContract](https://docs.cryptolegacy.app/documentation/events-reference#setdestinationchaincontract-ilcg1)
* [SetSourceChainContract](https://docs.cryptolegacy.app/documentation/events-reference#setsourcechaincontract-ilcg1)
* [SetReferralCode](https://docs.cryptolegacy.app/documentation/events-reference#setreferralcode-ilcg1)
* [SetCustomChainId](https://docs.cryptolegacy.app/documentation/events-reference#setcustomchainid-ilcg1)
* [LockNft](https://docs.cryptolegacy.app/documentation/events-reference#locknft-ilcg1)
* [CrossLockNft](https://docs.cryptolegacy.app/documentation/events-reference#crosslocknft-ilcg1)
* [LockToChain](https://docs.cryptolegacy.app/documentation/events-reference#locktochain-ilcg1)
* [UnlockNft](https://docs.cryptolegacy.app/documentation/events-reference#unlocknft-ilcg1)
* [UnlockFromChain](https://docs.cryptolegacy.app/documentation/events-reference#unlockfromchain-ilcg1)
* [CrossUnlockNft](https://docs.cryptolegacy.app/documentation/events-reference#crossunlocknft-ilcg1)
* [CrossUpdateNftOwner](https://docs.cryptolegacy.app/documentation/events-reference#crossupdatenftowner-ilcg1)
* [SendToChain](https://docs.cryptolegacy.app/documentation/events-reference#sendtochain-ilcg1)
* [ApproveNft](https://docs.cryptolegacy.app/documentation/events-reference#approvenft-ilcg1)
* [TransferNft](https://docs.cryptolegacy.app/documentation/events-reference#transfernft-ilcg1)
* [UpdateLockToChain](https://docs.cryptolegacy.app/documentation/events-reference#updatelocktochain-ilcg1)
* [Update](https://docs.cryptolegacy.app/documentation/events-reference#update-ilcg1)

### Errors

* [AlreadyLocked](https://docs.cryptolegacy.app/documentation/errors-reference#alreadylocked-ilcg1)
* [ArrayLengthMismatch](https://docs.cryptolegacy.app/documentation/errors-reference#arraylengthmismatch-ilcg1)
* [IncorrectFee](https://docs.cryptolegacy.app/documentation/errors-reference#incorrectfee-ilcg1)
* [AlreadyLockedToChain](https://docs.cryptolegacy.app/documentation/errors-reference#alreadylockedtochain-ilcg1)
* [NotAvailable](https://docs.cryptolegacy.app/documentation/errors-reference#notavailable-ilcg1)
* [LockedToChains](https://docs.cryptolegacy.app/documentation/errors-reference#lockedtochains-ilcg1)
* [NotLockedByChain](https://docs.cryptolegacy.app/documentation/errors-reference#notlockedbychain-ilcg1)
* [DestinationNotSpecified](https://docs.cryptolegacy.app/documentation/errors-reference#destinationnotspecified-ilcg1)
* [NotCallProxy](https://docs.cryptolegacy.app/documentation/errors-reference#notcallproxy-ilcg1)
* [ChainIdMismatch](https://docs.cryptolegacy.app/documentation/errors-reference#chainidmismatch-ilcg1)
* [NotValidSender](https://docs.cryptolegacy.app/documentation/errors-reference#notvalidsender-ilcg1)
* [SameAddress](https://docs.cryptolegacy.app/documentation/errors-reference#sameaddress-ilcg1)
* [RecipientLocked](https://docs.cryptolegacy.app/documentation/errors-reference#recipientlocked-ilcg1)
* [TransferFeeFailed](https://docs.cryptolegacy.app/documentation/errors-reference#transferfeefailed-ilcg1)
* [TransferLockTimeout](https://docs.cryptolegacy.app/documentation/errors-reference#transferlocktimeout-ilcg1)
* [TokenIdMismatch](https://docs.cryptolegacy.app/documentation/errors-reference#tokenidmismatch-ilcg1)
* [DestinationChainNotSpecified](https://docs.cryptolegacy.app/documentation/errors-reference#destinationchainnotspecified-ilcg1)
* [TokenNotLocked](https://docs.cryptolegacy.app/documentation/errors-reference#tokennotlocked-ilcg1)
* [CrossChainLock](https://docs.cryptolegacy.app/documentation/errors-reference#crosschainlock-ilcg1)
* [TooEarly](https://docs.cryptolegacy.app/documentation/errors-reference#tooearly-ilcg1)
* [SourceNotSpecified](https://docs.cryptolegacy.app/documentation/errors-reference#sourcenotspecified-ilcg1)
* [NotAllowed](https://docs.cryptolegacy.app/documentation/errors-reference#notallowed-ilcg1)

### Access / Roles

* `_initializeLockChainGate`: `initializer`
* `setLockOperator`: `onlyOwner`
* `setDebridgeGate`: `onlyOwner`
* `setDebridgeNativeFee`: `onlyOwner`
* `setDestinationChainContract`: `onlyOwner`
* `setSourceChainContract`: `onlyOwner`
* `setSourceAndDestinationChainContract`: `onlyOwner`
* `setLockPeriod`: `onlyOwner`
* `setReferralCode`: `onlyOwner`
* `setCustomChainId`: `onlyOwner`
* `lockLifetimeNft`: `nonReentrant`
* `crossLockLifetimeNft`: `nonReentrant`
* `lockLifetimeNftToChains`: `nonReentrant`
* `unlockLifetimeNft`: `nonReentrant`
* `unlockLifetimeNftFromChain`: `nonReentrant`
* `crossUnlockLifetimeNft`: `nonReentrant`
* `crossUpdateNftOwner`: `nonReentrant`
* `approveLifetimeNftTo`: `nonReentrant`
* `transferLifetimeNftTo`: `nonReentrant`
* `updateNftOwnerOnChainList`: `nonReentrant`

### Interacts With

* `Flags`
* `ICallProxy`
* `IDeBridgeGate`
* `ILifetimeNft`

### Missing Links

None.

## MultiPermit

### Purpose

MultiPermit batches token permit and approval calls to reduce transaction overhead for treasury flows.

### Inheritance

None.

### Key Methods

* [approveTreasuryTokensToLegacy(...)](https://docs.cryptolegacy.app/documentation/functions-reference#approvetreasurytokenstolegacy-mp1) - Executes multiple ERC‑2612 `permit` approvals in a single transaction.

### All Functions

* [constructor()](https://docs.cryptolegacy.app/documentation/functions-reference#constructor-mp1) - Deploys the MultiPermit helper contract.
* [approveTreasuryTokensToLegacy(...)](https://docs.cryptolegacy.app/documentation/functions-reference#approvetreasurytokenstolegacy-mp1) - Executes multiple ERC‑2612 `permit` approvals in a single transaction.

### Events

None.

### Errors

None.

### Access / Roles

None.

### Interacts With

None.

### Missing Links

None.

## PluginsRegistry

### Purpose

PluginsRegistry tracks approved plugins and versioned plugin metadata used by protocol composition logic.

### Inheritance

* `IPluginsRegistry`
* `Ownable`

### Key Methods

* [addPlugin(...)](https://docs.cryptolegacy.app/documentation/functions-reference#addplugin-pr1) - Registers a plugin and records a description block number, then emits `AddPlugin`.
* [addPluginDescription(...)](https://docs.cryptolegacy.app/documentation/functions-reference#addplugindescription-pr1) - Appends a new description block number for an existing plugin and emits `AddPluginDescription`.
* [removePlugin(...)](https://docs.cryptolegacy.app/documentation/functions-reference#removeplugin-pr1) - Unregisters a plugin and emits `RemovePlugin`.
* [isPluginRegistered(...)](https://docs.cryptolegacy.app/documentation/functions-reference#ispluginregistered-pr1) - Returns whether `_plugin` is currently registered.
* [getPluginMetadata(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getpluginmetadata-pr1) - Reads a plugin’s `name`, `version`, and its description block numbers.
* [getPluginDescriptionBlockNumbers(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getplugindescriptionblocknumbers-pr1) - Returns the full array of description block numbers for `_plugin`.
* [getPluginAddressList(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getpluginaddresslist-pr1) - Returns an array of all registered plugin addresses.
* [getPluginInfoList(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getplugininfolist-pr1) - Aggregates metadata for all registered plugins into an array of [`PluginInfo`](https://docs.cryptolegacy.app/documentation/data-structures-reference#plugininfo-ipr1-s1).

### All Functions

* [constructor(...)](https://docs.cryptolegacy.app/documentation/functions-reference#constructor-pr1) - Initializes ownership and sets the provided `_owner` as the contract owner.
* [addPlugin(...)](https://docs.cryptolegacy.app/documentation/functions-reference#addplugin-pr1) - Registers a plugin and records a description block number, then emits `AddPlugin`.
* [addPluginDescription(...)](https://docs.cryptolegacy.app/documentation/functions-reference#addplugindescription-pr1) - Appends a new description block number for an existing plugin and emits `AddPluginDescription`.
* [removePlugin(...)](https://docs.cryptolegacy.app/documentation/functions-reference#removeplugin-pr1) - Unregisters a plugin and emits `RemovePlugin`.
* [isPluginRegistered(...)](https://docs.cryptolegacy.app/documentation/functions-reference#ispluginregistered-pr1) - Returns whether `_plugin` is currently registered.
* [getPluginMetadata(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getpluginmetadata-pr1) - Reads a plugin’s `name`, `version`, and its description block numbers.
* [getPluginDescriptionBlockNumbers(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getplugindescriptionblocknumbers-pr1) - Returns the full array of description block numbers for `_plugin`.
* [getPluginAddressList()](https://docs.cryptolegacy.app/documentation/functions-reference#getpluginaddresslist-pr1) - Returns an array of all registered plugin addresses.
* [getPluginInfoList()](https://docs.cryptolegacy.app/documentation/functions-reference#getplugininfolist-pr1) - Aggregates metadata for all registered plugins into an array of [`PluginInfo`](https://docs.cryptolegacy.app/documentation/data-structures-reference#plugininfo-ipr1-s1).

### Events

* [AddPlugin](https://docs.cryptolegacy.app/documentation/events-reference#addplugin-ipr1)
* [AddPluginDescription](https://docs.cryptolegacy.app/documentation/events-reference#addplugindescription-ipr1)
* [RemovePlugin](https://docs.cryptolegacy.app/documentation/events-reference#removeplugin-ipr1)

### Errors

None.

### Access / Roles

* `addPlugin`: `onlyOwner`
* `addPluginDescription`: `onlyOwner`
* `removePlugin`: `onlyOwner`

### Interacts With

* `ArbSys`
* `ICryptoLegacyPlugin`

### Missing Links

None.

## ProxyBuilder

### Purpose

ProxyBuilder deploys proxy instances and binds them to the configured proxy-admin authority.

### Inheritance

* `Ownable`

### Key Methods

* [setProxyAdmin(...)](https://docs.cryptolegacy.app/documentation/functions-reference#setproxyadmin-pb1) - Updates the ProxyAdmin controller address.
* [build(...)](https://docs.cryptolegacy.app/documentation/functions-reference#build-pb1) - Deploys a `TransparentUpgradeableProxy` deterministically via CREATE3.
* [proxyBytecode(...)](https://docs.cryptolegacy.app/documentation/functions-reference#proxybytecode-pb1) - Produces creation bytecode for `TransparentUpgradeableProxy`.
* [computeAddress(...)](https://docs.cryptolegacy.app/documentation/functions-reference#computeaddress-pb1) - Computes the deterministic CREATE3 address for a given salt.

### All Functions

* [constructor(...)](https://docs.cryptolegacy.app/documentation/functions-reference#constructor-pb1) - Initializes the builder with an optional ProxyAdmin and sets the owner.
* [setProxyAdmin(...)](https://docs.cryptolegacy.app/documentation/functions-reference#setproxyadmin-pb1) - Updates the ProxyAdmin controller address.
* [build(...)](https://docs.cryptolegacy.app/documentation/functions-reference#build-pb1) - Deploys a `TransparentUpgradeableProxy` deterministically via CREATE3.
* [proxyBytecode(...)](https://docs.cryptolegacy.app/documentation/functions-reference#proxybytecode-pb1) - Produces creation bytecode for `TransparentUpgradeableProxy`.
* [computeAddress(...)](https://docs.cryptolegacy.app/documentation/functions-reference#computeaddress-pb1) - Computes the deterministic CREATE3 address for a given salt.

### Events

* [Build](https://docs.cryptolegacy.app/documentation/events-reference#build-pb1)
* [SetProxyAdmin](https://docs.cryptolegacy.app/documentation/events-reference#setproxyadmin-pb1)

### Errors

* [AdminAlreadyCreated](https://docs.cryptolegacy.app/documentation/errors-reference#adminalreadycreated-pb1)
* [AddressMismatch](https://docs.cryptolegacy.app/documentation/errors-reference#addressmismatch-pb1)

### Access / Roles

* `setProxyAdmin`: `onlyOwner`
* `build`: `onlyOwner`

### Interacts With

* `LibCreate3`

### Missing Links

None.

## ProxyBuilderAdmin

### Purpose

ProxyBuilderAdmin centralizes administrative controls for deployed beneficiary proxies in the protocol deployment stack.

### Inheritance

* `ProxyAdmin`

### Key Methods

None.

### All Functions

* [constructor(...)](https://docs.cryptolegacy.app/documentation/functions-reference#constructor-pba1) - Initializes the ProxyBuilderAdmin and sets the initial owner.

### Events

None.

### Errors

None.

### Access / Roles

None.

### Interacts With

None.

### Missing Links

None.

## SignatureRoleTimelock

### Purpose

SignatureRoleTimelock enforces role-based timelocks and scheduled execution for restricted function calls.

### Inheritance

* `ISignatureRoleTimelock`
* `AccessControl`
* `ReentrancyGuard`

### Key Methods

* [setMaxExecutionPeriod(...)](https://docs.cryptolegacy.app/documentation/functions-reference#setmaxexecutionperiod-srt1) - Updates the maximum allowed execution window after timelock expiry.
* [setRoleAccounts(...)](https://docs.cryptolegacy.app/documentation/functions-reference#setroleaccounts-srt1) - Batch adds, removes, or replaces role accounts.
* [renounceRole(...)](https://docs.cryptolegacy.app/documentation/functions-reference#renouncerole-srt1) - Disabled AccessControl function; always reverts.
* [addSignatureRoleList(...)](https://docs.cryptolegacy.app/documentation/functions-reference#addsignaturerolelist-srt1) - Batch-assigns signature roles to target functions.
* [removeSignatureRoleList(...)](https://docs.cryptolegacy.app/documentation/functions-reference#removesignaturerolelist-srt1) - Batch-removes signature role bindings.
* [scheduleCallList(...)](https://docs.cryptolegacy.app/documentation/functions-reference#schedulecalllist-srt1) - Schedules a batch of authorized calls with per-signature timelocks.
* [executeCallList(...)](https://docs.cryptolegacy.app/documentation/functions-reference#executecalllist-srt1) - Executes a batch of scheduled calls after their timelocks expire.
* [cancelCallList(...)](https://docs.cryptolegacy.app/documentation/functions-reference#cancelcalllist-srt1) - Cancels pending scheduled calls (admin-only).

### All Functions

* [constructor(...)](https://docs.cryptolegacy.app/documentation/functions-reference#constructor-srt1) - Initializes admin role, seeds role accounts, and installs initial signature roles with timelocks.
* [setMaxExecutionPeriod(...)](https://docs.cryptolegacy.app/documentation/functions-reference#setmaxexecutionperiod-srt1) - Updates the maximum allowed execution window after timelock expiry.
* [setRoleAccounts(...)](https://docs.cryptolegacy.app/documentation/functions-reference#setroleaccounts-srt1) - Batch adds, removes, or replaces role accounts.
* [\_addRoleAccount(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_addroleaccount-srt1) - Adds an account to a role and grants it in AccessControl.
* [\_getAddressIndex(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_getaddressindex-srt1) - Finds index of address in array or returns `type(uint256).max`.
* [\_getBytes4Index(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_getbytes4index-srt1) - Finds index of bytes4 selector in array or returns `type(uint256).max`.
* [\_removeRoleAccount(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_removeroleaccount-srt1) - Removes an account from a role and revokes it in AccessControl.
* [renounceRole(...)](https://docs.cryptolegacy.app/documentation/functions-reference#renouncerole-srt1) - Disabled AccessControl function; always reverts.
* [addSignatureRoleList(...)](https://docs.cryptolegacy.app/documentation/functions-reference#addsignaturerolelist-srt1) - Batch-assigns signature roles to target functions.
* [\_addSignatureRole(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_addsignaturerole-srt1) - Adds a single `(target, selector)` signature role binding.
* [removeSignatureRoleList(...)](https://docs.cryptolegacy.app/documentation/functions-reference#removesignaturerolelist-srt1) - Batch-removes signature role bindings.
* [\_removeSignatureRole(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_removesignaturerole-srt1) - Removes a single `(target, selector)` signature role binding.
* [scheduleCallList(...)](https://docs.cryptolegacy.app/documentation/functions-reference#schedulecalllist-srt1) - Schedules a batch of authorized calls with per-signature timelocks.
* [\_checkRole(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_checkrole-srt1) - AccessControl hook override to enforce role checks with custom error.
* [\_scheduleCall(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_schedulecall-srt1) - Schedules a single authorized call with timelock and execution window.
* [executeCallList(...)](https://docs.cryptolegacy.app/documentation/functions-reference#executecalllist-srt1) - Executes a batch of scheduled calls after their timelocks expire.
* [\_executeCall(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_executecall-srt1) - Executes an individual scheduled call when permitted by time window.
* [cancelCallList(...)](https://docs.cryptolegacy.app/documentation/functions-reference#cancelcalllist-srt1) - Cancels pending scheduled calls (admin-only).
* [\_cancelCall(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_cancelcall-srt1) - Cancels a single scheduled call if still pending.
* [getRoleAccounts(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getroleaccounts-srt1) - Returns accounts that hold a given role.
* [getTargets()](https://docs.cryptolegacy.app/documentation/functions-reference#gettargets-srt1) - Lists all targets that have signature role bindings.
* [getTargetSigs(...)](https://docs.cryptolegacy.app/documentation/functions-reference#gettargetsigs-srt1) - Returns signature role details for a given target.
* [getCallId(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getcallid-srt1) - Computes a deterministic call ID for a pending call.
* [getCall(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getcall-srt1) - Returns details of a scheduled call.
* [getCallsList(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getcallslist-srt1) - Paginates scheduled call IDs and their details.
* [getCallIds()](https://docs.cryptolegacy.app/documentation/functions-reference#getcallids-srt1) - Returns all scheduled call IDs.
* [getCallsLength()](https://docs.cryptolegacy.app/documentation/functions-reference#getcallslength-srt1) - Returns the number of scheduled calls.

### Events

* [SetMaxExecutionPeriod](https://docs.cryptolegacy.app/documentation/events-reference#setmaxexecutionperiod-isrt1)
* [AddRoleAccount](https://docs.cryptolegacy.app/documentation/events-reference#addroleaccount-isrt1)
* [RemoveRoleAccount](https://docs.cryptolegacy.app/documentation/events-reference#removeroleaccount-isrt1)
* [AddTarget](https://docs.cryptolegacy.app/documentation/events-reference#addtarget-isrt1)
* [AddSignatureRole](https://docs.cryptolegacy.app/documentation/events-reference#addsignaturerole-isrt1)
* [RemoveTarget](https://docs.cryptolegacy.app/documentation/events-reference#removetarget-isrt1)
* [RemoveSignatureRole](https://docs.cryptolegacy.app/documentation/events-reference#removesignaturerole-isrt1)
* [CallScheduled](https://docs.cryptolegacy.app/documentation/events-reference#callscheduled-isrt1)
* [CallExecuted](https://docs.cryptolegacy.app/documentation/events-reference#callexecuted-isrt1)
* [CallCanceled](https://docs.cryptolegacy.app/documentation/events-reference#callcanceled-isrt1)

### Errors

* [CallerNotCurrentAddress](https://docs.cryptolegacy.app/documentation/errors-reference#callernotcurrentaddress-isrt1)
* [OutOfMaxExecutionPeriodBounds](https://docs.cryptolegacy.app/documentation/errors-reference#outofmaxexecutionperiodbounds-isrt1)
* [AlreadyHaveRole](https://docs.cryptolegacy.app/documentation/errors-reference#alreadyhaverole-isrt1)
* [DoesntHaveRole](https://docs.cryptolegacy.app/documentation/errors-reference#doesnthaverole-isrt1)
* [IncorrectRoleIndex](https://docs.cryptolegacy.app/documentation/errors-reference#incorrectroleindex-isrt1)
* [DisabledFunction](https://docs.cryptolegacy.app/documentation/errors-reference#disabledfunction-isrt1)
* [RoleDontExist](https://docs.cryptolegacy.app/documentation/errors-reference#roledontexist-isrt1)
* [SignatureAlreadyExists](https://docs.cryptolegacy.app/documentation/errors-reference#signaturealreadyexists-isrt1)
* [OutOfTimelockBounds](https://docs.cryptolegacy.app/documentation/errors-reference#outoftimelockbounds-isrt1)
* [IncorrectSignatureIndex](https://docs.cryptolegacy.app/documentation/errors-reference#incorrectsignatureindex-isrt1)
* [CallerHaveNoRequiredRole](https://docs.cryptolegacy.app/documentation/errors-reference#callerhavenorequiredrole-isrt1)
* [SignatureTimeLockNotSet](https://docs.cryptolegacy.app/documentation/errors-reference#signaturetimelocknotset-isrt1)
* [CallAlreadyScheduled](https://docs.cryptolegacy.app/documentation/errors-reference#callalreadyscheduled-isrt1)
* [CallNotScheduled](https://docs.cryptolegacy.app/documentation/errors-reference#callnotscheduled-isrt1)
* [NotPending](https://docs.cryptolegacy.app/documentation/errors-reference#notpending-isrt1)
* [TimelockActive](https://docs.cryptolegacy.app/documentation/errors-reference#timelockactive-isrt1)
* [TimelockExpired](https://docs.cryptolegacy.app/documentation/errors-reference#timelockexpired-isrt1)
* [CallFailed](https://docs.cryptolegacy.app/documentation/errors-reference#callfailed-isrt1)

### Access / Roles

* `setMaxExecutionPeriod`: `onlyCurrentAddress`
* `setRoleAccounts`: `onlyCurrentAddress`
* `addSignatureRoleList`: `onlyCurrentAddress`
* `removeSignatureRoleList`: `onlyCurrentAddress`
* `scheduleCallList`: `nonReentrant`
* `executeCallList`: `nonReentrant`
* `cancelCallList`: `nonReentrant, onlyRole`

### Interacts With

None.

### Missing Links

None.

## WethUnwrapIWETH (Interface)

### Purpose

WethUnwrapIWETH defines the minimal WETH transfer and withdrawal calls required by the `WethUnwrap` helper contract.

### Inheritance

None.

### Key Methods

* [transferFrom(...)](https://docs.cryptolegacy.app/documentation/functions-reference#transferfrom-wui1) - Transfers WETH from one address to another.
* [withdraw(...)](https://docs.cryptolegacy.app/documentation/functions-reference#withdraw-wui1) - Burns WETH and releases the same amount of native ETH.

### All Functions

* [transferFrom(...)](https://docs.cryptolegacy.app/documentation/functions-reference#transferfrom-wui1) - Transfers WETH from one address to another.
* [withdraw(...)](https://docs.cryptolegacy.app/documentation/functions-reference#withdraw-wui1) - Burns WETH and releases the same amount of native ETH.

### Events

None.

### Errors

None.

### Access / Roles

None.

### Interacts With

None.

### Missing Links

None.

## WethUnwrap

### Purpose

WethUnwrap is a helper contract that pulls WETH from the caller, unwraps it into native ETH, and forwards the ETH back to the caller through a callback payload. It exists to support plugin flows that need native ETH for downstream protocol actions while keeping the unwrap logic isolated.

### Inheritance

None.

### Key Methods

* [unwrap\_weth(...)](https://docs.cryptolegacy.app/documentation/functions-reference#unwrap_weth-wu1) - Pulls WETH from the caller, unwraps it to ETH, and immediately forwards the ETH back with callback calldata.

### All Functions

* [constructor(...)](https://docs.cryptolegacy.app/documentation/functions-reference#constructor-wu1) - Stores the canonical WETH contract address used for unwrap operations.
* [unwrap\_weth(...)](https://docs.cryptolegacy.app/documentation/functions-reference#unwrap_weth-wu1) - Pulls WETH from the caller, unwraps it to ETH, and immediately forwards the ETH back with callback calldata.
* [receive(...)](https://docs.cryptolegacy.app/documentation/functions-reference#receive-wu1) - Accepts native ETH released by the WETH contract during an unwrap.

### Events

None.

### Errors

* [CallbackCallFailed](https://docs.cryptolegacy.app/documentation/errors-reference#callbackcallfailed-wu1)

### Access / Roles

None.

### Interacts With

* `WethUnwrapIWETH`

### Missing Links

None.

## ArbSys (Interface)

### Purpose

ArbSys defines the Arbitrum system interface used for chain-specific context queries.

### Inheritance

None.

### Key Methods

* [arbBlockNumber(...)](https://docs.cryptolegacy.app/documentation/functions-reference#arbblocknumber-as1) - Returns the current Arbitrum L2 block number.

### All Functions

* [arbBlockNumber()](https://docs.cryptolegacy.app/documentation/functions-reference#arbblocknumber-as1) - Returns the current Arbitrum L2 block number.

### Events

None.

### Errors

None.

### Access / Roles

None.

### Interacts With

None.

### Missing Links

None.

## Flags (Library)

### Purpose

Flags centralizes bit-flag read/write helpers used by storage-efficient modules.

### Inheritance

None.

### Key Methods

* [getFlag(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getflag-flg1) - Tests whether a specific bit is enabled inside a packed flags word.
* [setFlag(...)](https://docs.cryptolegacy.app/documentation/functions-reference#setflag-flg1) - Returns a new flags word with a specific bit set or cleared.

### All Functions

* [getFlag(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getflag-flg1) - Tests whether a specific bit is enabled inside a packed flags word.
* [setFlag(...)](https://docs.cryptolegacy.app/documentation/functions-reference#setflag-flg1) - Returns a new flags word with a specific bit set or cleared.

### Events

None.

### Errors

None.

### Access / Roles

None.

### Interacts With

None.

### Missing Links

None.

## IAaveV3Pool (Interface)

### Purpose

IAaveV3Pool defines the subset of Aave V3 pool calls used by the beneficiary-supply plugin for supply, withdrawal, and reserve-data access.

### Inheritance

None.

### Key Methods

* [supply(...)](https://docs.cryptolegacy.app/documentation/functions-reference#supply-iav3p1) - Supplies an asset into the Aave V3 pool on behalf of a target account.
* [withdraw(...)](https://docs.cryptolegacy.app/documentation/functions-reference#withdraw-iav3p1) - Withdraws a reserve asset from Aave V3 to a recipient address.

### All Functions

* [supply(...)](https://docs.cryptolegacy.app/documentation/functions-reference#supply-iav3p1) - Supplies an asset into the Aave V3 pool on behalf of a target account.
* [withdraw(...)](https://docs.cryptolegacy.app/documentation/functions-reference#withdraw-iav3p1) - Withdraws a reserve asset from Aave V3 to a recipient address.

### Events

None.

### Errors

None.

### Access / Roles

None.

### Interacts With

None.

### Missing Links

None.

## IAaveV3PoolDataProvider (Interface)

### Purpose

IAaveV3PoolDataProvider exposes reserve-token metadata used by the Aave beneficiary-supply plugin to discover the aToken corresponding to an underlying asset.

### Inheritance

None.

### Key Methods

* [getReserveTokensAddresses(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getreservetokensaddresses-iav3pdp1) - Returns the token-contract addresses associated with an Aave reserve.

### All Functions

* [getReserveTokensAddresses(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getreservetokensaddresses-iav3pdp1) - Returns the token-contract addresses associated with an Aave reserve.

### Events

None.

### Errors

None.

### Access / Roles

None.

### Interacts With

None.

### Missing Links

None.

## IBeneficiaryRegistry (Interface)

### Purpose

IBeneficiaryRegistry specifies the external registry API for beneficiary/owner/guardian/recovery indexing.

### Inheritance

None.

### Key Methods

* [setCryptoLegacyBeneficiary(...)](https://docs.cryptolegacy.app/documentation/functions-reference#setcryptolegacybeneficiary-ibr1) - Registers or removes a CryptoLegacy contract for a beneficiary hash.
* [setCryptoLegacyOwner(...)](https://docs.cryptolegacy.app/documentation/functions-reference#setcryptolegacyowner-ibr1) - Registers or removes a CryptoLegacy contract for an owner hash.
* [setCryptoLegacyGuardian(...)](https://docs.cryptolegacy.app/documentation/functions-reference#setcryptolegacyguardian-ibr1) - Toggles guardian-role membership for a CryptoLegacy contract.
* [setCryptoLegacyRecoveryAddresses(...)](https://docs.cryptolegacy.app/documentation/functions-reference#setcryptolegacyrecoveryaddresses-ibr1) - Batch updates recovery-role mappings for a CryptoLegacy contract.
* [getAllCryptoLegacyListByRoles(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getallcryptolegacylistbyroles-ibr1) - Returns all CryptoLegacy addresses associated with a hash across roles.

### All Functions

* [setCryptoLegacyBeneficiary(...)](https://docs.cryptolegacy.app/documentation/functions-reference#setcryptolegacybeneficiary-ibr1) - Registers or removes a CryptoLegacy contract for a beneficiary hash.
* [setCryptoLegacyOwner(...)](https://docs.cryptolegacy.app/documentation/functions-reference#setcryptolegacyowner-ibr1) - Registers or removes a CryptoLegacy contract for an owner hash.
* [setCryptoLegacyGuardian(...)](https://docs.cryptolegacy.app/documentation/functions-reference#setcryptolegacyguardian-ibr1) - Toggles guardian-role membership for a CryptoLegacy contract.
* [setCryptoLegacyRecoveryAddresses(...)](https://docs.cryptolegacy.app/documentation/functions-reference#setcryptolegacyrecoveryaddresses-ibr1) - Batch updates recovery-role mappings for a CryptoLegacy contract.
* [getAllCryptoLegacyListByRoles(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getallcryptolegacylistbyroles-ibr1) - Returns all CryptoLegacy addresses associated with a hash across roles.

### Events

* [AddCryptoLegacyForBeneficiary](https://docs.cryptolegacy.app/documentation/events-reference#addcryptolegacyforbeneficiary-ibr1)
* [RemoveCryptoLegacyForBeneficiary](https://docs.cryptolegacy.app/documentation/events-reference#removecryptolegacyforbeneficiary-ibr1)
* [AddCryptoLegacyForGuardian](https://docs.cryptolegacy.app/documentation/events-reference#addcryptolegacyforguardian-ibr1)
* [RemoveCryptoLegacyForGuardian](https://docs.cryptolegacy.app/documentation/events-reference#removecryptolegacyforguardian-ibr1)
* [AddCryptoLegacyForRecovery](https://docs.cryptolegacy.app/documentation/events-reference#addcryptolegacyforrecovery-ibr1)
* [RemoveCryptoLegacyForRecovery](https://docs.cryptolegacy.app/documentation/events-reference#removecryptolegacyforrecovery-ibr1)
* [AddCryptoLegacyForOwner](https://docs.cryptolegacy.app/documentation/events-reference#addcryptolegacyforowner-ibr1)
* [RemoveCryptoLegacyForOwner](https://docs.cryptolegacy.app/documentation/events-reference#removecryptolegacyforowner-ibr1)

### Errors

None.

### Access / Roles

None.

### Interacts With

None.

### Missing Links

None.

## IBuildManagerOwnable (Interface)

### Purpose

IBuildManagerOwnable defines owner-controlled build-manager allowlist operations.

### Inheritance

None.

### Key Methods

None.

### All Functions

None.

### Events

* [AddBuildManager](https://docs.cryptolegacy.app/documentation/events-reference#addbuildmanager-ibmo1)
* [RemoveBuildManager](https://docs.cryptolegacy.app/documentation/events-reference#removebuildmanager-ibmo1)

### Errors

* [NotTheOwnerOfCryptoLegacy](https://docs.cryptolegacy.app/documentation/errors-reference#nottheownerofcryptolegacy-ibmo1)
* [CryptoLegacyNotRegistered](https://docs.cryptolegacy.app/documentation/errors-reference#cryptolegacynotregistered-ibmo1)
* [BuildManagerNotAdded](https://docs.cryptolegacy.app/documentation/errors-reference#buildmanagernotadded-ibmo1)

### Access / Roles

None.

### Interacts With

None.

### Missing Links

None.

## ICallProxy (Interface)

### Purpose

ICallProxy defines the cross-chain call relay interface and sender-submission metadata accessors.

### Inheritance

None.

### Key Methods

* [submissionChainIdFrom(...)](https://docs.cryptolegacy.app/documentation/functions-reference#submissionchainidfrom-icp1) - Returns the source chain ID for the current cross-chain submission.
* [submissionNativeSender(...)](https://docs.cryptolegacy.app/documentation/functions-reference#submissionnativesender-icp1) - Returns the original sender (encoded as bytes) of the cross-chain submission.
* [call(...)](https://docs.cryptolegacy.app/documentation/functions-reference#call-icp1) - Executes a cross-chain call with optional native asset transfer.
* [callERC20(...)](https://docs.cryptolegacy.app/documentation/functions-reference#callerc20-icp1) - Executes a cross-chain call that also transfers ERC20 tokens.

### All Functions

* [submissionChainIdFrom()](https://docs.cryptolegacy.app/documentation/functions-reference#submissionchainidfrom-icp1) - Returns the source chain ID for the current cross-chain submission.
* [submissionNativeSender()](https://docs.cryptolegacy.app/documentation/functions-reference#submissionnativesender-icp1) - Returns the original sender (encoded as bytes) of the cross-chain submission.
* [call(...)](https://docs.cryptolegacy.app/documentation/functions-reference#call-icp1) - Executes a cross-chain call with optional native asset transfer.
* [callERC20(...)](https://docs.cryptolegacy.app/documentation/functions-reference#callerc20-icp1) - Executes a cross-chain call that also transfers ERC20 tokens.

### Events

None.

### Errors

None.

### Access / Roles

None.

### Interacts With

None.

### Missing Links

None.

## ICryptoLegacy (Interface)

### Purpose

ICryptoLegacy defines the primary protocol storage and operational interface consumed by plugins and managers.

### Inheritance

None.

### Key Methods

* [buildManager(...)](https://docs.cryptolegacy.app/documentation/functions-reference#buildmanager-icl1) - Returns the build manager contract associated with the CryptoLegacy instance.
* [owner(...)](https://docs.cryptolegacy.app/documentation/functions-reference#owner-icl1) - Returns the current diamond owner address.

### All Functions

* [buildManager()](https://docs.cryptolegacy.app/documentation/functions-reference#buildmanager-icl1) - Returns the build manager contract associated with the CryptoLegacy instance.
* [owner()](https://docs.cryptolegacy.app/documentation/functions-reference#owner-icl1) - Returns the current diamond owner address.

### Events

* [PauseSet](https://docs.cryptolegacy.app/documentation/events-reference#pauseset-icl1)
* [Update](https://docs.cryptolegacy.app/documentation/events-reference#update-icl1)
* [FeePaidByLifetime](https://docs.cryptolegacy.app/documentation/events-reference#feepaidbylifetime-icl1)
* [FeePaidByDefault](https://docs.cryptolegacy.app/documentation/events-reference#feepaidbydefault-icl1)
* [FeePaidByTransfer](https://docs.cryptolegacy.app/documentation/events-reference#feepaidbytransfer-icl1)
* [FeeSentToRefByTransfer](https://docs.cryptolegacy.app/documentation/events-reference#feesenttorefbytransfer-icl1)
* [BeneficiaryClaim](https://docs.cryptolegacy.app/documentation/events-reference#beneficiaryclaim-icl1)
* [BeneficiaryClaimAmountDecrease](https://docs.cryptolegacy.app/documentation/events-reference#beneficiaryclaimamountdecrease-icl1)
* [TransferTreasuryTokensToLegacy](https://docs.cryptolegacy.app/documentation/events-reference#transfertreasurytokenstolegacy-icl1)
* [TransferTokensFromLegacy](https://docs.cryptolegacy.app/documentation/events-reference#transfertokensfromlegacy-icl1)
* [SetGasLimitMultiplier](https://docs.cryptolegacy.app/documentation/events-reference#setgaslimitmultiplier-icl1)
* [AddFunctions](https://docs.cryptolegacy.app/documentation/events-reference#addfunctions-icl1)
* [RemoveFunctions](https://docs.cryptolegacy.app/documentation/events-reference#removefunctions-icl1)
* [SkipSendFeeByTransfer](https://docs.cryptolegacy.app/documentation/events-reference#skipsendfeebytransfer-icl1)
* [IsLifetimeNftLockedAndUpdateCatch](https://docs.cryptolegacy.app/documentation/events-reference#islifetimenftlockedandupdatecatch-icl1)
* [GetUpdateFeeCatch](https://docs.cryptolegacy.app/documentation/events-reference#getupdatefeecatch-icl1)
* [PayFeeCatch](https://docs.cryptolegacy.app/documentation/events-reference#payfeecatch-icl1)
* [SetCryptoLegacyOwnerCatch](https://docs.cryptolegacy.app/documentation/events-reference#setcryptolegacyownercatch-icl1)
* [SetCryptoLegacyBeneficiaryCatch](https://docs.cryptolegacy.app/documentation/events-reference#setcryptolegacybeneficiarycatch-icl1)
* [SetCryptoLegacyGuardianCatch](https://docs.cryptolegacy.app/documentation/events-reference#setcryptolegacyguardiancatch-icl1)
* [SetCryptoLegacyRecoveryAddressesCatch](https://docs.cryptolegacy.app/documentation/events-reference#setcryptolegacyrecoveryaddressescatch-icl1)
* [BeneficiaryRegistryCatch](https://docs.cryptolegacy.app/documentation/events-reference#beneficiaryregistrycatch-icl1)
* [BeneficiaryRegistryNotDefined](https://docs.cryptolegacy.app/documentation/events-reference#beneficiaryregistrynotdefined-icl1)

### Errors

* [BeneficiarySwitchTimelock](https://docs.cryptolegacy.app/documentation/errors-reference#beneficiaryswitchtimelock-icl1)
* [ArrayLengthMismatch](https://docs.cryptolegacy.app/documentation/errors-reference#arraylengthmismatch-icl1)
* [DisabledFunc](https://docs.cryptolegacy.app/documentation/errors-reference#disabledfunc-icl1)
* [NotTheOwner](https://docs.cryptolegacy.app/documentation/errors-reference#nottheowner-icl1)
* [NotTheBeneficiary](https://docs.cryptolegacy.app/documentation/errors-reference#notthebeneficiary-icl1)
* [BeneficiaryNotExist](https://docs.cryptolegacy.app/documentation/errors-reference#beneficiarynotexist-icl1)
* [TooEarly](https://docs.cryptolegacy.app/documentation/errors-reference#tooearly-icl1)
* [IncorrectRefShare](https://docs.cryptolegacy.app/documentation/errors-reference#incorrectrefshare-icl1)
* [NoValueAllowed](https://docs.cryptolegacy.app/documentation/errors-reference#novalueallowed-icl1)
* [TooLongArray](https://docs.cryptolegacy.app/documentation/errors-reference#toolongarray-icl1)
* [IncorrectFee](https://docs.cryptolegacy.app/documentation/errors-reference#incorrectfee-icl1)
* [ZeroAddress](https://docs.cryptolegacy.app/documentation/errors-reference#zeroaddress-icl1)
* [ZeroTokens](https://docs.cryptolegacy.app/documentation/errors-reference#zerotokens-icl1)
* [InitialFeeNotPaid](https://docs.cryptolegacy.app/documentation/errors-reference#initialfeenotpaid-icl1)
* [InitialFeeAlreadyPaid](https://docs.cryptolegacy.app/documentation/errors-reference#initialfeealreadypaid-icl1)
* [NotBuildManager](https://docs.cryptolegacy.app/documentation/errors-reference#notbuildmanager-icl1)
* [LengthMismatch](https://docs.cryptolegacy.app/documentation/errors-reference#lengthmismatch-icl1)
* [ShareSumDoesntMatchBase](https://docs.cryptolegacy.app/documentation/errors-reference#sharesumdoesntmatchbase-icl1)
* [OriginalHashDuplicate](https://docs.cryptolegacy.app/documentation/errors-reference#originalhashduplicate-icl1)
* [DistributionStarted](https://docs.cryptolegacy.app/documentation/errors-reference#distributionstarted-icl1)
* [DistributionStartAlreadySet](https://docs.cryptolegacy.app/documentation/errors-reference#distributionstartalreadyset-icl1)
* [DistributionDelay](https://docs.cryptolegacy.app/documentation/errors-reference#distributiondelay-icl1)
* [ChallengePeriodStarted](https://docs.cryptolegacy.app/documentation/errors-reference#challengeperiodstarted-icl1)
* [AlreadySet](https://docs.cryptolegacy.app/documentation/errors-reference#alreadyset-icl1)
* [BeneficiaryNotSet](https://docs.cryptolegacy.app/documentation/errors-reference#beneficiarynotset-icl1)
* [Pause](https://docs.cryptolegacy.app/documentation/errors-reference#pause-icl1)
* [IncorrectFacetCutAction](https://docs.cryptolegacy.app/documentation/errors-reference#incorrectfacetcutaction-icl1)
* [NotContractOwner](https://docs.cryptolegacy.app/documentation/errors-reference#notcontractowner-icl1)
* [FacetNotFound](https://docs.cryptolegacy.app/documentation/errors-reference#facetnotfound-icl1)
* [FacetHasNoCode](https://docs.cryptolegacy.app/documentation/errors-reference#facethasnocode-icl1)
* [NoSelectorsInFacetToCut](https://docs.cryptolegacy.app/documentation/errors-reference#noselectorsinfacettocut-icl1)
* [FacetCantBeZero](https://docs.cryptolegacy.app/documentation/errors-reference#facetcantbezero-icl1)
* [CantRemoveImmutableFunctions](https://docs.cryptolegacy.app/documentation/errors-reference#cantremoveimmutablefunctions-icl1)
* [CantAddFunctionThatAlreadyExists](https://docs.cryptolegacy.app/documentation/errors-reference#cantaddfunctionthatalreadyexists-icl1)
* [CantReplaceFunctionWithSameFunction](https://docs.cryptolegacy.app/documentation/errors-reference#cantreplacefunctionwithsamefunction-icl1)
* [InitFunctionReverted](https://docs.cryptolegacy.app/documentation/errors-reference#initfunctionreverted-icl1)
* [InitAddressZeroButCalldataIsNot](https://docs.cryptolegacy.app/documentation/errors-reference#initaddresszerobutcalldataisnot-icl1)
* [InitCalldataZeroButAddressIsNot](https://docs.cryptolegacy.app/documentation/errors-reference#initcalldatazerobutaddressisnot-icl1)
* [PluginNotRegistered](https://docs.cryptolegacy.app/documentation/errors-reference#pluginnotregistered-icl1)
* [TransferFeeFailed](https://docs.cryptolegacy.app/documentation/errors-reference#transferfeefailed-icl1)
* [TooBigMultiplier](https://docs.cryptolegacy.app/documentation/errors-reference#toobigmultiplier-icl1)

### Access / Roles

None.

### Interacts With

None.

### Missing Links

None.

## ICryptoLegacyBuildManager (Interface)

### Purpose

ICryptoLegacyBuildManager defines the deployment, fee-payment, and registry setup interface for protocol-instance creation.

### Inheritance

None.

### Key Methods

* [payInitialFee(...)](https://docs.cryptolegacy.app/documentation/functions-reference#payinitialfee-iclbm1) - Collects the initial protocol fee when a CryptoLegacy instance is created.
* [payFee(...)](https://docs.cryptolegacy.app/documentation/functions-reference#payfee-iclbm1) - Processes ongoing registry update fees for an existing CryptoLegacy.
* [getUpdateFee(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getupdatefee-iclbm1) - Returns the configured update fee for a referral code.
* [isLifetimeNftLocked(...)](https://docs.cryptolegacy.app/documentation/functions-reference#islifetimenftlocked-iclbm1) - Checks whether the owner’s lifetime NFT is locked.
* [isLifetimeNftLockedAndUpdate(...)](https://docs.cryptolegacy.app/documentation/functions-reference#islifetimenftlockedandupdate-iclbm1) - Checks and updates lifetime NFT lock status in a single call.
* [isPluginRegistered(...)](https://docs.cryptolegacy.app/documentation/functions-reference#ispluginregistered-iclbm1) - Returns whether a plugin address is approved by the build manager.
* [isCryptoLegacyBuilt(...)](https://docs.cryptolegacy.app/documentation/functions-reference#iscryptolegacybuilt-iclbm1) - Indicates whether a CryptoLegacy address was deployed via the build manager.
* [pluginsRegistry(...)](https://docs.cryptolegacy.app/documentation/functions-reference#pluginsregistry-iclbm1) - Returns the plugins registry contract address.

### All Functions

* [payInitialFee(...)](https://docs.cryptolegacy.app/documentation/functions-reference#payinitialfee-iclbm1) - Collects the initial protocol fee when a CryptoLegacy instance is created.
* [payFee(...)](https://docs.cryptolegacy.app/documentation/functions-reference#payfee-iclbm1) - Processes ongoing registry update fees for an existing CryptoLegacy.
* [getUpdateFee(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getupdatefee-iclbm1) - Returns the configured update fee for a referral code.
* [isLifetimeNftLocked(...)](https://docs.cryptolegacy.app/documentation/functions-reference#islifetimenftlocked-iclbm1) - Checks whether the owner’s lifetime NFT is locked.
* [isLifetimeNftLockedAndUpdate(...)](https://docs.cryptolegacy.app/documentation/functions-reference#islifetimenftlockedandupdate-iclbm1) - Checks and updates lifetime NFT lock status in a single call.
* [isPluginRegistered(...)](https://docs.cryptolegacy.app/documentation/functions-reference#ispluginregistered-iclbm1) - Returns whether a plugin address is approved by the build manager.
* [isCryptoLegacyBuilt(...)](https://docs.cryptolegacy.app/documentation/functions-reference#iscryptolegacybuilt-iclbm1) - Indicates whether a CryptoLegacy address was deployed via the build manager.
* [pluginsRegistry()](https://docs.cryptolegacy.app/documentation/functions-reference#pluginsregistry-iclbm1) - Returns the plugins registry contract address.
* [getFactoryAddress()](https://docs.cryptolegacy.app/documentation/functions-reference#getfactoryaddress-iclbm1) - Returns the configured factory contract address.
* [beneficiaryRegistry()](https://docs.cryptolegacy.app/documentation/functions-reference#beneficiaryregistry-iclbm1) - Returns the beneficiary registry address used by the build manager.
* [externalLens()](https://docs.cryptolegacy.app/documentation/functions-reference#externallens-iclbm1) - Returns the external lens contract used for off-chain queries.

### Events

* [CreateRef](https://docs.cryptolegacy.app/documentation/events-reference#createref-iclbm1)
* [CreateCustomRef](https://docs.cryptolegacy.app/documentation/events-reference#createcustomref-iclbm1)
* [SetCrossChainsRef](https://docs.cryptolegacy.app/documentation/events-reference#setcrosschainsref-iclbm1)
* [WithdrawFee](https://docs.cryptolegacy.app/documentation/events-reference#withdrawfee-iclbm1)
* [SetRegistries](https://docs.cryptolegacy.app/documentation/events-reference#setregistries-iclbm1)
* [SetFactory](https://docs.cryptolegacy.app/documentation/events-reference#setfactory-iclbm1)
* [SetSupplyLimit](https://docs.cryptolegacy.app/documentation/events-reference#setsupplylimit-iclbm1)
* [SetExternalLens](https://docs.cryptolegacy.app/documentation/events-reference#setexternallens-iclbm1)
* [PaidForMint](https://docs.cryptolegacy.app/documentation/events-reference#paidformint-iclbm1)
* [PaidForMultipleNft](https://docs.cryptolegacy.app/documentation/events-reference#paidformultiplenft-iclbm1)
* [Build](https://docs.cryptolegacy.app/documentation/events-reference#build-iclbm1)

### Errors

* [AlreadyLifetime](https://docs.cryptolegacy.app/documentation/errors-reference#alreadylifetime-iclbm1)
* [WithdrawFeeFailed](https://docs.cryptolegacy.app/documentation/errors-reference#withdrawfeefailed-iclbm1)
* [NotValidTimeout](https://docs.cryptolegacy.app/documentation/errors-reference#notvalidtimeout-iclbm1)
* [IncorrectFee](https://docs.cryptolegacy.app/documentation/errors-reference#incorrectfee-iclbm1)
* [BelowMinimumSupply](https://docs.cryptolegacy.app/documentation/errors-reference#belowminimumsupply-iclbm1)
* [NotRegisteredCryptoLegacy](https://docs.cryptolegacy.app/documentation/errors-reference#notregisteredcryptolegacy-iclbm1)
* [NotOwnerOfCryptoLegacy](https://docs.cryptolegacy.app/documentation/errors-reference#notownerofcryptolegacy-iclbm1)
* [TransferFeeFailed](https://docs.cryptolegacy.app/documentation/errors-reference#transferfeefailed-iclbm1)

### Access / Roles

None.

### Interacts With

None.

### Missing Links

None.

## ICryptoLegacyDiamondBase (Interface)

### Purpose

ICryptoLegacyDiamondBase defines base diamond helper calls shared by core protocol contracts.

### Inheritance

None.

### Key Methods

None.

### All Functions

None.

### Events

* [StaticCallCheck](https://docs.cryptolegacy.app/documentation/events-reference#staticcallcheck-icldb1)

### Errors

* [FunctionNotExists](https://docs.cryptolegacy.app/documentation/errors-reference#functionnotexists-icldb1)
* [NotSelfCall](https://docs.cryptolegacy.app/documentation/errors-reference#notselfcall-icldb1)

### Access / Roles

None.

### Interacts With

None.

### Missing Links

None.

## ICryptoLegacyFactory (Interface)

### Purpose

ICryptoLegacyFactory defines protocol-instance deployment and build-operator management functions.

### Inheritance

None.

### Key Methods

* [createCryptoLegacy(...)](https://docs.cryptolegacy.app/documentation/functions-reference#createcryptolegacy-iclf1) - Deploys a new CryptoLegacy diamond with the supplied owner, plugin list, and optional CREATE2 parameters.
* [setBuildOperator(...)](https://docs.cryptolegacy.app/documentation/functions-reference#setbuildoperator-iclf1) - Grants or revokes build-operator permissions for the factory.

### All Functions

* [createCryptoLegacy(...)](https://docs.cryptolegacy.app/documentation/functions-reference#createcryptolegacy-iclf1) - Deploys a new CryptoLegacy diamond with the supplied owner, plugin list, and optional CREATE2 parameters.
* [setBuildOperator(...)](https://docs.cryptolegacy.app/documentation/functions-reference#setbuildoperator-iclf1) - Grants or revokes build-operator permissions for the factory.

### Events

* [AddBuildOperator](https://docs.cryptolegacy.app/documentation/events-reference#addbuildoperator-iclf1)
* [RemoveBuildOperator](https://docs.cryptolegacy.app/documentation/events-reference#removebuildoperator-iclf1)

### Errors

* [NotBuildOperator](https://docs.cryptolegacy.app/documentation/errors-reference#notbuildoperator-iclf1)

### Access / Roles

None.

### Interacts With

None.

### Missing Links

None.

## ICryptoLegacyLens (Interface)

### Purpose

ICryptoLegacyLens defines read-only lens calls for protocol status, messages, and beneficiary data.

### Inheritance

None.

### Key Methods

* [getMessagesBlockNumbersByRecipient(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getmessagesblocknumbersbyrecipient-icll1) - Returns the message block numbers recorded for a recipient hash.
* [getVestedAndClaimedData(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getvestedandclaimeddata-icll1) - Returns per-token vested and claimed data for a beneficiary.
* [getCryptoLegacyBaseData(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getcryptolegacybasedata-icll1) - Returns the core configuration snapshot for a CryptoLegacy.
* [getCryptoLegacyListData(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getcryptolegacylistdata-icll1) - Returns aggregated beneficiaries, transfers, plugins, and token distribution data.

### All Functions

* [getMessagesBlockNumbersByRecipient(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getmessagesblocknumbersbyrecipient-icll1) - Returns the message block numbers recorded for a recipient hash.
* [getVestedAndClaimedData(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getvestedandclaimeddata-icll1) - Returns per-token vested and claimed data for a beneficiary.
* [getCryptoLegacyBaseData()](https://docs.cryptolegacy.app/documentation/functions-reference#getcryptolegacybasedata-icll1) - Returns the core configuration snapshot for a CryptoLegacy.
* [getCryptoLegacyListData(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getcryptolegacylistdata-icll1) - Returns aggregated beneficiaries, transfers, plugins, and token distribution data.

### Events

None.

### Errors

None.

### Access / Roles

None.

### Interacts With

None.

### Missing Links

None.

## ICryptoLegacyOwnable (Interface)

### Purpose

ICryptoLegacyOwnable defines ownership and pause control calls for CryptoLegacy-compatible modules.

### Inheritance

None.

### Key Methods

None.

### All Functions

None.

### Events

* [OwnershipTransferStarted](https://docs.cryptolegacy.app/documentation/events-reference#ownershiptransferstarted-iclo1)
* [OwnershipTransferred](https://docs.cryptolegacy.app/documentation/events-reference#ownershiptransferred-iclo1)

### Errors

* [OwnableUnauthorizedAccount](https://docs.cryptolegacy.app/documentation/errors-reference#ownableunauthorizedaccount-iclo1)

### Access / Roles

None.

### Interacts With

None.

### Missing Links

None.

## ICryptoLegacyPlugin (Interface)

### Purpose

ICryptoLegacyPlugin defines the plugin ABI for selectors, setup hooks, and plugin metadata.

### Inheritance

None.

### Key Methods

* [getSigs(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getsigs-iclp1) - Returns the function selectors supported by the plugin.
* [getSetupSigs(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getsetupsigs-iclp1) - Returns the setup selectors required when installing the plugin.
* [getPluginName(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getpluginname-iclp1) - Returns the human-readable plugin name.
* [getPluginVer(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getpluginver-iclp1) - Returns the plugin version number.

### All Functions

* [getSigs()](https://docs.cryptolegacy.app/documentation/functions-reference#getsigs-iclp1) - Returns the function selectors supported by the plugin.
* [getSetupSigs()](https://docs.cryptolegacy.app/documentation/functions-reference#getsetupsigs-iclp1) - Returns the setup selectors required when installing the plugin.
* [getPluginName()](https://docs.cryptolegacy.app/documentation/functions-reference#getpluginname-iclp1) - Returns the human-readable plugin name.
* [getPluginVer()](https://docs.cryptolegacy.app/documentation/functions-reference#getpluginver-iclp1) - Returns the plugin version number.

### Events

None.

### Errors

None.

### Access / Roles

None.

### Interacts With

None.

### Missing Links

None.

## ICryptoLegacyUpdaterPlugin (Interface)

### Purpose

ICryptoLegacyUpdaterPlugin defines updater-plugin behavior for role and state migration operations.

### Inheritance

None.

### Key Methods

None.

### All Functions

None.

### Events

* [AddUpdater](https://docs.cryptolegacy.app/documentation/events-reference#addupdater-iclup1)
* [RemoveUpdater](https://docs.cryptolegacy.app/documentation/events-reference#removeupdater-iclup1)

### Errors

* [NotTheUpdater](https://docs.cryptolegacy.app/documentation/errors-reference#nottheupdater-iclup1)

### Access / Roles

None.

### Interacts With

None.

### Missing Links

None.

## IDeBridgeGate (Interface)

### Purpose

IDeBridgeGate defines bridge-gateway calls for message delivery and token movement across chains.

### Inheritance

None.

### Key Methods

* [isSubmissionUsed(...)](https://docs.cryptolegacy.app/documentation/functions-reference#issubmissionused-idbg1) - Reports whether a deBridge submission has already been claimed.
* [getNativeInfo(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getnativeinfo-idbg1) - Returns the origin chain metadata for a wrapped asset.
* [callProxy(...)](https://docs.cryptolegacy.app/documentation/functions-reference#callproxy-idbg1) - Exposes the call proxy contract used to execute bridged payloads on the destination chain.
* [globalFixedNativeFee(...)](https://docs.cryptolegacy.app/documentation/functions-reference#globalfixednativefee-idbg1) - Returns the global base native fee charged for bridging operations.
* [globalTransferFeeBps(...)](https://docs.cryptolegacy.app/documentation/functions-reference#globaltransferfeebps-idbg1) - Returns the global percentage fee (in basis points) applied to bridged transfers.
* [sendMessage(...)](https://docs.cryptolegacy.app/documentation/functions-reference#sendmessageuint256bytesbytes-idbg1) - Submits a cross-chain message to a destination contract without transferring assets.
* [sendMessage(...)](https://docs.cryptolegacy.app/documentation/functions-reference#sendmessageuint256bytesbytesuint256uint32-idbg1) - Submits a cross-chain message with explicit flags and referral code.
* [send(...)](https://docs.cryptolegacy.app/documentation/functions-reference#send-idbg1) - Bridges assets from the native chain to a destination chain.

### All Functions

* [isSubmissionUsed(...)](https://docs.cryptolegacy.app/documentation/functions-reference#issubmissionused-idbg1) - Reports whether a deBridge submission has already been claimed.
* [getNativeInfo(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getnativeinfo-idbg1) - Returns the origin chain metadata for a wrapped asset.
* [callProxy()](https://docs.cryptolegacy.app/documentation/functions-reference#callproxy-idbg1) - Exposes the call proxy contract used to execute bridged payloads on the destination chain.
* [globalFixedNativeFee()](https://docs.cryptolegacy.app/documentation/functions-reference#globalfixednativefee-idbg1) - Returns the global base native fee charged for bridging operations.
* [globalTransferFeeBps()](https://docs.cryptolegacy.app/documentation/functions-reference#globaltransferfeebps-idbg1) - Returns the global percentage fee (in basis points) applied to bridged transfers.
* [sendMessage(...)](https://docs.cryptolegacy.app/documentation/functions-reference#sendmessageuint256bytesbytes-idbg1) - Submits a cross-chain message to a destination contract without transferring assets.
* [sendMessage(...)](https://docs.cryptolegacy.app/documentation/functions-reference#sendmessageuint256bytesbytesuint256uint32-idbg1) - Submits a cross-chain message with explicit flags and referral code.
* [send(...)](https://docs.cryptolegacy.app/documentation/functions-reference#send-idbg1) - Bridges assets from the native chain to a destination chain.
* [claim(...)](https://docs.cryptolegacy.app/documentation/functions-reference#claim-idbg1) - Claims bridged assets on the destination chain.
* [withdrawFee(...)](https://docs.cryptolegacy.app/documentation/functions-reference#withdrawfee-idbg1) - Withdraws accumulated protocol fees for an asset.
* [getDebridgeChainAssetFixedFee(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getdebridgechainassetfixedfee-idbg1) - Returns the fixed native fee for an asset on a specific chain.

### Events

* [Sent](https://docs.cryptolegacy.app/documentation/events-reference#sent-idbg1)
* [Claimed](https://docs.cryptolegacy.app/documentation/events-reference#claimed-idbg1)
* [PairAdded](https://docs.cryptolegacy.app/documentation/events-reference#pairadded-idbg1)
* [MonitoringSendEvent](https://docs.cryptolegacy.app/documentation/events-reference#monitoringsendevent-idbg1)
* [MonitoringClaimEvent](https://docs.cryptolegacy.app/documentation/events-reference#monitoringclaimevent-idbg1)
* [ChainSupportUpdated](https://docs.cryptolegacy.app/documentation/events-reference#chainsupportupdated-idbg1)
* [ChainsSupportUpdated](https://docs.cryptolegacy.app/documentation/events-reference#chainssupportupdated-idbg1)
* [CallProxyUpdated](https://docs.cryptolegacy.app/documentation/events-reference#callproxyupdated-idbg1)
* [AutoRequestExecuted](https://docs.cryptolegacy.app/documentation/events-reference#autorequestexecuted-idbg1)
* [Blocked](https://docs.cryptolegacy.app/documentation/events-reference#blocked-idbg1)
* [Unblocked](https://docs.cryptolegacy.app/documentation/events-reference#unblocked-idbg1)
* [WithdrawnFee](https://docs.cryptolegacy.app/documentation/events-reference#withdrawnfee-idbg1)
* [FixedNativeFeeUpdated](https://docs.cryptolegacy.app/documentation/events-reference#fixednativefeeupdated-idbg1)
* [FixedNativeFeeAutoUpdated](https://docs.cryptolegacy.app/documentation/events-reference#fixednativefeeautoupdated-idbg1)

### Errors

None.

### Access / Roles

None.

### Interacts With

None.

### Missing Links

None.

## IDiamondCut (Interface)

### Purpose

IDiamondCut defines facet-cut structures and upgrade entrypoints for the diamond proxy standard.

### Inheritance

None.

### Key Methods

* [diamondCut(...)](https://docs.cryptolegacy.app/documentation/functions-reference#diamondcut-idc1) - External entry point for applying diamond facet cuts with optional initialization.

### All Functions

* [diamondCut(...)](https://docs.cryptolegacy.app/documentation/functions-reference#diamondcut-idc1) - External entry point for applying diamond facet cuts with optional initialization.

### Events

* [DiamondCut](https://docs.cryptolegacy.app/documentation/events-reference#diamondcut-idc1)

### Errors

None.

### Access / Roles

None.

### Interacts With

None.

### Missing Links

None.

## IDiamondLoupe (Interface)

### Purpose

IDiamondLoupe defines introspection views for facets, selectors, and interface support.

### Inheritance

None.

### Key Methods

* [facets(...)](https://docs.cryptolegacy.app/documentation/functions-reference#facets-idl1) - Returns the full list of facet addresses together with their selectors.
* [facetFunctionSelectors(...)](https://docs.cryptolegacy.app/documentation/functions-reference#facetfunctionselectors-idl1) - Returns the selector list exposed by a specific facet.
* [facetAddresses(...)](https://docs.cryptolegacy.app/documentation/functions-reference#facetaddresses-idl1) - Lists every facet address installed on the diamond.
* [facetAddress(...)](https://docs.cryptolegacy.app/documentation/functions-reference#facetaddress-idl1) - Resolves which facet implements a given selector.

### All Functions

* [facets()](https://docs.cryptolegacy.app/documentation/functions-reference#facets-idl1) - Returns the full list of facet addresses together with their selectors.
* [facetFunctionSelectors(...)](https://docs.cryptolegacy.app/documentation/functions-reference#facetfunctionselectors-idl1) - Returns the selector list exposed by a specific facet.
* [facetAddresses()](https://docs.cryptolegacy.app/documentation/functions-reference#facetaddresses-idl1) - Lists every facet address installed on the diamond.
* [facetAddress(...)](https://docs.cryptolegacy.app/documentation/functions-reference#facetaddress-idl1) - Resolves which facet implements a given selector.

### Events

None.

### Errors

None.

### Access / Roles

None.

### Interacts With

None.

### Missing Links

None.

## IFeeRegistry (Interface)

### Purpose

IFeeRegistry defines referral and fee lookup APIs used by builders and plugins.

### Inheritance

None.

### Key Methods

* [getContractCaseFee(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getcontractcasefee-ifr1) - Returns the configured base fee for a specific contract-case combination.
* [getContractCaseFeeForCode(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getcontractcasefeeforcode-ifr1) - Returns the effective fee for a contract-case after applying a referral code’s discount.
* [takeFee(...)](https://docs.cryptolegacy.app/documentation/functions-reference#takefee-ifr1) - Charges the calculated fee for a contract-case and processes referral payouts.
* [createCustomCode(...)](https://docs.cryptolegacy.app/documentation/functions-reference#createcustomcode-ifr1) - Creates a specific referral code and optionally pushes it to other chains.
* [createCode(...)](https://docs.cryptolegacy.app/documentation/functions-reference#createcode-ifr1) - Generates a new referral code and optionally propagates it cross-chain.
* [updateCrossChainsRef(...)](https://docs.cryptolegacy.app/documentation/functions-reference#updatecrosschainsref-ifr1) - Updates cross-chain propagation settings for an existing referral code.
* [accumulatedFee(...)](https://docs.cryptolegacy.app/documentation/functions-reference#accumulatedfee-ifr1) - Returns the protocol fee balance awaiting distribution.
* [getSupportedRefInChainsList(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getsupportedrefinchainslist-ifr1) - Lists the chain IDs where referral codes are currently supported.

### All Functions

* [getContractCaseFee(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getcontractcasefee-ifr1) - Returns the configured base fee for a specific contract-case combination.
* [getContractCaseFeeForCode(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getcontractcasefeeforcode-ifr1) - Returns the effective fee for a contract-case after applying a referral code’s discount.
* [takeFee(...)](https://docs.cryptolegacy.app/documentation/functions-reference#takefee-ifr1) - Charges the calculated fee for a contract-case and processes referral payouts.
* [createCustomCode(...)](https://docs.cryptolegacy.app/documentation/functions-reference#createcustomcode-ifr1) - Creates a specific referral code and optionally pushes it to other chains.
* [createCode(...)](https://docs.cryptolegacy.app/documentation/functions-reference#createcode-ifr1) - Generates a new referral code and optionally propagates it cross-chain.
* [updateCrossChainsRef(...)](https://docs.cryptolegacy.app/documentation/functions-reference#updatecrosschainsref-ifr1) - Updates cross-chain propagation settings for an existing referral code.
* [accumulatedFee()](https://docs.cryptolegacy.app/documentation/functions-reference#accumulatedfee-ifr1) - Returns the protocol fee balance awaiting distribution.
* [getSupportedRefInChainsList()](https://docs.cryptolegacy.app/documentation/functions-reference#getsupportedrefinchainslist-ifr1) - Lists the chain IDs where referral codes are currently supported.

### Events

* [AddCodeOperator](https://docs.cryptolegacy.app/documentation/events-reference#addcodeoperator-ifr1)
* [RemoveCodeOperator](https://docs.cryptolegacy.app/documentation/events-reference#removecodeoperator-ifr1)
* [SetDefaultPct](https://docs.cryptolegacy.app/documentation/events-reference#setdefaultpct-ifr1)
* [SetRefererSpecificPct](https://docs.cryptolegacy.app/documentation/events-reference#setrefererspecificpct-ifr1)
* [SetContractCaseFee](https://docs.cryptolegacy.app/documentation/events-reference#setcontractcasefee-ifr1)
* [TakeFee](https://docs.cryptolegacy.app/documentation/events-reference#takefee-ifr1)
* [SentFee](https://docs.cryptolegacy.app/documentation/events-reference#sentfee-ifr1)
* [AccumulateFee](https://docs.cryptolegacy.app/documentation/events-reference#accumulatefee-ifr1)
* [CreateCode](https://docs.cryptolegacy.app/documentation/events-reference#createcode-ifr1)
* [UpdateCode](https://docs.cryptolegacy.app/documentation/events-reference#updatecode-ifr1)
* [ChangeCode](https://docs.cryptolegacy.app/documentation/events-reference#changecode-ifr1)
* [ChangeRecipient](https://docs.cryptolegacy.app/documentation/events-reference#changerecipient-ifr1)
* [SetCrossChainsRef](https://docs.cryptolegacy.app/documentation/events-reference#setcrosschainsref-ifr1)
* [SetFeeBeneficiaries](https://docs.cryptolegacy.app/documentation/events-reference#setfeebeneficiaries-ifr1)
* [AddSupportedRefCodeInChain](https://docs.cryptolegacy.app/documentation/events-reference#addsupportedrefcodeinchain-ifr1)
* [RemoveSupportedRefCodeInChain](https://docs.cryptolegacy.app/documentation/events-reference#removesupportedrefcodeinchain-ifr1)
* [WithdrawFee](https://docs.cryptolegacy.app/documentation/events-reference#withdrawfee-ifr1)
* [WithdrawRefFee](https://docs.cryptolegacy.app/documentation/events-reference#withdrawreffee-ifr1)

### Errors

* [WithdrawAccumulatedFeeFailed](https://docs.cryptolegacy.app/documentation/errors-reference#withdrawaccumulatedfeefailed-ifr1)
* [PctSumDoesntMatchBase](https://docs.cryptolegacy.app/documentation/errors-reference#pctsumdoesntmatchbase-ifr1)
* [TooBigPct](https://docs.cryptolegacy.app/documentation/errors-reference#toobigpct-ifr1)
* [RefAlreadyCreated](https://docs.cryptolegacy.app/documentation/errors-reference#refalreadycreated-ifr1)
* [ZeroCode](https://docs.cryptolegacy.app/documentation/errors-reference#zerocode-ifr1)
* [NotOperator](https://docs.cryptolegacy.app/documentation/errors-reference#notoperator-ifr1)
* [NotReferrer](https://docs.cryptolegacy.app/documentation/errors-reference#notreferrer-ifr1)
* [AlreadyReferrer](https://docs.cryptolegacy.app/documentation/errors-reference#alreadyreferrer-ifr1)
* [CodeNotCreated](https://docs.cryptolegacy.app/documentation/errors-reference#codenotcreated-ifr1)

### Access / Roles

None.

### Interacts With

None.

### Missing Links

None.

## ILockChainGate (Interface)

### Purpose

ILockChainGate defines lock-gate operations for locking, unlocking, and bridge-synchronized NFT state.

### Inheritance

None.

### Key Methods

* [lockLifetimeNft(...)](https://docs.cryptolegacy.app/documentation/functions-reference#locklifetimenft-ilcg1) - Locks a lifetime NFT and optionally propagates the lock across chains.
* [isNftLocked(...)](https://docs.cryptolegacy.app/documentation/functions-reference#isnftlocked-ilcg1) - Reports whether the owner has an active lifetime NFT lock.
* [isNftLockedAndUpdate(...)](https://docs.cryptolegacy.app/documentation/functions-reference#isnftlockedandupdate-ilcg1) - Checks lock status and updates timing when required.
* [calculateCrossChainCreateRefNativeFee(...)](https://docs.cryptolegacy.app/documentation/functions-reference#calculatecrosschaincreaterefnativefee-ilcg1) - Computes the total native fee required for cross-chain referral creation.

### All Functions

* [lockLifetimeNft(...)](https://docs.cryptolegacy.app/documentation/functions-reference#locklifetimenft-ilcg1) - Locks a lifetime NFT and optionally propagates the lock across chains.
* [isNftLocked(...)](https://docs.cryptolegacy.app/documentation/functions-reference#isnftlocked-ilcg1) - Reports whether the owner has an active lifetime NFT lock.
* [isNftLockedAndUpdate(...)](https://docs.cryptolegacy.app/documentation/functions-reference#isnftlockedandupdate-ilcg1) - Checks lock status and updates timing when required.
* [calculateCrossChainCreateRefNativeFee(...)](https://docs.cryptolegacy.app/documentation/functions-reference#calculatecrosschaincreaterefnativefee-ilcg1) - Computes the total native fee required for cross-chain referral creation.

### Events

* [AddLockOperator](https://docs.cryptolegacy.app/documentation/events-reference#addlockoperator-ilcg1)
* [RemoveLockOperator](https://docs.cryptolegacy.app/documentation/events-reference#removelockoperator-ilcg1)
* [SetDestinationChainContract](https://docs.cryptolegacy.app/documentation/events-reference#setdestinationchaincontract-ilcg1)
* [SetSourceChainContract](https://docs.cryptolegacy.app/documentation/events-reference#setsourcechaincontract-ilcg1)
* [SetDeBridgeGate](https://docs.cryptolegacy.app/documentation/events-reference#setdebridgegate-ilcg1)
* [SetDeBridgeNativeFee](https://docs.cryptolegacy.app/documentation/events-reference#setdebridgenativefee-ilcg1)
* [SetLockPeriodConfig](https://docs.cryptolegacy.app/documentation/events-reference#setlockperiodconfig-ilcg1)
* [SendToChain](https://docs.cryptolegacy.app/documentation/events-reference#sendtochain-ilcg1)
* [LockNft](https://docs.cryptolegacy.app/documentation/events-reference#locknft-ilcg1)
* [UnlockNft](https://docs.cryptolegacy.app/documentation/events-reference#unlocknft-ilcg1)
* [ApproveNft](https://docs.cryptolegacy.app/documentation/events-reference#approvenft-ilcg1)
* [TransferNft](https://docs.cryptolegacy.app/documentation/events-reference#transfernft-ilcg1)
* [LockToChain](https://docs.cryptolegacy.app/documentation/events-reference#locktochain-ilcg1)
* [UpdateLockToChain](https://docs.cryptolegacy.app/documentation/events-reference#updatelocktochain-ilcg1)
* [Update](https://docs.cryptolegacy.app/documentation/events-reference#update-ilcg1)
* [UnlockFromChain](https://docs.cryptolegacy.app/documentation/events-reference#unlockfromchain-ilcg1)
* [CrossLockNft](https://docs.cryptolegacy.app/documentation/events-reference#crosslocknft-ilcg1)
* [CrossUnlockNft](https://docs.cryptolegacy.app/documentation/events-reference#crossunlocknft-ilcg1)
* [CrossUpdateNftOwner](https://docs.cryptolegacy.app/documentation/events-reference#crossupdatenftowner-ilcg1)
* [SetReferralCode](https://docs.cryptolegacy.app/documentation/events-reference#setreferralcode-ilcg1)
* [SetCustomChainId](https://docs.cryptolegacy.app/documentation/events-reference#setcustomchainid-ilcg1)

### Errors

* [ArrayLengthMismatch](https://docs.cryptolegacy.app/documentation/errors-reference#arraylengthmismatch-ilcg1)
* [AlreadyLocked](https://docs.cryptolegacy.app/documentation/errors-reference#alreadylocked-ilcg1)
* [LockedToChains](https://docs.cryptolegacy.app/documentation/errors-reference#lockedtochains-ilcg1)
* [CrossChainLock](https://docs.cryptolegacy.app/documentation/errors-reference#crosschainlock-ilcg1)
* [TooEarly](https://docs.cryptolegacy.app/documentation/errors-reference#tooearly-ilcg1)
* [DestinationChainNotSpecified](https://docs.cryptolegacy.app/documentation/errors-reference#destinationchainnotspecified-ilcg1)
* [TokenNotLocked](https://docs.cryptolegacy.app/documentation/errors-reference#tokennotlocked-ilcg1)
* [TokenIdMismatch](https://docs.cryptolegacy.app/documentation/errors-reference#tokenidmismatch-ilcg1)
* [AlreadyLockedToChain](https://docs.cryptolegacy.app/documentation/errors-reference#alreadylockedtochain-ilcg1)
* [SourceNotSpecified](https://docs.cryptolegacy.app/documentation/errors-reference#sourcenotspecified-ilcg1)
* [NotLockedByChain](https://docs.cryptolegacy.app/documentation/errors-reference#notlockedbychain-ilcg1)
* [DestinationNotSpecified](https://docs.cryptolegacy.app/documentation/errors-reference#destinationnotspecified-ilcg1)
* [NotAvailable](https://docs.cryptolegacy.app/documentation/errors-reference#notavailable-ilcg1)
* [IncorrectFee](https://docs.cryptolegacy.app/documentation/errors-reference#incorrectfee-ilcg1)
* [SameAddress](https://docs.cryptolegacy.app/documentation/errors-reference#sameaddress-ilcg1)
* [RecipientLocked](https://docs.cryptolegacy.app/documentation/errors-reference#recipientlocked-ilcg1)
* [TransferLockTimeout](https://docs.cryptolegacy.app/documentation/errors-reference#transferlocktimeout-ilcg1)
* [NotCallProxy](https://docs.cryptolegacy.app/documentation/errors-reference#notcallproxy-ilcg1)
* [ChainIdMismatch](https://docs.cryptolegacy.app/documentation/errors-reference#chainidmismatch-ilcg1)
* [NotValidSender](https://docs.cryptolegacy.app/documentation/errors-reference#notvalidsender-ilcg1)
* [NotAllowed](https://docs.cryptolegacy.app/documentation/errors-reference#notallowed-ilcg1)
* [TransferFeeFailed](https://docs.cryptolegacy.app/documentation/errors-reference#transferfeefailed-ilcg1)

### Access / Roles

None.

### Interacts With

None.

### Missing Links

None.

## ILegacyMessenger (Interface)

### Purpose

ILegacyMessenger defines message-sending and retrieval calls for legacy communication records.

### Inheritance

None.

### Key Methods

None.

### All Functions

None.

### Events

* [LegacyMessage](https://docs.cryptolegacy.app/documentation/events-reference#legacymessage-ilm1)
* [LegacyMessageCheck](https://docs.cryptolegacy.app/documentation/events-reference#legacymessagecheck-ilm1)

### Errors

None.

### Access / Roles

None.

### Interacts With

None.

### Missing Links

None.

## ILido (Interface)

### Purpose

ILido defines the subset of Lido staking and share-transfer calls required by integrations.

### Inheritance

None.

### Key Methods

* [submit(...)](https://docs.cryptolegacy.app/documentation/functions-reference#submit-ild1) - Stakes ETH into Lido and mints stETH, crediting the caller.
* [transferShares(...)](https://docs.cryptolegacy.app/documentation/functions-reference#transfershares-ild1) - Transfers a specified amount of Lido shares to another address.
* [transferSharesFrom(...)](https://docs.cryptolegacy.app/documentation/functions-reference#transfersharesfrom-ild1) - Transfers Lido shares from one address to another using allowance semantics.
* [sharesOf(...)](https://docs.cryptolegacy.app/documentation/functions-reference#sharesof-ild1) - Returns the number of Lido shares owned by an account.

### All Functions

* [submit(...)](https://docs.cryptolegacy.app/documentation/functions-reference#submit-ild1) - Stakes ETH into Lido and mints stETH, crediting the caller.
* [transferShares(...)](https://docs.cryptolegacy.app/documentation/functions-reference#transfershares-ild1) - Transfers a specified amount of Lido shares to another address.
* [transferSharesFrom(...)](https://docs.cryptolegacy.app/documentation/functions-reference#transfersharesfrom-ild1) - Transfers Lido shares from one address to another using allowance semantics.
* [sharesOf(...)](https://docs.cryptolegacy.app/documentation/functions-reference#sharesof-ild1) - Returns the number of Lido shares owned by an account.

### Events

None.

### Errors

None.

### Access / Roles

None.

### Interacts With

None.

### Missing Links

None.

## ILidoWithdrawalQueue (Interface)

### Purpose

ILidoWithdrawalQueue defines the withdrawal-request and claim calls used by the Lido staking beneficiary plugin. It standardizes request and claim entry points so Lido-side exits can be orchestrated through a stable interface.

### Inheritance

None.

### Key Methods

* [requestWithdrawals(...)](https://docs.cryptolegacy.app/documentation/functions-reference#requestwithdrawals-ilwq1) - Requests ETH withdrawals for stETH amounts through Lido's withdrawal queue.
* [requestWithdrawalsWstETH(...)](https://docs.cryptolegacy.app/documentation/functions-reference#requestwithdrawalswsteth-ilwq1) - Requests ETH withdrawals for wstETH amounts through the Lido queue.
* [claimWithdrawals(...)](https://docs.cryptolegacy.app/documentation/functions-reference#claimwithdrawals-ilwq1) - Claims finalized Lido withdrawals for previously created request IDs.

### All Functions

* [requestWithdrawals(...)](https://docs.cryptolegacy.app/documentation/functions-reference#requestwithdrawals-ilwq1) - Requests ETH withdrawals for stETH amounts through Lido's withdrawal queue.
* [requestWithdrawalsWstETH(...)](https://docs.cryptolegacy.app/documentation/functions-reference#requestwithdrawalswsteth-ilwq1) - Requests ETH withdrawals for wstETH amounts through the Lido queue.
* [claimWithdrawals(...)](https://docs.cryptolegacy.app/documentation/functions-reference#claimwithdrawals-ilwq1) - Claims finalized Lido withdrawals for previously created request IDs.

### Events

None.

### Errors

None.

### Access / Roles

None.

### Interacts With

None.

### Missing Links

None.

## ILifetimeNft (Interface)

### Purpose

ILifetimeNft defines NFT minting and metadata administration calls required by protocol modules.

### Inheritance

* `IERC721Enumerable`

### Key Methods

* [mint(...)](https://docs.cryptolegacy.app/documentation/functions-reference#mint-iln1) - Mints a new Lifetime NFT to the specified owner.
* [setMinterOperator(...)](https://docs.cryptolegacy.app/documentation/functions-reference#setminteroperator-iln1) - Grants or revokes minting permission for an address.
* [setBaseUri(...)](https://docs.cryptolegacy.app/documentation/functions-reference#setbaseuri-iln1) - Updates the base metadata URI used for token metadata.

### All Functions

* [mint(...)](https://docs.cryptolegacy.app/documentation/functions-reference#mint-iln1) - Mints a new Lifetime NFT to the specified owner.
* [setMinterOperator(...)](https://docs.cryptolegacy.app/documentation/functions-reference#setminteroperator-iln1) - Grants or revokes minting permission for an address.
* [setBaseUri(...)](https://docs.cryptolegacy.app/documentation/functions-reference#setbaseuri-iln1) - Updates the base metadata URI used for token metadata.

### Events

None.

### Errors

* [NotTheMinter](https://docs.cryptolegacy.app/documentation/errors-reference#nottheminter-iln1)

### Access / Roles

None.

### Interacts With

None.

### Missing Links

None.

## IPermit2 (Interface)

### Purpose

IPermit2 defines the token-allowance approval call used by the Uniswap V4 beneficiary-swap plugin before handing control to the Universal Router.

### Inheritance

None.

### Key Methods

* [approve(...)](https://docs.cryptolegacy.app/documentation/functions-reference#approve-ipm21) - Grants a spender an ERC20 transfer allowance through Permit2.

### All Functions

* [approve(...)](https://docs.cryptolegacy.app/documentation/functions-reference#approve-ipm21) - Grants a spender an ERC20 transfer allowance through Permit2.

### Events

None.

### Errors

None.

### Access / Roles

None.

### Interacts With

None.

### Missing Links

None.

## IPluginsRegistry (Interface)

### Purpose

IPluginsRegistry defines plugin registration and plugin-metadata query functions.

### Inheritance

None.

### Key Methods

* [getPluginDescriptionBlockNumbers(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getplugindescriptionblocknumbers-ipr1) - Returns the history of description update block numbers for a plugin.
* [isPluginRegistered(...)](https://docs.cryptolegacy.app/documentation/functions-reference#ispluginregistered-ipr1) - Indicates whether a plugin is registered in the registry.
* [addPlugin(...)](https://docs.cryptolegacy.app/documentation/functions-reference#addplugin-ipr1) - Registers a new plugin address with an accompanying description.
* [addPluginDescription(...)](https://docs.cryptolegacy.app/documentation/functions-reference#addplugindescription-ipr1) - Appends an additional description entry for an existing plugin.
* [removePlugin(...)](https://docs.cryptolegacy.app/documentation/functions-reference#removeplugin-ipr1) - Deregisters a plugin and removes it from the registry list.

### All Functions

* [getPluginDescriptionBlockNumbers(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getplugindescriptionblocknumbers-ipr1) - Returns the history of description update block numbers for a plugin.
* [isPluginRegistered(...)](https://docs.cryptolegacy.app/documentation/functions-reference#ispluginregistered-ipr1) - Indicates whether a plugin is registered in the registry.
* [addPlugin(...)](https://docs.cryptolegacy.app/documentation/functions-reference#addplugin-ipr1) - Registers a new plugin address with an accompanying description.
* [addPluginDescription(...)](https://docs.cryptolegacy.app/documentation/functions-reference#addplugindescription-ipr1) - Appends an additional description entry for an existing plugin.
* [removePlugin(...)](https://docs.cryptolegacy.app/documentation/functions-reference#removeplugin-ipr1) - Deregisters a plugin and removes it from the registry list.

### Events

* [AddPlugin](https://docs.cryptolegacy.app/documentation/events-reference#addplugin-ipr1)
* [AddPluginDescription](https://docs.cryptolegacy.app/documentation/events-reference#addplugindescription-ipr1)
* [RemovePlugin](https://docs.cryptolegacy.app/documentation/events-reference#removeplugin-ipr1)

### Errors

None.

### Access / Roles

None.

### Interacts With

None.

### Missing Links

None.

## ISafeMinimalMultisig (Interface)

### Purpose

ISafeMinimalMultisig defines proposal lifecycle and signature-voting structures for multisig flows.

### Inheritance

None.

### Key Methods

None.

### All Functions

None.

### Events

* [CreateSafeMinimalMultisigProposal](https://docs.cryptolegacy.app/documentation/events-reference#createsafeminimalmultisigproposal-ism1)
* [CancelSafeMinimalMultisigProposal](https://docs.cryptolegacy.app/documentation/events-reference#cancelsafeminimalmultisigproposal-ism1)
* [ConfirmSafeMinimalMultisigProposal](https://docs.cryptolegacy.app/documentation/events-reference#confirmsafeminimalmultisigproposal-ism1)
* [ExecuteSafeMinimalMultisigProposal](https://docs.cryptolegacy.app/documentation/events-reference#executesafeminimalmultisigproposal-ism1)
* [SetVotersAndConfirmations](https://docs.cryptolegacy.app/documentation/events-reference#setvotersandconfirmations-ism1)
* [SetConfirmations](https://docs.cryptolegacy.app/documentation/events-reference#setconfirmations-ism1)
* [AddHeldEth](https://docs.cryptolegacy.app/documentation/events-reference#addheldeth-ism1)
* [WithdrawHeldEth](https://docs.cryptolegacy.app/documentation/events-reference#withdrawheldeth-ism1)

### Errors

* [MultisigProposalNotPending](https://docs.cryptolegacy.app/documentation/errors-reference#multisigproposalnotpending-ism1)
* [MultisigNotConfirmed](https://docs.cryptolegacy.app/documentation/errors-reference#multisignotconfirmed-ism1)
* [MultisigExecutionFailed](https://docs.cryptolegacy.app/documentation/errors-reference#multisigexecutionfailed-ism1)
* [MultisigMethodNotAllowed](https://docs.cryptolegacy.app/documentation/errors-reference#multisigmethodnotallowed-ism1)
* [MultisigVoterNotAllowed](https://docs.cryptolegacy.app/documentation/errors-reference#multisigvoternotallowed-ism1)
* [MultisigOnlyExecutor](https://docs.cryptolegacy.app/documentation/errors-reference#multisigonlyexecutor-ism1)
* [MultisigIncorrectRequiredConfirmations](https://docs.cryptolegacy.app/documentation/errors-reference#multisigincorrectrequiredconfirmations-ism1)
* [MultisigNothingToWithdraw](https://docs.cryptolegacy.app/documentation/errors-reference#multisignothingtowithdraw-ism1)
* [TransferFeeFailed](https://docs.cryptolegacy.app/documentation/errors-reference#transferfeefailed-ism1)

### Access / Roles

None.

### Interacts With

None.

### Missing Links

None.

## ISignatureRoleTimelock (Interface)

### Purpose

ISignatureRoleTimelock defines role assignment, signature mapping, and scheduled-call state for timelocked execution.

### Inheritance

None.

### Key Methods

None.

### All Functions

None.

### Events

* [SetMaxExecutionPeriod](https://docs.cryptolegacy.app/documentation/events-reference#setmaxexecutionperiod-isrt1)
* [AddRoleAccount](https://docs.cryptolegacy.app/documentation/events-reference#addroleaccount-isrt1)
* [RemoveRoleAccount](https://docs.cryptolegacy.app/documentation/events-reference#removeroleaccount-isrt1)
* [AddSignatureRole](https://docs.cryptolegacy.app/documentation/events-reference#addsignaturerole-isrt1)
* [RemoveSignatureRole](https://docs.cryptolegacy.app/documentation/events-reference#removesignaturerole-isrt1)
* [AddTarget](https://docs.cryptolegacy.app/documentation/events-reference#addtarget-isrt1)
* [RemoveTarget](https://docs.cryptolegacy.app/documentation/events-reference#removetarget-isrt1)
* [CallScheduled](https://docs.cryptolegacy.app/documentation/events-reference#callscheduled-isrt1)
* [CallExecuted](https://docs.cryptolegacy.app/documentation/events-reference#callexecuted-isrt1)
* [CallCanceled](https://docs.cryptolegacy.app/documentation/events-reference#callcanceled-isrt1)

### Errors

* [DisabledFunction](https://docs.cryptolegacy.app/documentation/errors-reference#disabledfunction-isrt1)
* [AlreadyHaveRole](https://docs.cryptolegacy.app/documentation/errors-reference#alreadyhaverole-isrt1)
* [DoesntHaveRole](https://docs.cryptolegacy.app/documentation/errors-reference#doesnthaverole-isrt1)
* [RoleDontExist](https://docs.cryptolegacy.app/documentation/errors-reference#roledontexist-isrt1)
* [CallerNotCurrentAddress](https://docs.cryptolegacy.app/documentation/errors-reference#callernotcurrentaddress-isrt1)
* [IncorrectSignatureIndex](https://docs.cryptolegacy.app/documentation/errors-reference#incorrectsignatureindex-isrt1)
* [IncorrectRoleIndex](https://docs.cryptolegacy.app/documentation/errors-reference#incorrectroleindex-isrt1)
* [CallFailed](https://docs.cryptolegacy.app/documentation/errors-reference#callfailed-isrt1)
* [CallNotScheduled](https://docs.cryptolegacy.app/documentation/errors-reference#callnotscheduled-isrt1)
* [NotPending](https://docs.cryptolegacy.app/documentation/errors-reference#notpending-isrt1)
* [TimelockActive](https://docs.cryptolegacy.app/documentation/errors-reference#timelockactive-isrt1)
* [TimelockExpired](https://docs.cryptolegacy.app/documentation/errors-reference#timelockexpired-isrt1)
* [CallerHaveNoRequiredRole](https://docs.cryptolegacy.app/documentation/errors-reference#callerhavenorequiredrole-isrt1)
* [CallAlreadyScheduled](https://docs.cryptolegacy.app/documentation/errors-reference#callalreadyscheduled-isrt1)
* [SignatureAlreadyExists](https://docs.cryptolegacy.app/documentation/errors-reference#signaturealreadyexists-isrt1)
* [SignatureTimeLockNotSet](https://docs.cryptolegacy.app/documentation/errors-reference#signaturetimelocknotset-isrt1)
* [OutOfTimelockBounds](https://docs.cryptolegacy.app/documentation/errors-reference#outoftimelockbounds-isrt1)
* [OutOfMaxExecutionPeriodBounds](https://docs.cryptolegacy.app/documentation/errors-reference#outofmaxexecutionperiodbounds-isrt1)

### Access / Roles

None.

### Interacts With

None.

### Missing Links

None.

## IStataToken (Interface)

### Purpose

IStataToken defines the wrapped-aToken interface used by the Aave beneficiary plugin for minting and redeeming Stata positions.

### Inheritance

None.

### Key Methods

* [deposit(...)](https://docs.cryptolegacy.app/documentation/functions-reference#deposit-ista1) - Deposits reserve assets into a StataToken vault and mints shares.
* [redeem(...)](https://docs.cryptolegacy.app/documentation/functions-reference#redeem-ista1) - Redeems StataToken shares for the underlying reserve asset.
* [depositATokens(...)](https://docs.cryptolegacy.app/documentation/functions-reference#depositatokens-ista1) - Deposits aTokens into the StataToken vault and mints shares.
* [redeemATokens(...)](https://docs.cryptolegacy.app/documentation/functions-reference#redeematokens-ista1) - Redeems StataToken shares directly into aTokens.

### All Functions

* [deposit(...)](https://docs.cryptolegacy.app/documentation/functions-reference#deposit-ista1) - Deposits reserve assets into a StataToken vault and mints shares.
* [redeem(...)](https://docs.cryptolegacy.app/documentation/functions-reference#redeem-ista1) - Redeems StataToken shares for the underlying reserve asset.
* [depositATokens(...)](https://docs.cryptolegacy.app/documentation/functions-reference#depositatokens-ista1) - Deposits aTokens into the StataToken vault and mints shares.
* [redeemATokens(...)](https://docs.cryptolegacy.app/documentation/functions-reference#redeematokens-ista1) - Redeems StataToken shares directly into aTokens.
* [asset(...)](https://docs.cryptolegacy.app/documentation/functions-reference#asset-ista1) - Returns the underlying reserve asset tracked by the StataToken vault.
* [balanceOf(...)](https://docs.cryptolegacy.app/documentation/functions-reference#balanceof-ista1) - Returns the StataToken share balance held by an account.

### Events

None.

### Errors

None.

### Access / Roles

None.

### Interacts With

None.

### Missing Links

None.

## IStataTokenFactory (Interface)

### Purpose

IStataTokenFactory defines the lookup and deployment interface for Stata token wrappers that the Aave beneficiary plugin uses when converting between aTokens and wrapped positions.

### Inheritance

None.

### Key Methods

* [getStataToken(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getstatatoken-istf1) - Resolves the StataToken vault address for an underlying reserve asset.
* [createStataTokens(...)](https://docs.cryptolegacy.app/documentation/functions-reference#createstatatokens-istf1) - Deploys StataToken vaults for one or more underlying reserve assets.

### All Functions

* [getStataToken(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getstatatoken-istf1) - Resolves the StataToken vault address for an underlying reserve asset.
* [createStataTokens(...)](https://docs.cryptolegacy.app/documentation/functions-reference#createstatatokens-istf1) - Deploys StataToken vaults for one or more underlying reserve assets.

### Events

None.

### Errors

None.

### Access / Roles

None.

### Interacts With

None.

### Missing Links

None.

## ITrustedGuardiansPlugin (Interface)

### Purpose

ITrustedGuardiansPlugin defines guardian-plugin state checks used by integrations and plugins.

### Inheritance

None.

### Key Methods

* [isGuardiansInitialized(...)](https://docs.cryptolegacy.app/documentation/functions-reference#isguardiansinitialized-itgp1) - Reports whether the guardian configuration has been fully initialised.

### All Functions

* [isGuardiansInitialized()](https://docs.cryptolegacy.app/documentation/functions-reference#isguardiansinitialized-itgp1) - Reports whether the guardian configuration has been fully initialised.

### Events

* [SetGuardian](https://docs.cryptolegacy.app/documentation/events-reference#setguardian-itgp1)
* [GuardiansVoteForDistribution](https://docs.cryptolegacy.app/documentation/events-reference#guardiansvotefordistribution-itgp1)
* [GuardiansDistributionStartSet](https://docs.cryptolegacy.app/documentation/events-reference#guardiansdistributionstartset-itgp1)
* [SetGuardiansConfig](https://docs.cryptolegacy.app/documentation/events-reference#setguardiansconfig-itgp1)
* [ResetGuardiansVoting](https://docs.cryptolegacy.app/documentation/events-reference#resetguardiansvoting-itgp1)
* [ClearGuardiansVoted](https://docs.cryptolegacy.app/documentation/events-reference#clearguardiansvoted-itgp1)

### Errors

* [NotGuardian](https://docs.cryptolegacy.app/documentation/errors-reference#notguardian-itgp1)
* [ZeroGuardian](https://docs.cryptolegacy.app/documentation/errors-reference#zeroguardian-itgp1)
* [ThresholdDontMet](https://docs.cryptolegacy.app/documentation/errors-reference#thresholddontmet-itgp1)
* [ThresholdTooBig](https://docs.cryptolegacy.app/documentation/errors-reference#thresholdtoobig-itgp1)
* [GuardianAlreadyVoted](https://docs.cryptolegacy.app/documentation/errors-reference#guardianalreadyvoted-itgp1)
* [GuardiansTimeoutCantBeZero](https://docs.cryptolegacy.app/documentation/errors-reference#guardianstimeoutcantbezero-itgp1)
* [MaxGuardiansTimeout](https://docs.cryptolegacy.app/documentation/errors-reference#maxguardianstimeout-itgp1)

### Access / Roles

None.

### Interacts With

None.

### Missing Links

None.

## IUniversalRouter (Interface)

### Purpose

IUniversalRouter defines the command-batch execution surface used by the Uniswap V4 beneficiary plugin to route exact-input swaps.

### Inheritance

None.

### Key Methods

* [execute(...)](https://docs.cryptolegacy.app/documentation/functions-reference#execute-iur1) - Executes a Universal Router command bundle before the deadline expires.

### All Functions

* [execute(...)](https://docs.cryptolegacy.app/documentation/functions-reference#execute-iur1) - Executes a Universal Router command bundle before the deadline expires.

### Events

None.

### Errors

None.

### Access / Roles

None.

### Interacts With

None.

### Missing Links

None.

## IWETH (Interface)

### Purpose

IWETH defines the wrapped-ETH mint, burn, approval, and balance calls used by helper contracts and plugins that bridge between native ETH and ERC-20 WETH.

### Inheritance

None.

### Key Methods

* [deposit(...)](https://docs.cryptolegacy.app/documentation/functions-reference#deposit-iweth1) - Wraps native ETH into WETH.
* [withdraw(...)](https://docs.cryptolegacy.app/documentation/functions-reference#withdraw-iweth1) - Unwraps WETH back into native ETH.
* [approve(...)](https://docs.cryptolegacy.app/documentation/functions-reference#approve-iweth1) - Approves a spender to transfer WETH on the caller's behalf.

### All Functions

* [deposit(...)](https://docs.cryptolegacy.app/documentation/functions-reference#deposit-iweth1) - Wraps native ETH into WETH.
* [withdraw(...)](https://docs.cryptolegacy.app/documentation/functions-reference#withdraw-iweth1) - Unwraps WETH back into native ETH.
* [approve(...)](https://docs.cryptolegacy.app/documentation/functions-reference#approve-iweth1) - Approves a spender to transfer WETH on the caller's behalf.
* [balanceOf(...)](https://docs.cryptolegacy.app/documentation/functions-reference#balanceof-iweth1) - Returns the WETH token balance held by an address.

### Events

None.

### Errors

None.

### Access / Roles

None.

### Interacts With

None.

### Missing Links

None.

## IWstETH (Interface)

### Purpose

IWstETH defines wrapped-stETH conversion calls used by the Lido beneficiary plugin when moving between stETH and wstETH positions.

### Inheritance

None.

### Key Methods

* [wrap(...)](https://docs.cryptolegacy.app/documentation/functions-reference#wrap-iwsteth1) - Wraps stETH into non-rebasing wstETH shares.
* [unwrap(...)](https://docs.cryptolegacy.app/documentation/functions-reference#unwrap-iwsteth1) - Unwraps wstETH into rebasing stETH.

### All Functions

* [wrap(...)](https://docs.cryptolegacy.app/documentation/functions-reference#wrap-iwsteth1) - Wraps stETH into non-rebasing wstETH shares.
* [unwrap(...)](https://docs.cryptolegacy.app/documentation/functions-reference#unwrap-iwsteth1) - Unwraps wstETH into rebasing stETH.

### Events

None.

### Errors

None.

### Access / Roles

None.

### Interacts With

None.

### Missing Links

None.

## DiamondLoupeFacet

### Purpose

DiamondLoupeFacet implements EIP-2535 loupe views for facet discovery and selector introspection.

### Inheritance

* `IDiamondLoupe`
* `IERC165`

### Key Methods

* [facets(...)](https://docs.cryptolegacy.app/documentation/functions-reference#facets-dlf1) - Lists every facet installed on the diamond along with their selectors.
* [facetFunctionSelectors(...)](https://docs.cryptolegacy.app/documentation/functions-reference#facetfunctionselectors-dlf1) - Returns the selectors exposed by a single facet.
* [facetAddresses(...)](https://docs.cryptolegacy.app/documentation/functions-reference#facetaddresses-dlf1) - Returns the ordered list of facet addresses in the diamond.
* [facetAddress(...)](https://docs.cryptolegacy.app/documentation/functions-reference#facetaddress-dlf1) - Resolves the facet address implementing a given selector, with plugin-aware fallback.
* [storageFacetAddress(...)](https://docs.cryptolegacy.app/documentation/functions-reference#storagefacetaddress-dlf1) - Reads the raw facet address mapped to a selector without plugin fallback.
* [supportsInterface(...)](https://docs.cryptolegacy.app/documentation/functions-reference#supportsinterface-dlf1) - Reports ERC-165 interface support flags for the diamond.

### All Functions

* [facets()](https://docs.cryptolegacy.app/documentation/functions-reference#facets-dlf1) - Lists every facet installed on the diamond along with their selectors.
* [facetFunctionSelectors(...)](https://docs.cryptolegacy.app/documentation/functions-reference#facetfunctionselectors-dlf1) - Returns the selectors exposed by a single facet.
* [facetAddresses()](https://docs.cryptolegacy.app/documentation/functions-reference#facetaddresses-dlf1) - Returns the ordered list of facet addresses in the diamond.
* [facetAddress(...)](https://docs.cryptolegacy.app/documentation/functions-reference#facetaddress-dlf1) - Resolves the facet address implementing a given selector, with plugin-aware fallback.
* [storageFacetAddress(...)](https://docs.cryptolegacy.app/documentation/functions-reference#storagefacetaddress-dlf1) - Reads the raw facet address mapped to a selector without plugin fallback.
* [supportsInterface(...)](https://docs.cryptolegacy.app/documentation/functions-reference#supportsinterface-dlf1) - Reports ERC-165 interface support flags for the diamond.

### Events

None.

### Errors

None.

### Access / Roles

None.

### Interacts With

* `ICryptoLegacyPlugin`
* `LibCryptoLegacyPlugins`
* `LibDiamond`

### Missing Links

None.

## LibCLUtils (Library)

### Purpose

LibCLUtils provides shared ERC-20 approval helpers used by migration and plugin flows. It centralizes the low-level approval call so callers can handle failures consistently.

### Inheritance

None.

### Key Methods

* [approveToken(...)](https://docs.cryptolegacy.app/documentation/functions-reference#approvetoken-lclu1) - Performs a low-level ERC-20 approval call and normalizes non-standard return behavior.

### All Functions

* [approveToken(...)](https://docs.cryptolegacy.app/documentation/functions-reference#approvetoken-lclu1) - Performs a low-level ERC-20 approval call and normalizes non-standard return behavior.

### Events

None.

### Errors

* [ApprovalFailed](https://docs.cryptolegacy.app/documentation/errors-reference#approvalfailed-lclu1)

### Access / Roles

None.

### Interacts With

None.

### Missing Links

None.

## LibClaimMigrationCore (Library)

### Purpose

LibClaimMigrationCore provides the fixed-point math and shared distribution-sync helpers used by both one-step and two-step beneficiary claim migrations.

### Inheritance

None.

### Key Methods

* [calculateFractionAndRatio(...)](https://docs.cryptolegacy.app/documentation/functions-reference#calculatefractionandratio-lcmc1) - Calculates the migration fraction and exchange ratio for a conversion step.
* [applyMigrationFormula(...)](https://docs.cryptolegacy.app/documentation/functions-reference#applymigrationformula-lcmc1) - Reallocates one beneficiary's claimed balances across a migration boundary.
* [syncDistributions(...)](https://docs.cryptolegacy.app/documentation/functions-reference#syncdistributions-lcmc1) - Updates distribution totals and last-balance snapshots after a migration.

### All Functions

* [calculateFractionAndRatio(...)](https://docs.cryptolegacy.app/documentation/functions-reference#calculatefractionandratio-lcmc1) - Calculates the migration fraction and exchange ratio for a conversion step.
* [applyMigrationFormula(...)](https://docs.cryptolegacy.app/documentation/functions-reference#applymigrationformula-lcmc1) - Reallocates one beneficiary's claimed balances across a migration boundary.
* [syncDistributions(...)](https://docs.cryptolegacy.app/documentation/functions-reference#syncdistributions-lcmc1) - Updates distribution totals and last-balance snapshots after a migration.

### Events

None.

### Errors

* [MigrationInvalidDelta](https://docs.cryptolegacy.app/documentation/errors-reference#migrationinvaliddelta-lcmc1)
* [MigrationAmountTooSmall](https://docs.cryptolegacy.app/documentation/errors-reference#migrationamounttoosmall-lcmc1)

### Access / Roles

None.

### Interacts With

* `ICryptoLegacy`

### Missing Links

None.

## LibOneStepClaimMigration (Library)

### Purpose

LibOneStepClaimMigration provides the immediate claim-migration path that updates beneficiary accounting in a single execution flow.

### Inheritance

None.

### Key Methods

* [migrate(...)](https://docs.cryptolegacy.app/documentation/functions-reference#migrate-loscm1) - Migrates beneficiary claim accounting for an atomic token conversion.
* [\_migrateClaims(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_migrateclaims-loscm1) - Applies the migration formula to every beneficiary in the current CryptoLegacy set.

### All Functions

* [migrate(...)](https://docs.cryptolegacy.app/documentation/functions-reference#migrate-loscm1) - Migrates beneficiary claim accounting for an atomic token conversion.
* [\_migrateClaims(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_migrateclaims-loscm1) - Applies the migration formula to every beneficiary in the current CryptoLegacy set.

### Events

None.

### Errors

None.

### Access / Roles

None.

### Interacts With

* `ICryptoLegacy`
* `LibClaimMigrationCore`

### Missing Links

None.

## LibTwoStepClaimMigration (Library)

### Purpose

LibTwoStepClaimMigration provides the delayed claim-migration flow that stages pending state, finalizes migrations later, or abandons them when necessary.

### Inheritance

None.

### Key Methods

* [start(...)](https://docs.cryptolegacy.app/documentation/functions-reference#start-ltscm1) - Starts a delayed claim migration when the source token leaves before the destination token arrives.
* [complete(...)](https://docs.cryptolegacy.app/documentation/functions-reference#complete-ltscm1) - Completes a delayed migration after the destination token arrives.
* [abandon(...)](https://docs.cryptolegacy.app/documentation/functions-reference#abandon-ltscm1) - Abandons an active pending migration and restores cached claim state.

### All Functions

* [isActive(...)](https://docs.cryptolegacy.app/documentation/functions-reference#isactive-ltscm1) - Returns whether a pending two-step migration is currently active.
* [getPendingTokens(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getpendingtokens-ltscm1) - Returns the token pair involved in the active pending migration.
* [start(...)](https://docs.cryptolegacy.app/documentation/functions-reference#start-ltscm1) - Starts a delayed claim migration when the source token leaves before the destination token arrives.
* [complete(...)](https://docs.cryptolegacy.app/documentation/functions-reference#complete-ltscm1) - Completes a delayed migration after the destination token arrives.
* [abandon(...)](https://docs.cryptolegacy.app/documentation/functions-reference#abandon-ltscm1) - Abandons an active pending migration and restores cached claim state.
* [\_applyPendingMigration(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_applypendingmigration-ltscm1) - Applies the cached pending-migration snapshot to all beneficiaries.

### Events

None.

### Errors

* [NoPendingMigration](https://docs.cryptolegacy.app/documentation/errors-reference#nopendingmigration-ltscm1)
* [PendingMigrationAlreadyExists](https://docs.cryptolegacy.app/documentation/errors-reference#pendingmigrationalreadyexists-ltscm1)
* [TokenAlreadyLocked](https://docs.cryptolegacy.app/documentation/errors-reference#tokenalreadylocked-ltscm1)

### Access / Roles

None.

### Interacts With

* `ICryptoLegacy`
* `LibClaimMigrationCore`

### Missing Links

None.

## LibCreate3 (Library)

### Purpose

LibCreate3 provides low-level CREATE3 deployment primitives and deterministic address derivation helpers.

### Inheritance

None.

### Key Methods

* [codeSize(...)](https://docs.cryptolegacy.app/documentation/functions-reference#codesize-lc31) - Returns the bytecode size at a target address.
* [create3(...)](https://docs.cryptolegacy.app/documentation/functions-reference#create3bytes32bytes-lc31) - Deploys bytecode deterministically with CREATE3 forwarding zero ether.
* [create3(...)](https://docs.cryptolegacy.app/documentation/functions-reference#create3bytes32bytesuint256-lc31) - Deterministically deploys contracts using the CREATE3 pattern, optionally forwarding ETH.
* [addressOf(...)](https://docs.cryptolegacy.app/documentation/functions-reference#addressof-lc31) - Computes the deterministic address yielded by CREATE3 for a given salt.

### All Functions

* [codeSize(...)](https://docs.cryptolegacy.app/documentation/functions-reference#codesize-lc31) - Returns the bytecode size at a target address.
* [create3(...)](https://docs.cryptolegacy.app/documentation/functions-reference#create3bytes32bytes-lc31) - Deploys bytecode deterministically with CREATE3 forwarding zero ether.
* [create3(...)](https://docs.cryptolegacy.app/documentation/functions-reference#create3bytes32bytesuint256-lc31) - Deterministically deploys contracts using the CREATE3 pattern, optionally forwarding ETH.
* [addressOf(...)](https://docs.cryptolegacy.app/documentation/functions-reference#addressof-lc31) - Computes the deterministic address yielded by CREATE3 for a given salt.

### Events

None.

### Errors

* [ErrorCreatingProxy](https://docs.cryptolegacy.app/documentation/errors-reference#errorcreatingproxy-lc31)
* [ErrorCreatingContract](https://docs.cryptolegacy.app/documentation/errors-reference#errorcreatingcontract-lc31)
* [TargetAlreadyExists](https://docs.cryptolegacy.app/documentation/errors-reference#targetalreadyexists-lc31)

### Access / Roles

None.

### Interacts With

None.

### Missing Links

None.

## LibCryptoLegacy (Library)

### Purpose

LibCryptoLegacy provides shared storage accessors and validation checks for core protocol logic.

### Inheritance

None.

### Key Methods

* [getCryptoLegacyStorage(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getcryptolegacystorage-lcl1) - Returns the storage slot backing the CryptoLegacy diamond data.
* [\_checkDisabledFunc(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_checkdisabledfunc-lcl1) - Ensures a flagged core function is not disabled by configuration.
* [\_checkDistributionStart(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_checkdistributionstart-lcl1) - Guards flows that must execute before distribution begins.
* [\_isDistributionStarted(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_isdistributionstarted-lcl1) - Reports whether the distribution window is active.
* [\_checkOwner(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_checkowner-lcl1) - Enforces that the caller is the diamond owner and the initial fee was paid.
* [\_checkSenderOwner(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_checksenderowner-lcl1) - Validates that `msg.sender` matches the diamond owner.
* [\_checkPause(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_checkpause-lcl1) - Blocks execution when the CryptoLegacy contract is paused.
* [\_setPause(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_setpause-lcl1) - Updates the pause flag while distribution is inactive.

### All Functions

* [getCryptoLegacyStorage()](https://docs.cryptolegacy.app/documentation/functions-reference#getcryptolegacystorage-lcl1) - Returns the storage slot backing the CryptoLegacy diamond data.
* [\_checkDisabledFunc(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_checkdisabledfunc-lcl1) - Ensures a flagged core function is not disabled by configuration.
* [\_checkDistributionStart(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_checkdistributionstart-lcl1) - Guards flows that must execute before distribution begins.
* [\_isDistributionStarted(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_isdistributionstarted-lcl1) - Reports whether the distribution window is active.
* [\_checkOwner()](https://docs.cryptolegacy.app/documentation/functions-reference#_checkowner-lcl1) - Enforces that the caller is the diamond owner and the initial fee was paid.
* [\_checkSenderOwner()](https://docs.cryptolegacy.app/documentation/functions-reference#_checksenderowner-lcl1) - Validates that `msg.sender` matches the diamond owner.
* [\_checkPause(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_checkpause-lcl1) - Blocks execution when the CryptoLegacy contract is paused.
* [\_setPause(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_setpause-lcl1) - Updates the pause flag while distribution is inactive.
* [\_getPause(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_getpause-lcl1) - Reads the pause status from storage.
* [\_checkAddressIsBeneficiary(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_checkaddressisbeneficiary-lcl1) - Verifies that an address corresponds to a registered beneficiary.
* [\_checkDistributionReadyForBeneficiary(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_checkdistributionreadyforbeneficiary-lcl1) - Ensures the caller is a registered beneficiary and distribution is active.
* [\_checkDistributionReady(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_checkdistributionready-lcl1) - Validates that the distribution window is open.
* [\_getBeneficiariesCount(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_getbeneficiariescount-lcl1) - Returns the number of registered beneficiaries.
* [\_isLifetimeActiveAndUpdate(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_islifetimeactiveandupdate-lcl1) - Queries the build manager to determine if a lifetime NFT is locked and updates state accordingly.
* [\_takeFee(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_takefee-lcl1) - Core fee processing routine covering lifetime, build-manager, and manual transfer paths.
* [\_checkFee(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_checkfee-lcl1) - Validates a fee payment matches expectations.
* [\_checkNoFee()](https://docs.cryptolegacy.app/documentation/functions-reference#_checknofee-lcl1) - Reverts when `msg.value` is non-zero.
* [\_sendFeeByTransfer(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_sendfeebytransfer-lcl1) - Pays fees via direct ETH transfers, optionally splitting referral amounts.
* [\_transferFee(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_transferfee-lcl1) - Performs a low-level ETH transfer with a configurable gas stipend.
* [\_tokenPrepareToDistribute(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_tokenpreparetodistribute-lcl1) - Reconciles token distribution state with the contract’s current ERC20 balance.
* [\_getBeneficiaryClaimed(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_getbeneficiaryclaimed-lcl1) - Reads the claimed amount for a beneficiary/token pair.
* [\_setBeneficiaryClaimed(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_setbeneficiaryclaimed-lcl1) - Updates the claimed amount for a beneficiary/token pair.
* [\_getTotalClaimed(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_gettotalclaimed-lcl1) - Aggregates claimed amounts for a token across all beneficiaries.
* [\_getStartAndEndDate(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_getstartandenddate-lcl1) - Calculates a beneficiary’s vesting window based on distribution start.
* [\_getVestedAndClaimedAmount(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_getvestedandclaimedamount-lcl1) - Computes vesting progress and claimable amounts for a beneficiary/token pair.
* [\_getBeneficiaryConfigAndVesting(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_getbeneficiaryconfigandvesting-lcl1) - Retrieves config and vesting storage for a beneficiary, enforcing existence.
* [\_setCryptoLegacyToBeneficiaryRegistry(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_setcryptolegacytobeneficiaryregistry-lcl1) - Adds or removes a single entity from the external BeneficiaryRegistry.
* [\_setCryptoLegacyListToBeneficiaryRegistry(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_setcryptolegacylisttobeneficiaryregistry-lcl1) - Updates recovery address lists in the BeneficiaryRegistry.
* [\_getBeneficiaryRegistry(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_getbeneficiaryregistry-lcl1) - Retrieves the BeneficiaryRegistry from the build manager, swallowing errors.
* [\_gasBySelector(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_gasbyselector-lcl1) - Computes the gas stipend for an external call, applying the configured multiplier.
* [\_gasWithoutMultiplierBySelector(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_gaswithoutmultiplierbyselector-lcl1) - Provides base gas estimates for known external calls.
* [\_updateOwnerInBeneficiaryRegistry(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_updateownerinbeneficiaryregistry-lcl1) - Swaps the owner entry in the BeneficiaryRegistry.
* [\_transferTreasuryTokensToLegacy(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_transfertreasurytokenstolegacy-lcl1) - Moves ERC20 balances from guardians/holders into the CryptoLegacy contract.
* [\_transferTokensFromLegacy(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_transfertokensfromlegacy-lcl1) - Sends ERC20 tokens from the CryptoLegacy contract to specified recipients.
* [\_addressToHash(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_addresstohash-lcl1) - Returns the keccak256 hash of an address.
* [\_addressWithSaltToHash(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_addresswithsalttohash-lcl1) - Hashes an address together with an additional salt.

### Events

* [PauseSet](https://docs.cryptolegacy.app/documentation/events-reference#pauseset-icl1)
* [FeePaidByLifetime](https://docs.cryptolegacy.app/documentation/events-reference#feepaidbylifetime-icl1)
* [FeePaidByDefault](https://docs.cryptolegacy.app/documentation/events-reference#feepaidbydefault-icl1)
* [FeePaidByTransfer](https://docs.cryptolegacy.app/documentation/events-reference#feepaidbytransfer-icl1)
* [FeeSentToRefByTransfer](https://docs.cryptolegacy.app/documentation/events-reference#feesenttorefbytransfer-icl1)
* [TransferTreasuryTokensToLegacy](https://docs.cryptolegacy.app/documentation/events-reference#transfertreasurytokenstolegacy-icl1)
* [TransferTokensFromLegacy](https://docs.cryptolegacy.app/documentation/events-reference#transfertokensfromlegacy-icl1)
* [SkipSendFeeByTransfer](https://docs.cryptolegacy.app/documentation/events-reference#skipsendfeebytransfer-icl1)
* [IsLifetimeNftLockedAndUpdateCatch](https://docs.cryptolegacy.app/documentation/events-reference#islifetimenftlockedandupdatecatch-icl1)
* [GetUpdateFeeCatch](https://docs.cryptolegacy.app/documentation/events-reference#getupdatefeecatch-icl1)
* [PayFeeCatch](https://docs.cryptolegacy.app/documentation/events-reference#payfeecatch-icl1)
* [SetCryptoLegacyOwnerCatch](https://docs.cryptolegacy.app/documentation/events-reference#setcryptolegacyownercatch-icl1)
* [SetCryptoLegacyBeneficiaryCatch](https://docs.cryptolegacy.app/documentation/events-reference#setcryptolegacybeneficiarycatch-icl1)
* [SetCryptoLegacyGuardianCatch](https://docs.cryptolegacy.app/documentation/events-reference#setcryptolegacyguardiancatch-icl1)
* [SetCryptoLegacyRecoveryAddressesCatch](https://docs.cryptolegacy.app/documentation/events-reference#setcryptolegacyrecoveryaddressescatch-icl1)
* [BeneficiaryRegistryCatch](https://docs.cryptolegacy.app/documentation/events-reference#beneficiaryregistrycatch-icl1)
* [BeneficiaryRegistryNotDefined](https://docs.cryptolegacy.app/documentation/events-reference#beneficiaryregistrynotdefined-icl1)

### Errors

* [BeneficiaryNotExist](https://docs.cryptolegacy.app/documentation/errors-reference#beneficiarynotexist-icl1)
* [ChallengePeriodStarted](https://docs.cryptolegacy.app/documentation/errors-reference#challengeperiodstarted-icl1)
* [DisabledFunc](https://docs.cryptolegacy.app/documentation/errors-reference#disabledfunc-icl1)
* [DistributionStarted](https://docs.cryptolegacy.app/documentation/errors-reference#distributionstarted-icl1)
* [IncorrectFee](https://docs.cryptolegacy.app/documentation/errors-reference#incorrectfee-icl1)
* [IncorrectRefShare](https://docs.cryptolegacy.app/documentation/errors-reference#incorrectrefshare-icl1)
* [InitialFeeNotPaid](https://docs.cryptolegacy.app/documentation/errors-reference#initialfeenotpaid-icl1)
* [NoValueAllowed](https://docs.cryptolegacy.app/documentation/errors-reference#novalueallowed-icl1)
* [NotOwnerOfCryptoLegacy](https://docs.cryptolegacy.app/documentation/errors-reference#notownerofcryptolegacy-iclbm1)
* [NotRegisteredCryptoLegacy](https://docs.cryptolegacy.app/documentation/errors-reference#notregisteredcryptolegacy-iclbm1)
* [NotTheBeneficiary](https://docs.cryptolegacy.app/documentation/errors-reference#notthebeneficiary-icl1)
* [NotTheOwner](https://docs.cryptolegacy.app/documentation/errors-reference#nottheowner-icl1)
* [Pause](https://docs.cryptolegacy.app/documentation/errors-reference#pause-icl1)
* [TooEarly](https://docs.cryptolegacy.app/documentation/errors-reference#tooearly-icl1)
* [TooLongArray](https://docs.cryptolegacy.app/documentation/errors-reference#toolongarray-icl1)
* [TransferFeeFailed](https://docs.cryptolegacy.app/documentation/errors-reference#transferfeefailed-icl1)

### Access / Roles

None.

### Interacts With

* `ArbSys`
* `IBeneficiaryRegistry`
* `ICryptoLegacy`
* `ICryptoLegacyBuildManager`
* `ILockChainGate`
* `LibDiamond`

### Missing Links

None.

## LibCryptoLegacyDeploy (Library)

### Purpose

LibCryptoLegacyDeploy encapsulates deployment helpers and deterministic-salt derivation for protocol-instance creation paths.

### Inheritance

None.

### Key Methods

* [\_deployByCreate3(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_deploybycreate3-lcld1) - Deterministically deploys a contract via CREATE3 and records the deployment event.
* [\_getContractOwnerSalt(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_getcontractownersalt-lcld1) - Derives an owner-specific salt for CREATE3 deployments.
* [\_computeAddress(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_computeaddress-lcld1) - Predicts the deterministic CREATE3 deployment address.

### All Functions

* [\_deployByCreate3(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_deploybycreate3-lcld1) - Deterministically deploys a contract via CREATE3 and records the deployment event.
* [\_getContractOwnerSalt(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_getcontractownersalt-lcld1) - Derives an owner-specific salt for CREATE3 deployments.
* [\_computeAddress(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_computeaddress-lcld1) - Predicts the deterministic CREATE3 deployment address.

### Events

* [CryptoLegacyCreation](https://docs.cryptolegacy.app/documentation/events-reference#cryptolegacycreation-lcld1)

### Errors

* [BytecodeEmpty](https://docs.cryptolegacy.app/documentation/errors-reference#bytecodeempty-lcld1)
* [AddressMismatch](https://docs.cryptolegacy.app/documentation/errors-reference#addressmismatch-lcld1)
* [Create3Failed](https://docs.cryptolegacy.app/documentation/errors-reference#create3failed-lcld1)

### Access / Roles

None.

### Interacts With

* `LibCreate3`

### Missing Links

None.

## LibCryptoLegacyPlugins (Library)

### Purpose

LibCryptoLegacyPlugins provides plugin validation, selector registration, and plugin lifecycle helpers.

### Inheritance

None.

### Key Methods

* [\_validatePlugin(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_validateplugin-lclp1) - Ensures a plugin address is approved by the build manager.
* [\_addPluginList(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_addpluginlist-lclp1) - Wires a batch of plugins into the diamond.
* [\_removePlugin(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_removeplugin-lclp1) - Removes a plugin’s selectors from the diamond.
* [\_getFacetAddressPosition(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_getfacetaddressposition-lclp1) - Locates a facet’s index within diamond storage.
* [\_addFacetAddressIfNotExists(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_addfacetaddressifnotexists-lclp1) - Appends a new facet address to storage when necessary.
* [\_removeFacetAddress(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_removefacetaddress-lclp1) - Removes a facet address from storage using swap-and-pop.
* [addFunctions(...)](https://docs.cryptolegacy.app/documentation/functions-reference#addfunctions-lclp1) - Registers selectors from a facet in diamond storage.
* [removeFunctions(...)](https://docs.cryptolegacy.app/documentation/functions-reference#removefunctions-lclp1) - Unregisters selectors associated with a facet.

### All Functions

* [\_validatePlugin(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_validateplugin-lclp1) - Ensures a plugin address is approved by the build manager.
* [\_addPluginList(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_addpluginlist-lclp1) - Wires a batch of plugins into the diamond.
* [\_removePlugin(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_removeplugin-lclp1) - Removes a plugin’s selectors from the diamond.
* [\_getFacetAddressPosition(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_getfacetaddressposition-lclp1) - Locates a facet’s index within diamond storage.
* [\_addFacetAddressIfNotExists(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_addfacetaddressifnotexists-lclp1) - Appends a new facet address to storage when necessary.
* [\_removeFacetAddress(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_removefacetaddress-lclp1) - Removes a facet address from storage using swap-and-pop.
* [addFunctions(...)](https://docs.cryptolegacy.app/documentation/functions-reference#addfunctions-lclp1) - Registers selectors from a facet in diamond storage.
* [removeFunctions(...)](https://docs.cryptolegacy.app/documentation/functions-reference#removefunctions-lclp1) - Unregisters selectors associated with a facet.
* [\_findFacetBySelector(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_findfacetbyselector-lclp1) - Searches installed plugins for a selector match.

### Events

* [AddFunctions](https://docs.cryptolegacy.app/documentation/events-reference#addfunctions-icl1)
* [RemoveFunctions](https://docs.cryptolegacy.app/documentation/events-reference#removefunctions-icl1)

### Errors

* [CantAddFunctionThatAlreadyExists](https://docs.cryptolegacy.app/documentation/errors-reference#cantaddfunctionthatalreadyexists-icl1)
* [CantRemoveImmutableFunctions](https://docs.cryptolegacy.app/documentation/errors-reference#cantremoveimmutablefunctions-icl1)
* [FacetCantBeZero](https://docs.cryptolegacy.app/documentation/errors-reference#facetcantbezero-icl1)
* [FacetNotFound](https://docs.cryptolegacy.app/documentation/errors-reference#facetnotfound-icl1)
* [PluginNotRegistered](https://docs.cryptolegacy.app/documentation/errors-reference#pluginnotregistered-icl1)

### Access / Roles

None.

### Interacts With

* `ICryptoLegacy`
* `ICryptoLegacyPlugin`
* `LibDiamond`

### Missing Links

None.

## LibDiamond (Library)

### Purpose

LibDiamond centralizes EIP-2535 storage layout and facet-cut execution helpers.

### Inheritance

None.

### Key Methods

* [diamondStorage(...)](https://docs.cryptolegacy.app/documentation/functions-reference#diamondstorage-ld1) - Returns the Diamond storage struct anchored at the EIP-2535 slot.
* [setContractOwner(...)](https://docs.cryptolegacy.app/documentation/functions-reference#setcontractowner-ld1) - Updates the diamond owner and emits the ownership transfer event.
* [contractOwner(...)](https://docs.cryptolegacy.app/documentation/functions-reference#contractowner-ld1) - Reads the current diamond owner from storage.
* [enforceIsContractOwner(...)](https://docs.cryptolegacy.app/documentation/functions-reference#enforceiscontractowner-ld1) - Reverts unless the caller is the diamond owner.
* [diamondCut(...)](https://docs.cryptolegacy.app/documentation/functions-reference#diamondcut-ld1) - Applies a batch of facet modifications and optionally executes initialization logic.
* [addFunctions(...)](https://docs.cryptolegacy.app/documentation/functions-reference#addfunctions-ld1) - Adds new selectors for a facet during a diamond cut.
* [replaceFunctions(...)](https://docs.cryptolegacy.app/documentation/functions-reference#replacefunctions-ld1) - Swaps existing selectors to point at a new facet implementation.
* [removeFunctions(...)](https://docs.cryptolegacy.app/documentation/functions-reference#removefunctions-ld1) - Removes selectors from the diamond’s routing table.

### All Functions

* [diamondStorage()](https://docs.cryptolegacy.app/documentation/functions-reference#diamondstorage-ld1) - Returns the Diamond storage struct anchored at the EIP-2535 slot.
* [setContractOwner(...)](https://docs.cryptolegacy.app/documentation/functions-reference#setcontractowner-ld1) - Updates the diamond owner and emits the ownership transfer event.
* [contractOwner()](https://docs.cryptolegacy.app/documentation/functions-reference#contractowner-ld1) - Reads the current diamond owner from storage.
* [enforceIsContractOwner()](https://docs.cryptolegacy.app/documentation/functions-reference#enforceiscontractowner-ld1) - Reverts unless the caller is the diamond owner.
* [diamondCut(...)](https://docs.cryptolegacy.app/documentation/functions-reference#diamondcut-ld1) - Applies a batch of facet modifications and optionally executes initialization logic.
* [addFunctions(...)](https://docs.cryptolegacy.app/documentation/functions-reference#addfunctions-ld1) - Adds new selectors for a facet during a diamond cut.
* [replaceFunctions(...)](https://docs.cryptolegacy.app/documentation/functions-reference#replacefunctions-ld1) - Swaps existing selectors to point at a new facet implementation.
* [removeFunctions(...)](https://docs.cryptolegacy.app/documentation/functions-reference#removefunctions-ld1) - Removes selectors from the diamond’s routing table.
* [addFacet(...)](https://docs.cryptolegacy.app/documentation/functions-reference#addfacet-ld1) - Registers a facet address in diamond storage.
* [addFunction(...)](https://docs.cryptolegacy.app/documentation/functions-reference#addfunction-ld1) - Records a selector → facet mapping within diamond storage.
* [removeFunction(...)](https://docs.cryptolegacy.app/documentation/functions-reference#removefunction-ld1) - Deletes a selector mapping and tidies facet metadata.
* [initializeDiamondCut(...)](https://docs.cryptolegacy.app/documentation/functions-reference#initializediamondcut-ld1) - Runs optional initialization logic after a diamond cut.
* [enforceHasContractCode(...)](https://docs.cryptolegacy.app/documentation/functions-reference#enforcehascontractcode-ld1) - Asserts that a target address contains contract bytecode.

### Events

* [OwnershipTransferred](https://docs.cryptolegacy.app/documentation/events-reference#ownershiptransferred-ld1)
* [DiamondCut](https://docs.cryptolegacy.app/documentation/events-reference#diamondcut-ld1)

### Errors

* [InitializationFunctionReverted](https://docs.cryptolegacy.app/documentation/errors-reference#initializationfunctionreverted-ld1)

### Access / Roles

None.

### Interacts With

* `IDiamondCut`

### Missing Links

None.

## LibSafeMinimalBeneficiaryMultisig (Library)

### Purpose

LibSafeMinimalBeneficiaryMultisig provides beneficiary-oriented multisig validation and proposal-state helpers.

### Inheritance

None.

### Key Methods

* [\_checkIsMultisigExecutor(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_checkismultisigexecutor-lsmb1) - Verifies that the caller is the multisig executor (the contract itself).
* [\_initializationStatus(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_initializationstatus-lsmb1) - Reports whether multisig storage has been fully initialised.
* [\_getVotersAndConfirmations(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_getvotersandconfirmations-lsmb1) - Returns the beneficiary voter list and active confirmation threshold.
* [\_getProposalListWithStatuses(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_getproposallistwithstatuses-lsmb1) - Builds a list of all multisig proposals along with confirmation metadata.
* [\_getProposalWithStatus(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_getproposalwithstatus-lsmb1) - Returns a single proposal enriched with confirmation flags and derived metadata.
* [\_getRequiredConfirmations(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_getrequiredconfirmations-lsmb1) - Derives the confirmation threshold, applying defaults and clamping.
* [\_getVoters(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_getvoters-lsmb1) - Retrieves the current beneficiary voter identifiers.
* [\_getDefaultRequiredConfirmations(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_getdefaultrequiredconfirmations-lsmb1) - Computes the default confirmation threshold for the current beneficiary set.

### All Functions

* [\_checkIsMultisigExecutor()](https://docs.cryptolegacy.app/documentation/functions-reference#_checkismultisigexecutor-lsmb1) - Verifies that the caller is the multisig executor (the contract itself).
* [\_initializationStatus(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_initializationstatus-lsmb1) - Reports whether multisig storage has been fully initialised.
* [\_getVotersAndConfirmations(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_getvotersandconfirmations-lsmb1) - Returns the beneficiary voter list and active confirmation threshold.
* [\_getProposalListWithStatuses(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_getproposallistwithstatuses-lsmb1) - Builds a list of all multisig proposals along with confirmation metadata.
* [\_getProposalWithStatus(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_getproposalwithstatus-lsmb1) - Returns a single proposal enriched with confirmation flags and derived metadata.
* [\_getRequiredConfirmations(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_getrequiredconfirmations-lsmb1) - Derives the confirmation threshold, applying defaults and clamping.
* [\_getVoters(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_getvoters-lsmb1) - Retrieves the current beneficiary voter identifiers.
* [\_getDefaultRequiredConfirmations(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_getdefaultrequiredconfirmations-lsmb1) - Computes the default confirmation threshold for the current beneficiary set.
* [\_setConfirmations(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_setconfirmations-lsmb1) - Persists an explicit confirmation threshold for the current voter set.
* [\_initializeIfNot(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_initializeifnot-lsmb1) - Lazily initialises multisig settings when first needed.
* [\_propose(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_propose-lsmb1) - Creates a multisig proposal on behalf of the caller.
* [\_confirm(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_confirm-lsmb1) - Records a beneficiary confirmation for a proposal.
* [\_cancel(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_cancel-lsmb1) - Allows a voter to withdraw their confirmation (and potentially cancel the proposal).
* [\_withdrawHeldEth(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_withdrawheldeth-lsmb1) - Transfers accumulated ETH credits for a voter to a recipient.

### Events

* [SetConfirmations](https://docs.cryptolegacy.app/documentation/events-reference#setconfirmations-ism1)

### Errors

* [MultisigIncorrectRequiredConfirmations](https://docs.cryptolegacy.app/documentation/errors-reference#multisigincorrectrequiredconfirmations-ism1)

### Access / Roles

None.

### Interacts With

* `ICryptoLegacy`
* `ISafeMinimalMultisig`
* `LibCryptoLegacy`
* `LibSafeMinimalMultisig`

### Missing Links

None.

## LibSafeMinimalMultisig (Library)

### Purpose

LibSafeMinimalMultisig provides generic proposal, signature, and quorum helpers for minimal multisig flows.

### Inheritance

None.

### Key Methods

* [\_checkIsMultisigExecutor(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_checkismultisigexecutor-lsm1) - Rejects calls from anything other than the multisig executor contract.
* [\_checkIsSenderAllowed(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_checkissenderallowed-lsm1) - Authenticates the caller against the allowed voter list.
* [\_setVotersAndConfirmations(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_setvotersandconfirmations-lsm1) - Stores the authoritative voter list and quorum threshold.
* [\_initializationStatus(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_initializationstatus-lsm1) - Indicates whether multisig storage has been initialised.
* [\_calcDefaultConfirmations(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_calcdefaultconfirmations-lsm1) - Computes a majority quorum for a given voter count.
* [\_isMethodAllowed(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_ismethodallowed-lsm1) - Checks whether a selector is permitted for multisig execution.
* [\_isVoterAllowed(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_isvoterallowed-lsm1) - Determines whether a voter hash exists in the authorised set.
* [\_getConfirmedCount(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_getconfirmedcount-lsm1) - Counts confirmations recorded for a proposal.

### All Functions

* [\_checkIsMultisigExecutor()](https://docs.cryptolegacy.app/documentation/functions-reference#_checkismultisigexecutor-lsm1) - Rejects calls from anything other than the multisig executor contract.
* [\_checkIsSenderAllowed(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_checkissenderallowed-lsm1) - Authenticates the caller against the allowed voter list.
* [\_setVotersAndConfirmations(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_setvotersandconfirmations-lsm1) - Stores the authoritative voter list and quorum threshold.
* [\_initializationStatus(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_initializationstatus-lsm1) - Indicates whether multisig storage has been initialised.
* [\_calcDefaultConfirmations(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_calcdefaultconfirmations-lsm1) - Computes a majority quorum for a given voter count.
* [\_isMethodAllowed(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_ismethodallowed-lsm1) - Checks whether a selector is permitted for multisig execution.
* [\_isVoterAllowed(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_isvoterallowed-lsm1) - Determines whether a voter hash exists in the authorised set.
* [\_getConfirmedCount(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_getconfirmedcount-lsm1) - Counts confirmations recorded for a proposal.
* [\_getProposalListWithStatusesAndStorageVoters(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_getproposallistwithstatusesandstoragevoters-lsm1) - Returns every proposal alongside stored voter metadata.
* [\_getProposalWithStatus(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_getproposalwithstatus-lsm1) - Derives a proposal’s confirmation status relative to a voter set.
* [\_propose(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_propose-lsm1) - Creates a proposal and records the proposer’s confirmation.
* [\_getPendingProposalForVoter(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_getpendingproposalforvoter-lsm1) - Fetches a proposal and authenticated voter, ensuring it is still pending.
* [\_cancel(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_cancel-lsm1) - Removes a voter’s confirmation and cancels the proposal if no approvals remain.
* [\_confirm(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_confirm-lsm1) - Records a voter’s confirmation and executes the proposal upon quorum.
* [\_execute(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_execute-lsm1) - Performs the proposal’s target call once quorum is achieved.
* [\_updateHeldEth(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_updateheldeth-lsm1) - Credits any leftover ETH from proposal execution to a voter.
* [\_withdrawHeldEth(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_withdrawheldeth-lsm1) - Withdraws a voter’s accumulated ETH balance to a recipient.

### Events

* [CreateSafeMinimalMultisigProposal](https://docs.cryptolegacy.app/documentation/events-reference#createsafeminimalmultisigproposal-ism1)
* [CancelSafeMinimalMultisigProposal](https://docs.cryptolegacy.app/documentation/events-reference#cancelsafeminimalmultisigproposal-ism1)
* [ConfirmSafeMinimalMultisigProposal](https://docs.cryptolegacy.app/documentation/events-reference#confirmsafeminimalmultisigproposal-ism1)
* [ExecuteSafeMinimalMultisigProposal](https://docs.cryptolegacy.app/documentation/events-reference#executesafeminimalmultisigproposal-ism1)
* [SetVotersAndConfirmations](https://docs.cryptolegacy.app/documentation/events-reference#setvotersandconfirmations-ism1)
* [AddHeldEth](https://docs.cryptolegacy.app/documentation/events-reference#addheldeth-ism1)
* [WithdrawHeldEth](https://docs.cryptolegacy.app/documentation/events-reference#withdrawheldeth-ism1)

### Errors

* [MultisigExecutionFailed](https://docs.cryptolegacy.app/documentation/errors-reference#multisigexecutionfailed-ism1)
* [MultisigIncorrectRequiredConfirmations](https://docs.cryptolegacy.app/documentation/errors-reference#multisigincorrectrequiredconfirmations-ism1)
* [MultisigMethodNotAllowed](https://docs.cryptolegacy.app/documentation/errors-reference#multisigmethodnotallowed-ism1)
* [MultisigNotConfirmed](https://docs.cryptolegacy.app/documentation/errors-reference#multisignotconfirmed-ism1)
* [MultisigNothingToWithdraw](https://docs.cryptolegacy.app/documentation/errors-reference#multisignothingtowithdraw-ism1)
* [MultisigOnlyExecutor](https://docs.cryptolegacy.app/documentation/errors-reference#multisigonlyexecutor-ism1)
* [MultisigProposalNotPending](https://docs.cryptolegacy.app/documentation/errors-reference#multisigproposalnotpending-ism1)
* [MultisigVoterNotAllowed](https://docs.cryptolegacy.app/documentation/errors-reference#multisigvoternotallowed-ism1)
* [TransferFeeFailed](https://docs.cryptolegacy.app/documentation/errors-reference#transferfeefailed-ism1)

### Access / Roles

None.

### Interacts With

* `ISafeMinimalMultisig`
* `LibCryptoLegacy`

### Missing Links

None.

## LibTrustedGuardiansPlugin (Library)

### Purpose

LibTrustedGuardiansPlugin provides storage and vote-state helpers for guardian-based plugin logic.

### Inheritance

None.

### Key Methods

* [getPluginStorage(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getpluginstorage-ltgp1) - Provides typed storage access for the Trusted Guardians plugin.
* [\_resetGuardianVoting(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_resetguardianvoting-ltgp1) - Clears guardian voting state and resets the distribution schedule.

### All Functions

* [getPluginStorage()](https://docs.cryptolegacy.app/documentation/functions-reference#getpluginstorage-ltgp1) - Provides typed storage access for the Trusted Guardians plugin.
* [\_resetGuardianVoting(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_resetguardianvoting-ltgp1) - Clears guardian voting state and resets the distribution schedule.

### Events

* [ResetGuardiansVoting](https://docs.cryptolegacy.app/documentation/events-reference#resetguardiansvoting-itgp1)

### Errors

None.

### Access / Roles

None.

### Interacts With

* `ICryptoLegacy`
* `ITrustedGuardiansPlugin`
* `LibCryptoLegacy`
* `LibDiamond`

### Missing Links

None.

## BeneficiaryAaveV3SupplyPlugin

### Purpose

BeneficiaryAaveV3SupplyPlugin routes beneficiary-approved Aave V3 supply, withdrawal, and Stata-token conversion flows through the plugin multisig.

### Inheritance

* `ICryptoLegacyPlugin`
* `ReentrancyGuardUpgradeable`

### Key Methods

* [baavesSetMultisigConfig(...)](https://docs.cryptolegacy.app/documentation/functions-reference#baavessetmultisigconfig-balp1) - Updates the beneficiary multisig confirmation threshold for the plugin.
* [baavesSupply(...)](https://docs.cryptolegacy.app/documentation/functions-reference#baavessupply-balp1) - Supplies a reserve asset into Aave V3 and migrates beneficiary claims into the corresponding aToken.
* [baavesWithdraw(...)](https://docs.cryptolegacy.app/documentation/functions-reference#baaveswithdraw-balp1) - Withdraws a reserve asset from Aave V3 and migrates beneficiary claims from the aToken back into the reserve asset.
* [baavesWrapATokenToStataToken(...)](https://docs.cryptolegacy.app/documentation/functions-reference#baaveswrapatokentostatatoken-balp1) - Wraps rebasing aTokens into non-rebasing StataToken shares.
* [baavesRedeemFromStataToken(...)](https://docs.cryptolegacy.app/documentation/functions-reference#baavesredeemfromstatatoken-balp1) - Redeems StataToken shares directly into the reserve asset in one step.

### All Functions

* [constructor(...)](https://docs.cryptolegacy.app/documentation/functions-reference#constructor-balp1) - Stores the Aave V3 and StataToken integration addresses used by the beneficiary plugin.
* [getSigs(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getsigs-balp1) - Returns the selectors exposed by the Aave beneficiary plugin.
* [getSetupSigs(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getsetupsigs-balp1) - Returns the setup-time selectors required by the Aave beneficiary plugin.
* [getMultisigAllowedMethods(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getmultisigallowedmethods-balp1) - Lists selectors that beneficiary multisig proposals are allowed to execute.
* [getPluginName(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getpluginname-balp1) - Returns the unique plugin name string.
* [getPluginVer(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getpluginver-balp1) - Returns the semantic version for the Aave beneficiary plugin.
* [modifier onlyDistributionReady](https://docs.cryptolegacy.app/documentation/functions-reference#modifier-onlydistributionready-balp1) - Restricts execution to phases where beneficiary distribution is already active.
* [getPluginMultisigStorage(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getpluginmultisigstorage-balp1) - Retrieves the plugin-specific multisig storage slot.
* [baavesSetMultisigConfig(...)](https://docs.cryptolegacy.app/documentation/functions-reference#baavessetmultisigconfig-balp1) - Updates the beneficiary multisig confirmation threshold for the plugin.
* [baavesPropose(...)](https://docs.cryptolegacy.app/documentation/functions-reference#baavespropose-balp1) - Creates a multisig proposal for an allowed Aave beneficiary action.
* [baavesConfirm(...)](https://docs.cryptolegacy.app/documentation/functions-reference#baavesconfirm-balp1) - Confirms an existing plugin proposal and executes it once quorum is reached.
* [baavesCancel(...)](https://docs.cryptolegacy.app/documentation/functions-reference#baavescancel-balp1) - Removes the caller's confirmation from a pending plugin proposal.
* [baavesGetInitializationStatus(...)](https://docs.cryptolegacy.app/documentation/functions-reference#baavesgetinitializationstatus-balp1) - Reports whether the plugin's multisig configuration has been initialized.
* [baavesGetVotersAndConfirmations(...)](https://docs.cryptolegacy.app/documentation/functions-reference#baavesgetvotersandconfirmations-balp1) - Returns the beneficiary voter list and current confirmation threshold.
* [baavesGetProposalWithStatus(...)](https://docs.cryptolegacy.app/documentation/functions-reference#baavesgetproposalwithstatus-balp1) - Returns a single multisig proposal together with its derived execution status.
* [baavesGetProposalListWithStatuses(...)](https://docs.cryptolegacy.app/documentation/functions-reference#baavesgetproposallistwithstatuses-balp1) - Returns the full plugin proposal list with derived statuses.
* [baavesSupply(...)](https://docs.cryptolegacy.app/documentation/functions-reference#baavessupply-balp1) - Supplies a reserve asset into Aave V3 and migrates beneficiary claims into the corresponding aToken.
* [baavesWithdraw(...)](https://docs.cryptolegacy.app/documentation/functions-reference#baaveswithdraw-balp1) - Withdraws a reserve asset from Aave V3 and migrates beneficiary claims from the aToken back into the reserve asset.
* [baavesWrapATokenToStataToken(...)](https://docs.cryptolegacy.app/documentation/functions-reference#baaveswrapatokentostatatoken-balp1) - Wraps rebasing aTokens into non-rebasing StataToken shares.
* [baavesUnwrapStataTokenToAToken(...)](https://docs.cryptolegacy.app/documentation/functions-reference#baavesunwrapstatatokentoatoken-balp1) - Redeems StataToken shares back into rebasing aTokens.
* [baavesDepositToStataToken(...)](https://docs.cryptolegacy.app/documentation/functions-reference#baavesdeposittostatatoken-balp1) - Deposits a reserve asset directly into its StataToken wrapper in one step.
* [baavesRedeemFromStataToken(...)](https://docs.cryptolegacy.app/documentation/functions-reference#baavesredeemfromstatatoken-balp1) - Redeems StataToken shares directly into the reserve asset in one step.
* [\_getAToken(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_getatoken-balp1) - Resolves the aToken address for a given reserve asset.
* [\_getStataToken(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_getstatatoken-balp1) - Resolves the StataToken wrapper address for a given reserve asset.

### Events

* [AaveSupply](https://docs.cryptolegacy.app/documentation/events-reference#aavesupply-balp1)
* [AaveWithdraw](https://docs.cryptolegacy.app/documentation/events-reference#aavewithdraw-balp1)
* [WrapATokenToStataToken](https://docs.cryptolegacy.app/documentation/events-reference#wrapatokentostatatoken-balp1)
* [UnwrapStataTokenToAToken](https://docs.cryptolegacy.app/documentation/events-reference#unwrapstatatokentoatoken-balp1)
* [DepositToStataToken](https://docs.cryptolegacy.app/documentation/events-reference#deposittostatatoken-balp1)
* [RedeemFromStataToken](https://docs.cryptolegacy.app/documentation/events-reference#redeemfromstatatoken-balp1)

### Errors

* [ZeroAmount](https://docs.cryptolegacy.app/documentation/errors-reference#zeroamount-balp1)
* [ATokenNotFound](https://docs.cryptolegacy.app/documentation/errors-reference#atokennotfound-balp1)
* [StataTokenNotFound](https://docs.cryptolegacy.app/documentation/errors-reference#statatokennotfound-balp1)

### Access / Roles

* `baaves*` state-changing execution methods require `onlyDistributionReady`; proposal lifecycle also enforces beneficiary multisig confirmation rules.

### Interacts With

* `IAaveV3Pool`
* `IAaveV3PoolDataProvider`
* `IStataToken`
* `IStataTokenFactory`
* `ISafeMinimalMultisig`
* `LibCryptoLegacy`
* `LibSafeMinimalBeneficiaryMultisig`

### Missing Links

None.

## BeneficiaryLidoStakingPlugin

### Purpose

BeneficiaryLidoStakingPlugin gates beneficiary-approved Lido staking, wrapping, withdrawal-request, and migration flows behind the plugin multisig.

### Inheritance

* `ICryptoLegacyPlugin`
* `ReentrancyGuardUpgradeable`

### Key Methods

* [blsSetMultisigConfig(...)](https://docs.cryptolegacy.app/documentation/functions-reference#blssetmultisigconfig-blsp1) - Updates the beneficiary multisig confirmation threshold for the Lido plugin.
* [blsLidoStakeWethToStEth(...)](https://docs.cryptolegacy.app/documentation/functions-reference#blslidostakewethtosteth-blsp1) - Unwraps WETH and stakes the resulting ETH into Lido, minting stETH.
* [blsLidoRequestStEthWithdrawal(...)](https://docs.cryptolegacy.app/documentation/functions-reference#blslidorequeststethwithdrawal-blsp1) - Requests stETH withdrawals from the Lido withdrawal queue and starts a pending migration to WETH.
* [blsLidoClaimWithdrawals(...)](https://docs.cryptolegacy.app/documentation/functions-reference#blslidoclaimwithdrawals-blsp1) - Claims finalized Lido withdrawals, wraps the received ETH into WETH, and completes the pending migration.
* [blsLidoAbandonMigration(...)](https://docs.cryptolegacy.app/documentation/functions-reference#blslidoabandonmigration-blsp1) - Abandons the active Lido two-step migration and restores claim state.

### All Functions

* [constructor(...)](https://docs.cryptolegacy.app/documentation/functions-reference#constructor-blsp1) - Stores the helper contract used to unwrap WETH into native ETH for the Lido flows.
* [getSigs(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getsigs-blsp1) - Returns the selectors exposed by the Lido beneficiary plugin.
* [getSetupSigs(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getsetupsigs-blsp1) - Returns the setup-time selectors required by the Lido beneficiary plugin.
* [getMultisigAllowedMethods(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getmultisigallowedmethods-blsp1) - Lists selectors that beneficiary multisig proposals are allowed to execute.
* [getPluginName(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getpluginname-blsp1) - Returns the unique plugin name string.
* [getPluginVer(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getpluginver-blsp1) - Returns the semantic version for the Lido beneficiary plugin.
* [modifier onlyDistributionReady](https://docs.cryptolegacy.app/documentation/functions-reference#modifier-onlydistributionready-blsp1) - Restricts execution to phases where beneficiary distribution is already active.
* [getPluginMultisigStorage(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getpluginmultisigstorage-blsp1) - Retrieves the plugin-specific multisig storage slot.
* [getPendingMigrationStorage(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getpendingmigrationstorage-blsp1) - Retrieves the plugin-local storage slot that holds the active two-step migration state.
* [getLidoWithdrawalStorage(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getlidowithdrawalstorage-blsp1) - Retrieves the plugin-local storage slot that caches pending Lido withdrawal request IDs.
* [getBeneficiarySwitchGuardStorage(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getbeneficiaryswitchguardstorage-blsp1) - Retrieves the plugin-local guard storage that freezes beneficiary switching while migration is pending.
* [blsSetMultisigConfig(...)](https://docs.cryptolegacy.app/documentation/functions-reference#blssetmultisigconfig-blsp1) - Updates the beneficiary multisig confirmation threshold for the Lido plugin.
* [blsPropose(...)](https://docs.cryptolegacy.app/documentation/functions-reference#blspropose-blsp1) - Creates a multisig proposal for an allowed Lido beneficiary action.
* [blsConfirm(...)](https://docs.cryptolegacy.app/documentation/functions-reference#blsconfirm-blsp1) - Confirms an existing Lido plugin proposal and executes it once quorum is reached.
* [blsCancel(...)](https://docs.cryptolegacy.app/documentation/functions-reference#blscancel-blsp1) - Removes the caller's confirmation from a pending Lido multisig proposal.
* [blsGetInitializationStatus(...)](https://docs.cryptolegacy.app/documentation/functions-reference#blsgetinitializationstatus-blsp1) - Reports whether the plugin multisig configuration has been initialized.
* [blsGetVotersAndConfirmations(...)](https://docs.cryptolegacy.app/documentation/functions-reference#blsgetvotersandconfirmations-blsp1) - Returns the current multisig voter list and confirmation threshold for the Lido plugin.
* [blsGetProposalWithStatus(...)](https://docs.cryptolegacy.app/documentation/functions-reference#blsgetproposalwithstatus-blsp1) - Fetches a single proposal and its per-voter confirmation flags.
* [blsGetProposalListWithStatuses(...)](https://docs.cryptolegacy.app/documentation/functions-reference#blsgetproposallistwithstatuses-blsp1) - Returns all plugin proposals with confirmation metadata.
* [blsLidoGetPendingRequestIds(...)](https://docs.cryptolegacy.app/documentation/functions-reference#blslidogetpendingrequestids-blsp1) - Returns the currently cached Lido withdrawal request IDs used by the fair-claim path.
* [blsLidoGetPendingMigration(...)](https://docs.cryptolegacy.app/documentation/functions-reference#blslidogetpendingmigration-blsp1) - Returns the details of the currently pending two-step migration.
* [blsLidoStakeWethToStEth(...)](https://docs.cryptolegacy.app/documentation/functions-reference#blslidostakewethtosteth-blsp1) - Unwraps WETH and stakes the resulting ETH into Lido, minting stETH.
* [blsLidoWrapWethToWstEth(...)](https://docs.cryptolegacy.app/documentation/functions-reference#blslidowrapwethtowsteth-blsp1) - Unwraps WETH and wraps the resulting ETH directly into wstETH.
* [blsLidoRequestStEthWithdrawal(...)](https://docs.cryptolegacy.app/documentation/functions-reference#blslidorequeststethwithdrawal-blsp1) - Requests stETH withdrawals from the Lido withdrawal queue and starts a pending migration to WETH.
* [blsLidoRequestWstEthWithdrawal(...)](https://docs.cryptolegacy.app/documentation/functions-reference#blslidorequestwstethwithdrawal-blsp1) - Requests wstETH withdrawals from the Lido withdrawal queue and starts a pending migration to WETH.
* [blsLidoClaimWithdrawals(...)](https://docs.cryptolegacy.app/documentation/functions-reference#blslidoclaimwithdrawals-blsp1) - Claims finalized Lido withdrawals, wraps the received ETH into WETH, and completes the pending migration.
* [blsLidoUnsafeClaimWithdrawals(...)](https://docs.cryptolegacy.app/documentation/functions-reference#blslidounsafeclaimwithdrawals-blsp1) - Claims finalized Lido withdrawals without completing claim-migration reconciliation.
* [blsLidoAbandonMigration(...)](https://docs.cryptolegacy.app/documentation/functions-reference#blslidoabandonmigration-blsp1) - Abandons the active Lido two-step migration and restores claim state.
* [blsLidoWrapStEthToWstEth(...)](https://docs.cryptolegacy.app/documentation/functions-reference#blslidowrapstethtowsteth-blsp1) - Wraps rebasing stETH into non-rebasing wstETH and migrates claim accounting in one step.
* [blsLidoUnwrapWstEthToStEth(...)](https://docs.cryptolegacy.app/documentation/functions-reference#blslidounwrapwstethtosteth-blsp1) - Unwraps wstETH into stETH and migrates claim accounting in one step.
* [\_storeLidoRequestIds(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_storelidorequestids-blsp1) - Replaces the cached pending-request list with the request IDs returned by Lido.
* [\_activateBeneficiarySwitchGuard(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_activatebeneficiaryswitchguard-blsp1) - Freezes beneficiary switching while a delayed migration is pending.
* [\_releaseBeneficiarySwitchGuard(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_releasebeneficiaryswitchguard-blsp1) - Restores beneficiary-switch timelocks and clears the migration guard snapshot.
* [\_setTokenBeneficiaryClaimsToZero(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_settokenbeneficiaryclaimstozero-blsp1) - Clears every beneficiary's claimed balance for a given token.

### Events

* [StakeWethToStEth](https://docs.cryptolegacy.app/documentation/events-reference#stakewethtosteth-blsp1)
* [WrapWethToWstEth](https://docs.cryptolegacy.app/documentation/events-reference#wrapwethtowsteth-blsp1)
* [RequestStEthWithdrawal](https://docs.cryptolegacy.app/documentation/events-reference#requeststethwithdrawal-blsp1)
* [RequestWstEthWithdrawal](https://docs.cryptolegacy.app/documentation/events-reference#requestwstethwithdrawal-blsp1)
* [ClaimWithdrawals](https://docs.cryptolegacy.app/documentation/events-reference#claimwithdrawals-blsp1)
* [UnsafeClaimWithdrawals](https://docs.cryptolegacy.app/documentation/events-reference#unsafeclaimwithdrawals-blsp1)
* [AbandonMigration](https://docs.cryptolegacy.app/documentation/events-reference#abandonmigration-blsp1)

### Errors

* [ZeroStEthAmount](https://docs.cryptolegacy.app/documentation/errors-reference#zerostethamount-blsp1)
* [ZeroWethAmount](https://docs.cryptolegacy.app/documentation/errors-reference#zerowethamount-blsp1)
* [ZeroWstEthAmount](https://docs.cryptolegacy.app/documentation/errors-reference#zerowstethamount-blsp1)
* [InsufficientStEth](https://docs.cryptolegacy.app/documentation/errors-reference#insufficientsteth-blsp1)
* [InsufficientWstEth](https://docs.cryptolegacy.app/documentation/errors-reference#insufficientwsteth-blsp1)
* [LidoRequestIdsEmpty](https://docs.cryptolegacy.app/documentation/errors-reference#lidorequestidsempty-blsp1)
* [WethUnwrapAmountMismatch](https://docs.cryptolegacy.app/documentation/errors-reference#wethunwrapamountmismatch-blsp1)
* [WstEthWrapFailed](https://docs.cryptolegacy.app/documentation/errors-reference#wstethwrapfailed-blsp1)
* [EmptyWithdrawalAmounts](https://docs.cryptolegacy.app/documentation/errors-reference#emptywithdrawalamounts-blsp1)
* [PendingMigrationActive](https://docs.cryptolegacy.app/documentation/errors-reference#pendingmigrationactive-blsp1)
* [BeneficiarySwitchGuardAlreadyActive](https://docs.cryptolegacy.app/documentation/errors-reference#beneficiaryswitchguardalreadyactive-blsp1)

### Access / Roles

* `bls*` state-changing execution methods require `onlyDistributionReady`; proposal lifecycle also enforces beneficiary multisig confirmation rules.

### Interacts With

* `ILido`
* `IWstETH`
* `ILidoWithdrawalQueue`
* `WethUnwrap`
* `ISafeMinimalMultisig`
* `LibCryptoLegacy`
* `LibSafeMinimalBeneficiaryMultisig`
* `LibTwoStepClaimMigration`

### Missing Links

None.

## BeneficiaryPluginAddRights

### Purpose

BeneficiaryPluginAddRights lets the beneficiary multisig approve and execute additional plugin-list installs for the CryptoLegacy diamond after distribution begins.

### Inheritance

* `ICryptoLegacyPlugin`
* `ReentrancyGuardUpgradeable`

### Key Methods

* [getSigs(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getsigs-bpar1) - Lists the external function selectors exposed by this plugin.
* [getSetupSigs(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getsetupsigs-bpar1) - Reports setup-time selectors required by the plugin.
* [getMultisigAllowedMethods(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getmultisigallowedmethods-bpar1) - Lists selectors that multisig proposals are permitted to execute.
* [getPluginName(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getpluginname-bpar1) - Returns the human-readable plugin identifier.
* [getPluginVer(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getpluginver-bpar1) - Reports the semantic version number for the plugin.
* [barSetMultisigConfig(...)](https://docs.cryptolegacy.app/documentation/functions-reference#barsetmultisigconfig-bpar1) - Updates multisig confirmation thresholds for beneficiary actions.
* [barPropose(...)](https://docs.cryptolegacy.app/documentation/functions-reference#barpropose-bpar1) - Creates a multisig proposal for an allowed beneficiary action.
* [barConfirm(...)](https://docs.cryptolegacy.app/documentation/functions-reference#barconfirm-bpar1) - Confirms an existing multisig proposal and executes it once quorum is reached.

### All Functions

* [getSigs()](https://docs.cryptolegacy.app/documentation/functions-reference#getsigs-bpar1) - Lists the external function selectors exposed by this plugin.
* [getSetupSigs()](https://docs.cryptolegacy.app/documentation/functions-reference#getsetupsigs-bpar1) - Reports setup-time selectors required by the plugin.
* [getMultisigAllowedMethods()](https://docs.cryptolegacy.app/documentation/functions-reference#getmultisigallowedmethods-bpar1) - Lists selectors that multisig proposals are permitted to execute.
* [getPluginName()](https://docs.cryptolegacy.app/documentation/functions-reference#getpluginname-bpar1) - Returns the human-readable plugin identifier.
* [getPluginVer()](https://docs.cryptolegacy.app/documentation/functions-reference#getpluginver-bpar1) - Reports the semantic version number for the plugin.
* [getPluginMultisigStorage()](https://docs.cryptolegacy.app/documentation/functions-reference#getpluginmultisigstorage-bpar1) - Retrieves the plugin-specific multisig storage slot.
* [barSetMultisigConfig(...)](https://docs.cryptolegacy.app/documentation/functions-reference#barsetmultisigconfig-bpar1) - Updates multisig confirmation thresholds for beneficiary actions.
* [barPropose(...)](https://docs.cryptolegacy.app/documentation/functions-reference#barpropose-bpar1) - Creates a multisig proposal for an allowed beneficiary action.
* [barConfirm(...)](https://docs.cryptolegacy.app/documentation/functions-reference#barconfirm-bpar1) - Confirms an existing multisig proposal and executes it once quorum is reached.
* [barCancel(...)](https://docs.cryptolegacy.app/documentation/functions-reference#barcancel-bpar1) - Removes the caller’s confirmation from a pending multisig proposal.
* [barAddPluginList(...)](https://docs.cryptolegacy.app/documentation/functions-reference#baraddpluginlist-bpar1) - Executes the approved plugin-addition proposal.
* [barWithdrawHeldEth(...)](https://docs.cryptolegacy.app/documentation/functions-reference#barwithdrawheldeth-bpar1) - Allows a voter to withdraw ETH accrued during proposal execution.
* [barGetHeldEth(...)](https://docs.cryptolegacy.app/documentation/functions-reference#bargetheldeth-bpar1) - Returns the held ETH balance for a beneficiary voter.
* [barGetInitializationStatus()](https://docs.cryptolegacy.app/documentation/functions-reference#bargetinitializationstatus-bpar1) - Reports whether the multisig configuration has been initialized.
* [barGetVotersAndConfirmations()](https://docs.cryptolegacy.app/documentation/functions-reference#bargetvotersandconfirmations-bpar1) - Returns the current multisig voter list and confirmation threshold.
* [barGetProposalWithStatus(...)](https://docs.cryptolegacy.app/documentation/functions-reference#bargetproposalwithstatus-bpar1) - Fetches a single proposal and its per-voter confirmation flags.
* [barGetProposalListWithStatuses()](https://docs.cryptolegacy.app/documentation/functions-reference#bargetproposallistwithstatuses-bpar1) - Returns all multisig proposals with confirmation metadata.

### Events

None.

### Errors

None.

### Access / Roles

* `barSetMultisigConfig`: `owner` only, or `address(this)` when distribution is ready
* `barPropose`: `nonReentrant, onlyDistributionReady`
* `barConfirm`: `nonReentrant, onlyDistributionReady`
* `barCancel`: `nonReentrant, onlyDistributionReady`
* `barAddPluginList`: `onlyDistributionReady`
* `barWithdrawHeldEth`: `nonReentrant`

### Interacts With

* `ICryptoLegacy`
* `ISafeMinimalMultisig`
* `LibCryptoLegacy`
* `LibCryptoLegacyPlugins`
* `LibSafeMinimalBeneficiaryMultisig`

### Missing Links

None.

## BeneficiaryUniswapV4SwapPlugin

### Purpose

BeneficiaryUniswapV4SwapPlugin executes beneficiary-approved Uniswap V4 exact-input swaps through the plugin multisig and the Universal Router dispatcher.

### Inheritance

* `ICryptoLegacyPlugin`
* `ReentrancyGuardUpgradeable`

### Key Methods

* [bunisSetMultisigConfig(...)](https://docs.cryptolegacy.app/documentation/functions-reference#bunissetmultisigconfig-bu4sp1) - Updates the beneficiary multisig confirmation threshold for the swap plugin.
* [bunisSwapExactInputSingle(...)](https://docs.cryptolegacy.app/documentation/functions-reference#bunisswapexactinputsingle-bu4sp1) - Executes a single-hop exact-input Uniswap V4 swap and migrates claims into the output token.
* [bunisSwapExactInput(...)](https://docs.cryptolegacy.app/documentation/functions-reference#bunisswapexactinput-bu4sp1) - Executes a multi-hop exact-input Uniswap V4 swap and migrates claims into the final output token.

### All Functions

* [constructor(...)](https://docs.cryptolegacy.app/documentation/functions-reference#constructor-bu4sp1) - Stores the Universal Router and Permit2 addresses used by the plugin.
* [getSigs(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getsigs-bu4sp1) - Returns the selectors exposed by the Uniswap V4 beneficiary plugin.
* [getSetupSigs(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getsetupsigs-bu4sp1) - Returns setup-time selectors required by the Uniswap V4 beneficiary plugin.
* [getMultisigAllowedMethods(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getmultisigallowedmethods-bu4sp1) - Lists selectors that beneficiary multisig proposals are allowed to execute.
* [getPluginName(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getpluginname-bu4sp1) - Returns the unique plugin name string.
* [getPluginVer(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getpluginver-bu4sp1) - Returns the semantic version for the Uniswap V4 beneficiary plugin.
* [modifier onlyDistributionReady](https://docs.cryptolegacy.app/documentation/functions-reference#modifier-onlydistributionready-bu4sp1) - Restricts execution to phases where beneficiary distribution is already active.
* [getPluginMultisigStorage(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getpluginmultisigstorage-bu4sp1) - Retrieves the plugin-specific multisig storage slot.
* [bunisSetMultisigConfig(...)](https://docs.cryptolegacy.app/documentation/functions-reference#bunissetmultisigconfig-bu4sp1) - Updates the beneficiary multisig confirmation threshold for the swap plugin.
* [bunisPropose(...)](https://docs.cryptolegacy.app/documentation/functions-reference#bunispropose-bu4sp1) - Creates a multisig proposal for an allowed Uniswap V4 beneficiary action.
* [bunisConfirm(...)](https://docs.cryptolegacy.app/documentation/functions-reference#bunisconfirm-bu4sp1) - Confirms an existing plugin proposal and executes it once quorum is reached.
* [bunisCancel(...)](https://docs.cryptolegacy.app/documentation/functions-reference#buniscancel-bu4sp1) - Removes the caller's confirmation from a pending plugin proposal.
* [bunisGetInitializationStatus(...)](https://docs.cryptolegacy.app/documentation/functions-reference#bunisgetinitializationstatus-bu4sp1) - Reports whether the plugin's multisig configuration has been initialized.
* [bunisGetVotersAndConfirmations(...)](https://docs.cryptolegacy.app/documentation/functions-reference#bunisgetvotersandconfirmations-bu4sp1) - Returns the beneficiary voter list and current confirmation threshold.
* [bunisGetProposalWithStatus(...)](https://docs.cryptolegacy.app/documentation/functions-reference#bunisgetproposalwithstatus-bu4sp1) - Returns a single multisig proposal together with its derived execution status.
* [bunisGetProposalListWithStatuses(...)](https://docs.cryptolegacy.app/documentation/functions-reference#bunisgetproposallistwithstatuses-bu4sp1) - Returns the full plugin proposal list with derived statuses.
* [bunisSwapExactInputSingle(...)](https://docs.cryptolegacy.app/documentation/functions-reference#bunisswapexactinputsingle-bu4sp1) - Executes a single-hop exact-input Uniswap V4 swap and migrates claims into the output token.
* [bunisSwapExactInput(...)](https://docs.cryptolegacy.app/documentation/functions-reference#bunisswapexactinput-bu4sp1) - Executes a multi-hop exact-input Uniswap V4 swap and migrates claims into the final output token.
* [\_executeExactInputSingleRouter(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_executeexactinputsinglerouter-bu4sp1) - Encodes and submits the single-hop exact-input swap command sequence to the Universal Router.
* [\_executeExactInputRouter(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_executeexactinputrouter-bu4sp1) - Encodes and submits the multi-hop exact-input swap command sequence to the Universal Router.

### Events

* [UniswapV4SwapExactInputSingle](https://docs.cryptolegacy.app/documentation/events-reference#uniswapv4swapexactinputsingle-bu4sp1)
* [UniswapV4SwapExactInput](https://docs.cryptolegacy.app/documentation/events-reference#uniswapv4swapexactinput-bu4sp1)

### Errors

* [ZeroAmount](https://docs.cryptolegacy.app/documentation/errors-reference#zeroamount-bu4sp1)
* [EmptyPath](https://docs.cryptolegacy.app/documentation/errors-reference#emptypath-bu4sp1)

### Access / Roles

* `bunis*` state-changing execution methods require `onlyDistributionReady`; proposal lifecycle also enforces beneficiary multisig confirmation rules.

### Interacts With

* `IPermit2`
* `IUniversalRouter`
* `ISafeMinimalMultisig`
* `LibCryptoLegacy`
* `LibSafeMinimalBeneficiaryMultisig`

### Missing Links

None.

## CryptoLegacyBasePlugin

### Purpose

CryptoLegacyBasePlugin implements core legacy distribution and claim workflows reused across protocol instances.

### Inheritance

* `ICryptoLegacy`
* `CryptoLegacyOwnable`
* `ReentrancyGuardUpgradeable`

### Key Methods

* [getSigs(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getsigs-clbp1) - Lists the primary external selectors exposed by the base plugin.
* [getSetupSigs(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getsetupsigs-clbp1) - Lists view selectors needed during plugin setup.
* [getPluginName(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getpluginname-clbp1) - Returns the canonical plugin name.
* [getPluginVer(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getpluginver-clbp1) - Returns the plugin’s semantic version.
* [getCryptoLegacyVer(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getcryptolegacyver-clbp1) - Returns the base CryptoLegacy protocol version.
* [initializeByBuildManager(...)](https://docs.cryptolegacy.app/documentation/functions-reference#initializebybuildmanager-clbp1) - Initializes core storage via the authorized build manager.
* [owner(...)](https://docs.cryptolegacy.app/documentation/functions-reference#owner-clbp1) - Returns the current contract owner.
* [isPaused(...)](https://docs.cryptolegacy.app/documentation/functions-reference#ispaused-clbp1) - Returns whether the contract is currently paused.

### All Functions

* [getSigs()](https://docs.cryptolegacy.app/documentation/functions-reference#getsigs-clbp1) - Lists the primary external selectors exposed by the base plugin.
* [getSetupSigs()](https://docs.cryptolegacy.app/documentation/functions-reference#getsetupsigs-clbp1) - Lists view selectors needed during plugin setup.
* [getPluginName()](https://docs.cryptolegacy.app/documentation/functions-reference#getpluginname-clbp1) - Returns the canonical plugin name.
* [getPluginVer()](https://docs.cryptolegacy.app/documentation/functions-reference#getpluginver-clbp1) - Returns the plugin’s semantic version.
* [getCryptoLegacyVer()](https://docs.cryptolegacy.app/documentation/functions-reference#getcryptolegacyver-clbp1) - Returns the base CryptoLegacy protocol version.
* [constructor()](https://docs.cryptolegacy.app/documentation/functions-reference#constructor-clbp1) - Empty constructor for upgradeable deployment pattern.
* [initializeByBuildManager(...)](https://docs.cryptolegacy.app/documentation/functions-reference#initializebybuildmanager-clbp1) - Initializes core storage via the authorized build manager.
* [owner()](https://docs.cryptolegacy.app/documentation/functions-reference#owner-clbp1) - Returns the current contract owner.
* [isPaused()](https://docs.cryptolegacy.app/documentation/functions-reference#ispaused-clbp1) - Returns whether the contract is currently paused.
* [buildManager()](https://docs.cryptolegacy.app/documentation/functions-reference#buildmanager-clbp1) - Returns the associated build manager contract.
* [transferOwnership(...)](https://docs.cryptolegacy.app/documentation/functions-reference#transferownership-clbp1) - Begins the two-step ownership transfer process.
* [payInitialFee(...)](https://docs.cryptolegacy.app/documentation/functions-reference#payinitialfee-clbp1) - Pays the one-time initial fee and unpauses the contract.
* [setBeneficiaries(...)](https://docs.cryptolegacy.app/documentation/functions-reference#setbeneficiaries-clbp1) - Updates beneficiary list and configs under owner control.
* [\_setBeneficiaries(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_setbeneficiaries-clbp1) - Internal routine to add, update, or remove beneficiary records.
* [update(...)](https://docs.cryptolegacy.app/documentation/functions-reference#update-clbp1) - Periodic upkeep that charges update fees and resets the distribution timer.
* [setGasLimitMultiplier(...)](https://docs.cryptolegacy.app/documentation/functions-reference#setgaslimitmultiplier-clbp1) - Adjusts the gas multiplier used for fee-related calls.
* [initiateChallenge()](https://docs.cryptolegacy.app/documentation/functions-reference#initiatechallenge-clbp1) - Starts the challenge window when upkeep is overdue.
* [transferTreasuryTokensToLegacy(...)](https://docs.cryptolegacy.app/documentation/functions-reference#transfertreasurytokenstolegacy-clbp1) - Pulls treasury tokens from holders into the legacy contract for distribution.
* [\_claimTokenWithVesting(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_claimtokenwithvesting-clbp1) - Internal helper to distribute vested ERC20 tokens.
* [beneficiaryClaim(...)](https://docs.cryptolegacy.app/documentation/functions-reference#beneficiaryclaim-clbp1) - Enables a beneficiary to claim vested ERC20 tokens.
* [beneficiarySwitch(...)](https://docs.cryptolegacy.app/documentation/functions-reference#beneficiaryswitch-clbp1) - Allows a beneficiary to switch their identifier hash.
* [sendMessagesToBeneficiary(...)](https://docs.cryptolegacy.app/documentation/functions-reference#sendmessagestobeneficiary-clbp1) - Owner broadcast of off-chain messages to beneficiaries.
* [isLifetimeActive()](https://docs.cryptolegacy.app/documentation/functions-reference#islifetimeactive-clbp1) - Checks if the owner’s lifetime NFT is locked.
* [getGasBySelector(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getgasbyselector-clbp1) - Returns the stored gas hint for a selector.

### Events

* [SetBeneficiary](https://docs.cryptolegacy.app/documentation/events-reference#setbeneficiary-clbp1)
* [SwitchBeneficiary](https://docs.cryptolegacy.app/documentation/events-reference#switchbeneficiary-clbp1)
* [ChallengeInitiate](https://docs.cryptolegacy.app/documentation/events-reference#challengeinitiate-clbp1)
* [BeneficiaryMessage](https://docs.cryptolegacy.app/documentation/events-reference#beneficiarymessage-clbp1)
* [BeneficiaryMessageCheck](https://docs.cryptolegacy.app/documentation/events-reference#beneficiarymessagecheck-clbp1)
* [PauseSet](https://docs.cryptolegacy.app/documentation/events-reference#pauseset-icl1)
* [Update](https://docs.cryptolegacy.app/documentation/events-reference#update-icl1)
* [FeePaidByLifetime](https://docs.cryptolegacy.app/documentation/events-reference#feepaidbylifetime-icl1)
* [FeePaidByDefault](https://docs.cryptolegacy.app/documentation/events-reference#feepaidbydefault-icl1)
* [FeePaidByTransfer](https://docs.cryptolegacy.app/documentation/events-reference#feepaidbytransfer-icl1)
* [FeeSentToRefByTransfer](https://docs.cryptolegacy.app/documentation/events-reference#feesenttorefbytransfer-icl1)
* [BeneficiaryClaim](https://docs.cryptolegacy.app/documentation/events-reference#beneficiaryclaim-icl1)
* [BeneficiaryClaimAmountDecrease](https://docs.cryptolegacy.app/documentation/events-reference#beneficiaryclaimamountdecrease-icl1)
* [TransferTreasuryTokensToLegacy](https://docs.cryptolegacy.app/documentation/events-reference#transfertreasurytokenstolegacy-icl1)
* [TransferTokensFromLegacy](https://docs.cryptolegacy.app/documentation/events-reference#transfertokensfromlegacy-icl1)
* [SetGasLimitMultiplier](https://docs.cryptolegacy.app/documentation/events-reference#setgaslimitmultiplier-icl1)
* [AddFunctions](https://docs.cryptolegacy.app/documentation/events-reference#addfunctions-icl1)
* [RemoveFunctions](https://docs.cryptolegacy.app/documentation/events-reference#removefunctions-icl1)
* [SkipSendFeeByTransfer](https://docs.cryptolegacy.app/documentation/events-reference#skipsendfeebytransfer-icl1)
* [IsLifetimeNftLockedAndUpdateCatch](https://docs.cryptolegacy.app/documentation/events-reference#islifetimenftlockedandupdatecatch-icl1)
* [GetUpdateFeeCatch](https://docs.cryptolegacy.app/documentation/events-reference#getupdatefeecatch-icl1)
* [PayFeeCatch](https://docs.cryptolegacy.app/documentation/events-reference#payfeecatch-icl1)
* [SetCryptoLegacyOwnerCatch](https://docs.cryptolegacy.app/documentation/events-reference#setcryptolegacyownercatch-icl1)
* [SetCryptoLegacyBeneficiaryCatch](https://docs.cryptolegacy.app/documentation/events-reference#setcryptolegacybeneficiarycatch-icl1)
* [SetCryptoLegacyGuardianCatch](https://docs.cryptolegacy.app/documentation/events-reference#setcryptolegacyguardiancatch-icl1)
* [SetCryptoLegacyRecoveryAddressesCatch](https://docs.cryptolegacy.app/documentation/events-reference#setcryptolegacyrecoveryaddressescatch-icl1)
* [BeneficiaryRegistryCatch](https://docs.cryptolegacy.app/documentation/events-reference#beneficiaryregistrycatch-icl1)
* [BeneficiaryRegistryNotDefined](https://docs.cryptolegacy.app/documentation/events-reference#beneficiaryregistrynotdefined-icl1)
* [OwnershipTransferStarted](https://docs.cryptolegacy.app/documentation/events-reference#ownershiptransferstarted-iclo1)
* [OwnershipTransferred](https://docs.cryptolegacy.app/documentation/events-reference#ownershiptransferred-iclo1)

### Errors

* [BeneficiarySwitchTimelock](https://docs.cryptolegacy.app/documentation/errors-reference#beneficiaryswitchtimelock-icl1)
* [ArrayLengthMismatch](https://docs.cryptolegacy.app/documentation/errors-reference#arraylengthmismatch-icl1)
* [DisabledFunc](https://docs.cryptolegacy.app/documentation/errors-reference#disabledfunc-icl1)
* [NotTheOwner](https://docs.cryptolegacy.app/documentation/errors-reference#nottheowner-icl1)
* [NotTheBeneficiary](https://docs.cryptolegacy.app/documentation/errors-reference#notthebeneficiary-icl1)
* [BeneficiaryNotExist](https://docs.cryptolegacy.app/documentation/errors-reference#beneficiarynotexist-icl1)
* [TooEarly](https://docs.cryptolegacy.app/documentation/errors-reference#tooearly-icl1)
* [IncorrectRefShare](https://docs.cryptolegacy.app/documentation/errors-reference#incorrectrefshare-icl1)
* [NoValueAllowed](https://docs.cryptolegacy.app/documentation/errors-reference#novalueallowed-icl1)
* [TooLongArray](https://docs.cryptolegacy.app/documentation/errors-reference#toolongarray-icl1)
* [IncorrectFee](https://docs.cryptolegacy.app/documentation/errors-reference#incorrectfee-icl1)
* [ZeroAddress](https://docs.cryptolegacy.app/documentation/errors-reference#zeroaddress-icl1)
* [ZeroTokens](https://docs.cryptolegacy.app/documentation/errors-reference#zerotokens-icl1)
* [InitialFeeNotPaid](https://docs.cryptolegacy.app/documentation/errors-reference#initialfeenotpaid-icl1)
* [InitialFeeAlreadyPaid](https://docs.cryptolegacy.app/documentation/errors-reference#initialfeealreadypaid-icl1)
* [NotBuildManager](https://docs.cryptolegacy.app/documentation/errors-reference#notbuildmanager-icl1)
* [LengthMismatch](https://docs.cryptolegacy.app/documentation/errors-reference#lengthmismatch-icl1)
* [ShareSumDoesntMatchBase](https://docs.cryptolegacy.app/documentation/errors-reference#sharesumdoesntmatchbase-icl1)
* [OriginalHashDuplicate](https://docs.cryptolegacy.app/documentation/errors-reference#originalhashduplicate-icl1)
* [DistributionStarted](https://docs.cryptolegacy.app/documentation/errors-reference#distributionstarted-icl1)
* [DistributionStartAlreadySet](https://docs.cryptolegacy.app/documentation/errors-reference#distributionstartalreadyset-icl1)
* [DistributionDelay](https://docs.cryptolegacy.app/documentation/errors-reference#distributiondelay-icl1)
* [ChallengePeriodStarted](https://docs.cryptolegacy.app/documentation/errors-reference#challengeperiodstarted-icl1)
* [AlreadySet](https://docs.cryptolegacy.app/documentation/errors-reference#alreadyset-icl1)
* [BeneficiaryNotSet](https://docs.cryptolegacy.app/documentation/errors-reference#beneficiarynotset-icl1)
* [Pause](https://docs.cryptolegacy.app/documentation/errors-reference#pause-icl1)
* [IncorrectFacetCutAction](https://docs.cryptolegacy.app/documentation/errors-reference#incorrectfacetcutaction-icl1)
* [NotContractOwner](https://docs.cryptolegacy.app/documentation/errors-reference#notcontractowner-icl1)
* [FacetNotFound](https://docs.cryptolegacy.app/documentation/errors-reference#facetnotfound-icl1)
* [FacetHasNoCode](https://docs.cryptolegacy.app/documentation/errors-reference#facethasnocode-icl1)
* [NoSelectorsInFacetToCut](https://docs.cryptolegacy.app/documentation/errors-reference#noselectorsinfacettocut-icl1)
* [FacetCantBeZero](https://docs.cryptolegacy.app/documentation/errors-reference#facetcantbezero-icl1)
* [CantRemoveImmutableFunctions](https://docs.cryptolegacy.app/documentation/errors-reference#cantremoveimmutablefunctions-icl1)
* [CantAddFunctionThatAlreadyExists](https://docs.cryptolegacy.app/documentation/errors-reference#cantaddfunctionthatalreadyexists-icl1)
* [CantReplaceFunctionWithSameFunction](https://docs.cryptolegacy.app/documentation/errors-reference#cantreplacefunctionwithsamefunction-icl1)
* [InitFunctionReverted](https://docs.cryptolegacy.app/documentation/errors-reference#initfunctionreverted-icl1)
* [InitAddressZeroButCalldataIsNot](https://docs.cryptolegacy.app/documentation/errors-reference#initaddresszerobutcalldataisnot-icl1)
* [InitCalldataZeroButAddressIsNot](https://docs.cryptolegacy.app/documentation/errors-reference#initcalldatazerobutaddressisnot-icl1)
* [PluginNotRegistered](https://docs.cryptolegacy.app/documentation/errors-reference#pluginnotregistered-icl1)
* [TransferFeeFailed](https://docs.cryptolegacy.app/documentation/errors-reference#transferfeefailed-icl1)
* [TooBigMultiplier](https://docs.cryptolegacy.app/documentation/errors-reference#toobigmultiplier-icl1)
* [OwnableUnauthorizedAccount](https://docs.cryptolegacy.app/documentation/errors-reference#ownableunauthorizedaccount-iclo1)

### Access / Roles

* `initializeByBuildManager`: `initializer`; `buildManager` only caller
* `transferOwnership`: `onlyOwner`
* `payInitialFee`: `nonReentrant`
* `setBeneficiaries`: `onlyOwner`
* `update`: `nonReentrant, onlyOwner`
* `setGasLimitMultiplier`: `nonReentrant, onlyOwner`
* `transferTreasuryTokensToLegacy`: `nonReentrant`
* `beneficiaryClaim`: `nonReentrant`
* `sendMessagesToBeneficiary`: `onlyOwner`

### Interacts With

* `ArbSys`
* `IBeneficiaryRegistry`
* `LibCryptoLegacy`
* `LibDiamond`

### Missing Links

None.

## LegacyRecoveryPlugin

### Purpose

LegacyRecoveryPlugin implements recovery-governance flows for regaining control through proposal-based execution.

### Inheritance

* `ICryptoLegacyPlugin`
* `ReentrancyGuardUpgradeable`

### Key Methods

* [getSigs(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getsigs-lrp1) - Lists the public selectors exposed by the recovery plugin facet.
* [getSetupSigs(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getsetupsigs-lrp1) - Reports selectors required during plugin setup.
* [getMultisigAllowedMethods(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getmultisigallowedmethods-lrp1) - Enumerates selectors that recovery multisig proposals may execute.
* [getPluginName(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getpluginname-lrp1) - Returns the canonical plugin identifier.
* [getPluginVer(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getpluginver-lrp1) - Reports the plugin version.
* [lrSetMultisigConfig(...)](https://docs.cryptolegacy.app/documentation/functions-reference#lrsetmultisigconfig-lrp1) - Owner-only configuration of recovery multisig voters and threshold.
* [lrPropose(...)](https://docs.cryptolegacy.app/documentation/functions-reference#lrpropose-lrp1) - Submits a new recovery multisig proposal.
* [lrConfirm(...)](https://docs.cryptolegacy.app/documentation/functions-reference#lrconfirm-lrp1) - Confirms a recovery proposal and executes it when quorum is met.

### All Functions

* [getSigs()](https://docs.cryptolegacy.app/documentation/functions-reference#getsigs-lrp1) - Lists the public selectors exposed by the recovery plugin facet.
* [getSetupSigs()](https://docs.cryptolegacy.app/documentation/functions-reference#getsetupsigs-lrp1) - Reports selectors required during plugin setup.
* [getMultisigAllowedMethods()](https://docs.cryptolegacy.app/documentation/functions-reference#getmultisigallowedmethods-lrp1) - Enumerates selectors that recovery multisig proposals may execute.
* [getPluginName()](https://docs.cryptolegacy.app/documentation/functions-reference#getpluginname-lrp1) - Returns the canonical plugin identifier.
* [getPluginVer()](https://docs.cryptolegacy.app/documentation/functions-reference#getpluginver-lrp1) - Reports the plugin version.
* [getPluginMultisigStorage()](https://docs.cryptolegacy.app/documentation/functions-reference#getpluginmultisigstorage-lrp1) - Retrieves plugin-specific multisig storage.
* [lrSetMultisigConfig(...)](https://docs.cryptolegacy.app/documentation/functions-reference#lrsetmultisigconfig-lrp1) - Owner-only configuration of recovery multisig voters and threshold.
* [lrPropose(...)](https://docs.cryptolegacy.app/documentation/functions-reference#lrpropose-lrp1) - Submits a new recovery multisig proposal.
* [lrConfirm(...)](https://docs.cryptolegacy.app/documentation/functions-reference#lrconfirm-lrp1) - Confirms a recovery proposal and executes it when quorum is met.
* [lrCancel(...)](https://docs.cryptolegacy.app/documentation/functions-reference#lrcancel-lrp1) - Removes the caller’s confirmation from a pending recovery proposal.
* [lrTransferTreasuryTokensToLegacy(...)](https://docs.cryptolegacy.app/documentation/functions-reference#lrtransfertreasurytokenstolegacy-lrp1) - Multisig-executor action to pull treasury ERC20 tokens into the legacy contract.
* [lrWithdrawTokensFromLegacy(...)](https://docs.cryptolegacy.app/documentation/functions-reference#lrwithdrawtokensfromlegacy-lrp1) - Multisig-executor withdrawal of tokens from the legacy contract to designated recipients.
* [lrResetGuardianVoting()](https://docs.cryptolegacy.app/documentation/functions-reference#lrresetguardianvoting-lrp1) - Multisig-executor action to reset guardian voting state and distribution start timestamp.
* [lrWithdrawHeldEth(...)](https://docs.cryptolegacy.app/documentation/functions-reference#lrwithdrawheldeth-lrp1) - Allows a voter to withdraw ETH accumulated during proposal execution.
* [lrGetHeldEth(...)](https://docs.cryptolegacy.app/documentation/functions-reference#lrgetheldeth-lrp1) - Returns the held ETH balance for a given voter hash.
* [lrGetInitializationStatus()](https://docs.cryptolegacy.app/documentation/functions-reference#lrgetinitializationstatus-lrp1) - Indicates whether the recovery multisig has been initialized.
* [lrGetProposalWithStatus(...)](https://docs.cryptolegacy.app/documentation/functions-reference#lrgetproposalwithstatus-lrp1) - Retrieves a specific proposal and its confirmation status.
* [lrGetProposalListWithStatuses()](https://docs.cryptolegacy.app/documentation/functions-reference#lrgetproposallistwithstatuses-lrp1) - Returns all recovery proposals with confirmation metadata.

### Events

None.

### Errors

None.

### Access / Roles

* `lrSetMultisigConfig`: `onlyOwner`
* `lrTransferTreasuryTokensToLegacy`: `nonReentrant`
* `lrWithdrawTokensFromLegacy`: `nonReentrant`
* `lrResetGuardianVoting`: `nonReentrant`
* `lrWithdrawHeldEth`: `nonReentrant`

### Interacts With

* `IBeneficiaryRegistry`
* `ICryptoLegacy`
* `ISafeMinimalMultisig`
* `LibCryptoLegacy`
* `LibSafeMinimalMultisig`
* `LibTrustedGuardiansPlugin`

### Missing Links

None.

## LensPlugin

### Purpose

LensPlugin exposes read-only protocol views to aggregate operational and beneficiary-related state.

### Inheritance

* `ICryptoLegacyPlugin`
* `ICryptoLegacyLens`

### Key Methods

* [getSigs(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getsigs-lp1) - Enumerates every externally exposed selector for the Lens plugin.
* [getSetupSigs(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getsetupsigs-lp1) - Reports setup-time selectors required by the Lens plugin.
* [getPluginName(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getpluginname-lp1) - Reveals the human-readable name of the plugin.
* [getPluginVer(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getpluginver-lp1) - Returns the semantic version of the Lens plugin.
* [updateInterval(...)](https://docs.cryptolegacy.app/documentation/functions-reference#updateinterval-lp1) - Reads the configured update interval for the CryptoLegacy instance.
* [challengeTimeout(...)](https://docs.cryptolegacy.app/documentation/functions-reference#challengetimeout-lp1) - Exposes the challenge timeout value.
* [distributionStartAt(...)](https://docs.cryptolegacy.app/documentation/functions-reference#distributionstartat-lp1) - Returns when beneficiary distribution began.
* [lastFeePaidAt(...)](https://docs.cryptolegacy.app/documentation/functions-reference#lastfeepaidat-lp1) - Reports the block timestamp of the last paid maintenance fee.

### All Functions

* [getSigs()](https://docs.cryptolegacy.app/documentation/functions-reference#getsigs-lp1) - Enumerates every externally exposed selector for the Lens plugin.
* [getSetupSigs()](https://docs.cryptolegacy.app/documentation/functions-reference#getsetupsigs-lp1) - Reports setup-time selectors required by the Lens plugin.
* [getPluginName()](https://docs.cryptolegacy.app/documentation/functions-reference#getpluginname-lp1) - Reveals the human-readable name of the plugin.
* [getPluginVer()](https://docs.cryptolegacy.app/documentation/functions-reference#getpluginver-lp1) - Returns the semantic version of the Lens plugin.
* [updateInterval()](https://docs.cryptolegacy.app/documentation/functions-reference#updateinterval-lp1) - Reads the configured update interval for the CryptoLegacy instance.
* [challengeTimeout()](https://docs.cryptolegacy.app/documentation/functions-reference#challengetimeout-lp1) - Exposes the challenge timeout value.
* [distributionStartAt()](https://docs.cryptolegacy.app/documentation/functions-reference#distributionstartat-lp1) - Returns when beneficiary distribution began.
* [lastFeePaidAt()](https://docs.cryptolegacy.app/documentation/functions-reference#lastfeepaidat-lp1) - Reports the block timestamp of the last paid maintenance fee.
* [lastUpdateAt()](https://docs.cryptolegacy.app/documentation/functions-reference#lastupdateat-lp1) - Exposes the timestamp of the most recent `update()` call.
* [initialFeeToPay()](https://docs.cryptolegacy.app/documentation/functions-reference#initialfeetopay-lp1) - Provides the initial fee amount required when activating a CryptoLegacy instance.
* [updateFee()](https://docs.cryptolegacy.app/documentation/functions-reference#updatefee-lp1) - Returns the recurring fee charged per update interval.
* [invitedByRefCode()](https://docs.cryptolegacy.app/documentation/functions-reference#invitedbyrefcode-lp1) - Exposes the referral code associated with the CryptoLegacy instance.
* [getBeneficiaryClaimed(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getbeneficiaryclaimed-lp1) - Returns how much of a given token a beneficiary has already claimed.
* [getOriginalBeneficiaryHash(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getoriginalbeneficiaryhash-lp1) - Reveals the original beneficiary hash mapped to a derived hash.
* [getBeneficiaryConfig(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getbeneficiaryconfig-lp1) - Retrieves the vesting configuration for a beneficiary hash.
* [getBeneficiaries()](https://docs.cryptolegacy.app/documentation/functions-reference#getbeneficiaries-lp1) - Lists all beneficiaries, their original hashes, and configurations.
* [\_getBeneficiaries(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_getbeneficiaries-lp1) - Internal helper that assembles beneficiary hashes, originals, and configs.
* [getTransferBlockNumbers()](https://docs.cryptolegacy.app/documentation/functions-reference#gettransferblocknumbers-lp1) - Returns the block numbers recorded for asset movements involving the CryptoLegacy contract.
* [getTokensDistribution(...)](https://docs.cryptolegacy.app/documentation/functions-reference#gettokensdistribution-lp1) - Summarises distribution totals for a token list.
* [\_getTokensDistribution(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_gettokensdistribution-lp1) - Internal aggregator that builds per-token distribution data.
* [getCryptoLegacyBaseData()](https://docs.cryptolegacy.app/documentation/functions-reference#getcryptolegacybasedata-lp1) - Returns a snapshot of the core CryptoLegacy configuration.
* [getCryptoLegacyListData(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getcryptolegacylistdata-lp1) - Provides a comprehensive snapshot including beneficiaries, plugins, and token distributions.
* [getMessagesBlockNumbersByRecipient(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getmessagesblocknumbersbyrecipient-lp1) - Lists when messages were received for a beneficiary.
* [getVestedAndClaimedData(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getvestedandclaimeddata-lp1) - Calculates vested, claimable, and claimed token amounts for a beneficiary.
* [\_getPluginInfoList(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_getplugininfolist-lp1) - Internal helper that compiles plugin metadata for all installed facets.
* [\_getPluginMetadata(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_getpluginmetadata-lp1) - Fetches metadata for a specific plugin address.
* [getPluginInfoList()](https://docs.cryptolegacy.app/documentation/functions-reference#getplugininfolist-lp1) - Exposes metadata for all plugins attached to the CryptoLegacy instance.
* [getPluginMetadata(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getpluginmetadata-lp1) - Returns metadata for a specific plugin address through the lens facet.

### Events

None.

### Errors

None.

### Access / Roles

None.

### Interacts With

* `ICryptoLegacy`
* `LibCryptoLegacy`
* `LibDiamond`

### Missing Links

None.

## NftLegacyPlugin

### Purpose

NftLegacyPlugin implements NFT-oriented legacy management and related beneficiary operations.

### Inheritance

* `ICryptoLegacyPlugin`
* `ReentrancyGuardUpgradeable`

### Key Methods

* [getSigs(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getsigs-nlp1) - Lists the externally callable selectors for the NFT inheritance facet.
* [getSetupSigs(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getsetupsigs-nlp1) - Reports any setup-time selectors required by the NFT plugin.
* [getPluginName(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getpluginname-nlp1) - Returns the human-readable identifier for the NFT plugin.
* [getPluginVer(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getpluginver-nlp1) - Provides the semantic version of the NFT plugin.
* [setNftBeneficiary(...)](https://docs.cryptolegacy.app/documentation/functions-reference#setnftbeneficiary-nlp1) - Assigns a beneficiary hash and claim delay to multiple NFTs.
* [transferNftTokensToLegacy(...)](https://docs.cryptolegacy.app/documentation/functions-reference#transfernfttokenstolegacy-nlp1) - Pulls configured NFTs into the CryptoLegacy contract once distribution is ready.
* [beneficiaryClaimNft(...)](https://docs.cryptolegacy.app/documentation/functions-reference#beneficiaryclaimnft-nlp1) - Lets the designated beneficiary withdraw NFTs after the claim delay.

### All Functions

* [getSigs()](https://docs.cryptolegacy.app/documentation/functions-reference#getsigs-nlp1) - Lists the externally callable selectors for the NFT inheritance facet.
* [getSetupSigs()](https://docs.cryptolegacy.app/documentation/functions-reference#getsetupsigs-nlp1) - Reports any setup-time selectors required by the NFT plugin.
* [getPluginName()](https://docs.cryptolegacy.app/documentation/functions-reference#getpluginname-nlp1) - Returns the human-readable identifier for the NFT plugin.
* [getPluginVer()](https://docs.cryptolegacy.app/documentation/functions-reference#getpluginver-nlp1) - Provides the semantic version of the NFT plugin.
* [getPluginStorage()](https://docs.cryptolegacy.app/documentation/functions-reference#getpluginstorage-nlp1) - Returns the plugin’s dedicated storage slot.
* [setNftBeneficiary(...)](https://docs.cryptolegacy.app/documentation/functions-reference#setnftbeneficiary-nlp1) - Assigns a beneficiary hash and claim delay to multiple NFTs.
* [transferNftTokensToLegacy(...)](https://docs.cryptolegacy.app/documentation/functions-reference#transfernfttokenstolegacy-nlp1) - Pulls configured NFTs into the CryptoLegacy contract once distribution is ready.
* [beneficiaryClaimNft(...)](https://docs.cryptolegacy.app/documentation/functions-reference#beneficiaryclaimnft-nlp1) - Lets the designated beneficiary withdraw NFTs after the claim delay.

### Events

* [SetNftBeneficiary](https://docs.cryptolegacy.app/documentation/events-reference#setnftbeneficiary-nlp1)
* [BeneficiaryClaimNft](https://docs.cryptolegacy.app/documentation/events-reference#beneficiaryclaimnft-nlp1)
* [TransferNftToCryptoLegacy](https://docs.cryptolegacy.app/documentation/events-reference#transfernfttocryptolegacy-nlp1)

### Errors

* [BeneficiaryNotSet](https://docs.cryptolegacy.app/documentation/errors-reference#beneficiarynotset-icl1)
* [DistributionDelay](https://docs.cryptolegacy.app/documentation/errors-reference#distributiondelay-icl1)
* [NotTheBeneficiary](https://docs.cryptolegacy.app/documentation/errors-reference#notthebeneficiary-icl1)
* [ZeroTokens](https://docs.cryptolegacy.app/documentation/errors-reference#zerotokens-icl1)

### Access / Roles

* `setNftBeneficiary`: `onlyOwner`
* `transferNftTokensToLegacy`: `nonReentrant`
* `beneficiaryClaimNft`: `nonReentrant`

### Interacts With

* `ICryptoLegacy`
* `LibCryptoLegacy`

### Missing Links

None.

## ReceiveEthPlugin

### Purpose

ReceiveEthPlugin enables a CryptoLegacy instance to accept plain ETH transfers and wrap the accumulated ETH into WETH when a beneficiary triggers the wrapping flow.

### Inheritance

* `ICryptoLegacyPlugin`

### Key Methods

* [getSigs(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getsigs-rep1) - Returns the selectors exposed by the receive-ETH plugin.
* [getSetupSigs(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getsetupsigs-rep1) - Returns setup-time selectors required for the receive-ETH plugin.
* [wrapEthToWeth(...)](https://docs.cryptolegacy.app/documentation/functions-reference#wrapethtoweth-rep1) - Wraps all ETH currently held by the CryptoLegacy diamond into WETH.

### All Functions

* [constructor(...)](https://docs.cryptolegacy.app/documentation/functions-reference#constructor-rep1) - Stores the WETH contract address used when wrapping received ETH.
* [getSigs(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getsigs-rep1) - Returns the selectors exposed by the receive-ETH plugin.
* [getSetupSigs(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getsetupsigs-rep1) - Returns setup-time selectors required for the receive-ETH plugin.
* [getPluginName(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getpluginname-rep1) - Returns the unique plugin name string.
* [getPluginVer(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getpluginver-rep1) - Returns the semantic version for the receive-ETH plugin.
* [wrapEthToWeth(...)](https://docs.cryptolegacy.app/documentation/functions-reference#wrapethtoweth-rep1) - Wraps all ETH currently held by the CryptoLegacy diamond into WETH.
* [receive(...)](https://docs.cryptolegacy.app/documentation/functions-reference#receive-rep1) - Accepts plain ETH transfers routed into the facet by the diamond.

### Events

* [WrapEthToWeth](https://docs.cryptolegacy.app/documentation/events-reference#wrapethtoweth-rep1)

### Errors

* [NoEthToWrap](https://docs.cryptolegacy.app/documentation/errors-reference#noethtowrap-rep1)

### Access / Roles

* `wrapEthToWeth`: beneficiary caller after the distribution-ready checks enforced by `LibCryptoLegacy`
* `receive`: open plain-ETH entry point

### Interacts With

* `ICryptoLegacy`
* `IWETH`
* `LibCryptoLegacy`

### Missing Links

None.

## TrustedGuardiansPlugin

### Purpose

TrustedGuardiansPlugin implements guardian-voting logic for distribution and safety-critical transitions.

### Inheritance

* `ICryptoLegacyPlugin`
* `ITrustedGuardiansPlugin`
* `ReentrancyGuardUpgradeable`

### Key Methods

* [getSigs(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getsigs-tgp1) - Enumerates every externally exposed selector for guardian management.
* [getSetupSigs(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getsetupsigs-tgp1) - Reports setup-time selectors that the facet expects during installation.
* [getPluginName(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getpluginname-tgp1) - Returns the facet’s human-readable identifier.
* [getPluginVer(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getpluginver-tgp1) - Exposes the semantic version of the guardians facet.
* [initializeGuardians(...)](https://docs.cryptolegacy.app/documentation/functions-reference#initializeguardians-tgp1) - Configures the guardian roster, threshold, and challenge timeout in a single owner call.
* [setGuardians(...)](https://docs.cryptolegacy.app/documentation/functions-reference#setguardians-tgp1) - Updates the guardian membership without touching threshold configuration.
* [setGuardiansConfig(...)](https://docs.cryptolegacy.app/documentation/functions-reference#setguardiansconfig-tgp1) - Updates guardian quorum configuration while preserving the existing guardian list.
* [guardiansVoteForDistribution(...)](https://docs.cryptolegacy.app/documentation/functions-reference#guardiansvotefordistribution-tgp1) - Records a guardian vote and optionally accelerates distribution start.

### All Functions

* [getSigs()](https://docs.cryptolegacy.app/documentation/functions-reference#getsigs-tgp1) - Enumerates every externally exposed selector for guardian management.
* [getSetupSigs()](https://docs.cryptolegacy.app/documentation/functions-reference#getsetupsigs-tgp1) - Reports setup-time selectors that the facet expects during installation.
* [getPluginName()](https://docs.cryptolegacy.app/documentation/functions-reference#getpluginname-tgp1) - Returns the facet’s human-readable identifier.
* [getPluginVer()](https://docs.cryptolegacy.app/documentation/functions-reference#getpluginver-tgp1) - Exposes the semantic version of the guardians facet.
* [\_isGuardianVoted(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_isguardianvoted-tgp1) - Checks whether a guardian hash already appears in the vote ledger.
* [\_checkGuardianAndRemoveInvalid(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_checkguardianandremoveinvalid-tgp1) - Validates a stored guardian vote and prunes it if the guardian is no longer recognised.
* [\_checkGuardian()](https://docs.cryptolegacy.app/documentation/functions-reference#_checkguardian-tgp1) - Ensures the caller is a registered guardian and the contract has paid its initial fee.
* [\_checkGuardianNotVoted()](https://docs.cryptolegacy.app/documentation/functions-reference#_checkguardiannotvoted-tgp1) - Validates that the caller is an authorised guardian who has not yet voted.
* [\_getGuardians(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_getguardians-tgp1) - Resolves the active guardian set, falling back to beneficiaries when no explicit list exists.
* [\_getGuardiansThreshold(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_getguardiansthreshold-tgp1) - Computes the effective vote threshold for guardians.
* [\_getGuardiansChallengeTimeout(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_getguardianschallengetimeout-tgp1) - Retrieves the challenge timeout applied once guardians reach quorum.
* [initializeGuardians(...)](https://docs.cryptolegacy.app/documentation/functions-reference#initializeguardians-tgp1) - Configures the guardian roster, threshold, and challenge timeout in a single owner call.
* [setGuardians(...)](https://docs.cryptolegacy.app/documentation/functions-reference#setguardians-tgp1) - Updates the guardian membership without touching threshold configuration.
* [\_setGuardians(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_setguardians-tgp1) - Internal helper that mutates the guardian set and beneficiary registry.
* [setGuardiansConfig(...)](https://docs.cryptolegacy.app/documentation/functions-reference#setguardiansconfig-tgp1) - Updates guardian quorum configuration while preserving the existing guardian list.
* [\_setGuardiansConfig(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_setguardiansconfig-tgp1) - Writes guardian threshold and timeout parameters with validation.
* [\_afterGuardiansSet(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_afterguardiansset-tgp1) - Validates quorum bounds and clears guardian vote progress.
* [guardiansVoteForDistribution()](https://docs.cryptolegacy.app/documentation/functions-reference#guardiansvotefordistribution-tgp1) - Records a guardian vote and optionally accelerates distribution start.
* [guardiansTransferTreasuryTokensToLegacy(...)](https://docs.cryptolegacy.app/documentation/functions-reference#guardianstransfertreasurytokenstolegacy-tgp1) - Allows guardians to move treasury ERC20 balances into the CryptoLegacy contract once distribution is live.
* [resetGuardianVoting()](https://docs.cryptolegacy.app/documentation/functions-reference#resetguardianvoting-tgp1) - Owner-controlled reset that clears guardian votes, resets distribution start, and processes the upkeep fee.
* [\_isGuardiansInitialized(...)](https://docs.cryptolegacy.app/documentation/functions-reference#_isguardiansinitialized-tgp1) - Indicates whether a dedicated guardian set is stored.
* [isGuardiansInitialized()](https://docs.cryptolegacy.app/documentation/functions-reference#isguardiansinitialized-tgp1) - Public getter indicating whether guardians have been explicitly set.
* [getGuardiansData()](https://docs.cryptolegacy.app/documentation/functions-reference#getguardiansdata-tgp1) - Provides a snapshot of guardian hashes, votes, quorum, and timeout.
* [checkGuardiansVotedAndGetGuardiansData()](https://docs.cryptolegacy.app/documentation/functions-reference#checkguardiansvotedandgetguardiansdata-tgp1) - Guardian-only getter that also reports whether the caller has voted.

### Events

* [SetGuardian](https://docs.cryptolegacy.app/documentation/events-reference#setguardian-itgp1)
* [SetGuardiansConfig](https://docs.cryptolegacy.app/documentation/events-reference#setguardiansconfig-itgp1)
* [ClearGuardiansVoted](https://docs.cryptolegacy.app/documentation/events-reference#clearguardiansvoted-itgp1)
* [GuardiansDistributionStartSet](https://docs.cryptolegacy.app/documentation/events-reference#guardiansdistributionstartset-itgp1)
* [GuardiansVoteForDistribution](https://docs.cryptolegacy.app/documentation/events-reference#guardiansvotefordistribution-itgp1)
* [ResetGuardiansVoting](https://docs.cryptolegacy.app/documentation/events-reference#resetguardiansvoting-itgp1)

### Errors

* [NotGuardian](https://docs.cryptolegacy.app/documentation/errors-reference#notguardian-itgp1)
* [GuardianAlreadyVoted](https://docs.cryptolegacy.app/documentation/errors-reference#guardianalreadyvoted-itgp1)
* [ZeroGuardian](https://docs.cryptolegacy.app/documentation/errors-reference#zeroguardian-itgp1)
* [MaxGuardiansTimeout](https://docs.cryptolegacy.app/documentation/errors-reference#maxguardianstimeout-itgp1)
* [GuardiansTimeoutCantBeZero](https://docs.cryptolegacy.app/documentation/errors-reference#guardianstimeoutcantbezero-itgp1)
* [ThresholdDontMet](https://docs.cryptolegacy.app/documentation/errors-reference#thresholddontmet-itgp1)
* [ThresholdTooBig](https://docs.cryptolegacy.app/documentation/errors-reference#thresholdtoobig-itgp1)
* [InitialFeeNotPaid](https://docs.cryptolegacy.app/documentation/errors-reference#initialfeenotpaid-icl1)

### Access / Roles

* `initializeGuardians`: `nonReentrant, onlyOwner`
* `setGuardians`: `nonReentrant, onlyOwner`
* `setGuardiansConfig`: `nonReentrant, onlyOwner`
* `guardiansVoteForDistribution`: `nonReentrant`
* `guardiansTransferTreasuryTokensToLegacy`: `nonReentrant`
* `resetGuardianVoting`: `nonReentrant, onlyOwner`

### Interacts With

* `IBeneficiaryRegistry`
* `ICryptoLegacy`
* `LibCryptoLegacy`
* `LibSafeMinimalMultisig`
* `LibTrustedGuardiansPlugin`

### Missing Links

None.

## UpdateRolePlugin

### Purpose

UpdateRolePlugin implements controlled updates of beneficiary, guardian, and related role assignments.

### Inheritance

* `ICryptoLegacyPlugin`
* `ReentrancyGuardUpgradeable`

### Key Methods

* [getSigs(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getsigs-urp1) - Lists external selectors provided by the updater role facet.
* [getSetupSigs(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getsetupsigs-urp1) - Reports setup selectors required during facet installation.
* [getPluginName(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getpluginname-urp1) - Returns the human-readable name of the updater facet.
* [getPluginVer(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getpluginver-urp1) - Reveals the semantic version for the updater role facet.
* [owner(...)](https://docs.cryptolegacy.app/documentation/functions-reference#owner-urp1) - Returns the current diamond owner address.
* [getUpdaterList(...)](https://docs.cryptolegacy.app/documentation/functions-reference#getupdaterlist-urp1) - Returns the full set of updater addresses.
* [isUpdater(...)](https://docs.cryptolegacy.app/documentation/functions-reference#isupdater-urp1) - Checks whether a given address currently has update permissions.
* [setUpdater(...)](https://docs.cryptolegacy.app/documentation/functions-reference#setupdater-urp1) - Adds or removes authorised updaters.

### All Functions

* [getSigs()](https://docs.cryptolegacy.app/documentation/functions-reference#getsigs-urp1) - Lists external selectors provided by the updater role facet.
* [getSetupSigs()](https://docs.cryptolegacy.app/documentation/functions-reference#getsetupsigs-urp1) - Reports setup selectors required during facet installation.
* [getPluginName()](https://docs.cryptolegacy.app/documentation/functions-reference#getpluginname-urp1) - Returns the human-readable name of the updater facet.
* [getPluginVer()](https://docs.cryptolegacy.app/documentation/functions-reference#getpluginver-urp1) - Reveals the semantic version for the updater role facet.
* [getPluginStorage()](https://docs.cryptolegacy.app/documentation/functions-reference#getpluginstorage-urp1) - Returns the plugin-specific storage slot used for updater data.
* [owner()](https://docs.cryptolegacy.app/documentation/functions-reference#owner-urp1) - Returns the current diamond owner address.
* [getUpdaterList()](https://docs.cryptolegacy.app/documentation/functions-reference#getupdaterlist-urp1) - Returns the full set of updater addresses.
* [isUpdater(...)](https://docs.cryptolegacy.app/documentation/functions-reference#isupdater-urp1) - Checks whether a given address currently has update permissions.
* [setUpdater(...)](https://docs.cryptolegacy.app/documentation/functions-reference#setupdater-urp1) - Adds or removes authorised updaters.
* [updateByUpdater(...)](https://docs.cryptolegacy.app/documentation/functions-reference#updatebyupdater-urp1) - Lets authorised updaters execute the `update` flow while paying required fees before distribution begins.

### Events

* [AddUpdater](https://docs.cryptolegacy.app/documentation/events-reference#addupdater-iclup1)
* [RemoveUpdater](https://docs.cryptolegacy.app/documentation/events-reference#removeupdater-iclup1)
* [Update](https://docs.cryptolegacy.app/documentation/events-reference#update-icl1)

### Errors

* [NotTheUpdater](https://docs.cryptolegacy.app/documentation/errors-reference#nottheupdater-iclup1)

### Access / Roles

* `setUpdater`: `nonReentrant, onlyOwner`
* `updateByUpdater`: `nonReentrant, onlyUpdater`

### Interacts With

* `ICryptoLegacy`
* `ICryptoLegacyUpdaterPlugin`
* `LibCryptoLegacy`
* `LibDiamond`

### Missing Links

None.


# Contract Functions Reference

Below is a clear overview of each major CryptoLegacy contract function: purpose, inputs, outputs, key logic, events, and external interactions.

## Table of Contents

1. [BeneficiaryRegistry (BR1)](#beneficiaryregistry-br1)
   * [constructor (BR1)](#constructor-br1)
   * [\_setBlockNumberChange (BR1)](#_setblocknumberchange-br1)
   * [setCryptoLegacyBeneficiary (BR1)](#setcryptolegacybeneficiary-br1)
   * [setCryptoLegacyGuardian (BR1)](#setcryptolegacyguardian-br1)
   * [setCryptoLegacyOwner (BR1)](#setcryptolegacyowner-br1)
   * [setCryptoLegacyRecoveryAddresses (BR1)](#setcryptolegacyrecoveryaddresses-br1)
   * [getCryptoLegacyListByBeneficiary (BR1)](#getcryptolegacylistbybeneficiary-br1)
   * [getCryptoLegacyListByOwner (BR1)](#getcryptolegacylistbyowner-br1)
   * [getCryptoLegacyListByGuardian (BR1)](#getcryptolegacylistbyguardian-br1)
   * [getCryptoLegacyListByRecovery (BR1)](#getcryptolegacylistbyrecovery-br1)
   * [getCryptoLegacyBlockNumberChanges (BR1)](#getcryptolegacyblocknumberchanges-br1)
   * [getAllCryptoLegacyListByRoles (BR1)](#getallcryptolegacylistbyroles-br1)
2. [BuildManagerOwnable (BMO1)](#buildmanagerownable-bmo1)
   * [constructor (BMO1)](#constructor-bmo1)
   * [setBuildManager (BMO1)](#setbuildmanager-bmo1)
   * [\_checkBuildManagerValid (BMO1)](#_checkbuildmanagervalid-bmo1)
   * [getBuildManagerAdded (BMO1)](#getbuildmanageradded-bmo1)
3. [Create3Factory (C3F1)](#create3factory-c3f1)
   * [constructor (C3F1)](#constructor-c3f1)
   * [build (C3F1)](#build-c3f1)
   * [computeAddress (C3F1)](#computeaddress-c3f1)
4. [CryptoLegacy (CL1)](#cryptolegacy-cl1)
   * [constructor (CL1)](#constructor-cl1)
   * [replacePlugin (CL1)](#replaceplugin-cl1)
   * [addPluginList (CL1)](#addpluginlist-cl1)
   * [removePluginList (CL1)](#removepluginlist-cl1)
   * [externalLens (CL1)](#externallens-cl1)
5. [CryptoLegacyBuildManager (CLBM1)](#cryptolegacybuildmanager-clbm1)
   * [receive (CLBM1)](#receive-clbm1)
   * [constructor (CLBM1)](#constructor-clbm1)
   * [setRegistries (CLBM1)](#setregistries-clbm1)
   * [\_setRegistries (CLBM1)](#_setregistries-clbm1)
   * [setFactory (CLBM1)](#setfactory-clbm1)
   * [\_setFactory (CLBM1)](#_setfactory-clbm1)
   * [setSupplyLimit (CLBM1)](#setsupplylimit-clbm1)
   * [setExternalLens (CLBM1)](#setexternallens-clbm1)
   * [withdrawFee (CLBM1)](#withdrawfee-clbm1)
   * [payFee (CLBM1)](#payfee-clbm1)
   * [\_payFee (CLBM1)](#_payfee-clbm1)
   * [\_returnFee (CLBM1)](#_returnfee-clbm1)
   * [\_checkFee (CLBM1)](#_checkfee-clbm1)
   * [\_mintAndLockLifetimeNft (CLBM1)](#_mintandlocklifetimenft-clbm1)
   * [payInitialFee (CLBM1)](#payinitialfee-clbm1)
   * [payForMultipleLifetimeNft (CLBM1)](#payformultiplelifetimenft-clbm1)
   * [createCustomRef (CLBM1)](#createcustomref-clbm1)
   * [\_createCustomRef (CLBM1)](#_createcustomref-clbm1)
   * [createRef (CLBM1)](#createref-clbm1)
   * [\_createRef (CLBM1)](#_createref-clbm1)
   * [updateCrossChainsRef (CLBM1)](#updatecrosschainsref-clbm1)
   * [\_createRefAndPayForBuild (CLBM1)](#_createrefandpayforbuild-clbm1)
   * [buildCryptoLegacy (CLBM1)](#buildcryptolegacy-clbm1)
   * [\_checkBuildArgs (CLBM1)](#_checkbuildargs-clbm1)
   * [\_getAndPayBuildFee (CLBM1)](#_getandpaybuildfee-clbm1)
   * [getUpdateFee (CLBM1)](#getupdatefee-clbm1)
   * [getAndPayBuildFee (CLBM1)](#getandpaybuildfee-clbm1)
   * [transferStuckNft (CLBM1)](#transferstucknft-clbm1)
   * [onERC721Received (CLBM1)](#onerc721received-clbm1)
   * [calculateCrossChainCreateRefFee (CLBM1)](#calculatecrosschaincreatereffee-clbm1)
   * [getFactoryAddress (CLBM1)](#getfactoryaddress-clbm1)
   * [isLifetimeNftLocked (CLBM1)](#islifetimenftlocked-clbm1)
   * [isLifetimeNftLockedAndUpdate (CLBM1)](#islifetimenftlockedandupdate-clbm1)
   * [isPluginRegistered (CLBM1)](#ispluginregistered-clbm1)
   * [isCryptoLegacyBuilt (CLBM1)](#iscryptolegacybuilt-clbm1)
6. [CryptoLegacyDiamondBase (CLDB1)](#cryptolegacydiamondbase-cldb1)
   * [staticCallChecker (CLDB1)](#staticcallchecker-cldb1)
   * [fallback (CLDB1)](#fallback-cldb1)
7. [CryptoLegacyExternalLens (CLEXL1)](#cryptolegacyexternallens-clexl1)
   * [isLifetimeActive (CLEXL1)](#islifetimeactive-clexl1)
   * [isPaused (CLEXL1)](#ispaused-clexl1)
   * [buildManager (CLEXL1)](#buildmanager-clexl1)
   * [owner (CLEXL1)](#owner-clexl1)
   * [\_baseData (CLEXL1)](#_basedata-clexl1)
   * [\_listTokensData (CLEXL1)](#_listtokensdata-clexl1)
   * [updateInterval (CLEXL1)](#updateinterval-clexl1)
   * [challengeTimeout (CLEXL1)](#challengetimeout-clexl1)
   * [distributionStartAt (CLEXL1)](#distributionstartat-clexl1)
   * [lastFeePaidAt (CLEXL1)](#lastfeepaidat-clexl1)
   * [lastUpdateAt (CLEXL1)](#lastupdateat-clexl1)
   * [initialFeeToPay (CLEXL1)](#initialfeetopay-clexl1)
   * [updateFee (CLEXL1)](#updatefee-clexl1)
   * [invitedByRefCode (CLEXL1)](#invitedbyrefcode-clexl1)
   * [getBeneficiaries (CLEXL1)](#getbeneficiaries-clexl1)
   * [getTokensDistribution (CLEXL1)](#gettokensdistribution-clexl1)
   * [getCryptoLegacyBaseData (CLEXL1)](#getcryptolegacybasedata-clexl1)
   * [getCryptoLegacyListData (CLEXL1)](#getcryptolegacylistdata-clexl1)
   * [getMessagesBlockNumbersByRecipient (CLEXL1)](#getmessagesblocknumbersbyrecipient-clexl1)
   * [getTransferBlockNumbers (CLEXL1)](#gettransferblocknumbers-clexl1)
   * [getVestedAndClaimedData (CLEXL1)](#getvestedandclaimeddata-clexl1)
   * [getPluginInfoList (CLEXL1)](#getplugininfolist-clexl1)
   * [getCryptoLegacyListWithStatuses (CLEXL1)](#getcryptolegacylistwithstatuses-clexl1)
8. [CryptoLegacyFactory (CLF1)](#cryptolegacyfactory-clf1)
   * [constructor (CLF1)](#constructor-clf1)
   * [setBuildOperator (CLF1)](#setbuildoperator-clf1)
   * [createCryptoLegacy (CLF1)](#createcryptolegacy-clf1)
   * [cryptoLegacyBytecode (CLF1)](#cryptolegacybytecode-clf1)
   * [computeAddress (CLF1)](#computeaddress-clf1)
9. [CryptoLegacyOwnable (CLO1)](#cryptolegacyownable-clo1)
   * [modifier onlyOwner (CLO1)](#modifier-onlyowner-clo1)
   * [\_transferOwnership (CLO1)](#_transferownership-clo1)
   * [acceptOwnership (CLO1)](#acceptownership-clo1)
   * [setPause (CLO1)](#setpause-clo1)
   * [pendingOwner (CLO1)](#pendingowner-clo1)
10. [FeeRegistry (FR1)](#feeregistry-fr1)
    * [constructor (FR1)](#constructor-fr1)
    * [lockFeeRegistryStorage (FR1)](#lockfeeregistrystorage-fr1)
    * [initialize (FR1)](#initialize-fr1)
    * [setCodeOperator (FR1)](#setcodeoperator-fr1)
    * [setSupportedRefCodeInChains (FR1)](#setsupportedrefcodeinchains-fr1)
    * [setFeeBeneficiaries (FR1)](#setfeebeneficiaries-fr1)
    * [setDefaultPct (FR1)](#setdefaultpct-fr1)
    * [\_setDefaultPct (FR1)](#_setdefaultpct-fr1)
    * [setRefererSpecificPct (FR1)](#setrefererspecificpct-fr1)
    * [setContractCaseFee (FR1)](#setcontractcasefee-fr1)
    * [takeFee (FR1)](#takefee-fr1)
    * [withdrawAccumulatedFee (FR1)](#withdrawaccumulatedfee-fr1)
    * [withdrawReferralAccumulatedFee (FR1)](#withdrawreferralaccumulatedfee-fr1)
    * [\_setCustomCode (FR1)](#_setcustomcode-fr1)
    * [\_createCustomCode (FR1)](#_createcustomcode-fr1)
    * [\_checkCodeNotZero (FR1)](#_checkcodenotzero-fr1)
    * [\_checkSenderIsOperator (FR1)](#_checksenderisoperator-fr1)
    * [createCustomCode (FR1)](#createcustomcode-fr1)
    * [createCode (FR1)](#createcode-fr1)
    * [\_setCrossChainsRef (FR1)](#_setcrosschainsref-fr1)
    * [updateCrossChainsRef (FR1)](#updatecrosschainsref-fr1)
    * [crossCreateCustomCode (FR1)](#crosscreatecustomcode-fr1)
    * [crossUpdateCustomCode (FR1)](#crossupdatecustomcode-fr1)
    * [\_encodeCrossCreateCustomCodeCommand (FR1)](#_encodecrosscreatecustomcodecommand-fr1)
    * [\_encodeCrossUpdateCustomCodeCommand (FR1)](#_encodecrossupdatecustomcodecommand-fr1)
    * [\_checkSenderIsReferrer (FR1)](#_checksenderisreferrer-fr1)
    * [\_checkNewOwnerIsNotReferrer (FR1)](#_checknewownerisnotreferrer-fr1)
    * [changeCodeReferrer (FR1)](#changecodereferrer-fr1)
    * [changeRecipientReferrer (FR1)](#changerecipientreferrer-fr1)
    * [getCodeOperatorsList (FR1)](#getcodeoperatorslist-fr1)
    * [isCodeOperator (FR1)](#iscodeoperator-fr1)
    * [getSupportedRefInChainsList (FR1)](#getsupportedrefinchainslist-fr1)
    * [isSupportedRefInChain (FR1)](#issupportedrefinchain-fr1)
    * [getFeeBeneficiaries (FR1)](#getfeebeneficiaries-fr1)
    * [getCodePct (FR1)](#getcodepct-fr1)
    * [\_getCodePct (FR1)](#_getcodepct-fr1)
    * [calculateFee (FR1)](#calculatefee-fr1)
    * [\_calculateFee (FR1)](#_calculatefee-fr1)
    * [getContractCaseFee (FR1)](#getcontractcasefee-fr1)
    * [getContractCaseFeeForCode (FR1)](#getcontractcasefeeforcode-fr1)
    * [getReferrerByAddress (FR1)](#getreferrerbyaddress-fr1)
    * [\_getReferrerByAddress (FR1)](#_getreferrerbyaddress-fr1)
    * [getReferrerByCode (FR1)](#getreferrerbycode-fr1)
    * [\_getReferrerByCode (FR1)](#_getreferrerbycode-fr1)
    * [defaultSharePct (FR1)](#defaultsharepct-fr1)
    * [defaultDiscountPct (FR1)](#defaultdiscountpct-fr1)
    * [refererByCode (FR1)](#refererbycode-fr1)
    * [codeByReferrer (FR1)](#codebyreferrer-fr1)
    * [accumulatedFee (FR1)](#accumulatedfee-fr1)
11. [LegacyMessenger (LM1)](#legacymessenger-lm1)
    * [constructor (LM1)](#constructor-lm1)
    * [sendMessagesTo (LM1)](#sendmessagesto-lm1)
    * [getMessagesBlockNumbersByRecipient (LM1)](#getmessagesblocknumbersbyrecipient-lm1)
12. [LifetimeNft (LN1)](#lifetimenft-ln1)
    * [constructor (LN1)](#constructor-ln1)
    * [setBaseUri (LN1)](#setbaseuri-ln1)
    * [\_setBaseUri (LN1)](#_setbaseuri-ln1)
    * [setMinterOperator (LN1)](#setminteroperator-ln1)
    * [mint (LN1)](#mint-ln1)
    * [\_baseURI (LN1)](#_baseuri-ln1)
    * [tokensOfOwner (LN1)](#tokensofowner-ln1)
    * [getTier (LN1)](#gettier-ln1)
13. [LockChainGate (LCG1)](#lockchaingate-lcg1)
    * [constructor (LCG1)](#constructor-lcg1)
    * [lockChainGateStorage (LCG1)](#lockchaingatestorage-lcg1)
    * [\_initializeLockChainGate (LCG1)](#_initializelockchaingate-lcg1)
    * [setLockOperator (LCG1)](#setlockoperator-lcg1)
    * [setDebridgeGate (LCG1)](#setdebridgegate-lcg1)
    * [setDebridgeNativeFee (LCG1)](#setdebridgenativefee-lcg1)
    * [\_setDestinationChainContract (LCG1)](#_setdestinationchaincontract-lcg1)
    * [setDestinationChainContract (LCG1)](#setdestinationchaincontract-lcg1)
    * [\_setSourceChainContract (LCG1)](#_setsourcechaincontract-lcg1)
    * [setSourceChainContract (LCG1)](#setsourcechaincontract-lcg1)
    * [setSourceAndDestinationChainContract (LCG1)](#setsourceanddestinationchaincontract-lcg1)
    * [setLockPeriod (LCG1)](#setlockperiod-lcg1)
    * [setReferralCode (LCG1)](#setreferralcode-lcg1)
    * [setCustomChainId (LCG1)](#setcustomchainid-lcg1)
    * [\_writeLockLifetimeNft (LCG1)](#_writelocklifetimenft-lcg1)
    * [lockLifetimeNft (LCG1)](#locklifetimenft-lcg1)
    * [\_calcAndReturnFee (LCG1)](#_calcandreturnfee-lcg1)
    * [\_returnFee (LCG1)](#_returnfee-lcg1)
    * [crossLockLifetimeNft (LCG1)](#crosslocklifetimenft-lcg1)
    * [\_lockLifetimeNftToChains (LCG1)](#_locklifetimenfttochains-lcg1)
    * [\_checkFee (LCG1)](#_checkfee-lcg1)
    * [lockLifetimeNftToChains (LCG1)](#locklifetimenfttochains-lcg1)
    * [\_lockLifetimeNftToChain (LCG1)](#_locklifetimenfttochain-lcg1)
    * [unlockLifetimeNft (LCG1)](#unlocklifetimenft-lcg1)
    * [unlockLifetimeNftFromChain (LCG1)](#unlocklifetimenftfromchain-lcg1)
    * [crossUnlockLifetimeNft (LCG1)](#crossunlocklifetimenft-lcg1)
    * [crossUpdateNftOwner (LCG1)](#crossupdatenftowner-lcg1)
    * [\_deleteTokenData (LCG1)](#_deletetokendata-lcg1)
    * [\_onlyCrossChain (LCG1)](#_onlycrosschain-lcg1)
    * [\_send (LCG1)](#_send-lcg1)
    * [approveLifetimeNftTo (LCG1)](#approvelifetimenftto-lcg1)
    * [\_transferLifetimeNftTo (LCG1)](#_transferlifetimenftto-lcg1)
    * [transferLifetimeNftTo (LCG1)](#transferlifetimenftto-lcg1)
    * [updateNftOwnerOnChainList (LCG1)](#updatenftowneronchainlist-lcg1)
    * [\_updateNftOwnerOnChainList (LCG1)](#_updatenftowneronchainlist-lcg1)
    * [\_updateLifetimeNftOwnerOnChain (LCG1)](#_updatelifetimenftowneronchain-lcg1)
    * [\_encodeCrossLockCommand (LCG1)](#_encodecrosslockcommand-lcg1)
    * [\_encodeCrossUnlockCommand (LCG1)](#_encodecrossunlockcommand-lcg1)
    * [\_encodeCrossUpdateOwnerCommand (LCG1)](#_encodecrossupdateownercommand-lcg1)
    * [\_checkDestinationLockedChain (LCG1)](#_checkdestinationlockedchain-lcg1)
    * [\_checkTokenLocked (LCG1)](#_checktokenlocked-lcg1)
    * [\_checkCrossChainLock (LCG1)](#_checkcrosschainlock-lcg1)
    * [\_checkTooEarly (LCG1)](#_checktooearly-lcg1)
    * [\_checkSource (LCG1)](#_checksource-lcg1)
    * [\_checkHolderTokenLock (LCG1)](#_checkholdertokenlock-lcg1)
    * [getLockedToChainsIdsOfAccount (LCG1)](#getlockedtochainsidsofaccount-lcg1)
    * [\_getLockedToChainsIdsOfAccount (LCG1)](#_getlockedtochainsidsofaccount-lcg1)
    * [getLockedUntil (LCG1)](#getlockeduntil-lcg1)
    * [\_getLockedUntil (LCG1)](#_getlockeduntil-lcg1)
    * [getLockedToChainsIds (LCG1)](#getlockedtochainsids-lcg1)
    * [lockPeriod (LCG1)](#lockperiod-lcg1)
    * [transferTimeout (LCG1)](#transfertimeout-lcg1)
    * [referralCode (LCG1)](#referralcode-lcg1)
    * [ownerOfTokenId (LCG1)](#owneroftokenid-lcg1)
    * [lockedNftFromChainId (LCG1)](#lockednftfromchainid-lcg1)
    * [lockedNftApprovedTo (LCG1)](#lockednftapprovedto-lcg1)
    * [lockedNft (LCG1)](#lockednft-lcg1)
    * [getDeBridgeChainNativeFeeAndCheck (LCG1)](#getdebridgechainnativefeeandcheck-lcg1)
    * [\_getDeBridgeChainNativeFeeAndCheck (LCG1)](#_getdebridgechainnativefeeandcheck-lcg1)
    * [getDeBridgeChainNativeFee (LCG1)](#getdebridgechainnativefee-lcg1)
    * [\_getDeBridgeChainNativeFee (LCG1)](#_getdebridgechainnativefee-lcg1)
    * [deBridgeGate (LCG1)](#debridgegate-lcg1)
    * [lifetimeNft (LCG1)](#lifetimenft-lcg1)
    * [deBridgeChainConfig (LCG1)](#debridgechainconfig-lcg1)
    * [getLockOperatorsList (LCG1)](#getlockoperatorslist-lcg1)
    * [isLockOperator (LCG1)](#islockoperator-lcg1)
    * [calculateCrossChainCreateRefNativeFee (LCG1)](#calculatecrosschaincreaterefnativefee-lcg1)
    * [isNftLocked (LCG1)](#isnftlocked-lcg1)
    * [\_isNftLocked (LCG1)](#_isnftlocked-lcg1)
    * [isNftLockedAndUpdate (LCG1)](#isnftlockedandupdate-lcg1)
    * [getChainId (LCG1)](#getchainid-lcg1)
    * [\_getChainId (LCG1)](#_getchainid-lcg1)
14. [MultiPermit (MP1)](#multipermit-mp1)
    * [constructor (MP1)](#constructor-mp1)
    * [approveTreasuryTokensToLegacy (MP1)](#approvetreasurytokenstolegacy-mp1)
15. [PluginsRegistry (PR1)](#pluginsregistry-pr1)
    * [constructor (PR1)](#constructor-pr1)
    * [addPlugin (PR1)](#addplugin-pr1)
    * [addPluginDescription (PR1)](#addplugindescription-pr1)
    * [removePlugin (PR1)](#removeplugin-pr1)
    * [isPluginRegistered (PR1)](#ispluginregistered-pr1)
    * [getPluginMetadata (PR1)](#getpluginmetadata-pr1)
    * [getPluginDescriptionBlockNumbers (PR1)](#getplugindescriptionblocknumbers-pr1)
    * [getPluginAddressList (PR1)](#getpluginaddresslist-pr1)
    * [getPluginInfoList (PR1)](#getplugininfolist-pr1)
16. [ProxyBuilder (PB1)](#proxybuilder-pb1)
    * [constructor (PB1)](#constructor-pb1)
    * [setProxyAdmin (PB1)](#setproxyadmin-pb1)
    * [build (PB1)](#build-pb1)
    * [proxyBytecode (PB1)](#proxybytecode-pb1)
    * [computeAddress (PB1)](#computeaddress-pb1)
17. [ProxyBuilderAdmin (PBA1)](#proxybuilderadmin-pba1)
    * [constructor (PBA1)](#constructor-pba1)
18. [SignatureRoleTimelock (SRT1)](#signatureroletimelock-srt1)
    * [constructor (SRT1)](#constructor-srt1)
    * [modifier onlyCurrentAddress (SRT1)](#modifier-onlycurrentaddress-srt1)
    * [setMaxExecutionPeriod (SRT1)](#setmaxexecutionperiod-srt1)
    * [setRoleAccounts (SRT1)](#setroleaccounts-srt1)
    * [\_addRoleAccount (SRT1)](#_addroleaccount-srt1)
    * [\_getAddressIndex (SRT1)](#_getaddressindex-srt1)
    * [\_getBytes4Index (SRT1)](#_getbytes4index-srt1)
    * [\_removeRoleAccount (SRT1)](#_removeroleaccount-srt1)
    * [renounceRole (SRT1)](#renouncerole-srt1)
    * [addSignatureRoleList (SRT1)](#addsignaturerolelist-srt1)
    * [\_addSignatureRole (SRT1)](#_addsignaturerole-srt1)
    * [removeSignatureRoleList (SRT1)](#removesignaturerolelist-srt1)
    * [\_removeSignatureRole (SRT1)](#_removesignaturerole-srt1)
    * [scheduleCallList (SRT1)](#schedulecalllist-srt1)
    * [\_checkRole (SRT1)](#_checkrole-srt1)
    * [\_scheduleCall (SRT1)](#_schedulecall-srt1)
    * [executeCallList (SRT1)](#executecalllist-srt1)
    * [\_executeCall (SRT1)](#_executecall-srt1)
    * [cancelCallList (SRT1)](#cancelcalllist-srt1)
    * [\_cancelCall (SRT1)](#_cancelcall-srt1)
    * [getRoleAccounts (SRT1)](#getroleaccounts-srt1)
    * [getTargets (SRT1)](#gettargets-srt1)
    * [getTargetSigs (SRT1)](#gettargetsigs-srt1)
    * [getCallId (SRT1)](#getcallid-srt1)
    * [getCall (SRT1)](#getcall-srt1)
    * [getCallsList (SRT1)](#getcallslist-srt1)
    * [getCallIds (SRT1)](#getcallids-srt1)
    * [getCallsLength (SRT1)](#getcallslength-srt1)
19. [BeneficiaryAaveV3SupplyPlugin (BALP1)](#beneficiaryaavev3supplyplugin-balp1)
    * [constructor (BALP1)](#constructor-balp1)
    * [getSigs (BALP1)](#getsigs-balp1)
    * [getSetupSigs (BALP1)](#getsetupsigs-balp1)
    * [getMultisigAllowedMethods (BALP1)](#getmultisigallowedmethods-balp1)
    * [getPluginName (BALP1)](#getpluginname-balp1)
    * [getPluginVer (BALP1)](#getpluginver-balp1)
    * [modifier onlyDistributionReady (BALP1)](#modifier-onlydistributionready-balp1)
    * [getPluginMultisigStorage (BALP1)](#getpluginmultisigstorage-balp1)
    * [baavesSetMultisigConfig (BALP1)](#baavessetmultisigconfig-balp1)
    * [baavesPropose (BALP1)](#baavespropose-balp1)
    * [baavesConfirm (BALP1)](#baavesconfirm-balp1)
    * [baavesCancel (BALP1)](#baavescancel-balp1)
    * [baavesGetInitializationStatus (BALP1)](#baavesgetinitializationstatus-balp1)
    * [baavesGetVotersAndConfirmations (BALP1)](#baavesgetvotersandconfirmations-balp1)
    * [baavesGetProposalWithStatus (BALP1)](#baavesgetproposalwithstatus-balp1)
    * [baavesGetProposalListWithStatuses (BALP1)](#baavesgetproposallistwithstatuses-balp1)
    * [baavesSupply (BALP1)](#baavessupply-balp1)
    * [baavesWithdraw (BALP1)](#baaveswithdraw-balp1)
    * [baavesWrapATokenToStataToken (BALP1)](#baaveswrapatokentostatatoken-balp1)
    * [baavesUnwrapStataTokenToAToken (BALP1)](#baavesunwrapstatatokentoatoken-balp1)
    * [baavesDepositToStataToken (BALP1)](#baavesdeposittostatatoken-balp1)
    * [baavesRedeemFromStataToken (BALP1)](#baavesredeemfromstatatoken-balp1)
    * [\_getAToken (BALP1)](#_getatoken-balp1)
    * [\_getStataToken (BALP1)](#_getstatatoken-balp1)
20. [BeneficiaryLidoStakingPlugin (BLSP1)](#beneficiarylidostakingplugin-blsp1)
    * [constructor (BLSP1)](#constructor-blsp1)
    * [getSigs (BLSP1)](#getsigs-blsp1)
    * [getSetupSigs (BLSP1)](#getsetupsigs-blsp1)
    * [getMultisigAllowedMethods (BLSP1)](#getmultisigallowedmethods-blsp1)
    * [getPluginName (BLSP1)](#getpluginname-blsp1)
    * [getPluginVer (BLSP1)](#getpluginver-blsp1)
    * [modifier onlyDistributionReady (BLSP1)](#modifier-onlydistributionready-blsp1)
    * [getPluginMultisigStorage (BLSP1)](#getpluginmultisigstorage-blsp1)
    * [getPendingMigrationStorage (BLSP1)](#getpendingmigrationstorage-blsp1)
    * [getLidoWithdrawalStorage (BLSP1)](#getlidowithdrawalstorage-blsp1)
    * [getBeneficiarySwitchGuardStorage (BLSP1)](#getbeneficiaryswitchguardstorage-blsp1)
    * [blsSetMultisigConfig (BLSP1)](#blssetmultisigconfig-blsp1)
    * [blsPropose (BLSP1)](#blspropose-blsp1)
    * [blsConfirm (BLSP1)](#blsconfirm-blsp1)
    * [blsCancel (BLSP1)](#blscancel-blsp1)
    * [blsGetInitializationStatus (BLSP1)](#blsgetinitializationstatus-blsp1)
    * [blsGetVotersAndConfirmations (BLSP1)](#blsgetvotersandconfirmations-blsp1)
    * [blsGetProposalWithStatus (BLSP1)](#blsgetproposalwithstatus-blsp1)
    * [blsGetProposalListWithStatuses (BLSP1)](#blsgetproposallistwithstatuses-blsp1)
    * [blsLidoGetPendingRequestIds (BLSP1)](#blslidogetpendingrequestids-blsp1)
    * [blsLidoGetPendingMigration (BLSP1)](#blslidogetpendingmigration-blsp1)
    * [blsLidoStakeWethToStEth (BLSP1)](#blslidostakewethtosteth-blsp1)
    * [blsLidoWrapWethToWstEth (BLSP1)](#blslidowrapwethtowsteth-blsp1)
    * [blsLidoRequestStEthWithdrawal (BLSP1)](#blslidorequeststethwithdrawal-blsp1)
    * [blsLidoRequestWstEthWithdrawal (BLSP1)](#blslidorequestwstethwithdrawal-blsp1)
    * [blsLidoClaimWithdrawals (BLSP1)](#blslidoclaimwithdrawals-blsp1)
    * [blsLidoUnsafeClaimWithdrawals (BLSP1)](#blslidounsafeclaimwithdrawals-blsp1)
    * [blsLidoAbandonMigration (BLSP1)](#blslidoabandonmigration-blsp1)
    * [blsLidoWrapStEthToWstEth (BLSP1)](#blslidowrapstethtowsteth-blsp1)
    * [blsLidoUnwrapWstEthToStEth (BLSP1)](#blslidounwrapwstethtosteth-blsp1)
    * [\_storeLidoRequestIds (BLSP1)](#_storelidorequestids-blsp1)
    * [\_activateBeneficiarySwitchGuard (BLSP1)](#_activatebeneficiaryswitchguard-blsp1)
    * [\_releaseBeneficiarySwitchGuard (BLSP1)](#_releasebeneficiaryswitchguard-blsp1)
    * [\_setTokenBeneficiaryClaimsToZero (BLSP1)](#_settokenbeneficiaryclaimstozero-blsp1)
21. [BeneficiaryPluginAddRights (BPAR1)](#beneficiarypluginaddrights-bpar1)
    * [getSigs (BPAR1)](#getsigs-bpar1)
    * [getSetupSigs (BPAR1)](#getsetupsigs-bpar1)
    * [getMultisigAllowedMethods (BPAR1)](#getmultisigallowedmethods-bpar1)
    * [getPluginName (BPAR1)](#getpluginname-bpar1)
    * [getPluginVer (BPAR1)](#getpluginver-bpar1)
    * [modifier onlyOwner (BPAR1)](#modifier-onlyowner-bpar1)
    * [modifier onlyDistributionReady (BPAR1)](#modifier-onlydistributionready-bpar1)
    * [getPluginMultisigStorage (BPAR1)](#getpluginmultisigstorage-bpar1)
    * [barSetMultisigConfig (BPAR1)](#barsetmultisigconfig-bpar1)
    * [barPropose (BPAR1)](#barpropose-bpar1)
    * [barConfirm (BPAR1)](#barconfirm-bpar1)
    * [barCancel (BPAR1)](#barcancel-bpar1)
    * [barAddPluginList (BPAR1)](#baraddpluginlist-bpar1)
    * [barWithdrawHeldEth (BPAR1)](#barwithdrawheldeth-bpar1)
    * [barGetHeldEth (BPAR1)](#bargetheldeth-bpar1)
    * [barGetInitializationStatus (BPAR1)](#bargetinitializationstatus-bpar1)
    * [barGetVotersAndConfirmations (BPAR1)](#bargetvotersandconfirmations-bpar1)
    * [barGetProposalWithStatus (BPAR1)](#bargetproposalwithstatus-bpar1)
    * [barGetProposalListWithStatuses (BPAR1)](#bargetproposallistwithstatuses-bpar1)
22. [BeneficiaryUniswapV4SwapPlugin (BU4SP1)](#beneficiaryuniswapv4swapplugin-bu4sp1)
    * [constructor (BU4SP1)](#constructor-bu4sp1)
    * [getSigs (BU4SP1)](#getsigs-bu4sp1)
    * [getSetupSigs (BU4SP1)](#getsetupsigs-bu4sp1)
    * [getMultisigAllowedMethods (BU4SP1)](#getmultisigallowedmethods-bu4sp1)
    * [getPluginName (BU4SP1)](#getpluginname-bu4sp1)
    * [getPluginVer (BU4SP1)](#getpluginver-bu4sp1)
    * [modifier onlyDistributionReady (BU4SP1)](#modifier-onlydistributionready-bu4sp1)
    * [getPluginMultisigStorage (BU4SP1)](#getpluginmultisigstorage-bu4sp1)
    * [bunisSetMultisigConfig (BU4SP1)](#bunissetmultisigconfig-bu4sp1)
    * [bunisPropose (BU4SP1)](#bunispropose-bu4sp1)
    * [bunisConfirm (BU4SP1)](#bunisconfirm-bu4sp1)
    * [bunisCancel (BU4SP1)](#buniscancel-bu4sp1)
    * [bunisGetInitializationStatus (BU4SP1)](#bunisgetinitializationstatus-bu4sp1)
    * [bunisGetVotersAndConfirmations (BU4SP1)](#bunisgetvotersandconfirmations-bu4sp1)
    * [bunisGetProposalWithStatus (BU4SP1)](#bunisgetproposalwithstatus-bu4sp1)
    * [bunisGetProposalListWithStatuses (BU4SP1)](#bunisgetproposallistwithstatuses-bu4sp1)
    * [bunisSwapExactInputSingle (BU4SP1)](#bunisswapexactinputsingle-bu4sp1)
    * [bunisSwapExactInput (BU4SP1)](#bunisswapexactinput-bu4sp1)
    * [\_executeExactInputSingleRouter (BU4SP1)](#_executeexactinputsinglerouter-bu4sp1)
    * [\_executeExactInputRouter (BU4SP1)](#_executeexactinputrouter-bu4sp1)
23. [CryptoLegacyBasePlugin (CLBP1)](#cryptolegacybaseplugin-clbp1)
    * [getSigs (CLBP1)](#getsigs-clbp1)
    * [getSetupSigs (CLBP1)](#getsetupsigs-clbp1)
    * [getPluginName (CLBP1)](#getpluginname-clbp1)
    * [getPluginVer (CLBP1)](#getpluginver-clbp1)
    * [getCryptoLegacyVer (CLBP1)](#getcryptolegacyver-clbp1)
    * [constructor (CLBP1)](#constructor-clbp1)
    * [initializeByBuildManager (CLBP1)](#initializebybuildmanager-clbp1)
    * [owner (CLBP1)](#owner-clbp1)
    * [isPaused (CLBP1)](#ispaused-clbp1)
    * [buildManager (CLBP1)](#buildmanager-clbp1)
    * [transferOwnership (CLBP1)](#transferownership-clbp1)
    * [payInitialFee (CLBP1)](#payinitialfee-clbp1)
    * [setBeneficiaries (CLBP1)](#setbeneficiaries-clbp1)
    * [\_setBeneficiaries (CLBP1)](#_setbeneficiaries-clbp1)
    * [update (CLBP1)](#update-clbp1)
    * [setGasLimitMultiplier (CLBP1)](#setgaslimitmultiplier-clbp1)
    * [initiateChallenge (CLBP1)](#initiatechallenge-clbp1)
    * [transferTreasuryTokensToLegacy (CLBP1)](#transfertreasurytokenstolegacy-clbp1)
    * [\_claimTokenWithVesting (CLBP1)](#_claimtokenwithvesting-clbp1)
    * [beneficiaryClaim (CLBP1)](#beneficiaryclaim-clbp1)
    * [beneficiarySwitch (CLBP1)](#beneficiaryswitch-clbp1)
    * [sendMessagesToBeneficiary (CLBP1)](#sendmessagestobeneficiary-clbp1)
    * [isLifetimeActive (CLBP1)](#islifetimeactive-clbp1)
    * [getGasBySelector (CLBP1)](#getgasbyselector-clbp1)
24. [LegacyRecoveryPlugin (LRP1)](#legacyrecoveryplugin-lrp1)
    * [getSigs (LRP1)](#getsigs-lrp1)
    * [getSetupSigs (LRP1)](#getsetupsigs-lrp1)
    * [getMultisigAllowedMethods (LRP1)](#getmultisigallowedmethods-lrp1)
    * [getPluginName (LRP1)](#getpluginname-lrp1)
    * [getPluginVer (LRP1)](#getpluginver-lrp1)
    * [modifier onlyOwner (LRP1)](#modifier-onlyowner-lrp1)
    * [getPluginMultisigStorage (LRP1)](#getpluginmultisigstorage-lrp1)
    * [lrSetMultisigConfig (LRP1)](#lrsetmultisigconfig-lrp1)
    * [lrPropose (LRP1)](#lrpropose-lrp1)
    * [lrConfirm (LRP1)](#lrconfirm-lrp1)
    * [lrCancel (LRP1)](#lrcancel-lrp1)
    * [lrTransferTreasuryTokensToLegacy (LRP1)](#lrtransfertreasurytokenstolegacy-lrp1)
    * [lrWithdrawTokensFromLegacy (LRP1)](#lrwithdrawtokensfromlegacy-lrp1)
    * [lrResetGuardianVoting (LRP1)](#lrresetguardianvoting-lrp1)
    * [lrWithdrawHeldEth (LRP1)](#lrwithdrawheldeth-lrp1)
    * [lrGetHeldEth (LRP1)](#lrgetheldeth-lrp1)
    * [lrGetInitializationStatus (LRP1)](#lrgetinitializationstatus-lrp1)
    * [lrGetProposalWithStatus (LRP1)](#lrgetproposalwithstatus-lrp1)
    * [lrGetProposalListWithStatuses (LRP1)](#lrgetproposallistwithstatuses-lrp1)
25. [LensPlugin (LP1)](#lensplugin-lp1)
    * [getSigs (LP1)](#getsigs-lp1)
    * [getSetupSigs (LP1)](#getsetupsigs-lp1)
    * [getPluginName (LP1)](#getpluginname-lp1)
    * [getPluginVer (LP1)](#getpluginver-lp1)
    * [updateInterval (LP1)](#updateinterval-lp1)
    * [challengeTimeout (LP1)](#challengetimeout-lp1)
    * [distributionStartAt (LP1)](#distributionstartat-lp1)
    * [lastFeePaidAt (LP1)](#lastfeepaidat-lp1)
    * [lastUpdateAt (LP1)](#lastupdateat-lp1)
    * [initialFeeToPay (LP1)](#initialfeetopay-lp1)
    * [updateFee (LP1)](#updatefee-lp1)
    * [invitedByRefCode (LP1)](#invitedbyrefcode-lp1)
    * [getBeneficiaryClaimed (LP1)](#getbeneficiaryclaimed-lp1)
    * [getOriginalBeneficiaryHash (LP1)](#getoriginalbeneficiaryhash-lp1)
    * [getBeneficiaryConfig (LP1)](#getbeneficiaryconfig-lp1)
    * [getBeneficiaries (LP1)](#getbeneficiaries-lp1)
    * [\_getBeneficiaries (LP1)](#_getbeneficiaries-lp1)
    * [getTransferBlockNumbers (LP1)](#gettransferblocknumbers-lp1)
    * [getTokensDistribution (LP1)](#gettokensdistribution-lp1)
    * [\_getTokensDistribution (LP1)](#_gettokensdistribution-lp1)
    * [getCryptoLegacyBaseData (LP1)](#getcryptolegacybasedata-lp1)
    * [getCryptoLegacyListData (LP1)](#getcryptolegacylistdata-lp1)
    * [getMessagesBlockNumbersByRecipient (LP1)](#getmessagesblocknumbersbyrecipient-lp1)
    * [getVestedAndClaimedData (LP1)](#getvestedandclaimeddata-lp1)
    * [\_getPluginInfoList (LP1)](#_getplugininfolist-lp1)
    * [\_getPluginMetadata (LP1)](#_getpluginmetadata-lp1)
    * [getPluginInfoList (LP1)](#getplugininfolist-lp1)
    * [getPluginMetadata (LP1)](#getpluginmetadata-lp1)
26. [NftLegacyPlugin (NLP1)](#nftlegacyplugin-nlp1)
    * [getSigs (NLP1)](#getsigs-nlp1)
    * [getSetupSigs (NLP1)](#getsetupsigs-nlp1)
    * [getPluginName (NLP1)](#getpluginname-nlp1)
    * [getPluginVer (NLP1)](#getpluginver-nlp1)
    * [getPluginStorage (NLP1)](#getpluginstorage-nlp1)
    * [modifier onlyOwner (NLP1)](#modifier-onlyowner-nlp1)
    * [setNftBeneficiary (NLP1)](#setnftbeneficiary-nlp1)
    * [transferNftTokensToLegacy (NLP1)](#transfernfttokenstolegacy-nlp1)
    * [beneficiaryClaimNft (NLP1)](#beneficiaryclaimnft-nlp1)
27. [ReceiveEthPlugin (REP1)](#receiveethplugin-rep1)
    * [constructor (REP1)](#constructor-rep1)
    * [getSigs (REP1)](#getsigs-rep1)
    * [getSetupSigs (REP1)](#getsetupsigs-rep1)
    * [getPluginName (REP1)](#getpluginname-rep1)
    * [getPluginVer (REP1)](#getpluginver-rep1)
    * [wrapEthToWeth (REP1)](#wrapethtoweth-rep1)
    * [receive (REP1)](#receive-rep1)
28. [TrustedGuardiansPlugin (TGP1)](#trustedguardiansplugin-tgp1)
    * [getSigs (TGP1)](#getsigs-tgp1)
    * [getSetupSigs (TGP1)](#getsetupsigs-tgp1)
    * [getPluginName (TGP1)](#getpluginname-tgp1)
    * [getPluginVer (TGP1)](#getpluginver-tgp1)
    * [modifier onlyOwner (TGP1)](#modifier-onlyowner-tgp1)
    * [\_isGuardianVoted (TGP1)](#_isguardianvoted-tgp1)
    * [\_checkGuardianAndRemoveInvalid (TGP1)](#_checkguardianandremoveinvalid-tgp1)
    * [\_checkGuardian (TGP1)](#_checkguardian-tgp1)
    * [\_checkGuardianNotVoted (TGP1)](#_checkguardiannotvoted-tgp1)
    * [\_getGuardians (TGP1)](#_getguardians-tgp1)
    * [\_getGuardiansThreshold (TGP1)](#_getguardiansthreshold-tgp1)
    * [\_getGuardiansChallengeTimeout (TGP1)](#_getguardianschallengetimeout-tgp1)
    * [initializeGuardians (TGP1)](#initializeguardians-tgp1)
    * [setGuardians (TGP1)](#setguardians-tgp1)
    * [\_setGuardians (TGP1)](#_setguardians-tgp1)
    * [setGuardiansConfig (TGP1)](#setguardiansconfig-tgp1)
    * [\_setGuardiansConfig (TGP1)](#_setguardiansconfig-tgp1)
    * [\_afterGuardiansSet (TGP1)](#_afterguardiansset-tgp1)
    * [guardiansVoteForDistribution (TGP1)](#guardiansvotefordistribution-tgp1)
    * [guardiansTransferTreasuryTokensToLegacy (TGP1)](#guardianstransfertreasurytokenstolegacy-tgp1)
    * [resetGuardianVoting (TGP1)](#resetguardianvoting-tgp1)
    * [\_isGuardiansInitialized (TGP1)](#_isguardiansinitialized-tgp1)
    * [isGuardiansInitialized (TGP1)](#isguardiansinitialized-tgp1)
    * [getGuardiansData (TGP1)](#getguardiansdata-tgp1)
    * [checkGuardiansVotedAndGetGuardiansData (TGP1)](#checkguardiansvotedandgetguardiansdata-tgp1)
29. [UpdateRolePlugin (URP1)](#updateroleplugin-urp1)
    * [getSigs (URP1)](#getsigs-urp1)
    * [getSetupSigs (URP1)](#getsetupsigs-urp1)
    * [getPluginName (URP1)](#getpluginname-urp1)
    * [getPluginVer (URP1)](#getpluginver-urp1)
    * [getPluginStorage (URP1)](#getpluginstorage-urp1)
    * [owner (URP1)](#owner-urp1)
    * [modifier onlyOwner (URP1)](#modifier-onlyowner-urp1)
    * [modifier onlyUpdater (URP1)](#modifier-onlyupdater-urp1)
    * [getUpdaterList (URP1)](#getupdaterlist-urp1)
    * [isUpdater (URP1)](#isupdater-urp1)
    * [setUpdater (URP1)](#setupdater-urp1)
    * [updateByUpdater (URP1)](#updatebyupdater-urp1)
30. [DiamondLoupeFacet (DLF1)](#diamondloupefacet-dlf1)
    * [facets (DLF1)](#facets-dlf1)
    * [facetFunctionSelectors (DLF1)](#facetfunctionselectors-dlf1)
    * [facetAddresses (DLF1)](#facetaddresses-dlf1)
    * [facetAddress (DLF1)](#facetaddress-dlf1)
    * [storageFacetAddress (DLF1)](#storagefacetaddress-dlf1)
    * [supportsInterface (DLF1)](#supportsinterface-dlf1)
31. [WethUnwrap (WU1)](#wethunwrap-wu1)
    * [constructor (WU1)](#constructor-wu1)
    * [unwrap\_weth (WU1)](#unwrap_weth-wu1)
    * [receive (WU1)](#receive-wu1)
32. [LibCreate3 (LC31)](#libcreate3-lc31)
    * [codeSize (LC31)](#codesize-lc31)
    * [create3(bytes32,bytes) (LC31)](#create3bytes32bytes-lc31)
    * [create3(bytes32,bytes,uint256) (LC31)](#create3bytes32bytesuint256-lc31)
    * [addressOf (LC31)](#addressof-lc31)
33. [LibCLUtils (LCLU1)](#libclutils-lclu1)
    * [approveToken (LCLU1)](#approvetoken-lclu1)
34. [LibClaimMigrationCore (LCMC1)](#libclaimmigrationcore-lcmc1)
    * [calculateFractionAndRatio (LCMC1)](#calculatefractionandratio-lcmc1)
    * [applyMigrationFormula (LCMC1)](#applymigrationformula-lcmc1)
    * [syncDistributions (LCMC1)](#syncdistributions-lcmc1)
35. [LibOneStepClaimMigration (LOSCM1)](#libonestepclaimmigration-loscm1)
    * [migrate (LOSCM1)](#migrate-loscm1)
    * [\_migrateClaims (LOSCM1)](#_migrateclaims-loscm1)
36. [LibTwoStepClaimMigration (LTSCM1)](#libtwostepclaimmigration-ltscm1)
    * [isActive (LTSCM1)](#isactive-ltscm1)
    * [getPendingTokens (LTSCM1)](#getpendingtokens-ltscm1)
    * [start (LTSCM1)](#start-ltscm1)
    * [complete (LTSCM1)](#complete-ltscm1)
    * [abandon (LTSCM1)](#abandon-ltscm1)
    * [\_applyPendingMigration (LTSCM1)](#_applypendingmigration-ltscm1)
37. [LibCryptoLegacy (LCL1)](#libcryptolegacy-lcl1)
    * [getCryptoLegacyStorage (LCL1)](#getcryptolegacystorage-lcl1)
    * [\_checkDisabledFunc (LCL1)](#_checkdisabledfunc-lcl1)
    * [\_checkDistributionStart (LCL1)](#_checkdistributionstart-lcl1)
    * [\_isDistributionStarted (LCL1)](#_isdistributionstarted-lcl1)
    * [\_checkOwner (LCL1)](#_checkowner-lcl1)
    * [\_checkSenderOwner (LCL1)](#_checksenderowner-lcl1)
    * [\_checkPause (LCL1)](#_checkpause-lcl1)
    * [\_setPause (LCL1)](#_setpause-lcl1)
    * [\_getPause (LCL1)](#_getpause-lcl1)
    * [\_checkAddressIsBeneficiary (LCL1)](#_checkaddressisbeneficiary-lcl1)
    * [\_checkDistributionReadyForBeneficiary (LCL1)](#_checkdistributionreadyforbeneficiary-lcl1)
    * [\_checkDistributionReady (LCL1)](#_checkdistributionready-lcl1)
    * [\_getBeneficiariesCount (LCL1)](#_getbeneficiariescount-lcl1)
    * [\_isLifetimeActiveAndUpdate (LCL1)](#_islifetimeactiveandupdate-lcl1)
    * [\_takeFee (LCL1)](#_takefee-lcl1)
    * [\_checkFee (LCL1)](#_checkfee-lcl1)
    * [\_checkNoFee (LCL1)](#_checknofee-lcl1)
    * [\_sendFeeByTransfer (LCL1)](#_sendfeebytransfer-lcl1)
    * [\_transferFee (LCL1)](#_transferfee-lcl1)
    * [\_tokenPrepareToDistribute (LCL1)](#_tokenpreparetodistribute-lcl1)
    * [\_getBeneficiaryClaimed (LCL1)](#_getbeneficiaryclaimed-lcl1)
    * [\_setBeneficiaryClaimed (LCL1)](#_setbeneficiaryclaimed-lcl1)
    * [\_getTotalClaimed (LCL1)](#_gettotalclaimed-lcl1)
    * [\_getStartAndEndDate (LCL1)](#_getstartandenddate-lcl1)
    * [\_getVestedAndClaimedAmount (LCL1)](#_getvestedandclaimedamount-lcl1)
    * [\_getBeneficiaryConfigAndVesting (LCL1)](#_getbeneficiaryconfigandvesting-lcl1)
    * [\_setCryptoLegacyToBeneficiaryRegistry (LCL1)](#_setcryptolegacytobeneficiaryregistry-lcl1)
    * [\_setCryptoLegacyListToBeneficiaryRegistry (LCL1)](#_setcryptolegacylisttobeneficiaryregistry-lcl1)
    * [\_getBeneficiaryRegistry (LCL1)](#_getbeneficiaryregistry-lcl1)
    * [\_gasBySelector (LCL1)](#_gasbyselector-lcl1)
    * [\_gasWithoutMultiplierBySelector (LCL1)](#_gaswithoutmultiplierbyselector-lcl1)
    * [\_updateOwnerInBeneficiaryRegistry (LCL1)](#_updateownerinbeneficiaryregistry-lcl1)
    * [\_transferTreasuryTokensToLegacy (LCL1)](#_transfertreasurytokenstolegacy-lcl1)
    * [\_transferTokensFromLegacy (LCL1)](#_transfertokensfromlegacy-lcl1)
    * [\_addressToHash (LCL1)](#_addresstohash-lcl1)
    * [\_addressWithSaltToHash (LCL1)](#_addresswithsalttohash-lcl1)
38. [LibCryptoLegacyDeploy (LCLD1)](#libcryptolegacydeploy-lcld1)
    * [\_deployByCreate3 (LCLD1)](#_deploybycreate3-lcld1)
    * [\_getContractOwnerSalt (LCLD1)](#_getcontractownersalt-lcld1)
    * [\_computeAddress (LCLD1)](#_computeaddress-lcld1)
39. [LibCryptoLegacyPlugins (LCLP1)](#libcryptolegacyplugins-lclp1)
    * [\_validatePlugin (LCLP1)](#_validateplugin-lclp1)
    * [\_addPluginList (LCLP1)](#_addpluginlist-lclp1)
    * [\_removePlugin (LCLP1)](#_removeplugin-lclp1)
    * [\_getFacetAddressPosition (LCLP1)](#_getfacetaddressposition-lclp1)
    * [\_addFacetAddressIfNotExists (LCLP1)](#_addfacetaddressifnotexists-lclp1)
    * [\_removeFacetAddress (LCLP1)](#_removefacetaddress-lclp1)
    * [addFunctions (LCLP1)](#addfunctions-lclp1)
    * [removeFunctions (LCLP1)](#removefunctions-lclp1)
    * [\_findFacetBySelector (LCLP1)](#_findfacetbyselector-lclp1)
40. [LibDiamond (LD1)](#libdiamond-ld1)
    * [diamondStorage (LD1)](#diamondstorage-ld1)
    * [setContractOwner (LD1)](#setcontractowner-ld1)
    * [contractOwner (LD1)](#contractowner-ld1)
    * [enforceIsContractOwner (LD1)](#enforceiscontractowner-ld1)
    * [diamondCut (LD1)](#diamondcut-ld1)
    * [addFunctions (LD1)](#addfunctions-ld1)
    * [replaceFunctions (LD1)](#replacefunctions-ld1)
    * [removeFunctions (LD1)](#removefunctions-ld1)
    * [addFacet (LD1)](#addfacet-ld1)
    * [addFunction (LD1)](#addfunction-ld1)
    * [removeFunction (LD1)](#removefunction-ld1)
    * [initializeDiamondCut (LD1)](#initializediamondcut-ld1)
    * [enforceHasContractCode (LD1)](#enforcehascontractcode-ld1)
41. [LibSafeMinimalBeneficiaryMultisig (LSMB1)](#libsafeminimalbeneficiarymultisig-lsmb1)
    * [\_checkIsMultisigExecutor (LSMB1)](#_checkismultisigexecutor-lsmb1)
    * [\_initializationStatus (LSMB1)](#_initializationstatus-lsmb1)
    * [\_getVotersAndConfirmations (LSMB1)](#_getvotersandconfirmations-lsmb1)
    * [\_getProposalListWithStatuses (LSMB1)](#_getproposallistwithstatuses-lsmb1)
    * [\_getProposalWithStatus (LSMB1)](#_getproposalwithstatus-lsmb1)
    * [\_getRequiredConfirmations (LSMB1)](#_getrequiredconfirmations-lsmb1)
    * [\_getVoters (LSMB1)](#_getvoters-lsmb1)
    * [\_getDefaultRequiredConfirmations (LSMB1)](#_getdefaultrequiredconfirmations-lsmb1)
    * [\_setConfirmations (LSMB1)](#_setconfirmations-lsmb1)
    * [\_initializeIfNot (LSMB1)](#_initializeifnot-lsmb1)
    * [\_propose (LSMB1)](#_propose-lsmb1)
    * [\_confirm (LSMB1)](#_confirm-lsmb1)
    * [\_cancel (LSMB1)](#_cancel-lsmb1)
    * [\_withdrawHeldEth (LSMB1)](#_withdrawheldeth-lsmb1)
42. [LibSafeMinimalMultisig (LSM1)](#libsafeminimalmultisig-lsm1)
    * [\_checkIsMultisigExecutor (LSM1)](#_checkismultisigexecutor-lsm1)
    * [\_checkIsSenderAllowed (LSM1)](#_checkissenderallowed-lsm1)
    * [\_setVotersAndConfirmations (LSM1)](#_setvotersandconfirmations-lsm1)
    * [\_initializationStatus (LSM1)](#_initializationstatus-lsm1)
    * [\_calcDefaultConfirmations (LSM1)](#_calcdefaultconfirmations-lsm1)
    * [\_isMethodAllowed (LSM1)](#_ismethodallowed-lsm1)
    * [\_isVoterAllowed (LSM1)](#_isvoterallowed-lsm1)
    * [\_getConfirmedCount (LSM1)](#_getconfirmedcount-lsm1)
    * [\_getProposalListWithStatusesAndStorageVoters (LSM1)](#_getproposallistwithstatusesandstoragevoters-lsm1)
    * [\_getProposalWithStatus (LSM1)](#_getproposalwithstatus-lsm1)
    * [\_propose (LSM1)](#_propose-lsm1)
    * [\_getPendingProposalForVoter (LSM1)](#_getpendingproposalforvoter-lsm1)
    * [\_cancel (LSM1)](#_cancel-lsm1)
    * [\_confirm (LSM1)](#_confirm-lsm1)
    * [\_execute (LSM1)](#_execute-lsm1)
    * [\_updateHeldEth (LSM1)](#_updateheldeth-lsm1)
    * [\_withdrawHeldEth (LSM1)](#_withdrawheldeth-lsm1)
43. [LibTrustedGuardiansPlugin (LTGP1)](#libtrustedguardiansplugin-ltgp1)
    * [getPluginStorage (LTGP1)](#getpluginstorage-ltgp1)
    * [\_resetGuardianVoting (LTGP1)](#_resetguardianvoting-ltgp1)
44. [ArbSys (AS1)](#arbsys-as1)
    * [arbBlockNumber (AS1)](#arbblocknumber-as1)
45. [Flags (FLG1)](#flags-flg1)
    * [getFlag (FLG1)](#getflag-flg1)
    * [setFlag (FLG1)](#setflag-flg1)
46. [IAaveV3Pool (IAV3P1)](#iaavev3pool-iav3p1)
    * [supply (IAV3P1)](#supply-iav3p1)
    * [withdraw (IAV3P1)](#withdraw-iav3p1)
47. [IAaveV3PoolDataProvider (IAV3PDP1)](#iaavev3pooldataprovider-iav3pdp1)
    * [getReserveTokensAddresses (IAV3PDP1)](#getreservetokensaddresses-iav3pdp1)
48. [IBeneficiaryRegistry (IBR1)](#ibeneficiaryregistry-ibr1)
    * [setCryptoLegacyBeneficiary (IBR1)](#setcryptolegacybeneficiary-ibr1)
    * [setCryptoLegacyOwner (IBR1)](#setcryptolegacyowner-ibr1)
    * [setCryptoLegacyGuardian (IBR1)](#setcryptolegacyguardian-ibr1)
    * [setCryptoLegacyRecoveryAddresses (IBR1)](#setcryptolegacyrecoveryaddresses-ibr1)
    * [getAllCryptoLegacyListByRoles (IBR1)](#getallcryptolegacylistbyroles-ibr1)
49. [IBuildManagerOwnable (IBMO1)](#ibuildmanagerownable-ibmo1)
50. [ICallProxy (ICP1)](#icallproxy-icp1)
    * [submissionChainIdFrom (ICP1)](#submissionchainidfrom-icp1)
    * [submissionNativeSender (ICP1)](#submissionnativesender-icp1)
    * [call (ICP1)](#call-icp1)
    * [callERC20 (ICP1)](#callerc20-icp1)
51. [ICryptoLegacy (ICL1)](#icryptolegacy-icl1)
    * [buildManager (ICL1)](#buildmanager-icl1)
    * [owner (ICL1)](#owner-icl1)
52. [ICryptoLegacyBuildManager (ICLBM1)](#icryptolegacybuildmanager-iclbm1)
    * [payInitialFee (ICLBM1)](#payinitialfee-iclbm1)
    * [payFee (ICLBM1)](#payfee-iclbm1)
    * [getUpdateFee (ICLBM1)](#getupdatefee-iclbm1)
    * [isLifetimeNftLocked (ICLBM1)](#islifetimenftlocked-iclbm1)
    * [isLifetimeNftLockedAndUpdate (ICLBM1)](#islifetimenftlockedandupdate-iclbm1)
    * [isPluginRegistered (ICLBM1)](#ispluginregistered-iclbm1)
    * [isCryptoLegacyBuilt (ICLBM1)](#iscryptolegacybuilt-iclbm1)
    * [pluginsRegistry (ICLBM1)](#pluginsregistry-iclbm1)
    * [getFactoryAddress (ICLBM1)](#getfactoryaddress-iclbm1)
    * [beneficiaryRegistry (ICLBM1)](#beneficiaryregistry-iclbm1)
    * [externalLens (ICLBM1)](#externallens-iclbm1)
53. [ICryptoLegacyDiamondBase (ICLDB1)](#icryptolegacydiamondbase-icldb1)
54. [ICryptoLegacyFactory (ICLF1)](#icryptolegacyfactory-iclf1)
    * [createCryptoLegacy (ICLF1)](#createcryptolegacy-iclf1)
    * [setBuildOperator (ICLF1)](#setbuildoperator-iclf1)
55. [ICryptoLegacyLens (ICLL1)](#icryptolegacylens-icll1)
    * [getMessagesBlockNumbersByRecipient (ICLL1)](#getmessagesblocknumbersbyrecipient-icll1)
    * [getVestedAndClaimedData (ICLL1)](#getvestedandclaimeddata-icll1)
    * [getCryptoLegacyBaseData (ICLL1)](#getcryptolegacybasedata-icll1)
    * [getCryptoLegacyListData (ICLL1)](#getcryptolegacylistdata-icll1)
56. [ICryptoLegacyOwnable (ICLO1)](#icryptolegacyownable-iclo1)
57. [ICryptoLegacyPlugin (ICLP1)](#icryptolegacyplugin-iclp1)
    * [getSigs (ICLP1)](#getsigs-iclp1)
    * [getSetupSigs (ICLP1)](#getsetupsigs-iclp1)
    * [getPluginName (ICLP1)](#getpluginname-iclp1)
    * [getPluginVer (ICLP1)](#getpluginver-iclp1)
58. [IDeBridgeGate (IDBG1)](#idebridgegate-idbg1)
    * [isSubmissionUsed (IDBG1)](#issubmissionused-idbg1)
    * [getNativeInfo (IDBG1)](#getnativeinfo-idbg1)
    * [callProxy (IDBG1)](#callproxy-idbg1)
    * [globalFixedNativeFee (IDBG1)](#globalfixednativefee-idbg1)
    * [globalTransferFeeBps (IDBG1)](#globaltransferfeebps-idbg1)
    * [sendMessage(uint256,bytes,bytes) (IDBG1)](#sendmessageuint256bytesbytes-idbg1)
    * [sendMessage(uint256,bytes,bytes,uint256,uint32) (IDBG1)](#sendmessageuint256bytesbytesuint256uint32-idbg1)
    * [send (IDBG1)](#send-idbg1)
    * [claim (IDBG1)](#claim-idbg1)
    * [withdrawFee (IDBG1)](#withdrawfee-idbg1)
    * [getDebridgeChainAssetFixedFee (IDBG1)](#getdebridgechainassetfixedfee-idbg1)
59. [IDiamondCut (IDC1)](#idiamondcut-idc1)
    * [diamondCut (IDC1)](#diamondcut-idc1)
60. [IDiamondLoupe (IDL1)](#idiamondloupe-idl1)
    * [facets (IDL1)](#facets-idl1)
    * [facetFunctionSelectors (IDL1)](#facetfunctionselectors-idl1)
    * [facetAddresses (IDL1)](#facetaddresses-idl1)
    * [facetAddress (IDL1)](#facetaddress-idl1)
61. [IFeeRegistry (IFR1)](#ifeeregistry-ifr1)
    * [getContractCaseFee (IFR1)](#getcontractcasefee-ifr1)
    * [getContractCaseFeeForCode (IFR1)](#getcontractcasefeeforcode-ifr1)
    * [takeFee (IFR1)](#takefee-ifr1)
    * [createCustomCode (IFR1)](#createcustomcode-ifr1)
    * [createCode (IFR1)](#createcode-ifr1)
    * [updateCrossChainsRef (IFR1)](#updatecrosschainsref-ifr1)
    * [accumulatedFee (IFR1)](#accumulatedfee-ifr1)
    * [getSupportedRefInChainsList (IFR1)](#getsupportedrefinchainslist-ifr1)
62. [ICryptoLegacyUpdaterPlugin (ICLUP1)](#icryptolegacyupdaterplugin-iclup1)
63. [ILockChainGate (ILCG1)](#ilockchaingate-ilcg1)
    * [lockLifetimeNft (ILCG1)](#locklifetimenft-ilcg1)
    * [isNftLocked (ILCG1)](#isnftlocked-ilcg1)
    * [isNftLockedAndUpdate (ILCG1)](#isnftlockedandupdate-ilcg1)
    * [calculateCrossChainCreateRefNativeFee (ILCG1)](#calculatecrosschaincreaterefnativefee-ilcg1)
64. [ILegacyMessenger (ILM1)](#ilegacymessenger-ilm1)
65. [ILido (ILD1)](#ilido-ild1)
    * [submit (ILD1)](#submit-ild1)
    * [transferShares (ILD1)](#transfershares-ild1)
    * [transferSharesFrom (ILD1)](#transfersharesfrom-ild1)
    * [sharesOf (ILD1)](#sharesof-ild1)
66. [ILidoWithdrawalQueue (ILWQ1)](#ilidowithdrawalqueue-ilwq1)
    * [requestWithdrawals (ILWQ1)](#requestwithdrawals-ilwq1)
    * [requestWithdrawalsWstETH (ILWQ1)](#requestwithdrawalswsteth-ilwq1)
    * [claimWithdrawals (ILWQ1)](#claimwithdrawals-ilwq1)
67. [ILifetimeNft (ILN1)](#ilifetimenft-iln1)
    * [mint (ILN1)](#mint-iln1)
    * [setMinterOperator (ILN1)](#setminteroperator-iln1)
    * [setBaseUri (ILN1)](#setbaseuri-iln1)
68. [IPermit2 (IPM21)](#ipermit2-ipm21)
    * [approve (IPM21)](#approve-ipm21)
69. [IPluginsRegistry (IPR1)](#ipluginsregistry-ipr1)
    * [getPluginDescriptionBlockNumbers (IPR1)](#getplugindescriptionblocknumbers-ipr1)
    * [isPluginRegistered (IPR1)](#ispluginregistered-ipr1)
    * [addPlugin (IPR1)](#addplugin-ipr1)
    * [addPluginDescription (IPR1)](#addplugindescription-ipr1)
    * [removePlugin (IPR1)](#removeplugin-ipr1)
70. [ISafeMinimalMultisig (ISM1)](#isafeminimalmultisig-ism1)
71. [ISignatureRoleTimelock (ISRT1)](#isignatureroletimelock-isrt1)
72. [IStataToken (ISTA1)](#istatatoken-ista1)
    * [deposit (ISTA1)](#deposit-ista1)
    * [redeem (ISTA1)](#redeem-ista1)
    * [depositATokens (ISTA1)](#depositatokens-ista1)
    * [redeemATokens (ISTA1)](#redeematokens-ista1)
    * [asset (ISTA1)](#asset-ista1)
    * [balanceOf (ISTA1)](#balanceof-ista1)
73. [IStataTokenFactory (ISTF1)](#istatatokenfactory-istf1)
    * [getStataToken (ISTF1)](#getstatatoken-istf1)
    * [createStataTokens (ISTF1)](#createstatatokens-istf1)
74. [ITrustedGuardiansPlugin (ITGP1)](#itrustedguardiansplugin-itgp1)
    * [isGuardiansInitialized (ITGP1)](#isguardiansinitialized-itgp1)
75. [IUniversalRouter (IUR1)](#iuniversalrouter-iur1)
    * [execute (IUR1)](#execute-iur1)
76. [IWETH (IWETH1)](#iweth-iweth1)
    * [deposit (IWETH1)](#deposit-iweth1)
    * [withdraw (IWETH1)](#withdraw-iweth1)
    * [approve (IWETH1)](#approve-iweth1)
    * [balanceOf (IWETH1)](#balanceof-iweth1)
77. [IWstETH (IWSTETH1)](#iwsteth-iwsteth1)
    * [wrap (IWSTETH1)](#wrap-iwsteth1)
    * [unwrap (IWSTETH1)](#unwrap-iwsteth1)
78. [WethUnwrapIWETH (WUI1)](#wethunwrapiweth-wui1)
    * [transferFrom (WUI1)](#transferfrom-wui1)
    * [withdraw (WUI1)](#withdraw-wui1)

## BeneficiaryRegistry (BR1)

### constructor (BR1)

**Contract/Library:** BeneficiaryRegistry

**Description:** Initializes the registry and transfers ownership to `_owner`.

**Detailed Description:** Executed once at deployment. The `BuildManagerOwnable` constructor (via `Ownable()`) sets `owner` to `msg.sender` and emits `OwnershipTransferred(address(0), msg.sender)`. Then `Ownable._transferOwnership(_owner)` updates the owner and emits `OwnershipTransferred(msg.sender, _owner)`.

**Parameters:**

* \_owner (address): Initial owner of the registry

**Returns:** None

**Modifiers / Visibility / Mutability:**

* constructor nonpayable

**Access Control:**

* Unrestricted (deployment only)

**Side Effects:**

* Sets `owner` (first to `msg.sender`, then to `_owner`)

**Emits:**

* [OwnershipTransferred](https://docs.cryptolegacy.app/documentation/events-reference#ownershiptransferred-iclo1) — `OwnershipTransferred(address indexed previousOwner, address indexed newOwner)` (via `Ownable()` constructor)
* [OwnershipTransferred](https://docs.cryptolegacy.app/documentation/events-reference#ownershiptransferred-iclo1) — `OwnershipTransferred(address indexed previousOwner, address indexed newOwner)` (via `Ownable._transferOwnership`)

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [constructor()](#constructor-bmo1) — BuildManagerOwnable, internal
* `Ownable._transferOwnership(address)` — OpenZeppelin Ownable, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Deploy with `new BeneficiaryRegistry(msg.sender)`.

***

### \_setBlockNumberChange (BR1)

**Contract/Library:** BeneficiaryRegistry

**Description:** Records the current L1/L2 block number for the given CryptoLegacy contract.

**Detailed Description:** Loads the change history array for `_cryptoLegacy`. Computes the current block number using Arbitrum’s `ArbSys.arbBlockNumber()` when `block.chainid == 42161`, otherwise uses `block.number`. Appends the block number only if the list is empty or the last recorded value differs, avoiding duplicates for multiple changes in the same block.

**Parameters:**

* \_cryptoLegacy (address): CryptoLegacy contract whose change is being recorded

**Returns:** None

**Modifiers / Visibility / Mutability:**

* internal nonpayable

**Access Control:** Unrestricted (internal)

**Side Effects:**

* Updates [`blockNumberChangesByCryptoLegacy`](https://docs.cryptolegacy.app/documentation/data-structures-reference#blocknumberchangesbycryptolegacy-br1-d5)\[\_cryptoLegacy]

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* `ArbSys.arbBlockNumber()` — `ArbSys` *(at `ArbSys(address(100))`)*, external (staticcall)

**Called by:**

* [setCryptoLegacyBeneficiary(bytes32,bool)](#setcryptolegacybeneficiary-br1) — BeneficiaryRegistry
* [setCryptoLegacyGuardian(bytes32,bool)](#setcryptolegacyguardian-br1) — BeneficiaryRegistry
* [setCryptoLegacyOwner(bytes32,bool)](#setcryptolegacyowner-br1) — BeneficiaryRegistry
* [setCryptoLegacyRecoveryAddresses(bytes32\[\],bytes32\[\])](#setcryptolegacyrecoveryaddresses-br1) — BeneficiaryRegistry

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### setCryptoLegacyBeneficiary (BR1)

**Contract/Library:** BeneficiaryRegistry

**Description:** Adds or removes the calling CryptoLegacy from a beneficiary hash index.

**Detailed Description:** Treats `msg.sender` as the CryptoLegacy contract and validates it via `_checkBuildManagerValid(...)`. If `_isAdd == true`, inserts the contract into [`cryptoLegacyByBeneficiary`](https://docs.cryptolegacy.app/documentation/data-structures-reference#cryptolegacybybeneficiary-br1-d1)\[\_beneficiary] (idempotent set semantics) and emits `AddCryptoLegacyForBeneficiary`. Otherwise removes it and emits `RemoveCryptoLegacyForBeneficiary`. Finally, records the block number via [\_setBlockNumberChange](#_setblocknumberchange-br1).

**Parameters:**

* \_beneficiary (bytes32): Beneficiary identifier hash
* \_isAdd (bool): true to add, false to remove

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external nonpayable

**Access Control:**

* Restricted: only a CryptoLegacy built by an added build manager (`_checkBuildManagerValid(msg.sender, address(0))`)

**Side Effects:**

* Updates [`cryptoLegacyByBeneficiary`](https://docs.cryptolegacy.app/documentation/data-structures-reference#cryptolegacybybeneficiary-br1-d1)\[\_beneficiary]
* Updates [`blockNumberChangesByCryptoLegacy`](https://docs.cryptolegacy.app/documentation/data-structures-reference#blocknumberchangesbycryptolegacy-br1-d5)\[msg.sender]

**Emits:**

* [AddCryptoLegacyForBeneficiary](https://docs.cryptolegacy.app/documentation/events-reference#addcryptolegacyforbeneficiary-ibr1) — `AddCryptoLegacyForBeneficiary(bytes32 indexed beneficiary, address indexed cryptoLegacy)`
* [RemoveCryptoLegacyForBeneficiary](https://docs.cryptolegacy.app/documentation/events-reference#removecryptolegacyforbeneficiary-ibr1) — `RemoveCryptoLegacyForBeneficiary(bytes32 indexed beneficiary, address indexed cryptoLegacy)`

**Reverts if:**

* `ICryptoLegacy(msg.sender).buildManager()` — may revert per CryptoLegacy implementation (bubbled)
* `ICryptoLegacyBuildManager(buildManager).isCryptoLegacyBuilt(address)` — may revert per build manager implementation (bubbled)
* `CryptoLegacy` is not registered by its build manager — [`CryptoLegacyNotRegistered()`](https://docs.cryptolegacy.app/documentation/errors-reference#cryptolegacynotregistered-ibmo1)
* The build manager of `CryptoLegacy` is not added — [`BuildManagerNotAdded()`](https://docs.cryptolegacy.app/documentation/errors-reference#buildmanagernotadded-ibmo1)

**Overrides:** None

**Function Calls:**

* [\_checkBuildManagerValid(address,address)](#_checkbuildmanagervalid-bmo1) — BuildManagerOwnable, internal
* `EnumerableSet.AddressSet.add(address)` — OpenZeppelin EnumerableSet, internal
* `EnumerableSet.AddressSet.remove(address)` — OpenZeppelin EnumerableSet, internal
* [\_setBlockNumberChange(address)](#_setblocknumberchange-br1) — BeneficiaryRegistry, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** A verified CryptoLegacy calls `setCryptoLegacyBeneficiary(keccak256("alice@email"), true)` to register itself under Alice’s beneficiary hash.

***

### setCryptoLegacyGuardian (BR1)

**Contract/Library:** BeneficiaryRegistry

**Description:** Adds or removes the calling CryptoLegacy from a guardian hash index.

**Detailed Description:** Validates `msg.sender` via `_checkBuildManagerValid`. If `_isAdd`, adds to [`cryptoLegacyByGuardian`](https://docs.cryptolegacy.app/documentation/data-structures-reference#cryptolegacybyguardian-br1-d3)\[\_guardian] and emits `AddCryptoLegacyForGuardian`; otherwise removes and emits `RemoveCryptoLegacyForGuardian`. Finally records the block number via [\_setBlockNumberChange](#_setblocknumberchange-br1).

**Parameters:**

* \_guardian (bytes32): Guardian identifier hash
* \_isAdd (bool): true to add, false to remove

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external nonpayable

**Access Control:**

* Restricted: only a CryptoLegacy built by an added build manager

**Side Effects:**

* Updates [`cryptoLegacyByGuardian`](https://docs.cryptolegacy.app/documentation/data-structures-reference#cryptolegacybyguardian-br1-d3)\[\_guardian]
* Updates [`blockNumberChangesByCryptoLegacy`](https://docs.cryptolegacy.app/documentation/data-structures-reference#blocknumberchangesbycryptolegacy-br1-d5)\[msg.sender]

**Emits:**

* [AddCryptoLegacyForGuardian](https://docs.cryptolegacy.app/documentation/events-reference#addcryptolegacyforguardian-ibr1) — `AddCryptoLegacyForGuardian(bytes32 indexed guardian, address indexed cryptoLegacy)`
* [RemoveCryptoLegacyForGuardian](https://docs.cryptolegacy.app/documentation/events-reference#removecryptolegacyforguardian-ibr1) — `RemoveCryptoLegacyForGuardian(bytes32 indexed guardian, address indexed cryptoLegacy)`

**Reverts if:**

* `ICryptoLegacy(msg.sender).buildManager()` — may revert per CryptoLegacy implementation (bubbled)
* `ICryptoLegacyBuildManager(buildManager).isCryptoLegacyBuilt(address)` — may revert per build manager implementation (bubbled)
* `CryptoLegacy` is not registered by its build manager — [`CryptoLegacyNotRegistered()`](https://docs.cryptolegacy.app/documentation/errors-reference#cryptolegacynotregistered-ibmo1)
* The build manager of `CryptoLegacy` is not added — [`BuildManagerNotAdded()`](https://docs.cryptolegacy.app/documentation/errors-reference#buildmanagernotadded-ibmo1)

**Overrides:** None

**Function Calls:**

* [\_checkBuildManagerValid(address,address)](#_checkbuildmanagervalid-bmo1) — BuildManagerOwnable, internal
* `EnumerableSet.AddressSet.add(address)` — OpenZeppelin EnumerableSet, internal
* `EnumerableSet.AddressSet.remove(address)` — OpenZeppelin EnumerableSet, internal
* [\_setBlockNumberChange(address)](#_setblocknumberchange-br1) — BeneficiaryRegistry, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** A verified CryptoLegacy calls `setCryptoLegacyGuardian(guardianHash, true)` to register its guardian linkage.

***

### setCryptoLegacyOwner (BR1)

**Contract/Library:** BeneficiaryRegistry

**Description:** Adds or removes the calling CryptoLegacy from an owner hash index.

**Detailed Description:** Validates `msg.sender` via `_checkBuildManagerValid`. If `_isAdd`, adds to [`cryptoLegacyByOwner`](https://docs.cryptolegacy.app/documentation/data-structures-reference#cryptolegacybyowner-br1-d2)\[\_owner] and emits `AddCryptoLegacyForOwner`; otherwise removes and emits `RemoveCryptoLegacyForOwner`. Always records the block change via [\_setBlockNumberChange](#_setblocknumberchange-br1).

**Parameters:**

* \_owner (bytes32): Owner identifier hash
* \_isAdd (bool): true to add, false to remove

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external nonpayable

**Access Control:**

* Restricted: only a CryptoLegacy built by an added build manager

**Side Effects:**

* Updates [`cryptoLegacyByOwner`](https://docs.cryptolegacy.app/documentation/data-structures-reference#cryptolegacybyowner-br1-d2)\[\_owner]
* Updates [`blockNumberChangesByCryptoLegacy`](https://docs.cryptolegacy.app/documentation/data-structures-reference#blocknumberchangesbycryptolegacy-br1-d5)\[msg.sender]

**Emits:**

* [AddCryptoLegacyForOwner](https://docs.cryptolegacy.app/documentation/events-reference#addcryptolegacyforowner-ibr1) — `AddCryptoLegacyForOwner(bytes32 indexed owner, address indexed cryptoLegacy)`
* [RemoveCryptoLegacyForOwner](https://docs.cryptolegacy.app/documentation/events-reference#removecryptolegacyforowner-ibr1) — `RemoveCryptoLegacyForOwner(bytes32 indexed owner, address indexed cryptoLegacy)`

**Reverts if:**

* `ICryptoLegacy(msg.sender).buildManager()` — may revert per CryptoLegacy implementation (bubbled)
* `ICryptoLegacyBuildManager(buildManager).isCryptoLegacyBuilt(address)` — may revert per build manager implementation (bubbled)
* `CryptoLegacy` is not registered by its build manager — [`CryptoLegacyNotRegistered()`](https://docs.cryptolegacy.app/documentation/errors-reference#cryptolegacynotregistered-ibmo1)
* The build manager of `CryptoLegacy` is not added — [`BuildManagerNotAdded()`](https://docs.cryptolegacy.app/documentation/errors-reference#buildmanagernotadded-ibmo1)

**Overrides:** None

**Function Calls:**

* [\_checkBuildManagerValid(address,address)](#_checkbuildmanagervalid-bmo1) — BuildManagerOwnable, internal
* `EnumerableSet.AddressSet.add(address)` — OpenZeppelin EnumerableSet, internal
* `EnumerableSet.AddressSet.remove(address)` — OpenZeppelin EnumerableSet, internal
* [\_setBlockNumberChange(address)](#_setblocknumberchange-br1) — BeneficiaryRegistry, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** A verified CryptoLegacy calls `setCryptoLegacyOwner(ownerHash, true)` to index itself by the owner’s hash.

***

### setCryptoLegacyRecoveryAddresses (BR1)

**Contract/Library:** BeneficiaryRegistry

**Description:** Updates recovery-hash indexes for the calling CryptoLegacy by removing old and adding new hashes.

**Detailed Description:** Validates `msg.sender` via `_checkBuildManagerValid`. Iterates `_oldRecoveryHashes` removing `msg.sender` from each related set and emits `RemoveCryptoLegacyForRecovery` per removal. Iterates `_newRecoveryHashes` adding `msg.sender` to each set and emits `AddCryptoLegacyForRecovery` per addition. Finally records the block change via [\_setBlockNumberChange](#_setblocknumberchange-br1).

**Parameters:**

* \_oldRecoveryHashes (bytes32\[], memory): Recovery hashes to remove
* \_newRecoveryHashes (bytes32\[], memory): Recovery hashes to add

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external nonpayable

**Access Control:**

* Restricted: only a CryptoLegacy built by an added build manager

**Side Effects:**

* Updates [`cryptoLegacyByRecovery`](https://docs.cryptolegacy.app/documentation/data-structures-reference#cryptolegacybyrecovery-br1-d4)\[\_oldRecoveryHashes\[i]]
* Updates [`cryptoLegacyByRecovery`](https://docs.cryptolegacy.app/documentation/data-structures-reference#cryptolegacybyrecovery-br1-d4)\[\_newRecoveryHashes\[i]]
* Updates [`blockNumberChangesByCryptoLegacy`](https://docs.cryptolegacy.app/documentation/data-structures-reference#blocknumberchangesbycryptolegacy-br1-d5)\[msg.sender]

**Emits:**

* [RemoveCryptoLegacyForRecovery](https://docs.cryptolegacy.app/documentation/events-reference#removecryptolegacyforrecovery-ibr1) — `RemoveCryptoLegacyForRecovery(bytes32 indexed recovery, address indexed cryptoLegacy)`
* [AddCryptoLegacyForRecovery](https://docs.cryptolegacy.app/documentation/events-reference#addcryptolegacyforrecovery-ibr1) — `AddCryptoLegacyForRecovery(bytes32 indexed recovery, address indexed cryptoLegacy)`

**Reverts if:**

* `ICryptoLegacy(msg.sender).buildManager()` — may revert per CryptoLegacy implementation (bubbled)
* `ICryptoLegacyBuildManager(buildManager).isCryptoLegacyBuilt(address)` — may revert per build manager implementation (bubbled)
* `CryptoLegacy` is not registered by its build manager — [`CryptoLegacyNotRegistered()`](https://docs.cryptolegacy.app/documentation/errors-reference#cryptolegacynotregistered-ibmo1)
* The build manager of `CryptoLegacy` is not added — [`BuildManagerNotAdded()`](https://docs.cryptolegacy.app/documentation/errors-reference#buildmanagernotadded-ibmo1)

**Overrides:** None

**Function Calls:**

* [\_checkBuildManagerValid(address,address)](#_checkbuildmanagervalid-bmo1) — BuildManagerOwnable, internal
* `EnumerableSet.AddressSet.remove(address)` — OpenZeppelin EnumerableSet, internal
* `EnumerableSet.AddressSet.add(address)` — OpenZeppelin EnumerableSet, internal
* [\_setBlockNumberChange(address)](#_setblocknumberchange-br1) — BeneficiaryRegistry, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(n\_old + n\_new)

**Example:** A verified CryptoLegacy calls `setCryptoLegacyRecoveryAddresses(oldList, newList)` to refresh all recovery hashes atomically.

***

### getCryptoLegacyListByBeneficiary (BR1)

**Contract/Library:** BeneficiaryRegistry

**Description:** Returns CryptoLegacy addresses indexed by a beneficiary hash.

**Detailed Description:** Reads the `EnumerableSet` for `_hash` and returns a copy of its values.

**Parameters:**

* \_hash (bytes32): Beneficiary identifier hash

**Returns:**

* result (address\[], memory): Array of CryptoLegacy addresses

**Modifiers / Visibility / Mutability:**

* public view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* `EnumerableSet.AddressSet.values()` — OpenZeppelin EnumerableSet, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(n) by number of indexed contracts for `_hash`

**Example:** `getCryptoLegacyListByBeneficiary(beneficiaryHash)`.

***

### getCryptoLegacyListByOwner (BR1)

**Contract/Library:** BeneficiaryRegistry

**Description:** Returns CryptoLegacy addresses indexed by an owner hash.

**Detailed Description:** Reads the `EnumerableSet` for `_hash` and returns a copy of its values.

**Parameters:**

* \_hash (bytes32): Owner identifier hash

**Returns:**

* result (address\[], memory): Array of CryptoLegacy addresses

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* `EnumerableSet.AddressSet.values()` — OpenZeppelin EnumerableSet, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(n) by number of indexed contracts for `_hash`

**Example:** `getCryptoLegacyListByOwner(ownerHash)`.

***

### getCryptoLegacyListByGuardian (BR1)

**Contract/Library:** BeneficiaryRegistry

**Description:** Returns CryptoLegacy addresses indexed by a guardian hash.

**Detailed Description:** Reads the `EnumerableSet` for `_hash` and returns a copy of its values.

**Parameters:**

* \_hash (bytes32): Guardian identifier hash

**Returns:**

* result (address\[], memory): Array of CryptoLegacy addresses

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* `EnumerableSet.AddressSet.values()` — OpenZeppelin EnumerableSet, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(n) by number of indexed contracts for `_hash`

**Example:** `getCryptoLegacyListByGuardian(guardianHash)`.

***

### getCryptoLegacyListByRecovery (BR1)

**Contract/Library:** BeneficiaryRegistry

**Description:** Returns CryptoLegacy addresses indexed by a recovery hash.

**Detailed Description:** Reads the `EnumerableSet` for `_hash` and returns a copy of its values.

**Parameters:**

* \_hash (bytes32): Recovery identifier hash

**Returns:**

* result (address\[], memory): Array of CryptoLegacy addresses

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* `EnumerableSet.AddressSet.values()` — OpenZeppelin EnumerableSet, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(n) by number of indexed contracts for `_hash`

**Example:** `getCryptoLegacyListByRecovery(recoveryHash)`.

***

### getCryptoLegacyBlockNumberChanges (BR1)

**Contract/Library:** BeneficiaryRegistry

**Description:** Returns recorded block numbers when the given CryptoLegacy triggered registry update calls.

**Detailed Description:** Reads and returns the array of recorded block numbers for `_cryptoLegacy` captured by [\_setBlockNumberChange](#_setblocknumberchange-br1). Records are appended when registry update functions are called, with same-block duplicates skipped.

**Parameters:**

* \_cryptoLegacy (address): CryptoLegacy address to query

**Returns:**

* result (uint256\[], memory): Array of block numbers

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:** None (entry point)

**Gas / Complexity note:** O(n) by number of recorded changes for `_cryptoLegacy`

**Example:** `getCryptoLegacyBlockNumberChanges(clAddress)`.

***

### getAllCryptoLegacyListByRoles (BR1)

**Contract/Library:** BeneficiaryRegistry

**Description:** Returns all CryptoLegacy lists for a given hash across beneficiary, owner, guardian, and recovery roles.

**Detailed Description:** Aggregates four role-based lists by reading each corresponding `EnumerableSet` for `_hash` and returning all four arrays.

**Parameters:**

* \_hash (bytes32): Identifier hash to query across all roles

**Returns:**

* listByBeneficiary (address\[], memory): CryptoLegacy addresses under beneficiary role
* listByOwner (address\[], memory): CryptoLegacy addresses under owner role
* listByGuardian (address\[], memory): CryptoLegacy addresses under guardian role
* listByRecovery (address\[], memory): CryptoLegacy addresses under recovery role

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:**

* getAllCryptoLegacyListByRoles(bytes32)(#getallcryptolegacylistbyroles-ibr1) — IBeneficiaryRegistry

**Function Calls:**

* `EnumerableSet.AddressSet.values()` — OpenZeppelin EnumerableSet, internal
* `EnumerableSet.AddressSet.values()` — OpenZeppelin EnumerableSet, internal
* `EnumerableSet.AddressSet.values()` — OpenZeppelin EnumerableSet, internal
* `EnumerableSet.AddressSet.values()` — OpenZeppelin EnumerableSet, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(nb + no + ng + nr), where each n\* is the set size for the corresponding role

**Example:** `getAllCryptoLegacyListByRoles(userHash)` to fetch all role associations at once.

***

## BuildManagerOwnable (BMO1)

### constructor (BMO1)

**Contract/Library:** BuildManagerOwnable

**Description:** Initializes ownership state via OpenZeppelin’s `Ownable` base.

**Detailed Description:** Executed once at deployment. Calls the `Ownable` constructor which sets the initial `owner` to `msg.sender` and emits `OwnershipTransferred(address(0), owner)`. No additional state is initialized here beyond the inherited behavior.

**Parameters:** None

**Returns:** None

**Modifiers / Visibility / Mutability:**

* constructor nonpayable

**Access Control:**

* Unrestricted (deployment only)

**Side Effects:**

* Sets `owner` (inherited from `Ownable`)

**Emits:**

* [OwnershipTransferred](https://docs.cryptolegacy.app/documentation/events-reference#ownershiptransferred-iclo1) — `OwnershipTransferred(address indexed previousOwner, address indexed newOwner)`

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* `Ownable()` — OpenZeppelin Ownable, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Deploy with `new BuildManagerOwnable()`.

***

### setBuildManager (BMO1)

**Contract/Library:** BuildManagerOwnable

**Description:** Adds or removes a build manager address from the allowed set.

**Detailed Description:** Restricted to the contract owner. If `_isAdd` is `true`, the address `_buildManager` is inserted into the [`buildManagerAdded`](https://docs.cryptolegacy.app/documentation/data-structures-reference#buildmanageradded-bmo1-d1) set (idempotently). Otherwise, the address is removed from the set if present. Emits a corresponding event after the mutation.

**Parameters:**

* \_buildManager (address): The build manager address to add or remove
* \_isAdd (bool): true to add \_buildManager, false to remove

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external nonpayable onlyOwner

**Access Control:**

* onlyOwner

**Side Effects:**

* Updates [`buildManagerAdded`](https://docs.cryptolegacy.app/documentation/data-structures-reference#buildmanageradded-bmo1-d1)

**Emits:**

* [AddBuildManager](https://docs.cryptolegacy.app/documentation/events-reference#addbuildmanager-ibmo1) — `AddBuildManager(address indexed buildManager)`
* [RemoveBuildManager](https://docs.cryptolegacy.app/documentation/events-reference#removebuildmanager-ibmo1) — `RemoveBuildManager(address indexed buildManager)`

**Reverts if:**

* Caller is not the owner — "Ownable: caller is not the owner"

**Overrides:** None

**Function Calls:**

* `EnumerableSet.AddressSet.add(address)` — OpenZeppelin EnumerableSet, internal
* `EnumerableSet.AddressSet.remove(address)` — OpenZeppelin EnumerableSet, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1) average (set add/remove).

**Example:** Owner calls `setBuildManager(0xB...eF, true)` to allow a new build manager, later `setBuildManager(0xB...eF, false)` to remove it.

***

### \_checkBuildManagerValid (BMO1)

**Contract/Library:** BuildManagerOwnable

**Description:** Verifies that a given CryptoLegacy contract was built by an added build manager and (optionally) that it has a specific owner.

**Detailed Description:** Reads the `buildManager` from the provided `_cryptoLegacy` by calling `ICryptoLegacy(_cryptoLegacy).buildManager()`. If `_clOwner` is non-zero, checks that `ICryptoLegacy(_cryptoLegacy).owner()` matches `_clOwner`. Then verifies that the `buildManager` marks `_cryptoLegacy` as built via `isCryptoLegacyBuilt(_cryptoLegacy)`. Finally ensures the retrieved `buildManager` address exists in [`buildManagerAdded`](https://docs.cryptolegacy.app/documentation/data-structures-reference#buildmanageradded-bmo1-d1). Reverts if any check fails.

**Parameters:**

* \_cryptoLegacy (address): Address of the CryptoLegacy contract to validate
* \_clOwner (address): Expected owner address (pass address(0) to skip owner check)

**Returns:** None

**Modifiers / Visibility / Mutability:**

* internal view

**Access Control:**

* Unrestricted (internal)

**Side Effects:** None

**Emits:** None

**Reverts if:**

* `ICryptoLegacy(_cryptoLegacy).buildManager()` — may revert per target implementation (bubbled)
* `ICryptoLegacy(_cryptoLegacy).owner()` — may revert per target implementation (bubbled)
* `_clOwner != address(0)` and owner mismatch — [`NotTheOwnerOfCryptoLegacy()`](https://docs.cryptolegacy.app/documentation/errors-reference#nottheownerofcryptolegacy-ibmo1)
* `ICryptoLegacyBuildManager(buildManager).isCryptoLegacyBuilt(address)` — may revert per build manager implementation (bubbled)
* Not built by its build manager — [`CryptoLegacyNotRegistered()`](https://docs.cryptolegacy.app/documentation/errors-reference#cryptolegacynotregistered-ibmo1)
* Build manager not added — [`BuildManagerNotAdded()`](https://docs.cryptolegacy.app/documentation/errors-reference#buildmanagernotadded-ibmo1)

**Overrides:** None

**Function Calls:**

* `ICryptoLegacy(_cryptoLegacy).buildManager()` — ICryptoLegacy *(at `_cryptoLegacy`)*, external (staticcall)
* `ICryptoLegacy(_cryptoLegacy).owner()` — ICryptoLegacy *(at `_cryptoLegacy`)*, external (staticcall)
* `ICryptoLegacyBuildManager(buildManager).isCryptoLegacyBuilt(address)` — ICryptoLegacyBuildManager *(at `buildManager`)*, external (staticcall)
* `EnumerableSet.AddressSet.contains(address)` — OpenZeppelin EnumerableSet, internal

**Called by:**

* [setCryptoLegacyBeneficiary(bytes32,bool)](#setcryptolegacybeneficiary-br1) — BeneficiaryRegistry
* [setCryptoLegacyGuardian(bytes32,bool)](#setcryptolegacyguardian-br1) — BeneficiaryRegistry
* [setCryptoLegacyOwner(bytes32,bool)](#setcryptolegacyowner-br1) — BeneficiaryRegistry
* [setCryptoLegacyRecoveryAddresses(bytes32\[\],bytes32\[\])](#setcryptolegacyrecoveryaddresses-br1) — BeneficiaryRegistry
* [sendMessagesTo(address,bytes32\[\],bytes32\[\],bytes\[\],bytes\[\],uint256)](#sendmessagesto-lm1) — LegacyMessenger

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### getBuildManagerAdded (BMO1)

**Contract/Library:** BuildManagerOwnable

**Description:** Returns the list of all added build manager addresses.

**Detailed Description:** Reads the [`buildManagerAdded`](https://docs.cryptolegacy.app/documentation/data-structures-reference#buildmanageradded-bmo1-d1) set and returns a newly allocated array of its values. This is a read-only view that enumerates the set at call time.

**Parameters:** None

**Returns:**

* result (address\[], memory): Array of build manager addresses currently added

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* `EnumerableSet.AddressSet.values()` — OpenZeppelin EnumerableSet, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(n) by number of build managers in the set

**Example:** `getBuildManagerAdded()` → returns `0x12..., 0x34..., ...`.

***

## Create3Factory (C3F1)

### constructor (C3F1)

**Contract/Library:** Create3Factory

**Description:** Initializes the factory and assigns ownership to the provided `_owner`.

**Detailed Description:** Runs once at deployment. The `Ownable()` constructor sets `owner` to `msg.sender` and emits `OwnershipTransferred(address(0), msg.sender)`, then `_transferOwnership(_owner)` updates the owner and emits `OwnershipTransferred(msg.sender, _owner)`. No CREATE3 address is computed or deployed during construction.

**Parameters:**

* \_owner (address): Address that will become the contract owner

**Returns:** None

**Modifiers / Visibility / Mutability:**

* constructor nonpayable

**Access Control:**

* Unrestricted (deployment only)

**Side Effects:**

* Sets `owner` (inherited from Ownable)

**Emits:**

* [OwnershipTransferred](https://docs.cryptolegacy.app/documentation/events-reference#ownershiptransferred-iclo1) — `OwnershipTransferred(address indexed previousOwner, address indexed newOwner)` (via `Ownable()` constructor)
* [OwnershipTransferred](https://docs.cryptolegacy.app/documentation/events-reference#ownershiptransferred-iclo1) — `OwnershipTransferred(address indexed previousOwner, address indexed newOwner)` (via `Ownable._transferOwnership`)

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* `Ownable()` — OpenZeppelin Ownable, internal
* `Ownable._transferOwnership(address)` — OpenZeppelin Ownable, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Deploy with `new Create3Factory(msg.sender)` to set the deployer as the owner.

***

### build (C3F1)

**Contract/Library:** Create3Factory

**Description:** Deploys a contract deterministically via CREATE3 using a salt and raw bytecode.

**Detailed Description:** Restricted to the owner. Computes and deploys a new contract using LibCreate3 `create3(_create3Salt, _contractBytecode)`, which determines the address following the CREATE3 scheme and performs the deployment. On success, the deployed address is returned and the factory emits `Create3Contract(result)`. Callers control the raw \_contractBytecode; ensure it is the correct creation code for the intended contract.

**Parameters:**

* \_create3Salt (bytes32): Salt used to derive the deterministic CREATE3 address
* \_contractBytecode (bytes, calldata): Full creation bytecode (constructor args ABI-encoded if required)

**Returns:**

* result (address): Address of the newly deployed contract

**Modifiers / Visibility / Mutability:**

* external nonpayable onlyOwner

**Access Control:**

* onlyOwner

**Side Effects:**

* Deploys a new contract at the CREATE3 address derived from \_create3Salt

**Emits:**

* [Create3Contract](https://docs.cryptolegacy.app/documentation/events-reference#create3contract-c3f1) — `Create3Contract(address contractAddress)`

**Reverts if:**

* caller is not the owner — "Ownable: caller is not the owner"
* target address for \_create3Salt already has code — [`TargetAlreadyExists()`](https://docs.cryptolegacy.app/documentation/errors-reference#targetalreadyexists-lc31)
* CREATE2 proxy deployment fails — [`ErrorCreatingProxy()`](https://docs.cryptolegacy.app/documentation/errors-reference#errorcreatingproxy-lc31)
* proxy call fails or target bytecode absent — [`ErrorCreatingContract()`](https://docs.cryptolegacy.app/documentation/errors-reference#errorcreatingcontract-lc31)

**Overrides:** None

**Function Calls:**

* [create3(bytes32,bytes)](#create3bytes32bytes-lc31) — LibCreate3, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(n) by \_contractBytecode.length (deployment cost scales with bytecode size)

**Example:**

```solidity
bytes memory bytecode = abi.encodePacked(type(MyContract).creationCode, abi.encode(arg1, arg2));
address deployed = create3Factory.build(keccak256("my-salt"), bytecode);
```

***

### computeAddress (C3F1)

**Contract/Library:** Create3Factory

**Description:** Predicts the deterministic CREATE3 address for a given salt without deploying.

**Detailed Description:** Returns the address computed by `LibCreate3.addressOf(_create3Salt)` with no state changes. Useful for precomputing addresses before calling [`build`](#build-c3f1).

**Parameters:**

* \_create3Salt (bytes32): Salt to derive the predicted CREATE3 address

**Returns:**

* result (address): Predicted address where a deployment with this salt would be created

**Modifiers / Visibility / Mutability:**

* public view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [addressOf(bytes32)](#addressof-lc31) — LibCreate3, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:**

```solidity
address predicted = create3Factory.computeAddress(keccak256("my-salt"));
```

***

## CryptoLegacy (CL1)

### constructor (CL1)

**Contract/Library:** CryptoLegacy

**Description:** Initializes core Diamond storage, sets the build manager and owner, timestamps the deployment, and installs initial plugins.

**Detailed Description:** Retrieves the Diamond storage struct via `LibCryptoLegacy.getCryptoLegacyStorage()`. Sets `cls.buildManager` to the provided `_buildManager`, and `cls.lastUpdateAt` to the current block timestamp. Transfers Diamond ownership to `_owner` using `LibDiamond.setContractOwner`. Finally, installs the initial plugins by invoking `LibCryptoLegacyPlugins._addPluginList` with the storage struct and `_plugins`. Ensures the contract starts with a known owner and requested plugin set.

**Parameters:**

* \_buildManager (address): Address of the ICryptoLegacyBuildManager to bind into storage
* \_owner (address): Address that will become the Diamond owner
* \_plugins (address\[], memory): Initial plugin addresses to add

**Returns:** None

**Modifiers / Visibility / Mutability:**

* constructor nonpayable

**Access Control:**

* Unrestricted (deployment only)

**Side Effects:**

* Sets `LibCryptoLegacy.CryptoLegacyStorage.buildManager`
* Sets `LibCryptoLegacy.CryptoLegacyStorage.lastUpdateAt`
* Updates Diamond owner via `LibDiamond`
* Mutates plugin-related Diamond storage via `LibCryptoLegacyPlugins`

**Emits:**

* [OwnershipTransferred](https://docs.cryptolegacy.app/documentation/events-reference#ownershiptransferred-ld1) — `OwnershipTransferred(address indexed previousOwner, address indexed newOwner)`
* [AddFunctions](https://docs.cryptolegacy.app/documentation/events-reference#addfunctions-icl1) — `AddFunctions(address _facetAddress, bytes4[] _functionSelectors, uint16 selectorPosition)`

**Reverts if:**

* `_pluginsi` not registered with build manager — [`PluginNotRegistered()`](https://docs.cryptolegacy.app/documentation/errors-reference#pluginnotregistered-icl1)
* `ICryptoLegacyPlugin(_pluginsi).getSetupSigs()` — may revert per plugin implementation
* `_pluginsi == address(0)` — [`FacetCantBeZero()`](https://docs.cryptolegacy.app/documentation/errors-reference#facetcantbezero-icl1)
* `_pluginsi` lacks contract code — "NO\_CODE"
* Selector already registered — [`CantAddFunctionThatAlreadyExists()`](https://docs.cryptolegacy.app/documentation/errors-reference#cantaddfunctionthatalreadyexists-icl1)

**Overrides:** None

**Function Calls:**

* [getCryptoLegacyStorage()](#getcryptolegacystorage-lcl1) — `LibCryptoLegacy`, internal
* [setContractOwner(address)](#setcontractowner-ld1) — `LibDiamond`, internal
* [\_addPluginList(ICryptoLegacy.CryptoLegacyStorage,address\[\])](#_addpluginlist-lclp1) — `LibCryptoLegacyPlugins`, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(n) by `_plugins.length`

**Example:** Deploy with:

```solidity
new CryptoLegacy(buildManager, owner, initialPlugins);
```

***

### replacePlugin (CL1)

**Contract/Library:** CryptoLegacy

**Description:** Replaces an existing set of plugins with a new set.

**Detailed Description:** Iterates through `_oldPlugins` and removes each plugin via `LibCryptoLegacyPlugins._removePlugin`. Then fetches Diamond storage and adds all `_newPlugins` in a single call to `_addPluginList`. Ensures the plugin set transitions atomically within a transaction.

**Parameters:**

* \_oldPlugins (address\[], memory): Plugins to remove
* \_newPlugins (address\[], memory): Plugins to add

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external nonpayable onlyOwner

**Access Control:**

* onlyOwner

**Side Effects:**

* Mutates plugin-related Diamond storage (removes `_oldPlugins`, adds `_newPlugins`)

**Emits:**

* [RemoveFunctions](https://docs.cryptolegacy.app/documentation/events-reference#removefunctions-icl1) — `RemoveFunctions(address _facetAddress, bytes4[] _functionSelectors)`
* [AddFunctions](https://docs.cryptolegacy.app/documentation/events-reference#addfunctions-icl1) — `AddFunctions(address _facetAddress, bytes4[] _functionSelectors, uint16 selectorPosition)`

**Reverts if:**

* Distribution already started — [`DistributionStarted()`](https://docs.cryptolegacy.app/documentation/errors-reference#distributionstarted-icl1)
* Initial fee not paid — [`InitialFeeNotPaid()`](https://docs.cryptolegacy.app/documentation/errors-reference#initialfeenotpaid-icl1)
* Caller is not the owner — [`NotTheOwner()`](https://docs.cryptolegacy.app/documentation/errors-reference#nottheowner-icl1)
* `ICryptoLegacyPlugin(_oldPluginsi).getSigs()` — may revert per plugin implementation
* `_oldPluginsi == address(0)` — [`FacetCantBeZero()`](https://docs.cryptolegacy.app/documentation/errors-reference#facetcantbezero-icl1)
* `_oldPluginsi` is the immutable facet — [`CantRemoveImmutableFunctions()`](https://docs.cryptolegacy.app/documentation/errors-reference#cantremoveimmutablefunctions-icl1)
* `_oldPluginsi` not installed — [`FacetNotFound()`](https://docs.cryptolegacy.app/documentation/errors-reference#facetnotfound-icl1)
* `_newPluginsi` not registered with build manager — [`PluginNotRegistered()`](https://docs.cryptolegacy.app/documentation/errors-reference#pluginnotregistered-icl1)
* `ICryptoLegacyPlugin(_newPluginsi).getSetupSigs()` — may revert per plugin implementation
* `_newPluginsi == address(0)` — [`FacetCantBeZero()`](https://docs.cryptolegacy.app/documentation/errors-reference#facetcantbezero-icl1)
* `_newPluginsi` lacks contract code — "NO\_CODE"
* Selector already registered — [`CantAddFunctionThatAlreadyExists()`](https://docs.cryptolegacy.app/documentation/errors-reference#cantaddfunctionthatalreadyexists-icl1)

**Overrides:** None

**Function Calls:**

* [\_removePlugin(ICryptoLegacyPlugin)](#_removeplugin-lclp1) — `LibCryptoLegacyPlugins`, internal
* [getCryptoLegacyStorage()](#getcryptolegacystorage-lcl1) — `LibCryptoLegacy`, internal
* [\_addPluginList(ICryptoLegacy.CryptoLegacyStorage,address\[\])](#_addpluginlist-lclp1) — `LibCryptoLegacyPlugins`, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(n\_old + n\_new)

**Example:** Owner replaces legacy plugins with improved implementations:

```solidity
cryptoLegacy.replacePlugin(oldPlugins, newPlugins);
```

***

### addPluginList (CL1)

**Contract/Library:** CryptoLegacy

**Description:** Adds a list of plugins to the contract.

**Detailed Description:** Retrieves Diamond storage and forwards `_plugins` to `LibCryptoLegacyPlugins._addPluginList`, which records and activates the plugins.

**Parameters:**

* \_plugins (address\[], memory): Plugins to add

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external nonpayable onlyOwner

**Access Control:**

* onlyOwner

**Side Effects:**

* Mutates plugin-related Diamond storage (adds `_plugins`)

**Emits:**

* [AddFunctions](https://docs.cryptolegacy.app/documentation/events-reference#addfunctions-icl1) — `AddFunctions(address _facetAddress, bytes4[] _functionSelectors, uint16 selectorPosition)`

**Reverts if:**

* Distribution already started — [`DistributionStarted()`](https://docs.cryptolegacy.app/documentation/errors-reference#distributionstarted-icl1)
* Initial fee not paid — [`InitialFeeNotPaid()`](https://docs.cryptolegacy.app/documentation/errors-reference#initialfeenotpaid-icl1)
* Caller is not the owner — [`NotTheOwner()`](https://docs.cryptolegacy.app/documentation/errors-reference#nottheowner-icl1)
* `_pluginsi` not registered with build manager — [`PluginNotRegistered()`](https://docs.cryptolegacy.app/documentation/errors-reference#pluginnotregistered-icl1)
* `ICryptoLegacyPlugin(_pluginsi).getSetupSigs()` — may revert per plugin implementation
* `_pluginsi == address(0)` — [`FacetCantBeZero()`](https://docs.cryptolegacy.app/documentation/errors-reference#facetcantbezero-icl1)
* `_pluginsi` lacks contract code — "NO\_CODE"
* Selector already registered — [`CantAddFunctionThatAlreadyExists()`](https://docs.cryptolegacy.app/documentation/errors-reference#cantaddfunctionthatalreadyexists-icl1)

**Overrides:** None

**Function Calls:**

* [getCryptoLegacyStorage()](#getcryptolegacystorage-lcl1) — `LibCryptoLegacy`, internal
* [\_addPluginList(ICryptoLegacy.CryptoLegacyStorage,address\[\])](#_addpluginlist-lclp1) — `LibCryptoLegacyPlugins`, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(n) by `_plugins.length`

**Example:**

```solidity
address[] memory plugins = new address[](2);
plugins[0] = pluginA;
plugins[1] = pluginB;
cryptoLegacy.addPluginList(plugins);
```

***

### removePluginList (CL1)

**Contract/Library:** CryptoLegacy

**Description:** Removes a list of plugins from the contract.

**Detailed Description:** Loops over `_plugins` and calls `LibCryptoLegacyPlugins._removePlugin` for each entry, deactivating and removing them from Diamond storage.

**Parameters:**

* \_plugins (address\[], memory): Plugins to remove

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external nonpayable onlyOwner

**Access Control:**

* onlyOwner

**Side Effects:**

* Removes facet address entries and selector mappings from Diamond storage

**Emits:**

* [RemoveFunctions](https://docs.cryptolegacy.app/documentation/events-reference#removefunctions-icl1) — `RemoveFunctions(address _facetAddress, bytes4[] _functionSelectors)`

**Reverts if:**

* Distribution already started — [`DistributionStarted()`](https://docs.cryptolegacy.app/documentation/errors-reference#distributionstarted-icl1)
* Initial fee not paid — [`InitialFeeNotPaid()`](https://docs.cryptolegacy.app/documentation/errors-reference#initialfeenotpaid-icl1)
* Caller is not the owner — [`NotTheOwner()`](https://docs.cryptolegacy.app/documentation/errors-reference#nottheowner-icl1)
* `ICryptoLegacyPlugin(_pluginsi).getSigs()` — may revert per plugin implementation
* `_pluginsi == address(0)` — [`FacetCantBeZero()`](https://docs.cryptolegacy.app/documentation/errors-reference#facetcantbezero-icl1)
* `_pluginsi` is the immutable facet — [`CantRemoveImmutableFunctions()`](https://docs.cryptolegacy.app/documentation/errors-reference#cantremoveimmutablefunctions-icl1)
* `_pluginsi` not installed — [`FacetNotFound()`](https://docs.cryptolegacy.app/documentation/errors-reference#facetnotfound-icl1)

**Overrides:** None

**Function Calls:**

* [\_removePlugin(ICryptoLegacyPlugin)](#_removeplugin-lclp1) — `LibCryptoLegacyPlugins`, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(n) by `_plugins.length`

**Example:**

```solidity
cryptoLegacy.removePluginList(obsoletePlugins);
```

***

### externalLens (CL1)

**Contract/Library:** CryptoLegacy

**Description:** Returns the address of the external lens configured in the build manager.

**Detailed Description:** Reads Diamond storage, then queries the bound `buildManager` for its [`externalLens`](https://docs.cryptolegacy.app/documentation/data-structures-reference#externallens-clbm1-d6) address. This is a read-only external call to the build manager.

**Parameters:** None

**Returns:**

* addr (address): External lens address exposed by the build manager

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:**

* `ICryptoLegacyBuildManager.externalLens()` — may revert per build manager implementation

**Overrides:** None

**Function Calls:**

* [getCryptoLegacyStorage()](#getcryptolegacystorage-lcl1) — `LibCryptoLegacy`, internal
* `ICryptoLegacyBuildManager.externalLens()` — `ICryptoLegacyBuildManager` *(at `cls.buildManager`)*, external (staticcall)

**Called by:** None (entry point)

**Gas / Complexity note:** O(1) (plus minimal external read cost)

**Example:**

```solidity
address lens = cryptoLegacy.externalLens();
```

***

***

## CryptoLegacyBuildManager (CLBM1)

### receive (CLBM1)

**Contract/Library:** CryptoLegacyBuildManager

**Description:** Accepts plain ETH transfers to the build manager.

**Detailed Description:** Allows the contract to receive ETH when called with empty calldata. This function contains no logic beyond accepting the transfer.

**Parameters:** None

**Returns:** None

**Modifiers / Visibility / Mutability:**

* receive external payable

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Send ETH directly to the CryptoLegacyBuildManager address.

***

### constructor (CLBM1)

**Contract/Library:** CryptoLegacyBuildManager

**Description:** Initializes registries and factory, stores the Lifetime NFT contract, and transfers ownership.

**Detailed Description:** Runs once at deployment. The `Ownable()` constructor sets `owner` to `msg.sender` and emits [OwnershipTransferred](https://docs.cryptolegacy.app/documentation/events-reference#ownershiptransferred-iclo1). It then calls [`_setRegistries`](#_setregistries-clbm1) to persist [`feeRegistry`](https://docs.cryptolegacy.app/documentation/data-structures-reference#feeregistry-clbm1-d1), [`pluginsRegistry`](https://docs.cryptolegacy.app/documentation/data-structures-reference#pluginsregistry-clbm1-d2), and [`beneficiaryRegistry`](https://docs.cryptolegacy.app/documentation/data-structures-reference#beneficiaryregistry-clbm1-d3) (emitting [SetRegistries](https://docs.cryptolegacy.app/documentation/events-reference#setregistries-iclbm1)), calls [`_setFactory`](#_setfactory-clbm1) to persist [`factory`](https://docs.cryptolegacy.app/documentation/data-structures-reference#factory-clbm1-d5) (emitting [SetFactory](https://docs.cryptolegacy.app/documentation/events-reference#setfactory-iclbm1)), stores [`lifetimeNft`](https://docs.cryptolegacy.app/documentation/data-structures-reference#lifetimenft-clbm1-d4), and finally calls `Ownable._transferOwnership(_owner)` to update the owner (emitting [OwnershipTransferred](https://docs.cryptolegacy.app/documentation/events-reference#ownershiptransferred-iclo1)).

**Parameters:**

* \_owner (address): Address to be set as the owner
* \_feeRegistry (IFeeRegistry): Fee registry contract
* \_pluginsRegistry (IPluginsRegistry): Plugins registry contract
* \_beneficiaryRegistry (IBeneficiaryRegistry): Beneficiary registry contract
* \_lifetimeNft (ILifetimeNft): Lifetime NFT contract
* \_factory (ICryptoLegacyFactory): Factory used to deploy CryptoLegacy contracts

**Returns:** None

**Modifiers / Visibility / Mutability:**

* constructor nonpayable

**Access Control:**

* Unrestricted (deployment only)

**Side Effects:**

* Sets [`feeRegistry`](https://docs.cryptolegacy.app/documentation/data-structures-reference#feeregistry-clbm1-d1), [`pluginsRegistry`](https://docs.cryptolegacy.app/documentation/data-structures-reference#pluginsregistry-clbm1-d2), [`beneficiaryRegistry`](https://docs.cryptolegacy.app/documentation/data-structures-reference#beneficiaryregistry-clbm1-d3)
* Sets [`factory`](https://docs.cryptolegacy.app/documentation/data-structures-reference#factory-clbm1-d5)
* Sets [`lifetimeNft`](https://docs.cryptolegacy.app/documentation/data-structures-reference#lifetimenft-clbm1-d4)
* Sets `owner` (first to `msg.sender`, then to `_owner`)

**Emits:**

* [OwnershipTransferred](https://docs.cryptolegacy.app/documentation/events-reference#ownershiptransferred-iclo1) — `OwnershipTransferred(address indexed previousOwner, address indexed newOwner)` (via `Ownable()` constructor)
* [SetRegistries](https://docs.cryptolegacy.app/documentation/events-reference#setregistries-iclbm1) — `SetRegistries(address indexed feeRegistry, address indexed pluginsRegistry, address indexed beneficiaryRegistry)`
* [SetFactory](https://docs.cryptolegacy.app/documentation/events-reference#setfactory-iclbm1) — `SetFactory(address indexed factory)`
* [OwnershipTransferred](https://docs.cryptolegacy.app/documentation/events-reference#ownershiptransferred-iclo1) — `OwnershipTransferred(address indexed previousOwner, address indexed newOwner)` (via `Ownable._transferOwnership`)

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* `Ownable()` — Ownable, internal
* [\_setRegistries(IFeeRegistry,IPluginsRegistry,IBeneficiaryRegistry)](#_setregistries-clbm1) — CryptoLegacyBuildManager, internal
* [\_setFactory(ICryptoLegacyFactory)](#_setfactory-clbm1) — CryptoLegacyBuildManager, internal
* `Ownable._transferOwnership(address)` — Ownable, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Deploy with the required addresses:

```solidity
new CryptoLegacyBuildManager(owner, feeReg, plugReg, benReg, lifetimeNft, factory);
```

***

### setRegistries (CLBM1)

**Contract/Library:** CryptoLegacyBuildManager

**Description:** Owner setter that updates Fee/Plugins/Beneficiary registries.

**Detailed Description:** Delegates to the internal helper [`_setRegistries`](#_setregistries-clbm1) which writes the new registry addresses and emits [SetRegistries](https://docs.cryptolegacy.app/documentation/events-reference#setregistries-iclbm1).

**Parameters:**

* \_feeRegistry (IFeeRegistry): New fee registry
* \_pluginsRegistry (IPluginsRegistry): New plugins registry
* \_beneficiaryRegistry (IBeneficiaryRegistry): New beneficiary registry

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external nonpayable onlyOwner

**Access Control:**

* onlyOwner

**Side Effects:**

* Updates [`feeRegistry`](https://docs.cryptolegacy.app/documentation/data-structures-reference#feeregistry-clbm1-d1), [`pluginsRegistry`](https://docs.cryptolegacy.app/documentation/data-structures-reference#pluginsregistry-clbm1-d2), [`beneficiaryRegistry`](https://docs.cryptolegacy.app/documentation/data-structures-reference#beneficiaryregistry-clbm1-d3)

**Emits:**

* [SetRegistries](https://docs.cryptolegacy.app/documentation/events-reference#setregistries-iclbm1) — `SetRegistries(address indexed feeRegistry, address indexed pluginsRegistry, address indexed beneficiaryRegistry)`

**Reverts if:**

* caller is not the owner — "Ownable: caller is not the owner"

**Overrides:** None

**Function Calls:**

* [\_setRegistries(IFeeRegistry,IPluginsRegistry,IBeneficiaryRegistry)](#_setregistries-clbm1) — CryptoLegacyBuildManager, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Owner rotates registries during an upgrade:

```solidity
buildManager.setRegistries(newFeeReg, newPlugReg, newBenReg);
```

***

### \_setRegistries (CLBM1)

**Contract/Library:** CryptoLegacyBuildManager

**Description:** Internal storage setter for main registries.

**Detailed Description:** Writes `_feeRegistry`, `_pluginsRegistry`, `_beneficiaryRegistry` to storage and emits [SetRegistries](https://docs.cryptolegacy.app/documentation/events-reference#setregistries-iclbm1) with their addresses. Used by the constructor and the public setter to keep logic DRY.

**Parameters:**

* \_feeRegistry (IFeeRegistry): Fee registry
* \_pluginsRegistry (IPluginsRegistry): Plugins registry
* \_beneficiaryRegistry (IBeneficiaryRegistry): Beneficiary registry

**Returns:** None

**Modifiers / Visibility / Mutability:**

* internal nonpayable

**Access Control:**

* Unrestricted (internal)

**Side Effects:**

* Updates [`feeRegistry`](https://docs.cryptolegacy.app/documentation/data-structures-reference#feeregistry-clbm1-d1), [`pluginsRegistry`](https://docs.cryptolegacy.app/documentation/data-structures-reference#pluginsregistry-clbm1-d2), [`beneficiaryRegistry`](https://docs.cryptolegacy.app/documentation/data-structures-reference#beneficiaryregistry-clbm1-d3)

**Emits:**

* [SetRegistries](https://docs.cryptolegacy.app/documentation/events-reference#setregistries-iclbm1) — `SetRegistries(address indexed feeRegistry, address indexed pluginsRegistry, address indexed beneficiaryRegistry)`

**Reverts if:**

None

**Overrides:** None

**Function Calls:** None

**Called by:**

* [constructor](#constructor-clbm1) — CryptoLegacyBuildManager
* [setRegistries](#setregistries-clbm1) — CryptoLegacyBuildManager

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### setFactory (CLBM1)

**Contract/Library:** CryptoLegacyBuildManager

**Description:** Owner setter that updates the deployment factory.

**Detailed Description:** Delegates to internal [`_setFactory`](#_setfactory-clbm1) which writes and emits `SetFactory`.

**Parameters:**

* \_factory (ICryptoLegacyFactory): New factory contract

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external nonpayable onlyOwner

**Access Control:**

* onlyOwner

**Side Effects:**

* Updates [`factory`](https://docs.cryptolegacy.app/documentation/data-structures-reference#factory-clbm1-d5)

**Emits:**

* [SetFactory](https://docs.cryptolegacy.app/documentation/events-reference#setfactory-iclbm1) — `SetFactory(address indexed factory)`

**Reverts if:**

* Caller is not the owner — "Ownable: caller is not the owner"

**Overrides:** None

**Function Calls:**

* [\_setFactory(ICryptoLegacyFactory)](#_setfactory-clbm1) — CryptoLegacyBuildManager, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:**

```solidity
buildManager.setFactory(newFactory);
```

***

### \_setFactory (CLBM1)

**Contract/Library:** CryptoLegacyBuildManager

**Description:** Internal storage setter for the factory contract.

**Detailed Description:** Assigns the `_factory` to storage and emits `SetFactory`.

**Parameters:**

* \_factory (ICryptoLegacyFactory): Factory to store

**Returns:** None

**Modifiers / Visibility / Mutability:**

* internal nonpayable

**Access Control:**

* Unrestricted (internal)

**Side Effects:**

* Updates [`factory`](https://docs.cryptolegacy.app/documentation/data-structures-reference#factory-clbm1-d5)

**Emits:**

* [SetFactory](https://docs.cryptolegacy.app/documentation/events-reference#setfactory-iclbm1) — `SetFactory(address indexed factory)`

**Reverts if:**

None

**Overrides:** None

**Function Calls:** None

**Called by:**

* [constructor](#constructor-clbm1) — CryptoLegacyBuildManager
* [setFactory](#setfactory-clbm1) — CryptoLegacyBuildManager

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### setSupplyLimit (CLBM1)

**Contract/Library:** CryptoLegacyBuildManager

**Description:** Owner setter for the minimum Lifetime NFT supply required to allow mass minting.

**Detailed Description:** Updates [`minMassMintSupply`](https://docs.cryptolegacy.app/documentation/data-structures-reference#minmassmintsupply-clbm1-d7) to `_newVal` and emits `SetSupplyLimit`. Used by the owner to gate the `payForMultipleLifetimeNft` path.

**Parameters:**

* \_newVal (uint256): New minimum totalSupply threshold

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external nonpayable onlyOwner

**Access Control:**

* onlyOwner

**Side Effects:**

* Updates [`minMassMintSupply`](https://docs.cryptolegacy.app/documentation/data-structures-reference#minmassmintsupply-clbm1-d7)

**Emits:**

* [SetSupplyLimit](https://docs.cryptolegacy.app/documentation/events-reference#setsupplylimit-iclbm1) — `SetSupplyLimit(uint256 supplyLimit)`

**Reverts if:**

* Caller is not the owner — "Ownable: caller is not the owner"

**Overrides:** None

**Function Calls:** None

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:**

```solidity
buildManager.setSupplyLimit(2_000);
```

***

### setExternalLens (CLBM1)

**Contract/Library:** CryptoLegacyBuildManager

**Description:** Owner setter for a helper "lens" address.

**Detailed Description:** Stores an external [`externalLens`](https://docs.cryptolegacy.app/documentation/data-structures-reference#externallens-clbm1-d6) address used by other components (e.g., UIs or contracts) and emits `SetExternalLens`.

**Parameters:**

* \_externalLens (address): New lens address

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external nonpayable onlyOwner

**Access Control:**

* onlyOwner

**Side Effects:**

* Updates [`externalLens`](https://docs.cryptolegacy.app/documentation/data-structures-reference#externallens-clbm1-d6)

**Emits:**

* [SetExternalLens](https://docs.cryptolegacy.app/documentation/events-reference#setexternallens-iclbm1) — `SetExternalLens(address indexed externalLens)`

**Reverts if:**

* Caller is not the owner — "Ownable: caller is not the owner"

**Overrides:** None

**Function Calls:** None

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:**

```solidity
buildManager.setExternalLens(lensAddr);
```

***

### withdrawFee (CLBM1)

**Contract/Library:** CryptoLegacyBuildManager

**Description:** Owner can withdraw ETH from the contract to a recipient.

**Detailed Description:** Performs a low-level `.call{value: _amount}("")` to `_recipient`. If the call fails, it reverts with `WithdrawFeeFailed(bytes)`. Emits `WithdrawFee` on success.

**Parameters:**

* \_recipient (address payable): Receiver of the ETH
* \_amount (uint256): Amount in wei to withdraw

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external nonpayable onlyOwner

**Access Control:**

* onlyOwner

**Side Effects:**

* Transfers ETH to `_recipient`

**Emits:**

* [WithdrawFee](https://docs.cryptolegacy.app/documentation/events-reference#withdrawfee-iclbm1) — `WithdrawFee(address indexed recipient, uint256 indexed amount)`

**Reverts if:**

* Caller is not the owner — "Ownable: caller is not the owner"
* Low-level ETH transfer to `_recipient` fails — [`WithdrawFeeFailed(bytes)`](https://docs.cryptolegacy.app/documentation/errors-reference#withdrawfeefailed-iclbm1)

**Overrides:** None

**Function Calls:**

* `call(bytes)` — address *(at `_recipient`)*, external

**Called by:** None (entry point)

**Gas / Complexity note:** O(1) (plus external call cost)

**Example:**

```solidity
buildManager.withdrawFee(payable(treasury), 1 ether);
```

***

### payFee (CLBM1)

**Contract/Library:** CryptoLegacyBuildManager

**Description:** Pays an update fee or, if sufficient, auto-switches to lifetime fee and mints/locks an NFT.

**Detailed Description:** Delegates to [`_payFee`](#_payfee-clbm1) with [`REGISTRY_UPDATE_CASE`](https://docs.cryptolegacy.app/documentation/data-structures-reference#registry_update_case-clbm1-d9). `_payFee` computes the applicable fee (update vs lifetime), verifies sufficiency, forwards funds to [`feeRegistry`](https://docs.cryptolegacy.app/documentation/data-structures-reference#feeregistry-clbm1-d1), optionally mints/locks a Lifetime NFT, and refunds any remainder.

**Parameters:**

* \_code (bytes8): Referral code (may affect fee)
* \_toHolder (address): Recipient of benefits or NFT holder (lifetime case)
* \_mul (uint256): Multiplier for repeated fee payments
* \_lockToChainIds (uint256\[], memory): Destination chain IDs to lock the Lifetime NFT
* \_crossChainFees (uint256\[], memory): Native fees per chain, or zeros to auto-quote

**Returns:**

* returnValue (uint256): Refunded remainder (in wei)

**Modifiers / Visibility / Mutability:**

* external payable

**Access Control:**

* Unrestricted

**Side Effects:**

* Forwards ETH to [`feeRegistry`](https://docs.cryptolegacy.app/documentation/data-structures-reference#feeregistry-clbm1-d1)
* May mint and lock a Lifetime NFT
* Approves [`feeRegistry`](https://docs.cryptolegacy.app/documentation/data-structures-reference#feeregistry-clbm1-d1) to transfer the minted Lifetime NFT
* May refund unused ETH

**Emits:** None

**Reverts if:**

* Insufficient `msg.value` for computed fee — [`IncorrectFee(uint256)`](https://docs.cryptolegacy.app/documentation/errors-reference#incorrectfee-iclbm1)
* [`feeRegistry.getContractCaseFeeForCode(...)`](https://docs.cryptolegacy.app/documentation/data-structures-reference#feeregistry-clbm1-d1) — may revert with [`TooBigPct()`](https://docs.cryptolegacy.app/documentation/errors-reference#toobigpct-ifr1) (bubbled)
* [`feeRegistry.takeFee(...)`](https://docs.cryptolegacy.app/documentation/data-structures-reference#feeregistry-clbm1-d1) — may revert per FeeRegistry implementation (bubbled)
* [`lifetimeNft.mint(...)`](https://docs.cryptolegacy.app/documentation/data-structures-reference#lifetimenft-clbm1-d4) — may revert per token implementation (bubbled)
* [`lifetimeNft.approve(...)`](https://docs.cryptolegacy.app/documentation/data-structures-reference#lifetimenft-clbm1-d4) — may revert per token implementation (bubbled)
* `ILockChainGate.lockLifetimeNft(...)` — may revert per LockChainGate implementation (bubbled)
* Refund to `msg.sender` fails — [`TransferFeeFailed(bytes)`](https://docs.cryptolegacy.app/documentation/errors-reference#transferfeefailed-iclbm1)

**Overrides:** None

**Function Calls:**

* [\_payFee(bytes8,address,uint8,uint256,uint256,uint256\[\],uint256\[\])](#_payfee-clbm1) — CryptoLegacyBuildManager, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1); lifetime path is O(n) by `_lockToChainIds.length`.

**Example:** User pays an update fee with referral:

```solidity
buildManager.payFee{value: msg.value}(code, user, 1, chains, fees);
```

***

### \_payFee (CLBM1)

**Contract/Library:** CryptoLegacyBuildManager

**Description:** Internal fee engine for build/update/lifetime fees, handling payment and optional NFT mint/lock.

**Detailed Description:** Computes `curValue = msg.value - _subValue`. Reads `feeToTake` for `_feeCase` and `lifetimeFee`. If `lifetimeFee > 0` and `curValue >= lifetimeFee`, switches `_feeCase` to lifetime and sets `_mul = 1`. Verifies sufficiency via [`_checkFee`](#_checkfee-clbm1). Forwards `feeToTake` to [`feeRegistry.takeFee`](https://docs.cryptolegacy.app/documentation/data-structures-reference#feeregistry-clbm1-d1). Computes `restValue = curValue - feeToTake`. If lifetime case, calls [`_mintAndLockLifetimeNft`](#_mintandlocklifetimenft-clbm1) and updates `restValue`. Finally refunds any remainder via [`_returnFee`](#_returnfee-clbm1) and returns `restValue`.

**Parameters:**

* \_code (bytes8): Referral code
* \_toHolder (address): Recipient/holder for lifetime NFT case
* \_feeCase (uint8): REGISTRY\_BUILD\_CASE | REGISTRY\_UPDATE\_CASE | REGISTRY\_LIFETIME\_CASE
* \_mul (uint256): Multiplier
* \_subValue (uint256): Value to subtract from msg.value before fee logic
* \_chainIds (uint256\[], memory): Chain IDs for locking
* \_crossChainFees (uint256\[], memory): Native fees per chain (or zeros)

**Returns:**

* restValue (uint256): Final remainder in wei (after fee and optional locking)

**Modifiers / Visibility / Mutability:**

* internal nonpayable

**Access Control:**

* Unrestricted

**Side Effects:**

* Forwards ETH to [`feeRegistry`](https://docs.cryptolegacy.app/documentation/data-structures-reference#feeregistry-clbm1-d1)
* May mint and lock a Lifetime NFT
* Approves [`feeRegistry`](https://docs.cryptolegacy.app/documentation/data-structures-reference#feeregistry-clbm1-d1) to transfer the minted Lifetime NFT
* May refund unused ETH

**Emits:** None

**Reverts if:**

* [`feeRegistry.getContractCaseFeeForCode(...)`](https://docs.cryptolegacy.app/documentation/data-structures-reference#feeregistry-clbm1-d1) — may revert with [`TooBigPct()`](https://docs.cryptolegacy.app/documentation/errors-reference#toobigpct-ifr1) (bubbled)
* `msg.value - _subValue < feeToTake` — [`IncorrectFee(uint256)`](https://docs.cryptolegacy.app/documentation/errors-reference#incorrectfee-iclbm1)
* [`feeRegistry.takeFee(...)`](https://docs.cryptolegacy.app/documentation/data-structures-reference#feeregistry-clbm1-d1) — may revert with [`IncorrectFee(uint256)`](https://docs.cryptolegacy.app/documentation/errors-reference#incorrectfee-iclbm1) or [`TooBigPct()`](https://docs.cryptolegacy.app/documentation/errors-reference#toobigpct-ifr1) (bubbled)
* [`lifetimeNft.mint(...)`](https://docs.cryptolegacy.app/documentation/data-structures-reference#lifetimenft-clbm1-d4) — may revert per token implementation (bubbled)
* [`lifetimeNft.approve(...)`](https://docs.cryptolegacy.app/documentation/data-structures-reference#lifetimenft-clbm1-d4) — may revert per token implementation (bubbled)
* `ILockChainGate.lockLifetimeNft(...)` — may revert with `"ERC721: transfer from incorrect owner"` or per ERC721 implementation, [`AlreadyLocked()`](https://docs.cryptolegacy.app/documentation/errors-reference#alreadylocked-ilcg1), [`ArrayLengthMismatch()`](https://docs.cryptolegacy.app/documentation/errors-reference#arraylengthmismatch-ilcg1), [`CrossChainLock()`](https://docs.cryptolegacy.app/documentation/errors-reference#crosschainlock-ilcg1), [`DestinationChainNotSpecified()`](https://docs.cryptolegacy.app/documentation/errors-reference#destinationchainnotspecified-ilcg1), [`AlreadyLockedToChain()`](https://docs.cryptolegacy.app/documentation/errors-reference#alreadylockedtochain-ilcg1), [`IncorrectFee(uint256)`](https://docs.cryptolegacy.app/documentation/errors-reference#incorrectfee-iclbm1), or [`TransferFeeFailed(bytes)`](https://docs.cryptolegacy.app/documentation/errors-reference#transferfeefailed-iclbm1) (bubbled)
* Refund to `msg.sender` fails — [`TransferFeeFailed(bytes)`](https://docs.cryptolegacy.app/documentation/errors-reference#transferfeefailed-iclbm1)

**Overrides:** None

**Function Calls:**

* [getContractCaseFeeForCode(address,uint8,bytes8)](#getcontractcasefeeforcode-fr1) — IFeeRegistry *(at* [*`feeRegistry`*](https://docs.cryptolegacy.app/documentation/data-structures-reference#feeregistry-clbm1-d1)*)*, external (staticcall)
* [getContractCaseFeeForCode(address,uint8,bytes8)](#getcontractcasefeeforcode-fr1) — IFeeRegistry *(at* [*`feeRegistry`*](https://docs.cryptolegacy.app/documentation/data-structures-reference#feeregistry-clbm1-d1)*)*, external (staticcall)
* [\_checkFee(uint256,uint256)](#_checkfee-clbm1) — CryptoLegacyBuildManager, internal
* [takeFee(address,uint8,bytes8,uint256)](#takefee-fr1) — IFeeRegistry *(at* [*`feeRegistry`*](https://docs.cryptolegacy.app/documentation/data-structures-reference#feeregistry-clbm1-d1)*)*, external
* [\_mintAndLockLifetimeNft(address,uint256\[\],uint256\[\],uint256)](#_mintandlocklifetimenft-clbm1) — CryptoLegacyBuildManager, internal
* [\_returnFee(uint256)](#_returnfee-clbm1) — CryptoLegacyBuildManager, internal

**Called by:**

* [payFee](#payfee-clbm1) — CryptoLegacyBuildManager
* [payInitialFee](#payinitialfee-clbm1) — CryptoLegacyBuildManager
* [\_getAndPayBuildFee(bytes8,uint256,uint256\[\],uint256\[\])](#_getandpaybuildfee-clbm1) — CryptoLegacyBuildManager

**Gas / Complexity note:** O(1); lifetime path is O(n) by `_chainIds.length`.

**Example:** Not applicable

***

### \_returnFee (CLBM1)

**Contract/Library:** CryptoLegacyBuildManager

**Description:** Refund helper to return surplus ETH to the caller.

**Detailed Description:** If `_returnValue > 0`, performs a low-level call to `msg.sender` transferring `_returnValue`. Reverts with `TransferFeeFailed(data)` if the refund fails.

**Parameters:**

* \_returnValue (uint256): Amount to refund in wei

**Returns:** None

**Modifiers / Visibility / Mutability:**

* internal nonpayable

**Access Control:**

* Unrestricted

**Side Effects:**

* Transfers ETH to `msg.sender`

**Emits:** None

**Reverts if:**

* Low-level refund to `msg.sender` fails — [`TransferFeeFailed(bytes)`](https://docs.cryptolegacy.app/documentation/errors-reference#transferfeefailed-iclbm1)

**Overrides:** None

**Function Calls:**

* `payable(msg.sender).call(bytes)` — address *(at `msg.sender`)*, external

**Called by:**

* [\_payFee](#_payfee-clbm1) — CryptoLegacyBuildManager
* [createCustomRef](#createcustomref-clbm1) — CryptoLegacyBuildManager
* [createRef](#createref-clbm1) — CryptoLegacyBuildManager
* [updateCrossChainsRef(uint256\[\],uint256\[\])](#updatecrosschainsref-clbm1) — CryptoLegacyBuildManager

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### \_checkFee (CLBM1)

**Contract/Library:** CryptoLegacyBuildManager

**Description:** Validates that `_value` covers `_fee`.

**Detailed Description:** Pure check that reverts with `IncorrectFee(_fee)` if `_value < _fee`.

**Parameters:**

* \_value (uint256): Provided value
* \_fee (uint256): Required fee

**Returns:** None

**Modifiers / Visibility / Mutability:**

* internal pure

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:**

* \_value < \_fee — [`IncorrectFee(uint256)`](https://docs.cryptolegacy.app/documentation/errors-reference#incorrectfee-iclbm1)

**Overrides:** None

**Function Calls:** None

**Called by:**

* [\_payFee](#_payfee-clbm1) — CryptoLegacyBuildManager
* [payForMultipleLifetimeNft](#payformultiplelifetimenft-clbm1) — CryptoLegacyBuildManager
* [\_createCustomRef](#_createcustomref-clbm1) — CryptoLegacyBuildManager
* [\_createRef](#_createref-clbm1) — CryptoLegacyBuildManager
* [updateCrossChainsRef(uint256\[\],uint256\[\])](#updatecrosschainsref-clbm1) — CryptoLegacyBuildManager

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### \_mintAndLockLifetimeNft (CLBM1)

**Contract/Library:** CryptoLegacyBuildManager

**Description:** Mints a Lifetime NFT to this contract, approves the registry, and locks it cross-chain.

**Detailed Description:** Mints a new NFT via [`lifetimeNft.mint(address(this))`](https://docs.cryptolegacy.app/documentation/data-structures-reference#lifetimenft-clbm1-d4), approves [`feeRegistry`](https://docs.cryptolegacy.app/documentation/data-structures-reference#feeregistry-clbm1-d1) for the token, then calls the lock-gate to lock the token to `_tokenOwner` across `_chainIds` using `_crossChainFees`, forwarding `_valueToSend`. Returns the remainder from the lock call.

**Parameters:**

* \_tokenOwner (address): Final owner to which the locked NFT is attributed
* \_chainIds (uint256\[], memory): Destination chain IDs
* \_crossChainFees (uint256\[], memory): Per-chain native fees
* \_valueToSend (uint256): ETH to forward with the lock call

**Returns:**

* returnValue (uint256): Unused ETH returned from the lock call

**Modifiers / Visibility / Mutability:**

* internal nonpayable

**Access Control:**

* Unrestricted

**Side Effects:**

* Mints ERC-721 to this contract
* Approves [`feeRegistry`](https://docs.cryptolegacy.app/documentation/data-structures-reference#feeregistry-clbm1-d1) for `tokenId`
* Transfers ERC-721 from this contract to [`feeRegistry`](https://docs.cryptolegacy.app/documentation/data-structures-reference#feeregistry-clbm1-d1) (LockChainGate)
* Forwards ETH to lock-gate (external state change)

**Emits:** None

**Reverts if:**

* [`lifetimeNft.mint(address)`](https://docs.cryptolegacy.app/documentation/data-structures-reference#lifetimenft-clbm1-d4) — may revert per token implementation (bubbled)
* [`lifetimeNft.approve(address,uint256)`](https://docs.cryptolegacy.app/documentation/data-structures-reference#lifetimenft-clbm1-d4) — may revert per token implementation (bubbled)
* `ILockChainGate.lockLifetimeNft(...)` — may revert with `"ERC721: transfer from incorrect owner"` or per ERC721 implementation, [`AlreadyLocked()`](https://docs.cryptolegacy.app/documentation/errors-reference#alreadylocked-ilcg1), [`ArrayLengthMismatch()`](https://docs.cryptolegacy.app/documentation/errors-reference#arraylengthmismatch-ilcg1), [`CrossChainLock()`](https://docs.cryptolegacy.app/documentation/errors-reference#crosschainlock-ilcg1), [`DestinationChainNotSpecified()`](https://docs.cryptolegacy.app/documentation/errors-reference#destinationchainnotspecified-ilcg1), [`AlreadyLockedToChain()`](https://docs.cryptolegacy.app/documentation/errors-reference#alreadylockedtochain-ilcg1), [`IncorrectFee(uint256)`](https://docs.cryptolegacy.app/documentation/errors-reference#incorrectfee-iclbm1), or [`TransferFeeFailed(bytes)`](https://docs.cryptolegacy.app/documentation/errors-reference#transferfeefailed-iclbm1) (bubbled)

**Overrides:** None

**Function Calls:**

* [mint(address)](#mint-iln1) — ILifetimeNft *(at* [*`lifetimeNft`*](https://docs.cryptolegacy.app/documentation/data-structures-reference#lifetimenft-clbm1-d4)*)*, external
* `approve(address,uint256)` — ILifetimeNft *(at* [*`lifetimeNft`*](https://docs.cryptolegacy.app/documentation/data-structures-reference#lifetimenft-clbm1-d4)*)*, external
* [lockLifetimeNft(uint256,address,uint256\[\],uint256\[\])](#locklifetimenft-lcg1) — ILockChainGate *(at* [*`feeRegistry`*](https://docs.cryptolegacy.app/documentation/data-structures-reference#feeregistry-clbm1-d1)*)*, external

**Called by:**

* [\_payFee](#_payfee-clbm1) — CryptoLegacyBuildManager

**Gas / Complexity note:** O(1); lock call is O(n) by `_chainIds.length`.

**Example:** Not applicable

***

### payInitialFee (CLBM1)

**Contract/Library:** CryptoLegacyBuildManager

**Description:** Pays the initial build fee (or lifetime) and optionally locks a Lifetime NFT.

**Detailed Description:** Delegates to [`_payFee`](#_payfee-clbm1) with [`REGISTRY_BUILD_CASE`](https://docs.cryptolegacy.app/documentation/data-structures-reference#registry_build_case-clbm1-d8). `_payFee` determines the applicable fee, forwards it to [`feeRegistry`](https://docs.cryptolegacy.app/documentation/data-structures-reference#feeregistry-clbm1-d1), optionally mints/locks a Lifetime NFT, and refunds any remainder.

**Parameters:**

* \_code (bytes8): Referral code (build case)
* \_toHolder (address): Recipient of NFT if lifetime case is chosen
* \_lockToChainIds (uint256\[], memory): Chains to lock to
* \_crossChainFees (uint256\[], memory): Native fees per chain

**Returns:**

* returnValue (uint256): Refunded remainder (in wei)

**Modifiers / Visibility / Mutability:**

* public payable

**Access Control:**

* Unrestricted

**Side Effects:**

* Forwards ETH to [`feeRegistry`](https://docs.cryptolegacy.app/documentation/data-structures-reference#feeregistry-clbm1-d1)
* May mint & lock Lifetime NFT
* May refund unused ETH

**Emits:** None

**Reverts if:**

* Insufficient `msg.value` for required build/lifetime fee — [`IncorrectFee(uint256)`](https://docs.cryptolegacy.app/documentation/errors-reference#incorrectfee-iclbm1)
* [`feeRegistry.getContractCaseFeeForCode(...)`](https://docs.cryptolegacy.app/documentation/data-structures-reference#feeregistry-clbm1-d1) — may revert with [`TooBigPct()`](https://docs.cryptolegacy.app/documentation/errors-reference#toobigpct-ifr1) (bubbled)
* [`feeRegistry.takeFee(...)`](https://docs.cryptolegacy.app/documentation/data-structures-reference#feeregistry-clbm1-d1) — may revert with [`IncorrectFee(uint256)`](https://docs.cryptolegacy.app/documentation/errors-reference#incorrectfee-iclbm1) or [`TooBigPct()`](https://docs.cryptolegacy.app/documentation/errors-reference#toobigpct-ifr1) (bubbled)
* [`lifetimeNft.mint(...)`](https://docs.cryptolegacy.app/documentation/data-structures-reference#lifetimenft-clbm1-d4) — may revert per token implementation (bubbled)
* [`lifetimeNft.approve(...)`](https://docs.cryptolegacy.app/documentation/data-structures-reference#lifetimenft-clbm1-d4) — may revert per token implementation (bubbled)
* `ILockChainGate.lockLifetimeNft(...)` — may revert with `"ERC721: transfer from incorrect owner"` or per ERC721 implementation, [`AlreadyLocked()`](https://docs.cryptolegacy.app/documentation/errors-reference#alreadylocked-ilcg1), [`ArrayLengthMismatch()`](https://docs.cryptolegacy.app/documentation/errors-reference#arraylengthmismatch-ilcg1), [`CrossChainLock()`](https://docs.cryptolegacy.app/documentation/errors-reference#crosschainlock-ilcg1), [`DestinationChainNotSpecified()`](https://docs.cryptolegacy.app/documentation/errors-reference#destinationchainnotspecified-ilcg1), [`AlreadyLockedToChain()`](https://docs.cryptolegacy.app/documentation/errors-reference#alreadylockedtochain-ilcg1), [`IncorrectFee(uint256)`](https://docs.cryptolegacy.app/documentation/errors-reference#incorrectfee-iclbm1), or [`TransferFeeFailed(bytes)`](https://docs.cryptolegacy.app/documentation/errors-reference#transferfeefailed-iclbm1) (bubbled)
* Refund to `msg.sender` fails — [`TransferFeeFailed(bytes)`](https://docs.cryptolegacy.app/documentation/errors-reference#transferfeefailed-iclbm1)

**Overrides:** ICryptoLegacyBuildManager

**Function Calls:**

* [\_payFee(bytes8,address,uint8,uint256,uint256,uint256\[\],uint256\[\])](#_payfee-clbm1) — CryptoLegacyBuildManager, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:**

```solidity
buildManager.payInitialFee{value: msg.value}(code, user, chains, fees);
```

***

### payForMultipleLifetimeNft (CLBM1)

**Contract/Library:** CryptoLegacyBuildManager

**Description:** Mass mints Lifetime NFTs when supply threshold is met.

**Detailed Description:** Requires [`lifetimeNft.totalSupply() >= minMassMintSupply`](https://docs.cryptolegacy.app/documentation/data-structures-reference#lifetimenft-clbm1-d4). Fetches `lifetimeFee`, checks `msg.value >= lifetimeFee`. Computes `totalAmount = msg.value / lifetimeFee` and forwards the full value to [`feeRegistry.takeFee`](https://docs.cryptolegacy.app/documentation/data-structures-reference#feeregistry-clbm1-d1). Iterates `_lifetimeNftMints`; for each entry, mints `amount` NFTs to `toHolder`, emitting `PaidForMint` per mint. Ensures `mintAmount == totalAmount`, otherwise reverts `IncorrectFee(uint256)`. Emits `PaidForMultipleNft` at end.

**Parameters:**

* \_code (bytes8): Referral code influencing lifetime fee
* \_lifetimeNftMints ([LifetimeNftMint](https://docs.cryptolegacy.app/documentation/data-structures-reference#lifetimenftmint-iclbm1-s3)\[], memory): Recipients and per-recipient mint counts

**Returns:** None

**Modifiers / Visibility / Mutability:**

* public payable

**Access Control:**

* Unrestricted

**Side Effects:**

* Forwards `msg.value` to [`feeRegistry.takeFee`](https://docs.cryptolegacy.app/documentation/data-structures-reference#feeregistry-clbm1-d1)
* Mints multiple ERC-721 tokens to recipients

**Emits:**

* [PaidForMint](https://docs.cryptolegacy.app/documentation/events-reference#paidformint-iclbm1) — `PaidForMint(address indexed sender, uint256 indexed tokenId, address indexed toHolder)`
* [PaidForMultipleNft](https://docs.cryptolegacy.app/documentation/events-reference#paidformultiplenft-iclbm1) — `PaidForMultipleNft(address indexed sender, bytes8 indexed code, uint256 value, uint256 totalAmount)`

**Reverts if:**

* [`lifetimeNft.totalSupply() < minMassMintSupply`](https://docs.cryptolegacy.app/documentation/data-structures-reference#lifetimenft-clbm1-d4) — [`BelowMinimumSupply(uint256)`](https://docs.cryptolegacy.app/documentation/errors-reference#belowminimumsupply-iclbm1)
* [`feeRegistry.getContractCaseFeeForCode(...)`](https://docs.cryptolegacy.app/documentation/data-structures-reference#feeregistry-clbm1-d1) — may revert with [`TooBigPct()`](https://docs.cryptolegacy.app/documentation/errors-reference#toobigpct-ifr1) (bubbled)
* `msg.value < lifetimeFee` — [`IncorrectFee(uint256)`](https://docs.cryptolegacy.app/documentation/errors-reference#incorrectfee-iclbm1)
* [`feeRegistry.takeFee(...)`](https://docs.cryptolegacy.app/documentation/data-structures-reference#feeregistry-clbm1-d1) — may revert with [`IncorrectFee(uint256)`](https://docs.cryptolegacy.app/documentation/errors-reference#incorrectfee-iclbm1) or [`TooBigPct()`](https://docs.cryptolegacy.app/documentation/errors-reference#toobigpct-ifr1) (bubbled)
* [`lifetimeNft.mint(...)`](https://docs.cryptolegacy.app/documentation/data-structures-reference#lifetimenft-clbm1-d4) — may revert per token implementation (bubbled)
* `mintAmount != totalAmount` — [`IncorrectFee(uint256)`](https://docs.cryptolegacy.app/documentation/errors-reference#incorrectfee-iclbm1)

**Overrides:** None

**Function Calls:**

* [`lifetimeNft.totalSupply()`](https://docs.cryptolegacy.app/documentation/data-structures-reference#lifetimenft-clbm1-d4) — ILifetimeNft, external (staticcall)
* [getContractCaseFeeForCode(address,uint8,bytes8)](#getcontractcasefeeforcode-fr1) — IFeeRegistry, external (staticcall)
* [\_checkFee(uint256,uint256)](#_checkfee-clbm1) — CryptoLegacyBuildManager, internal
* [takeFee(address,uint8,bytes8,uint256)](#takefee-fr1) — IFeeRegistry, external
* [mint(address)](#mint-iln1) — ILifetimeNft *(at* [*`lifetimeNft`*](https://docs.cryptolegacy.app/documentation/data-structures-reference#lifetimenft-clbm1-d4)*)*, external

**Called by:** None (entry point)

**Gas / Complexity note:** O(T) where `T = sum(_lifetimeNftMintsi.amount)`

**Example:**

```solidity
ICryptoLegacyBuildManager.LifetimeNftMint[] memory batch = new ICryptoLegacyBuildManager.LifetimeNftMint[](1);
batch[0] = ICryptoLegacyBuildManager.LifetimeNftMint({toHolder: user, amount: 2});
buildManager.payForMultipleLifetimeNft{value: msg.value}(code, batch);
```

***

### createCustomRef (CLBM1)

**Contract/Library:** CryptoLegacyBuildManager

**Description:** Creates a custom referral code and optionally locks it cross-chain; refunds any surplus.

**Detailed Description:** Delegates to internal [`_createCustomRef`](#_createcustomref-clbm1) that validates and pays cross-chain fees, then refunds any remainder via [`_returnFee`](#_returnfee-clbm1).

**Parameters:**

* \_customRefCode (bytes8): Desired custom referral code
* \_recipient (address): Address receiving referral benefits
* \_chainIds (uint256\[], memory): Destination chains (optional)
* \_crossChainFees (uint256\[], memory): Per-chain native fees (or zeros)

**Returns:**

* refCode (bytes8): Created/assigned code
* crossChainFee (uint256): Total native fee used
* returnValue (uint256): Refunded remainder

**Modifiers / Visibility / Mutability:**

* public payable

**Access Control:**

* Unrestricted

**Side Effects:**

* Forwards ETH to [`feeRegistry`](https://docs.cryptolegacy.app/documentation/data-structures-reference#feeregistry-clbm1-d1) (via `_createCustomRef`)
* May refund unused ETH to `msg.sender`

**Emits:**

* [CreateCustomRef](https://docs.cryptolegacy.app/documentation/events-reference#createcustomref-iclbm1) — `CreateCustomRef(address indexed sender, bytes8 indexed refCode, address indexed recipient, uint256[] chainIds)`

**Reverts if:**

* `msg.value < valueToSend` — [`IncorrectFee(uint256)`](https://docs.cryptolegacy.app/documentation/errors-reference#incorrectfee-iclbm1)
* [`feeRegistry.createCustomCode(...)`](https://docs.cryptolegacy.app/documentation/data-structures-reference#feeregistry-clbm1-d1) — may revert with [`NotOperator()`](https://docs.cryptolegacy.app/documentation/errors-reference#notoperator-ifr1), [`RefAlreadyCreated()`](https://docs.cryptolegacy.app/documentation/errors-reference#refalreadycreated-ifr1), [`ZeroCode()`](https://docs.cryptolegacy.app/documentation/errors-reference#zerocode-ifr1), [`AlreadyReferrer()`](https://docs.cryptolegacy.app/documentation/errors-reference#alreadyreferrer-ifr1), [`ArrayLengthMismatch()`](https://docs.cryptolegacy.app/documentation/errors-reference#arraylengthmismatch-ilcg1), [`DestinationChainNotSpecified()`](https://docs.cryptolegacy.app/documentation/errors-reference#destinationchainnotspecified-ilcg1), or [`TransferFeeFailed(bytes)`](https://docs.cryptolegacy.app/documentation/errors-reference#transferfeefailed-iclbm1) (bubbled)
* Refund to `msg.sender` fails — [`TransferFeeFailed(bytes)`](https://docs.cryptolegacy.app/documentation/errors-reference#transferfeefailed-iclbm1)

**Overrides:** None

**Function Calls:**

* [\_createCustomRef(bytes8,address,uint256\[\],uint256\[\])](#_createcustomref-clbm1) — CryptoLegacyBuildManager, internal
* [\_returnFee(uint256)](#_returnfee-clbm1) — CryptoLegacyBuildManager, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(n) by `_crossChainFees.length`

**Example:**

```solidity
(bytes8 code,,) = buildManager.createCustomRef{value: msg.value}(wantedCode, refRecipient, chains, fees);
```

***

### \_createCustomRef (CLBM1)

**Contract/Library:** CryptoLegacyBuildManager

**Description:** Internal custom-ref creation with cross-chain fee handling.

**Detailed Description:** Computes `valueToSend` via [`calculateCrossChainCreateRefFee`](#calculatecrosschaincreatereffee-clbm1). Ensures sufficiency using [`_checkFee`](#_checkfee-clbm1). Calls [`feeRegistry.createCustomCode{value: valueToSend}`](https://docs.cryptolegacy.app/documentation/data-structures-reference#feeregistry-clbm1-d1) and emits `CreateCustomRef`. Returns `(refCode, crossChainFee, returnValue)` where `returnValue` combines unused local ETH and any refund from the registry.

**Parameters:**

* \_customRefCode (bytes8): Desired code
* \_recipient (address): Referral recipient
* \_chainIds (uint256\[], memory): Chains to enable
* \_crossChainFees (uint256\[], memory): Per-chain fees (or zeros to auto-quote)

**Returns:**

* refCode (bytes8): Resulting code
* crossChainFee (uint256): Total fee used
* returnValue (uint256): Surplus (local + registry refund)

**Modifiers / Visibility / Mutability:**

* internal nonpayable

**Access Control:**

* Unrestricted (internal)

**Side Effects:**

* Forwards ETH to [`feeRegistry.createCustomCode`](https://docs.cryptolegacy.app/documentation/data-structures-reference#feeregistry-clbm1-d1)
* Receives any refund from [`feeRegistry`](https://docs.cryptolegacy.app/documentation/data-structures-reference#feeregistry-clbm1-d1) (if returned)

**Emits:**

* [CreateCustomRef](https://docs.cryptolegacy.app/documentation/events-reference#createcustomref-iclbm1) — `CreateCustomRef(address indexed sender, bytes8 indexed refCode, address indexed recipient, uint256[] chainIds)`

**Reverts if:**

* `msg.value < valueToSend` — [`IncorrectFee(uint256)`](https://docs.cryptolegacy.app/documentation/errors-reference#incorrectfee-iclbm1)
* [`feeRegistry.createCustomCode(...)`](https://docs.cryptolegacy.app/documentation/data-structures-reference#feeregistry-clbm1-d1) — may revert with [`NotOperator()`](https://docs.cryptolegacy.app/documentation/errors-reference#notoperator-ifr1), [`RefAlreadyCreated()`](https://docs.cryptolegacy.app/documentation/errors-reference#refalreadycreated-ifr1), [`ZeroCode()`](https://docs.cryptolegacy.app/documentation/errors-reference#zerocode-ifr1), [`AlreadyReferrer()`](https://docs.cryptolegacy.app/documentation/errors-reference#alreadyreferrer-ifr1), [`ArrayLengthMismatch()`](https://docs.cryptolegacy.app/documentation/errors-reference#arraylengthmismatch-ilcg1), [`DestinationChainNotSpecified()`](https://docs.cryptolegacy.app/documentation/errors-reference#destinationchainnotspecified-ilcg1), or [`TransferFeeFailed(bytes)`](https://docs.cryptolegacy.app/documentation/errors-reference#transferfeefailed-iclbm1) (bubbled)

**Overrides:** None

**Function Calls:**

* [calculateCrossChainCreateRefFee(uint256\[\],uint256\[\])](#calculatecrosschaincreatereffee-clbm1) — CryptoLegacyBuildManager, internal
* [\_checkFee(uint256,uint256)](#_checkfee-clbm1) — CryptoLegacyBuildManager, internal
* [createCustomCode(address,address,bytes8,uint256\[\],uint256\[\])](#createcustomcode-fr1) — IFeeRegistry, external

**Called by:**

* [createCustomRef](#createcustomref-clbm1) — CryptoLegacyBuildManager
* [\_createRefAndPayForBuild](#_createrefandpayforbuild-clbm1) — CryptoLegacyBuildManager

**Gas / Complexity note:** O(n) by `_crossChainFees.length`

**Example:** Not applicable

***

### createRef (CLBM1)

**Contract/Library:** CryptoLegacyBuildManager

**Description:** Creates a short referral code and optionally locks it cross-chain; refunds surplus.

**Detailed Description:** Delegates to internal [`_createRef`](#_createref-clbm1) that validates/forwards cross-chain fees and returns surplus, which is refunded via [`_returnFee`](#_returnfee-clbm1).

**Parameters:**

* \_recipient (address): Referral recipient
* \_chainIds (uint256\[], memory): Destination chains
* \_crossChainFees (uint256\[], memory): Per-chain native fees (or zeros)

**Returns:**

* refCode (bytes8): New short code
* crossChainFee (uint256): Total fee used
* returnValue (uint256): Refunded remainder

**Modifiers / Visibility / Mutability:**

* public payable

**Access Control:**

* Unrestricted

**Side Effects:**

* Forwards ETH to [`feeRegistry`](https://docs.cryptolegacy.app/documentation/data-structures-reference#feeregistry-clbm1-d1)
* Updates referral state in [`feeRegistry`](https://docs.cryptolegacy.app/documentation/data-structures-reference#feeregistry-clbm1-d1) (external)
* May refund ETH to `msg.sender` via [`_returnFee`](#_returnfee-clbm1)

**Emits:**

* [CreateRef](https://docs.cryptolegacy.app/documentation/events-reference#createref-iclbm1) — `CreateRef(address indexed sender, bytes8 indexed refCode, address indexed recipient, uint256[] chainIds)`

**Reverts if:**

* `_crossChainFees` empty or contains zeros — `ILockChainGate(feeRegistry).calculateCrossChainCreateRefNativeFee(...)` may revert per implementation (bubbled)
* `msg.value < valueToSend` — [`IncorrectFee(uint256)`](https://docs.cryptolegacy.app/documentation/errors-reference#incorrectfee-iclbm1)
* [`feeRegistry.createCode(...)`](https://docs.cryptolegacy.app/documentation/data-structures-reference#feeregistry-clbm1-d1) — may revert with [`NotOperator()`](https://docs.cryptolegacy.app/documentation/errors-reference#notoperator-ifr1), [`RefAlreadyCreated()`](https://docs.cryptolegacy.app/documentation/errors-reference#refalreadycreated-ifr1), [`ZeroCode()`](https://docs.cryptolegacy.app/documentation/errors-reference#zerocode-ifr1), [`AlreadyReferrer()`](https://docs.cryptolegacy.app/documentation/errors-reference#alreadyreferrer-ifr1), [`ArrayLengthMismatch()`](https://docs.cryptolegacy.app/documentation/errors-reference#arraylengthmismatch-ilcg1), [`DestinationChainNotSpecified()`](https://docs.cryptolegacy.app/documentation/errors-reference#destinationchainnotspecified-ilcg1), [`IncorrectFee(uint256)`](https://docs.cryptolegacy.app/documentation/errors-reference#incorrectfee-iclbm1), or [`TransferFeeFailed(bytes)`](https://docs.cryptolegacy.app/documentation/errors-reference#transferfeefailed-iclbm1) (bubbled)
* refund to caller fails — [`TransferFeeFailed(bytes)`](https://docs.cryptolegacy.app/documentation/errors-reference#transferfeefailed-iclbm1)

**Overrides:** None

**Function Calls:**

* [\_createRef(address,uint256\[\],uint256\[\])](#_createref-clbm1) — CryptoLegacyBuildManager, internal
* [\_returnFee(uint256)](#_returnfee-clbm1) — CryptoLegacyBuildManager, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(n) by `_crossChainFees.length`

**Example:**

```solidity
(bytes8 code,,) = buildManager.createRef{value: msg.value}(recipient, chains, fees);
```

***

### \_createRef (CLBM1)

**Contract/Library:** CryptoLegacyBuildManager

**Description:** Internal short-ref creation with cross-chain fee handling.

**Detailed Description:** Computes `valueToSend` via [`calculateCrossChainCreateRefFee`](#calculatecrosschaincreatereffee-clbm1). Ensures sufficiency via [`_checkFee`](#_checkfee-clbm1). Calls [`feeRegistry.createCode{value: valueToSend}`](https://docs.cryptolegacy.app/documentation/data-structures-reference#feeregistry-clbm1-d1) and emits `CreateRef`. Returns `(refCode, crossChainFee, returnValue)` combining local surplus and any registry refund.

**Parameters:**

* \_recipient (address): Referral recipient
* \_chainIds (uint256\[], memory): Chains to enable
* \_crossChainFees (uint256\[], memory): Per-chain fees or zeros

**Returns:**

* refCode (bytes8): Resulting short code
* crossChainFee (uint256): Total fee used
* returnValue (uint256): Surplus (local + registry refund)

**Modifiers / Visibility / Mutability:**

* internal nonpayable

**Access Control:**

* Unrestricted (internal)

**Side Effects:**

* Forwards ETH to [`feeRegistry`](https://docs.cryptolegacy.app/documentation/data-structures-reference#feeregistry-clbm1-d1)
* Updates referral state in [`feeRegistry`](https://docs.cryptolegacy.app/documentation/data-structures-reference#feeregistry-clbm1-d1) (external)

**Emits:**

* [CreateRef](https://docs.cryptolegacy.app/documentation/events-reference#createref-iclbm1) — `CreateRef(address indexed sender, bytes8 indexed refCode, address indexed recipient, uint256[] chainIds)`

**Reverts if:**

* `_crossChainFees` empty or contains zeros — `ILockChainGate(feeRegistry).calculateCrossChainCreateRefNativeFee(...)` may revert per implementation (bubbled)
* `msg.value < valueToSend` — [`IncorrectFee(uint256)`](https://docs.cryptolegacy.app/documentation/errors-reference#incorrectfee-iclbm1)
* [`feeRegistry.createCode(...)`](https://docs.cryptolegacy.app/documentation/data-structures-reference#feeregistry-clbm1-d1) — may revert with [`NotOperator()`](https://docs.cryptolegacy.app/documentation/errors-reference#notoperator-ifr1), [`RefAlreadyCreated()`](https://docs.cryptolegacy.app/documentation/errors-reference#refalreadycreated-ifr1), [`ZeroCode()`](https://docs.cryptolegacy.app/documentation/errors-reference#zerocode-ifr1), [`AlreadyReferrer()`](https://docs.cryptolegacy.app/documentation/errors-reference#alreadyreferrer-ifr1), [`ArrayLengthMismatch()`](https://docs.cryptolegacy.app/documentation/errors-reference#arraylengthmismatch-ilcg1), [`DestinationChainNotSpecified()`](https://docs.cryptolegacy.app/documentation/errors-reference#destinationchainnotspecified-ilcg1), [`IncorrectFee(uint256)`](https://docs.cryptolegacy.app/documentation/errors-reference#incorrectfee-iclbm1), or [`TransferFeeFailed(bytes)`](https://docs.cryptolegacy.app/documentation/errors-reference#transferfeefailed-iclbm1) (bubbled)

**Overrides:** None

**Function Calls:**

* [calculateCrossChainCreateRefFee(uint256\[\],uint256\[\])](#calculatecrosschaincreatereffee-clbm1) — CryptoLegacyBuildManager, internal
* [\_checkFee(uint256,uint256)](#_checkfee-clbm1) — CryptoLegacyBuildManager, internal
* [createCode(address,address,uint256\[\],uint256\[\])](#createcode-fr1) — IFeeRegistry *(at* [*`feeRegistry`*](https://docs.cryptolegacy.app/documentation/data-structures-reference#feeregistry-clbm1-d1)*)*, external

**Called by:**

* [createRef](#createref-clbm1) — CryptoLegacyBuildManager
* [\_createRefAndPayForBuild](#_createrefandpayforbuild-clbm1) — CryptoLegacyBuildManager

**Gas / Complexity note:** O(n) by `_crossChainFees.length`

**Example:** Not applicable

***

### updateCrossChainsRef (CLBM1)

**Contract/Library:** CryptoLegacyBuildManager

**Description:** Updates chain coverage for the caller’s referral code.

**Detailed Description:** Computes cross-chain fee via [`calculateCrossChainCreateRefFee`](#calculatecrosschaincreatereffee-clbm1), ensures sufficiency via [`_checkFee`](#_checkfee-clbm1), updates chains via [`feeRegistry.updateCrossChainsRef{value: valueToSend}`](https://docs.cryptolegacy.app/documentation/data-structures-reference#feeregistry-clbm1-d1), emits `SetCrossChainsRef`, then refunds any `returnValue`.

**Parameters:**

* \_chainIds (uint256\[], memory): Destination chain IDs to set/update
* \_crossChainFees (uint256\[], memory): Per-chain native fees or zeros

**Returns:**

* crossChainFee (uint256): Total fee used
* returnValue (uint256): Refunded remainder

**Modifiers / Visibility / Mutability:**

* external payable

**Access Control:**

* Unrestricted

**Side Effects:**

* Forwards ETH to [`feeRegistry`](https://docs.cryptolegacy.app/documentation/data-structures-reference#feeregistry-clbm1-d1)
* Sends cross-chain update messages via [`feeRegistry`](https://docs.cryptolegacy.app/documentation/data-structures-reference#feeregistry-clbm1-d1)
* May refund ETH to `msg.sender` via [`_returnFee`](#_returnfee-clbm1)

**Emits:**

* [SetCrossChainsRef](https://docs.cryptolegacy.app/documentation/events-reference#setcrosschainsref-iclbm1) — `SetCrossChainsRef(address indexed sender, uint256[] chainIds)`

**Reverts if:**

* `_crossChainFees` empty or contains zeros — `ILockChainGate(feeRegistry).calculateCrossChainCreateRefNativeFee(...)` may revert per implementation (bubbled)
* `msg.value < valueToSend` — [`IncorrectFee(uint256)`](https://docs.cryptolegacy.app/documentation/errors-reference#incorrectfee-iclbm1)
* [`feeRegistry.updateCrossChainsRef(...)`](https://docs.cryptolegacy.app/documentation/data-structures-reference#feeregistry-clbm1-d1) — may revert with [`NotOperator()`](https://docs.cryptolegacy.app/documentation/errors-reference#notoperator-ifr1), [`CodeNotCreated()`](https://docs.cryptolegacy.app/documentation/errors-reference#codenotcreated-ifr1), [`ArrayLengthMismatch()`](https://docs.cryptolegacy.app/documentation/errors-reference#arraylengthmismatch-ilcg1), [`DestinationChainNotSpecified()`](https://docs.cryptolegacy.app/documentation/errors-reference#destinationchainnotspecified-ilcg1), [`IncorrectFee(uint256)`](https://docs.cryptolegacy.app/documentation/errors-reference#incorrectfee-iclbm1), or [`TransferFeeFailed(bytes)`](https://docs.cryptolegacy.app/documentation/errors-reference#transferfeefailed-iclbm1) (bubbled)
* refund to caller fails — [`TransferFeeFailed(bytes)`](https://docs.cryptolegacy.app/documentation/errors-reference#transferfeefailed-iclbm1)

**Overrides:** None

**Function Calls:**

* [calculateCrossChainCreateRefFee(uint256\[\],uint256\[\])](#calculatecrosschaincreatereffee-clbm1) — CryptoLegacyBuildManager, internal
* [\_checkFee(uint256,uint256)](#_checkfee-clbm1) — CryptoLegacyBuildManager, internal
* [updateCrossChainsRef(uint256\[\],uint256\[\])](#updatecrosschainsref-fr1) — IFeeRegistry *(at* [*`feeRegistry`*](https://docs.cryptolegacy.app/documentation/data-structures-reference#feeregistry-clbm1-d1)*)*, external
* [\_returnFee(uint256)](#_returnfee-clbm1) — CryptoLegacyBuildManager, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(n) by `_crossChainFees.length`

**Example:**

```solidity
(, uint256 refund) = buildManager.updateCrossChainsRef{value: msg.value}(chains, fees);
```

***

### \_createRefAndPayForBuild (CLBM1)

**Contract/Library:** CryptoLegacyBuildManager

**Description:** Internal helper to optionally create a referral and then obtain/pay the build fee.

**Detailed Description:** If `_refArgs.createRefRecipient != address(0)`, creates a referral:

* If `_refArgs.createRefCustomCode == 0`, calls [`_createRef`](#_createref-clbm1); otherwise calls [`_createCustomRef`](#_createcustomref-clbm1).
* Stores the spent cross-chain fee as `subValue`, then calls [`_getAndPayBuildFee`](#_getandpaybuildfee-clbm1) with `_buildArgs.invitedByRefCode` and `subValue`. Returns `initialFeeToPay` and `updateFee`.

**Parameters:**

* \_buildArgs ([BuildArgs](https://docs.cryptolegacy.app/documentation/data-structures-reference#buildargs-iclbm1-s1), memory): Build parameters (includes invitedByRefCode)
* \_refArgs ([RefArgs](https://docs.cryptolegacy.app/documentation/data-structures-reference#refargs-iclbm1-s2), memory): Referral creation parameters

**Returns:**

* initialFeeToPay (uint256): Initial build fee owed (0 if lifetime/locked)
* updateFee (uint256): Subsequent update fee

**Modifiers / Visibility / Mutability:**

* internal nonpayable

**Access Control:**

* Unrestricted (internal)

**Side Effects:**

* May forward ETH to [`feeRegistry`](https://docs.cryptolegacy.app/documentation/data-structures-reference#feeregistry-clbm1-d1) via referral creation and build-fee payment
* May mint and lock a lifetime NFT via [`lifetimeNft`](https://docs.cryptolegacy.app/documentation/data-structures-reference#lifetimenft-clbm1-d4) and `ILockChainGate(address(feeRegistry))` (in [`_getAndPayBuildFee`](#_getandpaybuildfee-clbm1))
* May refund ETH to `msg.sender` via [`_returnFee`](#_returnfee-clbm1)

**Emits:**

* [CreateRef](https://docs.cryptolegacy.app/documentation/events-reference#createref-iclbm1) — `CreateRef(address indexed sender, bytes8 indexed refCode, address indexed recipient, uint256[] chainIds)` (conditional)
* [CreateCustomRef](https://docs.cryptolegacy.app/documentation/events-reference#createcustomref-iclbm1) — `CreateCustomRef(address indexed sender, bytes8 indexed refCode, address indexed recipient, uint256[] chainIds)` (conditional)

**Reverts if:**

* `_createRef(...)` or `_createCustomRef(...)` checks fail — [`IncorrectFee(uint256)`](https://docs.cryptolegacy.app/documentation/errors-reference#incorrectfee-iclbm1)
* [`feeRegistry.createCode(...)`](https://docs.cryptolegacy.app/documentation/data-structures-reference#feeregistry-clbm1-d1) — may revert with [`NotOperator()`](https://docs.cryptolegacy.app/documentation/errors-reference#notoperator-ifr1), [`RefAlreadyCreated()`](https://docs.cryptolegacy.app/documentation/errors-reference#refalreadycreated-ifr1), [`ZeroCode()`](https://docs.cryptolegacy.app/documentation/errors-reference#zerocode-ifr1), [`AlreadyReferrer()`](https://docs.cryptolegacy.app/documentation/errors-reference#alreadyreferrer-ifr1), [`ArrayLengthMismatch()`](https://docs.cryptolegacy.app/documentation/errors-reference#arraylengthmismatch-ilcg1), [`DestinationChainNotSpecified()`](https://docs.cryptolegacy.app/documentation/errors-reference#destinationchainnotspecified-ilcg1), [`IncorrectFee(uint256)`](https://docs.cryptolegacy.app/documentation/errors-reference#incorrectfee-iclbm1), or [`TransferFeeFailed(bytes)`](https://docs.cryptolegacy.app/documentation/errors-reference#transferfeefailed-iclbm1) (bubbled)
* [`feeRegistry.createCustomCode(...)`](https://docs.cryptolegacy.app/documentation/data-structures-reference#feeregistry-clbm1-d1) — may revert with [`NotOperator()`](https://docs.cryptolegacy.app/documentation/errors-reference#notoperator-ifr1), [`RefAlreadyCreated()`](https://docs.cryptolegacy.app/documentation/errors-reference#refalreadycreated-ifr1), [`ZeroCode()`](https://docs.cryptolegacy.app/documentation/errors-reference#zerocode-ifr1), [`AlreadyReferrer()`](https://docs.cryptolegacy.app/documentation/errors-reference#alreadyreferrer-ifr1), [`ArrayLengthMismatch()`](https://docs.cryptolegacy.app/documentation/errors-reference#arraylengthmismatch-ilcg1), [`DestinationChainNotSpecified()`](https://docs.cryptolegacy.app/documentation/errors-reference#destinationchainnotspecified-ilcg1), [`IncorrectFee(uint256)`](https://docs.cryptolegacy.app/documentation/errors-reference#incorrectfee-iclbm1), or [`TransferFeeFailed(bytes)`](https://docs.cryptolegacy.app/documentation/errors-reference#transferfeefailed-iclbm1) (bubbled)
* [`feeRegistry.getContractCaseFeeForCode(...)`](https://docs.cryptolegacy.app/documentation/data-structures-reference#feeregistry-clbm1-d1) — may revert with [`TooBigPct()`](https://docs.cryptolegacy.app/documentation/errors-reference#toobigpct-ifr1) (bubbled)
* [`feeRegistry.takeFee(...)`](https://docs.cryptolegacy.app/documentation/data-structures-reference#feeregistry-clbm1-d1) — may revert with [`IncorrectFee(uint256)`](https://docs.cryptolegacy.app/documentation/errors-reference#incorrectfee-iclbm1) or [`TooBigPct()`](https://docs.cryptolegacy.app/documentation/errors-reference#toobigpct-ifr1) (bubbled)
* [`lifetimeNft.mint(...)`](https://docs.cryptolegacy.app/documentation/data-structures-reference#lifetimenft-clbm1-d4) — may revert per token implementation (bubbled)
* [`lifetimeNft.approve(...)`](https://docs.cryptolegacy.app/documentation/data-structures-reference#lifetimenft-clbm1-d4) — may revert per token implementation (bubbled)
* `ILockChainGate.lockLifetimeNft(...)` — may revert with `"ERC721: transfer from incorrect owner"`, [`AlreadyLocked()`](https://docs.cryptolegacy.app/documentation/errors-reference#alreadylocked-ilcg1), [`ArrayLengthMismatch()`](https://docs.cryptolegacy.app/documentation/errors-reference#arraylengthmismatch-ilcg1), [`CrossChainLock()`](https://docs.cryptolegacy.app/documentation/errors-reference#crosschainlock-ilcg1), [`DestinationChainNotSpecified()`](https://docs.cryptolegacy.app/documentation/errors-reference#destinationchainnotspecified-ilcg1), [`AlreadyLockedToChain()`](https://docs.cryptolegacy.app/documentation/errors-reference#alreadylockedtochain-ilcg1), [`IncorrectFee(uint256)`](https://docs.cryptolegacy.app/documentation/errors-reference#incorrectfee-iclbm1), or [`TransferFeeFailed(bytes)`](https://docs.cryptolegacy.app/documentation/errors-reference#transferfeefailed-iclbm1) (bubbled)
* `ILockChainGate.isNftLockedAndUpdate(...)` — may revert with [`NotAllowed()`](https://docs.cryptolegacy.app/documentation/errors-reference#notallowed-ilcg1) (bubbled)
* refund to caller fails — [`TransferFeeFailed(bytes)`](https://docs.cryptolegacy.app/documentation/errors-reference#transferfeefailed-iclbm1)

**Overrides:** None

**Function Calls:**

* [\_createRef(address,uint256\[\],uint256\[\])](#_createref-clbm1) — CryptoLegacyBuildManager, internal
* [\_createCustomRef(bytes8,address,uint256\[\],uint256\[\])](#_createcustomref-clbm1) — CryptoLegacyBuildManager, internal
* [\_getAndPayBuildFee(bytes8,uint256,uint256\[\],uint256\[\])](#_getandpaybuildfee-clbm1) — CryptoLegacyBuildManager, internal

**Called by:**

* [buildCryptoLegacy](#buildcryptolegacy-clbm1) — CryptoLegacyBuildManager

**Gas / Complexity note:** O(n) by `_refArgs.crossChainFees.length` (when creating refs)

**Example:** Not applicable

***

### buildCryptoLegacy (CLBM1)

**Contract/Library:** CryptoLegacyBuildManager

**Description:** Deploys and initializes a new CryptoLegacy instance after handling referral creation and fees.

**Detailed Description:** Calls [`_createRefAndPayForBuild`](#_createrefandpayforbuild-clbm1) to optionally create refs and compute/pay the build fee, then validates timeouts via [`_checkBuildArgs`](#_checkbuildargs-clbm1). Deploys a new contract using [`factory.createCryptoLegacy`](https://docs.cryptolegacy.app/documentation/data-structures-reference#factory-clbm1-d5), marks it as built in [`cryptoLegacyBuilt`](https://docs.cryptolegacy.app/documentation/data-structures-reference#cryptolegacybuilt-clbm1-d11), and calls `CryptoLegacyBasePlugin.initializeByBuildManager` with fees, beneficiaries, and timing parameters. Emits `Build` and returns the deployed address.

**Parameters:**

* \_buildArgs ([BuildArgs](https://docs.cryptolegacy.app/documentation/data-structures-reference#buildargs-iclbm1-s1), memory): Build arguments containing inviter ref code, beneficiaries, plugins, update interval, and challenge timeout
* \_refArgs ([RefArgs](https://docs.cryptolegacy.app/documentation/data-structures-reference#refargs-iclbm1-s2), memory): Referral-creation arguments
* \_create2Args ([ICryptoLegacyFactory.Create2Args](https://docs.cryptolegacy.app/documentation/data-structures-reference#create2args-iclf1-s1), memory): Deterministic deployment args

**Returns:**

* cl (address payable): Newly deployed CryptoLegacy address

**Modifiers / Visibility / Mutability:**

* public payable

**Access Control:**

* Unrestricted

**Side Effects:**

* Updates [`cryptoLegacyBuilt`](https://docs.cryptolegacy.app/documentation/data-structures-reference#cryptolegacybuilt-clbm1-d11)\[cl]
* Deploys a new CryptoLegacy via [`factory.createCryptoLegacy`](https://docs.cryptolegacy.app/documentation/data-structures-reference#factory-clbm1-d5) (external)
* Initializes the deployed contract via `CryptoLegacyBasePlugin.initializeByBuildManager` (external state changes)
* May forward ETH to [`feeRegistry`](https://docs.cryptolegacy.app/documentation/data-structures-reference#feeregistry-clbm1-d1) via referral creation and/or build-fee payment
* May mint and lock a lifetime NFT via [`lifetimeNft`](https://docs.cryptolegacy.app/documentation/data-structures-reference#lifetimenft-clbm1-d4) and `ILockChainGate(address(feeRegistry))` (conditional)
* May refund ETH to `msg.sender` (conditional)
* May update referral state in [`feeRegistry`](https://docs.cryptolegacy.app/documentation/data-structures-reference#feeregistry-clbm1-d1) (conditional, via ref creation)
* May update lifetime lock timestamp via `ILockChainGate.isNftLockedAndUpdate` (conditional)

**Emits:**

* [Build](https://docs.cryptolegacy.app/documentation/events-reference#build-iclbm1) — `Build(address indexed sender, address indexed cryptoLegacy, address[] plugins, bytes32[] beneficiaryHashes, ICryptoLegacy.BeneficiaryConfig[] beneficiaryConfig, bool isPaid, uint64 updateInterval, uint64 challengeTimeout)`

**Reverts if:**

* \_buildArgs.updateInterval != 180 days — [`NotValidTimeout()`](https://docs.cryptolegacy.app/documentation/errors-reference#notvalidtimeout-iclbm1)
* \_buildArgs.challengeTimeout != 90 days — [`NotValidTimeout()`](https://docs.cryptolegacy.app/documentation/errors-reference#notvalidtimeout-iclbm1)
* msg.value minus spent referral fee is below required build fee — [`IncorrectFee(uint256)`](https://docs.cryptolegacy.app/documentation/errors-reference#incorrectfee-iclbm1) (via [`_getAndPayBuildFee`](#_getandpaybuildfee-clbm1))
* msg.value < required referral fee (when creating a ref) — [`IncorrectFee(uint256)`](https://docs.cryptolegacy.app/documentation/errors-reference#incorrectfee-iclbm1) (via [`_createRef`](#_createref-clbm1) or [`_createCustomRef`](#_createcustomref-clbm1))
* `ILockChainGate(feeRegistry).calculateCrossChainCreateRefNativeFee(...)` — may revert per implementation (bubbled)
* [`feeRegistry.createCode(...)`](https://docs.cryptolegacy.app/documentation/data-structures-reference#feeregistry-clbm1-d1) — may revert with [`NotOperator()`](https://docs.cryptolegacy.app/documentation/errors-reference#notoperator-ifr1), [`RefAlreadyCreated()`](https://docs.cryptolegacy.app/documentation/errors-reference#refalreadycreated-ifr1), [`ZeroCode()`](https://docs.cryptolegacy.app/documentation/errors-reference#zerocode-ifr1), [`AlreadyReferrer()`](https://docs.cryptolegacy.app/documentation/errors-reference#alreadyreferrer-ifr1), [`ArrayLengthMismatch()`](https://docs.cryptolegacy.app/documentation/errors-reference#arraylengthmismatch-ilcg1), [`DestinationChainNotSpecified()`](https://docs.cryptolegacy.app/documentation/errors-reference#destinationchainnotspecified-ilcg1), [`IncorrectFee(uint256)`](https://docs.cryptolegacy.app/documentation/errors-reference#incorrectfee-iclbm1), or [`TransferFeeFailed(bytes)`](https://docs.cryptolegacy.app/documentation/errors-reference#transferfeefailed-iclbm1) (bubbled)
* [`feeRegistry.createCustomCode(...)`](https://docs.cryptolegacy.app/documentation/data-structures-reference#feeregistry-clbm1-d1) — may revert with [`NotOperator()`](https://docs.cryptolegacy.app/documentation/errors-reference#notoperator-ifr1), [`RefAlreadyCreated()`](https://docs.cryptolegacy.app/documentation/errors-reference#refalreadycreated-ifr1), [`ZeroCode()`](https://docs.cryptolegacy.app/documentation/errors-reference#zerocode-ifr1), [`AlreadyReferrer()`](https://docs.cryptolegacy.app/documentation/errors-reference#alreadyreferrer-ifr1), [`ArrayLengthMismatch()`](https://docs.cryptolegacy.app/documentation/errors-reference#arraylengthmismatch-ilcg1), [`DestinationChainNotSpecified()`](https://docs.cryptolegacy.app/documentation/errors-reference#destinationchainnotspecified-ilcg1), [`IncorrectFee(uint256)`](https://docs.cryptolegacy.app/documentation/errors-reference#incorrectfee-iclbm1), or [`TransferFeeFailed(bytes)`](https://docs.cryptolegacy.app/documentation/errors-reference#transferfeefailed-iclbm1) (bubbled)
* [`feeRegistry.getContractCaseFeeForCode(...)`](https://docs.cryptolegacy.app/documentation/data-structures-reference#feeregistry-clbm1-d1) — may revert with [`TooBigPct()`](https://docs.cryptolegacy.app/documentation/errors-reference#toobigpct-ifr1) (bubbled)
* [`feeRegistry.takeFee(...)`](https://docs.cryptolegacy.app/documentation/data-structures-reference#feeregistry-clbm1-d1) — may revert with [`IncorrectFee(uint256)`](https://docs.cryptolegacy.app/documentation/errors-reference#incorrectfee-iclbm1) or [`TooBigPct()`](https://docs.cryptolegacy.app/documentation/errors-reference#toobigpct-ifr1) (bubbled)
* [`lifetimeNft.mint(...)`](https://docs.cryptolegacy.app/documentation/data-structures-reference#lifetimenft-clbm1-d4) — may revert per token implementation (bubbled)
* [`lifetimeNft.approve(...)`](https://docs.cryptolegacy.app/documentation/data-structures-reference#lifetimenft-clbm1-d4) — may revert per token implementation (bubbled)
* `ILockChainGate.lockLifetimeNft(...)` — may revert with `"ERC721: transfer from incorrect owner"`, [`AlreadyLocked()`](https://docs.cryptolegacy.app/documentation/errors-reference#alreadylocked-ilcg1), [`ArrayLengthMismatch()`](https://docs.cryptolegacy.app/documentation/errors-reference#arraylengthmismatch-ilcg1), [`CrossChainLock()`](https://docs.cryptolegacy.app/documentation/errors-reference#crosschainlock-ilcg1), [`DestinationChainNotSpecified()`](https://docs.cryptolegacy.app/documentation/errors-reference#destinationchainnotspecified-ilcg1), [`AlreadyLockedToChain()`](https://docs.cryptolegacy.app/documentation/errors-reference#alreadylockedtochain-ilcg1), [`IncorrectFee(uint256)`](https://docs.cryptolegacy.app/documentation/errors-reference#incorrectfee-iclbm1), or [`TransferFeeFailed(bytes)`](https://docs.cryptolegacy.app/documentation/errors-reference#transferfeefailed-iclbm1) (bubbled)
* `ILockChainGate.isNftLockedAndUpdate(...)` — may revert with [`NotAllowed()`](https://docs.cryptolegacy.app/documentation/errors-reference#notallowed-ilcg1) (bubbled)
* Refund to msg.sender fails — [`TransferFeeFailed(bytes)`](https://docs.cryptolegacy.app/documentation/errors-reference#transferfeefailed-iclbm1) (via [`_returnFee`](#_returnfee-clbm1))
* [`factory.createCryptoLegacy(...)`](https://docs.cryptolegacy.app/documentation/data-structures-reference#factory-clbm1-d5) — may revert with [`NotBuildOperator()`](https://docs.cryptolegacy.app/documentation/errors-reference#notbuildoperator-iclf1), [`BytecodeEmpty()`](https://docs.cryptolegacy.app/documentation/errors-reference#bytecodeempty-lcld1), `panic(0x11)`, [`AddressMismatch()`](https://docs.cryptolegacy.app/documentation/errors-reference#addressmismatch-lcld1), [`TargetAlreadyExists()`](https://docs.cryptolegacy.app/documentation/errors-reference#targetalreadyexists-lc31), [`ErrorCreatingProxy()`](https://docs.cryptolegacy.app/documentation/errors-reference#errorcreatingproxy-lc31), or [`ErrorCreatingContract()`](https://docs.cryptolegacy.app/documentation/errors-reference#errorcreatingcontract-lc31) (bubbled)
* `initializeByBuildManager(...)` — may revert with [`NotBuildManager()`](https://docs.cryptolegacy.app/documentation/errors-reference#notbuildmanager-icl1), [`LengthMismatch()`](https://docs.cryptolegacy.app/documentation/errors-reference#lengthmismatch-icl1), [`OriginalHashDuplicate()`](https://docs.cryptolegacy.app/documentation/errors-reference#originalhashduplicate-icl1), [`ShareSumDoesntMatchBase()`](https://docs.cryptolegacy.app/documentation/errors-reference#sharesumdoesntmatchbase-icl1), [`ChallengePeriodStarted()`](https://docs.cryptolegacy.app/documentation/errors-reference#challengeperiodstarted-icl1), or "Initializable: contract is already initialized" (bubbled)

**Overrides:** None

**Function Calls:**

* [\_createRefAndPayForBuild(BuildArgs,RefArgs)](#_createrefandpayforbuild-clbm1) — CryptoLegacyBuildManager, internal
* [\_checkBuildArgs(BuildArgs)](#_checkbuildargs-clbm1) — CryptoLegacyBuildManager, internal
* [createCryptoLegacy(address,address\[\],Create2Args)](#createcryptolegacy-clf1) — ICryptoLegacyFactory *(at* [*`factory`*](https://docs.cryptolegacy.app/documentation/data-structures-reference#factory-clbm1-d5)*)*, external
* [initializeByBuildManager(uint256,uint256,bytes32\[\],BeneficiaryConfig\[\],bytes8,uint64,uint64)](#initializebybuildmanager-clbp1) — CryptoLegacyBasePlugin *(at `cl`)*, external

**Called by:** None (entry point)

**Gas / Complexity note:** O(p + b), where *p* is the number of plugins and *b* is the number of beneficiary entries (runtime is dominated by initialization inside `initializeByBuildManager`).

**Example:**

```solidity
address payable cl = buildManager.buildCryptoLegacy{value: msg.value}(buildArgs, refArgs, create2Args);
```

***

### \_checkBuildArgs (CLBM1)

**Contract/Library:** CryptoLegacyBuildManager

**Description:** Validates required default timeouts in build arguments.

**Detailed Description:** Ensures `_buildArgs.updateInterval == 180 days` and `_buildArgs.challengeTimeout == 90 days`. Otherwise reverts `NotValidTimeout()`.

**Parameters:**

* \_buildArgs ([BuildArgs](https://docs.cryptolegacy.app/documentation/data-structures-reference#buildargs-iclbm1-s1), memory): Build arguments containing timing fields

**Returns:** None

**Modifiers / Visibility / Mutability:**

* internal nonpayable

**Access Control:**

* Unrestricted (internal)

**Side Effects:** None

**Emits:** None

**Reverts if:**

* \_buildArgs.updateInterval != 180 days — [`NotValidTimeout()`](https://docs.cryptolegacy.app/documentation/errors-reference#notvalidtimeout-iclbm1)
* \_buildArgs.challengeTimeout != 90 days — [`NotValidTimeout()`](https://docs.cryptolegacy.app/documentation/errors-reference#notvalidtimeout-iclbm1)

**Overrides:** None

**Function Calls:** None

**Called by:**

* [buildCryptoLegacy](#buildcryptolegacy-clbm1) — CryptoLegacyBuildManager

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### \_getAndPayBuildFee (CLBM1)

**Contract/Library:** CryptoLegacyBuildManager

**Description:** Retrieves (and optionally pays) the initial build fee and always returns the update fee.

**Detailed Description:** If `msg.value - _subValue > 0`, calls [`_payFee`](#_payfee-clbm1) with [`REGISTRY_BUILD_CASE`](https://docs.cryptolegacy.app/documentation/data-structures-reference#registry_build_case-clbm1-d8); otherwise reads `initialFeeToPay` from [`feeRegistry.getContractCaseFeeForCode`](https://docs.cryptolegacy.app/documentation/data-structures-reference#feeregistry-clbm1-d1). If the caller has a locked lifetime NFT (checked via `ILockChainGate.isNftLockedAndUpdate`), sets `initialFeeToPay = 0`. Finally reads the `updateFee` for the supplied referral code.

**Parameters:**

* \_invitedByRefCode (bytes8): Referral code
* \_subValue (uint256): Amount already spent (deducted from msg.value)
* \_chainIds (uint256\[], memory): Chains for potential locking (if paying now)
* \_crossChainFees (uint256\[], memory): Per-chain fees (if paying now)

**Returns:**

* initialFeeToPay (uint256): Initial fee owed (0 if lifetime locked)
* updateFee (uint256): Update fee for future operations

**Modifiers / Visibility / Mutability:**

* internal nonpayable

**Access Control:**

* Unrestricted (internal)

**Side Effects:**

* May forward ETH to [`feeRegistry`](https://docs.cryptolegacy.app/documentation/data-structures-reference#feeregistry-clbm1-d1) (via [`_payFee`](#_payfee-clbm1), conditional)
* May mint and lock a lifetime NFT via [`lifetimeNft`](https://docs.cryptolegacy.app/documentation/data-structures-reference#lifetimenft-clbm1-d4) and `ILockChainGate(address(feeRegistry))` (via [`_payFee`](#_payfee-clbm1), conditional)
* May refund ETH to `msg.sender` (via [`_payFee`](#_payfee-clbm1))
* May update lifetime lock timestamp in `ILockChainGate` (via [`isNftLockedAndUpdate`](#isnftlockedandupdate-lcg1))

**Emits:** None

**Reverts if:**

* Paying path: msg.value - \_subValue < feeToTake — [`IncorrectFee(uint256)`](https://docs.cryptolegacy.app/documentation/errors-reference#incorrectfee-iclbm1) (via [`_payFee`](#_payfee-clbm1))
* [`feeRegistry.getContractCaseFeeForCode(...)`](https://docs.cryptolegacy.app/documentation/data-structures-reference#feeregistry-clbm1-d1) — may revert with [`TooBigPct()`](https://docs.cryptolegacy.app/documentation/errors-reference#toobigpct-ifr1) (bubbled)
* [`feeRegistry.takeFee(...)`](https://docs.cryptolegacy.app/documentation/data-structures-reference#feeregistry-clbm1-d1) — may revert with [`IncorrectFee(uint256)`](https://docs.cryptolegacy.app/documentation/errors-reference#incorrectfee-iclbm1) or [`TooBigPct()`](https://docs.cryptolegacy.app/documentation/errors-reference#toobigpct-ifr1) (bubbled, via [`_payFee`](#_payfee-clbm1))
* [`lifetimeNft.mint(...)`](https://docs.cryptolegacy.app/documentation/data-structures-reference#lifetimenft-clbm1-d4) — may revert per token implementation (bubbled, via [`_payFee`](#_payfee-clbm1))
* [`lifetimeNft.approve(...)`](https://docs.cryptolegacy.app/documentation/data-structures-reference#lifetimenft-clbm1-d4) — may revert per token implementation (bubbled, via [`_payFee`](#_payfee-clbm1))
* `ILockChainGate.lockLifetimeNft(...)` — may revert with `"ERC721: transfer from incorrect owner"`, [`AlreadyLocked()`](https://docs.cryptolegacy.app/documentation/errors-reference#alreadylocked-ilcg1), [`ArrayLengthMismatch()`](https://docs.cryptolegacy.app/documentation/errors-reference#arraylengthmismatch-ilcg1), [`CrossChainLock()`](https://docs.cryptolegacy.app/documentation/errors-reference#crosschainlock-ilcg1), [`DestinationChainNotSpecified()`](https://docs.cryptolegacy.app/documentation/errors-reference#destinationchainnotspecified-ilcg1), [`AlreadyLockedToChain()`](https://docs.cryptolegacy.app/documentation/errors-reference#alreadylockedtochain-ilcg1), [`IncorrectFee(uint256)`](https://docs.cryptolegacy.app/documentation/errors-reference#incorrectfee-iclbm1), or [`TransferFeeFailed(bytes)`](https://docs.cryptolegacy.app/documentation/errors-reference#transferfeefailed-iclbm1) (bubbled, via [`_payFee`](#_payfee-clbm1))
* `ILockChainGate.isNftLockedAndUpdate(...)` — may revert with [`NotAllowed()`](https://docs.cryptolegacy.app/documentation/errors-reference#notallowed-ilcg1) (bubbled)
* Refund to msg.sender fails — [`TransferFeeFailed(bytes)`](https://docs.cryptolegacy.app/documentation/errors-reference#transferfeefailed-iclbm1) (via [`_payFee`](#_payfee-clbm1))

**Overrides:** None

**Function Calls:**

* [\_payFee(bytes8,address,uint8,uint256,uint256,uint256\[\],uint256\[\])](#_payfee-clbm1) — CryptoLegacyBuildManager, internal
* [getContractCaseFeeForCode(address,uint8,bytes8)](#getcontractcasefeeforcode-fr1) — IFeeRegistry *(at* [*`feeRegistry`*](https://docs.cryptolegacy.app/documentation/data-structures-reference#feeregistry-clbm1-d1)*)*, external (staticcall)
* [isNftLockedAndUpdate(address)](#isnftlockedandupdate-lcg1) — ILockChainGate *(at* [*`feeRegistry`*](https://docs.cryptolegacy.app/documentation/data-structures-reference#feeregistry-clbm1-d1)*)*, external
* [getContractCaseFeeForCode(address,uint8,bytes8)](#getcontractcasefeeforcode-fr1) — IFeeRegistry *(at* [*`feeRegistry`*](https://docs.cryptolegacy.app/documentation/data-structures-reference#feeregistry-clbm1-d1)*)*, external (staticcall)

**Called by:**

* [\_createRefAndPayForBuild](#_createrefandpayforbuild-clbm1) — CryptoLegacyBuildManager
* [getAndPayBuildFee](#getandpaybuildfee-clbm1) — CryptoLegacyBuildManager

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### getUpdateFee (CLBM1)

**Contract/Library:** CryptoLegacyBuildManager

**Description:** Returns the configured update fee for a referral code.

**Detailed Description:** Thin view wrapper over the fee registry.

**Parameters:**

* \_refCode (bytes8): Referral code

**Returns:**

* updateFee (uint256): Update fee in wei

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:**

* [`feeRegistry.getContractCaseFeeForCode(...)`](https://docs.cryptolegacy.app/documentation/data-structures-reference#feeregistry-clbm1-d1) — may revert with [`TooBigPct()`](https://docs.cryptolegacy.app/documentation/errors-reference#toobigpct-ifr1) (bubbled)

**Overrides:** None

**Function Calls:**

* [getContractCaseFeeForCode(address,uint8,bytes8)](#getcontractcasefeeforcode-fr1) — IFeeRegistry *(at* [*`feeRegistry`*](https://docs.cryptolegacy.app/documentation/data-structures-reference#feeregistry-clbm1-d1)*)*, external (staticcall)

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:**

```solidity
uint256 fee = buildManager.getUpdateFee(code);
```

***

### getAndPayBuildFee (CLBM1)

**Contract/Library:** CryptoLegacyBuildManager

**Description:** Convenience entry point to fetch build/update fees and optionally pay if ETH is sent.

**Detailed Description:** Allocates empty arrays and delegates to [`_getAndPayBuildFee`](#_getandpaybuildfee-clbm1). If `msg.value > 0`, the internal call pays immediately; otherwise it reads the current fee quotes. In both paths it calls `ILockChainGate.isNftLockedAndUpdate`, which may zero `initialFeeToPay` for a locked lifetime NFT.

**Parameters:**

* \_invitedByRefCode (bytes8): Referral code

**Returns:**

* initialFeeToPay (uint256): Initial build fee (zero if lifetime locked)
* updateFee (uint256): Update fee for future operations

**Modifiers / Visibility / Mutability:**

* external payable

**Access Control:**

* Unrestricted

**Side Effects:**

* May forward ETH to [`feeRegistry`](https://docs.cryptolegacy.app/documentation/data-structures-reference#feeregistry-clbm1-d1) (via [`_payFee`](#_payfee-clbm1), conditional)
* May mint and lock a lifetime NFT via [`lifetimeNft`](https://docs.cryptolegacy.app/documentation/data-structures-reference#lifetimenft-clbm1-d4) and `ILockChainGate(address(feeRegistry))` (via [`_payFee`](#_payfee-clbm1), conditional)
* May refund ETH to `msg.sender` (via [`_payFee`](#_payfee-clbm1), conditional)
* May update lifetime lock timestamp in `ILockChainGate` (via [`isNftLockedAndUpdate`](#isnftlockedandupdate-lcg1))

**Emits:** None

**Reverts if:**

* [`feeRegistry.getContractCaseFeeForCode(...)`](https://docs.cryptolegacy.app/documentation/data-structures-reference#feeregistry-clbm1-d1) — may revert with [`TooBigPct()`](https://docs.cryptolegacy.app/documentation/errors-reference#toobigpct-ifr1) (bubbled, build fee quote)
* [`feeRegistry.getContractCaseFeeForCode(...)`](https://docs.cryptolegacy.app/documentation/data-structures-reference#feeregistry-clbm1-d1) — may revert with [`TooBigPct()`](https://docs.cryptolegacy.app/documentation/errors-reference#toobigpct-ifr1) (bubbled, via [`_payFee`](#_payfee-clbm1), lifetime fee quote)
* `msg.value` is insufficient for the required build/lifetime fee (paying path) — [`IncorrectFee(uint256)`](https://docs.cryptolegacy.app/documentation/errors-reference#incorrectfee-iclbm1) (via [`_payFee`](#_payfee-clbm1))
* [`feeRegistry.takeFee(...)`](https://docs.cryptolegacy.app/documentation/data-structures-reference#feeregistry-clbm1-d1) — may revert with [`IncorrectFee(uint256)`](https://docs.cryptolegacy.app/documentation/errors-reference#incorrectfee-iclbm1) or [`TooBigPct()`](https://docs.cryptolegacy.app/documentation/errors-reference#toobigpct-ifr1) (bubbled, via [`_payFee`](#_payfee-clbm1))
* [`lifetimeNft.mint(...)`](https://docs.cryptolegacy.app/documentation/data-structures-reference#lifetimenft-clbm1-d4) — may revert per token implementation (bubbled, via [`_payFee`](#_payfee-clbm1))
* [`lifetimeNft.approve(...)`](https://docs.cryptolegacy.app/documentation/data-structures-reference#lifetimenft-clbm1-d4) — may revert per token implementation (bubbled, via [`_payFee`](#_payfee-clbm1))
* `ILockChainGate.lockLifetimeNft(...)` — may revert with `"ERC721: transfer from incorrect owner"`, [`AlreadyLocked()`](https://docs.cryptolegacy.app/documentation/errors-reference#alreadylocked-ilcg1), [`ArrayLengthMismatch()`](https://docs.cryptolegacy.app/documentation/errors-reference#arraylengthmismatch-ilcg1), [`CrossChainLock()`](https://docs.cryptolegacy.app/documentation/errors-reference#crosschainlock-ilcg1), [`DestinationChainNotSpecified()`](https://docs.cryptolegacy.app/documentation/errors-reference#destinationchainnotspecified-ilcg1), [`AlreadyLockedToChain()`](https://docs.cryptolegacy.app/documentation/errors-reference#alreadylockedtochain-ilcg1), [`IncorrectFee(uint256)`](https://docs.cryptolegacy.app/documentation/errors-reference#incorrectfee-iclbm1), or [`TransferFeeFailed(bytes)`](https://docs.cryptolegacy.app/documentation/errors-reference#transferfeefailed-iclbm1) (bubbled, via [`_payFee`](#_payfee-clbm1))
* Refund to `msg.sender` fails — [`TransferFeeFailed(bytes)`](https://docs.cryptolegacy.app/documentation/errors-reference#transferfeefailed-iclbm1) (via [`_payFee`](#_payfee-clbm1))
* `ILockChainGate.isNftLockedAndUpdate(...)` — may revert with [`NotAllowed()`](https://docs.cryptolegacy.app/documentation/errors-reference#notallowed-ilcg1) (bubbled)
* [`feeRegistry.getContractCaseFeeForCode(...)`](https://docs.cryptolegacy.app/documentation/data-structures-reference#feeregistry-clbm1-d1) — may revert with [`TooBigPct()`](https://docs.cryptolegacy.app/documentation/errors-reference#toobigpct-ifr1) (bubbled, update fee quote)

**Overrides:** None

**Function Calls:**

* [\_getAndPayBuildFee(bytes8,uint256,uint256\[\],uint256\[\])](#_getandpaybuildfee-clbm1) — CryptoLegacyBuildManager, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:**

```solidity
(uint256 initial, uint256 update) = buildManager.getAndPayBuildFee{value: 0}(code);
```

***

### transferStuckNft (CLBM1)

**Contract/Library:** CryptoLegacyBuildManager

**Description:** Owner rescue function to transfer out an ERC721 token held by this contract.

**Detailed Description:** Transfers `tokenId` of [`lifetimeNft`](https://docs.cryptolegacy.app/documentation/data-structures-reference#lifetimenft-clbm1-d4) from this contract to `to` via `safeTransferFrom`. Useful to recover erroneously sent NFTs.

**Parameters:**

* to (address): Recipient address
* tokenId (uint256): ERC721 token ID

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external nonpayable onlyOwner

**Access Control:**

* onlyOwner

**Side Effects:**

* Transfers `tokenId` of [`lifetimeNft`](https://docs.cryptolegacy.app/documentation/data-structures-reference#lifetimenft-clbm1-d4) from this contract to `to`

**Emits:** None

**Reverts if:**

* caller is not owner — "Ownable: caller is not the owner"
* `IERC721(lifetimeNft).safeTransferFrom(...)` — may revert per ERC721 implementation (bubbled)

**Overrides:** None

**Function Calls:**

* `IERC721(lifetimeNft).safeTransferFrom(address,address,uint256)` — IERC721 *(at* [*`lifetimeNft`*](https://docs.cryptolegacy.app/documentation/data-structures-reference#lifetimenft-clbm1-d4)*)*, external

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:**

```solidity
buildManager.transferStuckNft(user, tokenId);
```

***

### onERC721Received (CLBM1)

**Contract/Library:** CryptoLegacyBuildManager

**Description:** ERC721 safe-transfer hook confirming receipt.

**Detailed Description:** Returns `this.onERC721Received.selector` if the sender is the configured [`lifetimeNft`](https://docs.cryptolegacy.app/documentation/data-structures-reference#lifetimenft-clbm1-d4); otherwise returns `bytes4(0)` to reject. Read-only.

**Parameters:**

* \_operator (address): Caller (token contract uses this field)
* \_from (address): Previous token owner
* \_tokenId (uint256): Token ID received
* \_data (bytes, calldata): Extra call data

**Returns:**

* selector (bytes4): Acceptance magic value or zero

**Modifiers / Visibility / Mutability:**

* external view override

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:**

None

**Overrides:**

* `IERC721Receiver.onERC721Received`

**Function Calls:** None

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### calculateCrossChainCreateRefFee (CLBM1)

**Contract/Library:** CryptoLegacyBuildManager

**Description:** Computes the total native fee needed to create/lock a referral across chains.

**Detailed Description:** If `_crossChainFees` is non-empty and all entries are non-zero, returns their sum. Otherwise, queries the lock-gate via `calculateCrossChainCreateRefNativeFee` for an up-to-date quote.

**Parameters:**

* \_chainIds (uint256\[], memory): Destination chains
* \_crossChainFees (uint256\[], memory): Per-chain fees or zeros to auto-quote

**Returns:**

* totalFee (uint256): Total native fee required

**Modifiers / Visibility / Mutability:**

* public view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:**

* `_crossChainFees` is empty or contains zeros — `ILockChainGate(feeRegistry).calculateCrossChainCreateRefNativeFee(...)` may revert per implementation (bubbled)

**Overrides:** None

**Function Calls:**

* [calculateCrossChainCreateRefNativeFee(uint256\[\],uint256\[\])](#calculatecrosschaincreaterefnativefee-lcg1) — ILockChainGate *(at* [*`feeRegistry`*](https://docs.cryptolegacy.app/documentation/data-structures-reference#feeregistry-clbm1-d1)*)*, external (staticcall)

**Called by:**

* [\_createCustomRef](#_createcustomref-clbm1) — CryptoLegacyBuildManager
* [\_createRef](#_createref-clbm1) — CryptoLegacyBuildManager
* [updateCrossChainsRef(uint256\[\],uint256\[\])](#updatecrosschainsref-clbm1) — CryptoLegacyBuildManager

**Gas / Complexity note:** O(n) by `_crossChainFees.length`; if it calls the lock-gate, O(n) by `_chainIds.length`

**Example:**

```solidity
uint256 fee = buildManager.calculateCrossChainCreateRefFee(chains, userFees);
```

***

### getFactoryAddress (CLBM1)

**Contract/Library:** CryptoLegacyBuildManager

**Description:** Returns the currently configured factory address.

**Detailed Description:** Simple view returning `address(factory)`.

**Parameters:** None

**Returns:**

* factoryAddr (address): Address of the deployment factory

**Modifiers / Visibility / Mutability:**

* external view override

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:**

None

**Overrides:**

* `ICryptoLegacyBuildManager.getFactoryAddress`

**Function Calls:** None

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:**

```solidity
address fac = buildManager.getFactoryAddress();
```

***

### isLifetimeNftLocked (CLBM1)

**Contract/Library:** CryptoLegacyBuildManager

**Description:** Checks whether a Lifetime NFT is locked for `_owner`.

**Detailed Description:** Proxies to the lock-gate via `isNftLocked(_owner)` without updating any state.

**Parameters:**

* \_owner (address): Owner to query

**Returns:**

* locked (bool): True if locked, false otherwise

**Modifiers / Visibility / Mutability:**

* public view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:**

None

**Overrides:**

* `ICryptoLegacyBuildManager.isLifetimeNftLocked`

**Function Calls:**

* [isNftLocked(address)](#isnftlocked-lcg1) — ILockChainGate *(at* [*`feeRegistry`*](https://docs.cryptolegacy.app/documentation/data-structures-reference#feeregistry-clbm1-d1)*)*, external (staticcall)

**Called by:**

* [isLifetimeActive()](#islifetimeactive-clbp1) — CryptoLegacyBasePlugin

**Gas / Complexity note:** O(1)

**Example:**

```solidity
bool locked = buildManager.isLifetimeNftLocked(user);
```

***

### isLifetimeNftLockedAndUpdate (CLBM1)

**Contract/Library:** CryptoLegacyBuildManager

**Description:** For a calling CryptoLegacy, verifies ownership and then checks/updates the Lifetime NFT lock status.

**Detailed Description:** Requires [`cryptoLegacyBuilt`](https://docs.cryptolegacy.app/documentation/data-structures-reference#cryptolegacybuilt-clbm1-d11)\[msg.sender] to be true, else reverts `NotRegisteredCryptoLegacy()`. Validates that `ICryptoLegacy(msg.sender).owner() == _owner`, else reverts `NotOwnerOfCryptoLegacy()`. Calls the lock-gate `isNftLockedAndUpdate(_owner)` to update and return lock status.

**Parameters:**

* \_owner (address): Expected owner of the calling CryptoLegacy

**Returns:**

* locked (bool): Updated lock status

**Modifiers / Visibility / Mutability:**

* public nonpayable

**Access Control:**

* Restricted: only built CryptoLegacy contracts; `ICryptoLegacy(msg.sender).owner()` must equal `_owner`

**Side Effects:**

* May update lock timestamp in LockChainGate for `_owner` via `isNftLockedAndUpdate`

**Emits:** None

**Reverts if:**

* [`cryptoLegacyBuilt`](https://docs.cryptolegacy.app/documentation/data-structures-reference#cryptolegacybuilt-clbm1-d11)\[msg.sender] == false — [`NotRegisteredCryptoLegacy()`](https://docs.cryptolegacy.app/documentation/errors-reference#notregisteredcryptolegacy-iclbm1)
* `ICryptoLegacy(msg.sender).owner() != _owner` — [`NotOwnerOfCryptoLegacy()`](https://docs.cryptolegacy.app/documentation/errors-reference#notownerofcryptolegacy-iclbm1)
* `ILockChainGate(feeRegistry).isNftLockedAndUpdate(...)` — may revert with [`NotAllowed()`](https://docs.cryptolegacy.app/documentation/errors-reference#notallowed-ilcg1) (bubbled)

**Overrides:**

* `ICryptoLegacyBuildManager.isLifetimeNftLockedAndUpdate`

**Function Calls:**

* `ICryptoLegacy(msg.sender).owner()` — ICryptoLegacy, external (staticcall)
* [isNftLockedAndUpdate(address)](#isnftlockedandupdate-lcg1) — ILockChainGate *(at* [*`feeRegistry`*](https://docs.cryptolegacy.app/documentation/data-structures-reference#feeregistry-clbm1-d1)*)*, external

**Called by:**

* [\_isLifetimeActiveAndUpdate(ICryptoLegacy.CryptoLegacyStorage,address)](#_islifetimeactiveandupdate-lcl1) — LibCryptoLegacy

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### isPluginRegistered (CLBM1)

**Contract/Library:** CryptoLegacyBuildManager

**Description:** Checks if a plugin is registered in the plugin registry.

**Detailed Description:** Simple view method returning [`pluginsRegistry.isPluginRegistered(_plugin)`](https://docs.cryptolegacy.app/documentation/data-structures-reference#pluginsregistry-clbm1-d2).

**Parameters:**

* \_plugin (address): Plugin address to query

**Returns:**

* registered (bool): True if registered

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:**

None

**Overrides:**

* `ICryptoLegacyBuildManager.isPluginRegistered`

**Function Calls:**

* [isPluginRegistered(address)](#ispluginregistered-ipr1) — IPluginsRegistry *(at* [*`pluginsRegistry`*](https://docs.cryptolegacy.app/documentation/data-structures-reference#pluginsregistry-clbm1-d2)*)*, external (staticcall)

**Called by:**

* [\_validatePlugin(ICryptoLegacy.CryptoLegacyStorage,address)](#_validateplugin-lclp1) — LibCryptoLegacyPlugins

**Gas / Complexity note:** O(1)

**Example:**

```solidity
bool ok = buildManager.isPluginRegistered(plugin);
```

***

### isCryptoLegacyBuilt (CLBM1)

**Contract/Library:** CryptoLegacyBuildManager

**Description:** Returns whether a given CryptoLegacy address was deployed by this manager.

**Detailed Description:** Reads the [`cryptoLegacyBuilt`](https://docs.cryptolegacy.app/documentation/data-structures-reference#cryptolegacybuilt-clbm1-d11) mapping.

**Parameters:**

* \_cryptoLegacy (address): CryptoLegacy contract address

**Returns:**

* built (bool): True if marked built

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:**

None

**Overrides:**

* `ICryptoLegacyBuildManager.isCryptoLegacyBuilt`

**Function Calls:** None

**Called by:**

* [\_checkBuildManagerValid(address,address)](#_checkbuildmanagervalid-bmo1) — BuildManagerOwnable

**Gas / Complexity note:** O(1)

**Example:**

```solidity
bool built = buildManager.isCryptoLegacyBuilt(clAddr);
```

***

## CryptoLegacyDiamondBase (CLDB1)

### staticCallChecker (CLDB1)

**Contract/Library:** CryptoLegacyDiamondBase

**Description:** Self-call probe used by the fallback to detect whether the current context is a static call.

**Detailed Description:** This function must be invoked via an external call from the contract to itself (`this.staticCallChecker()`). It verifies `msg.sender == address(this)` to ensure it is indeed a self-call; otherwise it reverts. When successfully invoked in a **non-static** context, it emits `StaticCallCheck()`. If it is invoked from within a **static** call (e.g., during `eth_call`), the attempt to execute this non-view function and emit an event causes a revert, which is caught by the caller (`fallback`) to infer static context.

**Parameters:** None

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external nonpayable

**Access Control:**

* Only self-call (enforced at runtime)

**Side Effects:** None

**Emits:**

* [StaticCallCheck](https://docs.cryptolegacy.app/documentation/events-reference#staticcallcheck-icldb1) — `StaticCallCheck()`

**Reverts if:**

* `msg.sender != address(this)` — [`NotSelfCall()`](https://docs.cryptolegacy.app/documentation/errors-reference#notselfcall-icldb1)
* Executed under static context — EVM static-call violation (revert without data)

**Overrides:** None

**Function Calls:** None

**Called by:**

* [fallback](#fallback-cldb1) — CryptoLegacyDiamondBase

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### fallback (CLDB1)

**Contract/Library:** CryptoLegacyDiamondBase

**Description:** Diamond fallback that routes unknown selectors to the correct facet via `delegatecall`, caching the facet address on non-static calls.

**Detailed Description:**

1. Loads Diamond storage (`LibDiamond.diamondStorage()`) and looks up the facet address for `msg.sig`.
2. If no cached facet is found:
   * Reads CryptoLegacy storage (`LibCryptoLegacy.getCryptoLegacyStorage()`) to fetch an optional `gasLimitMultiplier`.
   * Performs a **gas-limited external self-call** to [`staticCallChecker`](#staticcallchecker-cldb1).
     * If this self-call reverts, the context is interpreted as **static** (`isStaticCall = true`).
   * Uses `LibCryptoLegacyPlugins._findFacetBySelector` to resolve the facet dynamically.
   * If a facet is found **and the call is not static**, caches it in `selectorToFacetAndPositionmsg.sig.facetAddress`.
3. If after lookup the facet address is still zero, reverts `FunctionNotExists(msg.sig)`.
4. Otherwise, forwards the calldata and gas to the facet using `delegatecall`. Return data or revert reason is bubbled to the caller.

**Parameters:** None

**Returns:** None

**Modifiers / Visibility / Mutability:**

* fallback external payable

**Access Control:**

* Unrestricted

**Side Effects:**

* Updates `LibDiamond.DiamondStorage.selectorToFacetAndPositionmsg.sig.facetAddress` (selector → facet cache on non-static calls)

**Emits:**

* [StaticCallCheck](https://docs.cryptolegacy.app/documentation/events-reference#staticcallcheck-icldb1) — `StaticCallCheck()`

**Reverts if:**

* `ICryptoLegacyPlugin.getSigs()` — may revert per plugin implementation (bubbled)
* No facet exists for `msg.sig` after lookup — [`FunctionNotExists(bytes4)`](https://docs.cryptolegacy.app/documentation/errors-reference#functionnotexists-icldb1)
* `delegatecall` to facet — may revert per facet implementation (bubbled)

**Overrides:** None

**Function Calls:**

* [LibDiamond.diamondStorage()](#diamondstorage-ld1) — LibDiamond, internal
* [LibCryptoLegacy.getCryptoLegacyStorage()](#getcryptolegacystorage-lcl1) — LibCryptoLegacy, internal
* [staticCallChecker()](#staticcallchecker-cldb1) — CryptoLegacyDiamondBase, external
* [LibCryptoLegacyPlugins.\_findFacetBySelector(LibDiamond.DiamondStorage, bytes4)](#_findfacetbyselector-lclp1) — LibCryptoLegacyPlugins, internal
* `delegatecall(gas(), facet, ...)` — EVM assembly, delegatecall

**Called by:** None (entry point)

**Gas / Complexity note:** Amortized O(1) per selector (cached); worst-case O(p) on cold path, where p is the number of plugin facets scanned by `_findFacetBySelector`.

**Example:** Not applicable

***

## CryptoLegacyExternalLens (CLEXL1)

### isLifetimeActive (CLEXL1)

**Contract/Library:** CryptoLegacyExternalLens

**Description:** Forwarder that reports whether lifetime mode is active on a target CryptoLegacy.

**Detailed Description:** Calls `isLifetimeActive()` on the target contract’s base plugin and returns the result; no state changes.

**Parameters:**

* \_cryptoLegacy (address): Target CryptoLegacy diamond address

**Returns:**

* isActive (bool): True if lifetime mode is active

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:**

* `CryptoLegacyBasePlugin(_cryptoLegacy).isLifetimeActive()` — bubbled revert

**Overrides:** None

**Function Calls:**

* `isLifetimeActive()` — `CryptoLegacyBasePlugin` *(at `_cryptoLegacy`)*, external (staticcall)

**Called by:** None (entry point)

**Gas / Complexity note:** O(1) for the forwarder.

**Example:** Call `isLifetimeActive(cl)` to decide whether to show lifetime-NFT UI.

***

### isPaused (CLEXL1)

**Contract/Library:** CryptoLegacyExternalLens

**Description:** Forwarder that reports whether the target CryptoLegacy is paused.

**Detailed Description:** Calls `isPaused()` on the target contract’s base plugin and returns the pause flag.

**Parameters:**

* \_cryptoLegacy (address): Target CryptoLegacy diamond address

**Returns:**

* paused (bool): True if paused

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:**

* `CryptoLegacyBasePlugin(_cryptoLegacy).isPaused()` — bubbled revert

**Overrides:** None

**Function Calls:**

* `isPaused()` — `CryptoLegacyBasePlugin` *(at `_cryptoLegacy`)*, external (staticcall)

**Called by:** None (entry point)

**Gas / Complexity note:** O(1) for the forwarder.

**Example:** Call `isPaused(cl)` before enabling actions.

***

### buildManager (CLEXL1)

**Contract/Library:** CryptoLegacyExternalLens

**Description:** Returns the build manager address of the target CryptoLegacy.

**Detailed Description:** Calls `buildManager()` on the target and returns the address.

**Parameters:**

* \_cryptoLegacy (address): Target CryptoLegacy diamond address

**Returns:**

* manager (address): Build manager address

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:**

* `ICryptoLegacy(_cryptoLegacy).buildManager()` — bubbled revert

**Overrides:** None

**Function Calls:**

* `buildManager()` — `ICryptoLegacy` *(at `_cryptoLegacy`)*, external (staticcall)

**Called by:** None (entry point)

**Gas / Complexity note:** O(1) for the forwarder.

**Example:** Call `buildManager(cl)`.

***

### owner (CLEXL1)

**Contract/Library:** CryptoLegacyExternalLens

**Description:** Returns the owner of the target CryptoLegacy.

**Detailed Description:** Calls `owner()` on the target and returns the address.

**Parameters:**

* \_cryptoLegacy (address): Target CryptoLegacy diamond address

**Returns:**

* owner\_ (address): Current owner address

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:**

* `ICryptoLegacy(_cryptoLegacy).owner()` — bubbled revert

**Overrides:** None

**Function Calls:**

* `owner()` — `ICryptoLegacy` *(at `_cryptoLegacy`)*, external (staticcall)

**Called by:** None (entry point)

**Gas / Complexity note:** O(1) for the forwarder.

**Example:** Call `owner(cl)`.

***

### \_baseData (CLEXL1)

**Contract/Library:** CryptoLegacyExternalLens

**Description:** Internal helper that fetches base lens data from the target.

**Detailed Description:** Calls `getCryptoLegacyBaseData()` on the target lens interface and returns the struct.

**Parameters:**

* \_cryptoLegacy (address): Target CryptoLegacy diamond address

**Returns:**

* data ([ICryptoLegacyLens.CryptoLegacyBaseData](https://docs.cryptolegacy.app/documentation/data-structures-reference#cryptolegacybasedata-icll1-s3), memory): Base data snapshot

**Modifiers / Visibility / Mutability:**

* internal view

**Access Control:**

* Internal only

**Side Effects:** None

**Emits:** None

**Reverts if:**

* `ICryptoLegacyLens(_cryptoLegacy).getCryptoLegacyBaseData()` — may revert with [`FunctionNotExists(bytes4)`](https://docs.cryptolegacy.app/documentation/errors-reference#functionnotexists-icldb1) (bubbled via diamond)

**Overrides:** None

**Function Calls:**

* [getCryptoLegacyBaseData()](#getcryptolegacybasedata-lp1) — `ICryptoLegacyLens` *(at `_cryptoLegacy`)*, external (staticcall)

**Called by:**

* [getCryptoLegacyBaseData(address)](#getcryptolegacybasedata-clexl1) — CryptoLegacyExternalLens

**Gas / Complexity note:** O(1) for the helper.

**Example:** Not applicable

***

### \_listTokensData (CLEXL1)

**Contract/Library:** CryptoLegacyExternalLens

**Description:** Internal helper that fetches list data for specified tokens.

**Detailed Description:** Calls `getCryptoLegacyListData(address[])` on the target lens interface with the provided tokens.

**Parameters:**

* \_cryptoLegacy (address): Target CryptoLegacy diamond address
* \_tokens (address\[], memory): ERC-20 token addresses to include

**Returns:**

* data ([ICryptoLegacyLens.CryptoLegacyListData](https://docs.cryptolegacy.app/documentation/data-structures-reference#cryptolegacylistdata-icll1-s5), memory): Aggregated list data

**Modifiers / Visibility / Mutability:**

* internal view

**Access Control:**

* Unrestricted (internal)

**Side Effects:** None

**Emits:** None

**Reverts if:**

* `ICryptoLegacyLens(_cryptoLegacy).getCryptoLegacyListData(address[])` — may revert with [`FunctionNotExists(bytes4)`](https://docs.cryptolegacy.app/documentation/errors-reference#functionnotexists-icldb1) (bubbled via diamond)
* `ICryptoLegacyPlugin(facet).getPluginName()` — may revert per plugin implementation (bubbled via target lens)
* `ICryptoLegacyPlugin(facet).getPluginVer()` — may revert per plugin implementation (bubbled via target lens)
* `cls.buildManager.pluginsRegistry().getPluginDescriptionBlockNumbers(facet)` — may revert per registry implementation (bubbled via target lens)

**Overrides:** None

**Function Calls:**

* [getCryptoLegacyListData(address\[\])](#getcryptolegacylistdata-lp1) — `ICryptoLegacyLens` *(at `_cryptoLegacy`)*, external (staticcall)

**Called by:**

* [getCryptoLegacyListData(address,address\[\])](#getcryptolegacylistdata-clexl1) — CryptoLegacyExternalLens

**Gas / Complexity note:** O(1) for the helper; target cost scales with `_tokens.length` plus full beneficiary and plugin counts on the target lens.

**Example:** Not applicable

***

### updateInterval (CLEXL1)

**Contract/Library:** CryptoLegacyExternalLens

**Description:** Returns the update interval of the target.

**Detailed Description:** Calls `updateInterval()` on the Lens plugin at the target address.

**Parameters:**

* \_cryptoLegacy (address): Target CryptoLegacy diamond address

**Returns:**

* interval (uint64): Update interval in seconds

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:**

* `LensPlugin(_cryptoLegacy).updateInterval()` — may revert with [`FunctionNotExists(bytes4)`](https://docs.cryptolegacy.app/documentation/errors-reference#functionnotexists-icldb1) (bubbled via diamond)

**Overrides:** None

**Function Calls:**

* [updateInterval()](#updateinterval-lp1) — `LensPlugin` *(at `_cryptoLegacy`)*, external (staticcall)

**Called by:** None (entry point)

**Gas / Complexity note:** O(1) for the forwarder; target cost is O(1).

**Example:** Call `updateInterval(cl)`.

***

### challengeTimeout (CLEXL1)

**Contract/Library:** CryptoLegacyExternalLens

**Description:** Returns the challenge timeout of the target.

**Detailed Description:** Calls `challengeTimeout()` on the Lens plugin at the target address.

**Parameters:**

* \_cryptoLegacy (address): Target CryptoLegacy diamond address

**Returns:**

* timeout (uint64): Challenge timeout in seconds

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:**

* `LensPlugin(_cryptoLegacy).challengeTimeout()` — may revert with [`FunctionNotExists(bytes4)`](https://docs.cryptolegacy.app/documentation/errors-reference#functionnotexists-icldb1) (bubbled via diamond)

**Overrides:** None

**Function Calls:**

* [challengeTimeout()](#challengetimeout-lp1) — `LensPlugin` *(at `_cryptoLegacy`)*, external (staticcall)

**Called by:** None (entry point)

**Gas / Complexity note:** O(1) for the forwarder; target cost is O(1).

**Example:** Call `challengeTimeout(cl)`.

***

### distributionStartAt (CLEXL1)

**Contract/Library:** CryptoLegacyExternalLens

**Description:** Returns the distribution start timestamp.

**Detailed Description:** Calls `distributionStartAt()` on the Lens plugin at the target address.

**Parameters:**

* \_cryptoLegacy (address): Target CryptoLegacy diamond address

**Returns:**

* start (uint64): Start timestamp (UNIX)

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:**

* `LensPlugin(_cryptoLegacy).distributionStartAt()` — may revert with [`FunctionNotExists(bytes4)`](https://docs.cryptolegacy.app/documentation/errors-reference#functionnotexists-icldb1) (bubbled via diamond)

**Overrides:** None

**Function Calls:**

* [distributionStartAt()](#distributionstartat-lp1) — `LensPlugin` *(at `_cryptoLegacy`)*, external (staticcall)

**Called by:** None (entry point)

**Gas / Complexity note:** O(1) for the forwarder; target cost is O(1).

**Example:** Call `distributionStartAt(cl)`.

***

### lastFeePaidAt (CLEXL1)

**Contract/Library:** CryptoLegacyExternalLens

**Description:** Returns the timestamp of the last fee payment.

**Detailed Description:** Calls `lastFeePaidAt()` on the Lens plugin at the target address.

**Parameters:**

* \_cryptoLegacy (address): Target CryptoLegacy diamond address

**Returns:**

* paidAt (uint64): Timestamp of the last fee payment

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:**

* `LensPlugin(_cryptoLegacy).lastFeePaidAt()` — may revert with [`FunctionNotExists(bytes4)`](https://docs.cryptolegacy.app/documentation/errors-reference#functionnotexists-icldb1) (bubbled via diamond)

**Overrides:** None

**Function Calls:**

* [lastFeePaidAt()](#lastfeepaidat-lp1) — `LensPlugin` *(at `_cryptoLegacy`)*, external (staticcall)

**Called by:** None (entry point)

**Gas / Complexity note:** O(1) for the forwarder; target cost is O(1).

**Example:** Call `lastFeePaidAt(cl)`.

***

### lastUpdateAt (CLEXL1)

**Contract/Library:** CryptoLegacyExternalLens

**Description:** Returns the timestamp of the last update.

**Detailed Description:** Calls `lastUpdateAt()` on the Lens plugin at the target address.

**Parameters:**

* \_cryptoLegacy (address): Target CryptoLegacy diamond address

**Returns:**

* updatedAt (uint64): Timestamp of the last update

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:**

* `LensPlugin(_cryptoLegacy).lastUpdateAt()` — may revert with [`FunctionNotExists(bytes4)`](https://docs.cryptolegacy.app/documentation/errors-reference#functionnotexists-icldb1) (bubbled via diamond)

**Overrides:** None

**Function Calls:**

* [lastUpdateAt()](#lastupdateat-lp1) — `LensPlugin` *(at `_cryptoLegacy`)*, external (staticcall)

**Called by:** None (entry point)

**Gas / Complexity note:** O(1) for the forwarder; target cost is O(1).

**Example:** Call `lastUpdateAt(cl)`.

***

### initialFeeToPay (CLEXL1)

**Contract/Library:** CryptoLegacyExternalLens

**Description:** Returns the initial fee required by the target.

**Detailed Description:** Calls `initialFeeToPay()` on the Lens plugin at the target address.

**Parameters:**

* \_cryptoLegacy (address): Target CryptoLegacy diamond address

**Returns:**

* fee (uint128): Initial fee in wei

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:**

* `LensPlugin(_cryptoLegacy).initialFeeToPay()` — may revert with [`FunctionNotExists(bytes4)`](https://docs.cryptolegacy.app/documentation/errors-reference#functionnotexists-icldb1) (bubbled via diamond)

**Overrides:** None

**Function Calls:**

* [initialFeeToPay()](#initialfeetopay-lp1) — `LensPlugin` *(at `_cryptoLegacy`)*, external (staticcall)

**Called by:** None (entry point)

**Gas / Complexity note:** O(1) for the forwarder; target cost is O(1).

**Example:** Call `initialFeeToPay(cl)`.

***

### updateFee (CLEXL1)

**Contract/Library:** CryptoLegacyExternalLens

**Description:** Returns the update fee required by the target.

**Detailed Description:** Calls `updateFee()` on the Lens plugin at the target address.

**Parameters:**

* \_cryptoLegacy (address): Target CryptoLegacy diamond address

**Returns:**

* fee (uint128): Update fee in wei

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:**

* `LensPlugin(_cryptoLegacy).updateFee()` — may revert with [`FunctionNotExists(bytes4)`](https://docs.cryptolegacy.app/documentation/errors-reference#functionnotexists-icldb1) (bubbled)

**Overrides:** None

**Function Calls:**

* [updateFee()](#updatefee-lp1) — `LensPlugin` *(at `_cryptoLegacy`)*, external (staticcall)

**Called by:** None (entry point)

**Gas / Complexity note:** O(1) for the forwarder; target cost is O(1).

**Example:** Call `updateFee(cl)`.

***

### invitedByRefCode (CLEXL1)

**Contract/Library:** CryptoLegacyExternalLens

**Description:** Returns the referral code associated with the target.

**Detailed Description:** Calls `invitedByRefCode()` on the Lens plugin at the target address.

**Parameters:**

* \_cryptoLegacy (address): Target CryptoLegacy diamond address

**Returns:**

* refCode (bytes8): Referral code

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:**

* `LensPlugin(_cryptoLegacy).invitedByRefCode()` — may revert with [`FunctionNotExists(bytes4)`](https://docs.cryptolegacy.app/documentation/errors-reference#functionnotexists-icldb1) (bubbled)

**Overrides:** None

**Function Calls:**

* [invitedByRefCode()](#invitedbyrefcode-lp1) — `LensPlugin` *(at `_cryptoLegacy`)*, external (staticcall)

**Called by:** None (entry point)

**Gas / Complexity note:** O(1) for the forwarder; target cost is O(1).

**Example:** Call `invitedByRefCode(cl)`.

***

### getBeneficiaries (CLEXL1)

**Contract/Library:** CryptoLegacyExternalLens

**Description:** Returns beneficiaries and their configs from the target.

**Detailed Description:** Calls `getBeneficiaries()` on the Lens plugin and returns hashes, original hashes, and configs.

**Parameters:**

* \_cryptoLegacy (address): Target CryptoLegacy diamond address

**Returns:**

* hashes (bytes32\[], memory): Beneficiary hashes (keccak256 of beneficiary addresses)
* originalHashes (bytes32\[], memory): Original beneficiary hashes
* configs ([ICryptoLegacy.BeneficiaryConfig](https://docs.cryptolegacy.app/documentation/data-structures-reference#beneficiaryconfig-icl1-s1)\[], memory): Config objects per beneficiary

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:**

* `LensPlugin(_cryptoLegacy).getBeneficiaries()` — may revert with [`FunctionNotExists(bytes4)`](https://docs.cryptolegacy.app/documentation/errors-reference#functionnotexists-icldb1) (bubbled)

**Overrides:** None

**Function Calls:**

* [getBeneficiaries()](#getbeneficiaries-lp1) — `LensPlugin` *(at `_cryptoLegacy`)*, external (staticcall)

**Called by:** None (entry point)

**Gas / Complexity note:** O(1) for the forwarder; target cost is O(n) by beneficiaries count.

**Example:** Call `getBeneficiaries(cl)`.

***

### getTokensDistribution (CLEXL1)

**Contract/Library:** CryptoLegacyExternalLens

**Description:** Returns token distribution info for a token list.

**Detailed Description:** Calls `getTokensDistribution(address[])` on the Lens plugin for the provided tokens.

**Parameters:**

* \_cryptoLegacy (address): Target CryptoLegacy diamond address
* \_tokens (address\[], calldata): Token addresses to query

**Returns:**

* list ([ICryptoLegacyLens.LensTokenDistribution](https://docs.cryptolegacy.app/documentation/data-structures-reference#lenstokendistribution-icll1-s4)\[], memory): Distribution data per token

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:**

* `LensPlugin(_cryptoLegacy).getTokensDistribution(_tokens)` — may revert with [`FunctionNotExists(bytes4)`](https://docs.cryptolegacy.app/documentation/errors-reference#functionnotexists-icldb1) (bubbled)

**Overrides:** None

**Function Calls:**

* [getTokensDistribution(address\[\])](#gettokensdistribution-lp1) — `LensPlugin` *(at `_cryptoLegacy`)*, external (staticcall)

**Called by:** None (entry point)

**Gas / Complexity note:** O(1) for the forwarder; target cost is O(n) by `_tokens.length`.

**Example:** Call `getTokensDistribution(cl, tokens)`.

***

### getCryptoLegacyBaseData (CLEXL1)

**Contract/Library:** CryptoLegacyExternalLens

**Description:** Returns consolidated base data for the target.

**Detailed Description:** Takes `_cryptoLegacy`, forwards to `_baseData`, and returns the struct it receives from the target lens interface unchanged. The function performs no validation or state changes; any failure from the target call bubbles up to the caller.

**Parameters:**

* \_cryptoLegacy (address): Target CryptoLegacy diamond address

**Returns:**

* data ([ICryptoLegacyLens.CryptoLegacyBaseData](https://docs.cryptolegacy.app/documentation/data-structures-reference#cryptolegacybasedata-icll1-s3), memory): Base data snapshot

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:**

* `ICryptoLegacyLens(_cryptoLegacy).getCryptoLegacyBaseData()` — may revert with [`FunctionNotExists(bytes4)`](https://docs.cryptolegacy.app/documentation/errors-reference#functionnotexists-icldb1) (bubbled via diamond)

**Overrides:** None

**Function Calls:**

* [\_baseData(address)](#_basedata-clexl1) — CryptoLegacyExternalLens, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1) for the forwarder; target cost is O(1).

**Example:** Call `getCryptoLegacyBaseData(cl)`.

***

### getCryptoLegacyListData (CLEXL1)

**Contract/Library:** CryptoLegacyExternalLens

**Description:** Returns aggregated list data for specified tokens.

**Detailed Description:** Takes `_cryptoLegacy` and `_tokens`, forwards them to `_listTokensData`, and returns the target’s [`CryptoLegacyListData`](https://docs.cryptolegacy.app/documentation/data-structures-reference#cryptolegacylistdata-icll1-s5) struct unchanged. The forwarder itself does no filtering or verification; all aggregation and any plugin lookups happen inside the target lens call, and its errors bubble up.

**Parameters:**

* \_cryptoLegacy (address): Target CryptoLegacy diamond address
* \_tokens (address\[], memory): Token addresses to include

**Returns:**

* data ([ICryptoLegacyLens.CryptoLegacyListData](https://docs.cryptolegacy.app/documentation/data-structures-reference#cryptolegacylistdata-icll1-s5), memory): Aggregated token and plugin data

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:**

* `ICryptoLegacyLens(_cryptoLegacy).getCryptoLegacyListData(_tokens)` — may revert with [`FunctionNotExists(bytes4)`](https://docs.cryptolegacy.app/documentation/errors-reference#functionnotexists-icldb1) (bubbled via diamond)
* `ICryptoLegacyPlugin(facet).getPluginName()` — may revert per plugin implementation (bubbled via target lens)
* `ICryptoLegacyPlugin(facet).getPluginVer()` — may revert per plugin implementation (bubbled via target lens)
* `cls.buildManager.pluginsRegistry().getPluginDescriptionBlockNumbers(facet)` — may revert per registry implementation (bubbled via target lens)

**Overrides:** None

**Function Calls:**

* [\_listTokensData(address,address\[\])](#_listtokensdata-clexl1) — CryptoLegacyExternalLens, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1) for the forwarder; helper’s target cost is O(b + p + t·b) where b = beneficiaries, p = plugins, t = `_tokens.length`.

**Example:** Call `getCryptoLegacyListData(cl, tokens)`.

***

### getMessagesBlockNumbersByRecipient (CLEXL1)

**Contract/Library:** CryptoLegacyExternalLens

**Description:** Returns message block numbers for a recipient hash.

**Detailed Description:** Passes `_recipient` to the target lens interface’s `getMessagesBlockNumbersByRecipient(bytes32)` and returns the resulting list unchanged. The forwarder does no recipient validation and does not mutate state; if the target has no records for the hash, it returns an empty array.

**Parameters:**

* \_cryptoLegacy (address): Target CryptoLegacy diamond address
* \_recipient (bytes32): Recipient identifier hash

**Returns:**

* blockNumbers (uint64\[], memory): Block numbers for recipient messages

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:**

* `ICryptoLegacyLens(_cryptoLegacy).getMessagesBlockNumbersByRecipient(_recipient)` — may revert with [`FunctionNotExists(bytes4)`](https://docs.cryptolegacy.app/documentation/errors-reference#functionnotexists-icldb1) (bubbled via diamond)

**Overrides:** None

**Function Calls:**

* [getMessagesBlockNumbersByRecipient(bytes32)](#getmessagesblocknumbersbyrecipient-lp1) — `ICryptoLegacyLens` *(at `_cryptoLegacy`)*, external (staticcall)

**Called by:** None (entry point)

**Gas / Complexity note:** O(1) for the forwarder; target cost is O(m) by number of stored message checkpoints.

**Example:** Call `getMessagesBlockNumbersByRecipient(cl, recipientHash)`.

***

### getTransferBlockNumbers (CLEXL1)

**Contract/Library:** CryptoLegacyExternalLens

**Description:** Returns block numbers where transfers occurred.

**Detailed Description:** Calls the target’s Lens plugin `getTransferBlockNumbers()` and returns the list unchanged. The function is a read-only forwarder; if the lens facet is not installed on the target, the diamond fallback reverts.

**Parameters:**

* \_cryptoLegacy (address): Target CryptoLegacy diamond address

**Returns:**

* blockNumbers (uint64\[], memory): Transfer block numbers

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:**

* `LensPlugin(_cryptoLegacy).getTransferBlockNumbers()` — may revert with [`FunctionNotExists(bytes4)`](https://docs.cryptolegacy.app/documentation/errors-reference#functionnotexists-icldb1) (bubbled via diamond)

**Overrides:** None

**Function Calls:**

* [getTransferBlockNumbers()](#gettransferblocknumbers-lp1) — `LensPlugin` *(at `_cryptoLegacy`)*, external (staticcall)

**Called by:** None (entry point)

**Gas / Complexity note:** O(1) for the forwarder; target cost is O(t) by number of stored transfer checkpoints.

**Example:** Call `getTransferBlockNumbers(cl)`.

***

### getVestedAndClaimedData (CLEXL1)

**Contract/Library:** CryptoLegacyExternalLens

**Description:** Returns vesting/claimed data for a beneficiary across tokens.

**Detailed Description:** Calls `getVestedAndClaimedData(bytes32,address[])` on the target lens interface and returns per-token results plus start/end dates.

**Parameters:**

* \_cryptoLegacy (address): Target CryptoLegacy diamond address
* \_beneficiary (bytes32): Beneficiary identifier hash
* \_tokens (address\[], calldata): Token addresses to query

**Returns:**

* result ([ICryptoLegacyLens.BeneficiaryTokenData](https://docs.cryptolegacy.app/documentation/data-structures-reference#beneficiarytokendata-icll1-s1)\[], memory): Per-token data
* startDate (uint64): Vesting start timestamp
* endDate (uint64): Vesting end timestamp

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:**

* `ICryptoLegacyLens(_cryptoLegacy).getVestedAndClaimedData(_beneficiary, _tokens)` — may revert with [`FunctionNotExists(bytes4)`](https://docs.cryptolegacy.app/documentation/errors-reference#functionnotexists-icldb1) (bubbled via diamond)
* `ICryptoLegacyLens(_cryptoLegacy).getVestedAndClaimedData(_beneficiary, _tokens)` — may revert with [`ICryptoLegacy.BeneficiaryNotExist()`](https://docs.cryptolegacy.app/documentation/errors-reference#beneficiarynotexist-icl1) (bubbled)
* `IERC20(_tokensi).balanceOf(address(this))` — may revert per token implementation (bubbled via lens)

**Overrides:** None

**Function Calls:**

* [getVestedAndClaimedData(bytes32,address\[\])](#getvestedandclaimeddata-lp1) — `ICryptoLegacyLens` *(at `_cryptoLegacy`)*, external (staticcall)

**Called by:** None (entry point)

**Gas / Complexity note:** O(1) for the forwarder; target cost is O(n) by `_tokens.length`.

**Example:** Call `getVestedAndClaimedData(cl, beneficiaryHash, tokens)`.

***

### getPluginInfoList (CLEXL1)

**Contract/Library:** CryptoLegacyExternalLens

**Description:** Returns plugin metadata installed on the target.

**Detailed Description:** Calls `getPluginInfoList()` on the Lens plugin to fetch plugin list and metadata.

**Parameters:**

* \_cryptoLegacy (address): Target CryptoLegacy diamond address

**Returns:**

* plugins ([ICryptoLegacyLens.PluginInfo](https://docs.cryptolegacy.app/documentation/data-structures-reference#plugininfo-ipr1-s1)\[], memory): Plugin info array

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:**

* `LensPlugin(_cryptoLegacy).getPluginInfoList()` — may revert with [`FunctionNotExists(bytes4)`](https://docs.cryptolegacy.app/documentation/errors-reference#functionnotexists-icldb1) (bubbled via diamond)
* `ICryptoLegacyPlugin(facet).getPluginName()` — may revert per plugin implementation (bubbled via LensPlugin)
* `ICryptoLegacyPlugin(facet).getPluginVer()` — may revert per plugin implementation (bubbled via LensPlugin)
* `cls.buildManager.pluginsRegistry().getPluginDescriptionBlockNumbers(facet)` — may revert per registry implementation (bubbled via LensPlugin)

**Overrides:** None

**Function Calls:**

* [getPluginInfoList()](#getplugininfolist-lp1) — `LensPlugin` *(at `_cryptoLegacy`)*, external (staticcall)

**Called by:** None (entry point)

**Gas / Complexity note:** O(1) for the forwarder; target cost is O(n) by plugins count.

**Example:** Call `getPluginInfoList(cl)`.

***

### getCryptoLegacyListWithStatuses (CLEXL1)

**Contract/Library:** CryptoLegacyExternalLens

**Description:** Returns CryptoLegacy addresses for all roles tied to a hash plus default-guardian status per beneficiary entry.

**Detailed Description:** Fetches role-based lists from the Beneficiary Registry; then for each beneficiary-list address, attempts `isGuardiansInitialized()`. Sets `beneficiaryDefaultGuardiani = !isInitialized`; failures are ignored via try/catch.

**Parameters:**

* \_beneficiaryRegistry (IBeneficiaryRegistry): Beneficiary registry contract
* \_hash (bytes32): Identifier hash reused across roles

**Returns:**

* listByBeneficiary (address\[], memory): Contracts where `_hash` is a beneficiary
* beneficiaryDefaultGuardian (bool\[], memory): True if default guardians are used (not initialized)
* listByOwner (address\[], memory): Contracts where `_hash` is an owner
* listByGuardian (address\[], memory): Contracts where `_hash` is a guardian
* listByRecovery (address\[], memory): Contracts where `_hash` is a recovery address

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:**

* `_beneficiaryRegistry.getAllCryptoLegacyListByRoles(_hash)` — may revert per implementation (bubbled)

**Overrides:** None

**Function Calls:**

* [getAllCryptoLegacyListByRoles(bytes32)](#getallcryptolegacylistbyroles-ibr1) — `IBeneficiaryRegistry` *(at `_beneficiaryRegistry`)*, external (staticcall)
* [isGuardiansInitialized()](#isguardiansinitialized-itgp1) — `ITrustedGuardiansPlugin` *(at `listByBeneficiaryi`)*, external (staticcall)

**Called by:** None (entry point)

**Gas / Complexity note:** O(n\_b + n\_o + n\_g + n\_r) for fetching role-based lists from the registry, plus O(n\_beneficiary) for the per-beneficiary `isGuardiansInitialized()` checks.

**Example:** Call `getCryptoLegacyListWithStatuses(registry, userHash)`.

***

## CryptoLegacyFactory (CLF1)

### constructor (CLF1)

**Contract/Library:** CryptoLegacyFactory

**Description:** Initializes the factory and sets the initial owner.

**Detailed Description:** Transfers ownership to `_owner` by calling OpenZeppelin Ownable's internal `_transferOwnership`. Executed once at deployment.

**Parameters:**

* \_owner (address): Address to be set as the initial owner

**Returns:** None

**Modifiers / Visibility / Mutability:**

* constructor nonpayable

**Access Control:**

* Unrestricted (deployment only)

**Side Effects:**

* Sets `owner` (Ownable storage)

**Emits:**

* [OwnershipTransferred](https://docs.cryptolegacy.app/documentation/events-reference#ownershiptransferred-iclo1) — `OwnershipTransferred(address indexed previousOwner, address indexed newOwner)`

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* `Ownable._transferOwnership(address)` — `Ownable`, internal

**Called by:**

None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Deploy with `new CryptoLegacyFactory(admin)`.

***

### setBuildOperator (CLF1)

**Contract/Library:** CryptoLegacyFactory

**Description:** Adds or removes an authorized build operator.

**Detailed Description:** If `_isAdd` is true, inserts `_operator` into [`buildOperators`](https://docs.cryptolegacy.app/documentation/data-structures-reference#buildoperators-clf1-d1); otherwise removes it. Emits the corresponding event.

**Parameters:**

* \_operator (address): Address to add or remove as a build operator
* \_isAdd (bool): True to add, false to remove

**Returns:** None

**Modifiers / Visibility / Mutability:**

* public nonpayable onlyOwner

**Access Control:**

* onlyOwner

**Side Effects:**

* Mutates [`buildOperators`](https://docs.cryptolegacy.app/documentation/data-structures-reference#buildoperators-clf1-d1) set (add/remove)

**Emits:**

* [AddBuildOperator](https://docs.cryptolegacy.app/documentation/events-reference#addbuildoperator-iclf1) — `AddBuildOperator(address indexed buildOperator)`
* [RemoveBuildOperator](https://docs.cryptolegacy.app/documentation/events-reference#removebuildoperator-iclf1) — `RemoveBuildOperator(address indexed buildOperator)`

**Reverts if:**

* Caller is not the owner — "Ownable: caller is not the owner"

**Overrides:** None

**Function Calls:**

* `add(address)` — `EnumerableSet.AddressSet`, internal
* `remove(address)` — `EnumerableSet.AddressSet`, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1) average (EnumerableSet operations)

**Example:** Owner calls `setBuildOperator(op, true)` to authorize `op` to deploy contracts.

***

### createCryptoLegacy (CLF1)

**Contract/Library:** CryptoLegacyFactory

**Description:** Deploys a new `CryptoLegacy` contract at a deterministic address using CREATE3.

**Detailed Description:** Requires `msg.sender` to be a registered build operator. Assembles the constructor bytecode with [`cryptoLegacyBytecode`](#cryptolegacybytecode-clf1), using `msg.sender` as `_buildManager`, and deploys via `LibCryptoLegacyDeploy._deployByCreate3`, passing `_create2Args.create2Salt` and `_create2Args.create2Address`. If `_create2Args.create2Salt` is zero, `_deployByCreate3` substitutes it with `blockhash(block.number - 1)`, so any precomputed `_create2Args.create2Address` must use that effective salt or it will mismatch. Returns the deployed address as payable.

**Parameters:**

* \_owner (address): Owner of the newly deployed CryptoLegacy
* \_plugins (address\[], memory): Plugins to initialize with the new CryptoLegacy
* \_create2Args ([Create2Args](https://docs.cryptolegacy.app/documentation/data-structures-reference#create2args-iclf1-s1), memory): Deployment parameters: `create2Address` (expected address) and `create2Salt` (salt)

**Returns:**

* deployed (address payable): Address of the newly deployed CryptoLegacy

**Modifiers / Visibility / Mutability:**

* external nonpayable

**Access Control:**

* Build operators only (address must be present in [`buildOperators`](https://docs.cryptolegacy.app/documentation/data-structures-reference#buildoperators-clf1-d1))

**Side Effects:**

* Creates a new contract via `CREATE3` through `LibCryptoLegacyDeploy`
* No factory storage mutated

**Emits:**

* [CryptoLegacyCreation](https://docs.cryptolegacy.app/documentation/events-reference#cryptolegacycreation-lcld1) — `CryptoLegacyCreation(address addr, bytes32 salt, bytes32 userSalt)`

**Reverts if:**

* [`buildOperators.contains(msg.sender) == false`](https://docs.cryptolegacy.app/documentation/data-structures-reference#buildoperators-clf1-d1) — [`NotBuildOperator()`](https://docs.cryptolegacy.app/documentation/errors-reference#notbuildoperator-iclf1)
* Constructor bytecode length == 0 — [`BytecodeEmpty()`](https://docs.cryptolegacy.app/documentation/errors-reference#bytecodeempty-lcld1) (bubbled via `LibCryptoLegacyDeploy._deployByCreate3`)
* `_create2Args.create2Salt == 0` and `block.number == 0` — `panic(0x11)` (bubbled via `LibCryptoLegacyDeploy._deployByCreate3`)
* `_create2Args.create2Address` provided but mismatched (e.g., when `_create2Args.create2Salt == 0` and the address was computed without the `blockhash(block.number - 1)` substitution) — [`AddressMismatch()`](https://docs.cryptolegacy.app/documentation/errors-reference#addressmismatch-lcld1) (bubbled via `LibCryptoLegacyDeploy._deployByCreate3`)
* `LibCreate3.create3(...)` — may revert with [`TargetAlreadyExists()`](https://docs.cryptolegacy.app/documentation/errors-reference#targetalreadyexists-lc31), [`ErrorCreatingProxy()`](https://docs.cryptolegacy.app/documentation/errors-reference#errorcreatingproxy-lc31), or [`ErrorCreatingContract()`](https://docs.cryptolegacy.app/documentation/errors-reference#errorcreatingcontract-lc31) (bubbled via `LibCryptoLegacyDeploy._deployByCreate3`)

**Overrides:** None

**Function Calls:**

* `contains(address)` — `EnumerableSet.AddressSet`, internal
* [cryptoLegacyBytecode(address,address,address\[\])](#cryptolegacybytecode-clf1) — CryptoLegacyFactory, internal
* [\_deployByCreate3(address,bytes32,address,bytes)](#_deploybycreate3-lcld1) — `LibCryptoLegacyDeploy`, internal

**Called by:**

* [buildCryptoLegacy(BuildArgs,RefArgs,ICryptoLegacyFactory.Create2Args)](#buildcryptolegacy-clbm1) — CryptoLegacyBuildManager

**Gas / Complexity note:** O(1) in factory; external deployment cost dominates

**Example:** Authorized operator calls `createCryptoLegacy(user, plugins, args)` to deploy a user's CryptoLegacy contract.

***

### cryptoLegacyBytecode (CLF1)

**Contract/Library:** CryptoLegacyFactory

**Description:** Returns the full constructor bytecode for a `CryptoLegacy` deployment.

**Detailed Description:** Concatenates `type(CryptoLegacy).creationCode` with ABI‑encoded constructor arguments `_buildManager`, `_owner`, `_plugins`.

**Parameters:**

* \_buildManager (address): Build manager address to pass to the constructor
* \_owner (address): Owner address to pass to the constructor
* \_plugins (address\[], memory): Plugin list to pass to the constructor

**Returns:**

* bytecode (bytes, memory): Complete deployment bytecode

**Modifiers / Visibility / Mutability:**

* public virtual pure

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:**

None

**Overrides:**

None

**Function Calls:** None

**Called by:**

* [createCryptoLegacy(address,address\[\],Create2Args)](#createcryptolegacy-clf1) — CryptoLegacyFactory

**Gas / Complexity note:** O(n) by `_plugins.length` (ABI encode cost); everything else is O(1)

**Example:** Call `cryptoLegacyBytecode(buildManager, owner, plugins)` to get deployment bytecode.

***

### computeAddress (CLF1)

**Contract/Library:** CryptoLegacyFactory

**Description:** Computes the deterministic address for a future `CryptoLegacy` deployment.

**Detailed Description:** Computes and returns the deterministic address where a `CryptoLegacy` contract would be deployed, given `_salt` and `_contractOwner`. This does not apply the zero-salt substitution used by `createCryptoLegacy` (it uses the salt as provided), so callers must pass the effective salt they intend to use. Does not perform deployment.

**Parameters:**

* \_salt (bytes32): Deployment salt
* \_contractOwner (address): Future owner used in address derivation

**Returns:**

* result (address): Predicted deployment address

**Modifiers / Visibility / Mutability:**

* public view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:**

None

**Overrides:** None

**Function Calls:**

* [\_computeAddress(bytes32,address)](#_computeaddress-lcld1) — `LibCryptoLegacyDeploy`, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Call `computeAddress(salt, owner)` to pre-compute where the contract will be deployed.

***

## CryptoLegacyOwnable (CLO1)

### modifier onlyOwner (CLO1)

**Contract/Library:** CryptoLegacyOwnable

**Description:** Restricts execution to the current contract owner.

**Detailed Description:** Invokes an ownership check before the function body executes; reverts if `msg.sender` is not the owner or initial fee/distribution checks fail.

**Parameters:** None

**Returns:** None

**Modifiers / Visibility / Mutability:**

* modifier nonpayable

**Access Control:**

* Owner only (enforced by `LibCryptoLegacy._checkOwner`)

**Side Effects:** None

**Emits:** None

**Reverts if:**

* Distribution has already started — [`DistributionStarted()`](https://docs.cryptolegacy.app/documentation/errors-reference#distributionstarted-icl1)
* Initial fee not paid — [`InitialFeeNotPaid()`](https://docs.cryptolegacy.app/documentation/errors-reference#initialfeenotpaid-icl1)
* Caller is not the owner — [`NotTheOwner()`](https://docs.cryptolegacy.app/documentation/errors-reference#nottheowner-icl1)

**Overrides:** None

**Function Calls:**

* [\_checkOwner()](#_checkowner-lcl1) — `LibCryptoLegacy`, internal

**Called by:**

* [setPause(bool)](#setpause-clo1) — CryptoLegacyOwnable
* [replacePlugin(address\[\],address\[\])](#replaceplugin-cl1) — CryptoLegacy
* [addPluginList(address\[\])](#addpluginlist-cl1) — CryptoLegacy
* [removePluginList(address\[\])](#removepluginlist-cl1) — CryptoLegacy
* [transferOwnership(address)](#transferownership-clbp1) — CryptoLegacyBasePlugin
* [setBeneficiaries(bytes32\[\],BeneficiaryConfig\[\])](#setbeneficiaries-clbp1) — CryptoLegacyBasePlugin
* [update(uint256\[\],uint256\[\])](#update-clbp1) — CryptoLegacyBasePlugin
* [setGasLimitMultiplier(uint8)](#setgaslimitmultiplier-clbp1) — CryptoLegacyBasePlugin
* [sendMessagesToBeneficiary(bytes32\[\],bytes32\[\],bytes\[\],bytes\[\],uint256)](#sendmessagestobeneficiary-clbp1) — CryptoLegacyBasePlugin

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### \_transferOwnership (CLO1)

**Contract/Library:** CryptoLegacyOwnable

**Description:** Starts a two-step ownership transfer by setting `pendingOwner` and emitting the start event.

**Detailed Description:** Validates the new owner is non-zero, writes `pendingOwner` in storage, and emits `OwnershipTransferStarted(previousOwner, newOwner)`. Finalization is performed by `acceptOwnership()`.

**Parameters:**

* cls ([ICryptoLegacy.CryptoLegacyStorage](https://docs.cryptolegacy.app/documentation/data-structures-reference#cryptolegacystorage-icl1-s4), storage): Contract storage reference
* \_owner (address): Address proposed as the new owner

**Returns:** None

**Modifiers / Visibility / Mutability:**

* internal virtual nonpayable

**Access Control:**

* Intended for internal use by inheriting contracts

**Side Effects:**

* Updates `cls.pendingOwner`

**Emits:**

* [OwnershipTransferStarted](https://docs.cryptolegacy.app/documentation/events-reference#ownershiptransferstarted-iclo1) — OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner)

**Reverts if:**

* \_owner == address(0) — [`ZeroAddress()`](https://docs.cryptolegacy.app/documentation/errors-reference#zeroaddress-icl1)

**Overrides:** None

**Function Calls:**

* [contractOwner()](#contractowner-ld1) — `LibDiamond`, internal

**Called by:**

* [transferOwnership(address)](#transferownership-clbp1) — CryptoLegacyBasePlugin

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### acceptOwnership (CLO1)

**Contract/Library:** CryptoLegacyOwnable

**Description:** Completes the two-step ownership transfer by moving ownership to `msg.sender`.

**Detailed Description:** Loads storage, checks `msg.sender` equals `pendingOwner`, updates the beneficiary registry about the new owner, sets the diamond owner, and clears `pendingOwner`.

**Parameters:** None

**Returns:** None

**Modifiers / Visibility / Mutability:**

* public virtual nonpayable

**Access Control:**

* Only `pendingOwner` (enforced via `pendingOwner` equality check)

**Side Effects:**

* Updates owner entry in Beneficiary Registry
* Updates diamond owner in `LibDiamond` storage
* Resets `pendingOwner` to `address(0)`

**Emits:**

* [BeneficiaryRegistryCatch](https://docs.cryptolegacy.app/documentation/events-reference#beneficiaryregistrycatch-icl1) — BeneficiaryRegistryCatch(bytes reason) *(only if buildManager.beneficiaryRegistry() reverts)*
* [BeneficiaryRegistryNotDefined](https://docs.cryptolegacy.app/documentation/events-reference#beneficiaryregistrynotdefined-icl1) — BeneficiaryRegistryNotDefined() *(only if BeneficiaryRegistry address is not set)*
* [SetCryptoLegacyOwnerCatch](https://docs.cryptolegacy.app/documentation/events-reference#setcryptolegacyownercatch-icl1) — SetCryptoLegacyOwnerCatch(bytes reason) *(only if updating BeneficiaryRegistry fails)*
* [OwnershipTransferred](https://docs.cryptolegacy.app/documentation/events-reference#ownershiptransferred-iclo1) — OwnershipTransferred(address indexed previousOwner, address indexed newOwner)

**Reverts if:**

* LibCryptoLegacy.getCryptoLegacyStorage().pendingOwner != msg.sender — [`OwnableUnauthorizedAccount(address)`](https://docs.cryptolegacy.app/documentation/errors-reference#ownableunauthorizedaccount-iclo1)

**Overrides:** None

**Function Calls:**

* [getCryptoLegacyStorage()](#getcryptolegacystorage-lcl1) — `LibCryptoLegacy`, internal
* [\_updateOwnerInBeneficiaryRegistry(ICryptoLegacy.CryptoLegacyStorage,address)](#_updateownerinbeneficiaryregistry-lcl1) — `LibCryptoLegacy`, internal
* [setContractOwner(address)](#setcontractowner-ld1) — `LibDiamond`, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Pending owner calls `acceptOwnership()` to finalize ownership transfer.

***

### setPause (CLO1)

**Contract/Library:** CryptoLegacyOwnable

**Description:** Sets the pause flag for the CryptoLegacy contract.

**Detailed Description:** Owner-only setter that writes the pause state via library logic to the diamond’s storage.

**Parameters:**

* \_isPaused (bool): True to pause, false to unpause

**Returns:** None

**Modifiers / Visibility / Mutability:**

* public virtual nonpayable onlyOwner

**Access Control:**

* onlyOwner

**Side Effects:**

* Updates [`CryptoLegacyStorage.isPaused`](https://docs.cryptolegacy.app/documentation/data-structures-reference#cryptolegacystorage-icl1-s4)

**Emits:**

* [PauseSet](https://docs.cryptolegacy.app/documentation/events-reference#pauseset-icl1) — PauseSet(bool indexed isPaused)

**Reverts if:**

* Distribution already started — [`DistributionStarted()`](https://docs.cryptolegacy.app/documentation/errors-reference#distributionstarted-icl1)
* Initial fee not paid — [`InitialFeeNotPaid()`](https://docs.cryptolegacy.app/documentation/errors-reference#initialfeenotpaid-icl1)
* Caller is not the owner — [`NotTheOwner()`](https://docs.cryptolegacy.app/documentation/errors-reference#nottheowner-icl1)
* Challenge period already started — [`ChallengePeriodStarted()`](https://docs.cryptolegacy.app/documentation/errors-reference#challengeperiodstarted-icl1)

**Overrides:** None

**Function Calls:**

* [getCryptoLegacyStorage()](#getcryptolegacystorage-lcl1) — `LibCryptoLegacy`, internal
* [\_setPause(ICryptoLegacy.CryptoLegacyStorage,bool)](#_setpause-lcl1) — `LibCryptoLegacy`, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Owner calls `setPause(true)` to pause the contract.

***

### pendingOwner (CLO1)

**Contract/Library:** CryptoLegacyOwnable

**Description:** Returns the current `pendingOwner`.

**Detailed Description:** Reads and returns the `pendingOwner` field from diamond storage via library accessor.

**Parameters:** None

**Returns:**

* pending (address): Address set to accept ownership, or zero address if none

**Modifiers / Visibility / Mutability:**

* public virtual view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [getCryptoLegacyStorage()](#getcryptolegacystorage-lcl1) — `LibCryptoLegacy`, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** External caller queries `pendingOwner()` to see who can accept ownership.

***

## FeeRegistry (FR1)

### constructor (FR1)

**Contract/Library:** FeeRegistry

**Description:** Deploy-time constructor that disables initializers and sets the initial owner.

**Detailed Description:** Runs `LockChainGate`'s constructor to call `_disableInitializers()` and relies on `Ownable`'s constructor to set the deployer as owner; runtime setup is performed by [initialize](#initialize-fr1).

**Parameters:** None

**Returns:** None

**Modifiers / Visibility / Mutability:**

* constructor nonpayable

**Access Control:**

* Unrestricted (deployment only)

**Side Effects:**

* Locks the `_initialized` flags within `Initializable`
* Sets `owner` (Ownable)

**Emits:**

* [OwnershipTransferred](https://docs.cryptolegacy.app/documentation/events-reference#ownershiptransferred-iclo1) — `OwnershipTransferred(address indexed previousOwner, address indexed newOwner)`

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [constructor()](#constructor-lcg1) — LockChainGate, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### lockFeeRegistryStorage (FR1)

**Contract/Library:** FeeRegistry

**Description:** Returns a namespaced storage pointer for FeeRegistry state.

**Detailed Description:** Uses a fixed storage slot ([`FR_STORAGE_POSITION`](https://docs.cryptolegacy.app/documentation/data-structures-reference#fr_storage_position-fr1-d2)) and inline assembly to bind and return the [`FRStorage`](https://docs.cryptolegacy.app/documentation/data-structures-reference#frstorage-ifr1-s1) pointer used across the contract.

**Parameters:** None

**Returns:**

* fs ([FRStorage](https://docs.cryptolegacy.app/documentation/data-structures-reference#frstorage-ifr1-s1), storage): Storage pointer to the FeeRegistry storage layout

**Modifiers / Visibility / Mutability:**

* internal pure

**Access Control:**

* Internal only

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

None

**Called by:**

* [initialize(address,uint32,uint32,ILifetimeNft,uint64,uint64)](#initialize-fr1) — FeeRegistry
* [setCodeOperator(address,bool)](#setcodeoperator-fr1) — FeeRegistry
* [setSupportedRefCodeInChains(uint256\[\],bool)](#setsupportedrefcodeinchains-fr1) — FeeRegistry
* [setFeeBeneficiaries(FeeBeneficiary\[\])](#setfeebeneficiaries-fr1) — FeeRegistry
* [setDefaultPct(uint32,uint32)](#setdefaultpct-fr1) — FeeRegistry
* [setRefererSpecificPct(address,uint32,uint32)](#setrefererspecificpct-fr1) — FeeRegistry
* [setContractCaseFee(address,uint8,uint128)](#setcontractcasefee-fr1) — FeeRegistry
* [takeFee(address,uint8,bytes8,uint256)](#takefee-fr1) — FeeRegistry
* [withdrawAccumulatedFee()](#withdrawaccumulatedfee-fr1) — FeeRegistry
* [withdrawReferralAccumulatedFee(bytes8)](#withdrawreferralaccumulatedfee-fr1) — FeeRegistry
* [createCustomCode(address,address,bytes8,uint256\[\],uint256\[\])](#createcustomcode-fr1) — FeeRegistry
* [createCode(address,address,uint256\[\],uint256\[\])](#createcode-fr1) — FeeRegistry
* [updateCrossChainsRef(uint256\[\],uint256\[\])](#updatecrosschainsref-fr1) — FeeRegistry
* [crossCreateCustomCode(uint256,address,address,bytes8,uint32,uint32)](#crosscreatecustomcode-fr1) — FeeRegistry
* [crossUpdateCustomCode(uint256,address,address,bytes8,uint32,uint32)](#crossupdatecustomcode-fr1) — FeeRegistry
* [changeCodeReferrer(bytes8,address,address,uint256\[\],uint256\[\])](#changecodereferrer-fr1) — FeeRegistry
* [changeRecipientReferrer(bytes8,address,uint256\[\],uint256\[\])](#changerecipientreferrer-fr1) — FeeRegistry
* [getCodeOperatorsList()](#getcodeoperatorslist-fr1) — FeeRegistry
* [isCodeOperator(address)](#iscodeoperator-fr1) — FeeRegistry
* [getSupportedRefInChainsList()](#getsupportedrefinchainslist-fr1) — FeeRegistry
* [isSupportedRefInChain(uint256)](#issupportedrefinchain-fr1) — FeeRegistry
* [getFeeBeneficiaries()](#getfeebeneficiaries-fr1) — FeeRegistry
* [getCodePct(bytes8)](#getcodepct-fr1) — FeeRegistry
* [calculateFee(bytes8,uint256)](#calculatefee-fr1) — FeeRegistry
* [getContractCaseFee(address,uint8)](#getcontractcasefee-fr1) — FeeRegistry
* [getContractCaseFeeForCode(address,uint8,bytes8)](#getcontractcasefeeforcode-fr1) — FeeRegistry
* [getReferrerByAddress(address)](#getreferrerbyaddress-fr1) — FeeRegistry
* [getReferrerByCode(bytes8)](#getreferrerbycode-fr1) — FeeRegistry
* [defaultSharePct()](#defaultsharepct-fr1) — FeeRegistry
* [defaultDiscountPct()](#defaultdiscountpct-fr1) — FeeRegistry
* [refererByCode(bytes8)](#refererbycode-fr1) — FeeRegistry
* [codeByReferrer(address)](#codebyreferrer-fr1) — FeeRegistry
* [accumulatedFee()](#accumulatedfee-fr1) — FeeRegistry

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### initialize (FR1)

**Contract/Library:** FeeRegistry

**Description:** Initializes default percentages and the cross-chain gate configuration.

**Detailed Description:** Sets default discount/share percentages in storage, then initializes Lifetime NFT and cross-chain parameters through the base gate initializer.

**Parameters:**

* \_owner (address): Target owner for LockChainGate init
* \_defaultDiscountPct (uint32): Default discount basis points (denominator 10,000)
* \_defaultSharePct (uint32): Default referrer share basis points (denominator 10,000)
* \_lifetimeNft (ILifetimeNft): Lifetime NFT contract
* \_lockPeriod (uint64): Lock duration for NFTs
* \_transferTimeout (uint64): Required delay between lock and transfer

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external initializer nonpayable

**Access Control:**

* Unrestricted (can be called once due to `initializer`)

**Side Effects:**

* Updates `defaultDiscountPct`
* Updates `defaultSharePct`
* Sets LockChainGate [`lifetimeNft`](https://docs.cryptolegacy.app/documentation/data-structures-reference#lifetimenft-clbm1-d4), `lockPeriod`, and `transferTimeout`
* Transfers ownership to `_owner`
* Initializes reentrancy guard state via `__ReentrancyGuard_init()`

**Emits:**

* [SetDefaultPct](https://docs.cryptolegacy.app/documentation/events-reference#setdefaultpct-ifr1) — `SetDefaultPct(uint32 defaultDiscountPct, uint32 defaultSharePct)`
* [SetLockPeriodConfig](https://docs.cryptolegacy.app/documentation/events-reference#setlockperiodconfig-ilcg1) — `SetLockPeriodConfig(uint256 lockPeriod, uint256 transferTimeout)`
* [OwnershipTransferred](https://docs.cryptolegacy.app/documentation/events-reference#ownershiptransferred-iclo1) — `OwnershipTransferred(address indexed previousOwner, address indexed newOwner)`
* OpenZeppelin base-type event (not mirrored in `events-reference.md`): `Initialized(uint8 version)`

**Reverts if:**

* Called more than once — "Initializable: contract is already initialized"

**Overrides:** None

**Function Calls:**

* [lockFeeRegistryStorage()](#lockfeeregistrystorage-fr1) — FeeRegistry, internal
* [\_setDefaultPct(FRStorage,uint32,uint32)](#_setdefaultpct-fr1) — FeeRegistry, internal
* [\_initializeLockChainGate(ILifetimeNft,uint64,uint64,address)](#_initializelockchaingate-lcg1) — LockChainGate, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Proxy admin calls `initialize(admin, 500, 1000, lifetimeNft, 180 days, 1 days)`.

***

### setCodeOperator (FR1)

**Contract/Library:** FeeRegistry

**Description:** Adds or removes an authorized referral-code operator.

**Detailed Description:** Fetches storage, toggles membership of `_operator` in `codeOperators`, and emits the corresponding event.

**Parameters:**

* \_operator (address): Address to add or remove
* \_isAdd (bool): True to add, false to remove

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external onlyOwner nonpayable

**Access Control:**

* onlyOwner (contract owner via LockChainGate/Ownable base)

**Side Effects:**

* Updates `codeOperators` set

**Emits:**

* [AddCodeOperator](https://docs.cryptolegacy.app/documentation/events-reference#addcodeoperator-ifr1) — `AddCodeOperator(address indexed codeOperator)`
* [RemoveCodeOperator](https://docs.cryptolegacy.app/documentation/events-reference#removecodeoperator-ifr1) — `RemoveCodeOperator(address indexed codeOperator)`

**Reverts if:**

* caller is not owner — "Ownable: caller is not the owner"

**Overrides:** None

**Function Calls:**

* [lockFeeRegistryStorage()](#lockfeeregistrystorage-fr1) — FeeRegistry, internal
* `add(address)` — `EnumerableSet` (library), internal
* `remove(address)` — `EnumerableSet` (library), internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Owner calls `setCodeOperator(0xOP...ER, true)` to authorize code management.

***

### setSupportedRefCodeInChains (FR1)

**Contract/Library:** FeeRegistry

**Description:** Adds or removes supported chain IDs for referral codes.

**Detailed Description:** Loops through `_chains`, updating `supportedRefInChains` and emitting per-chain add/remove events.

**Parameters:**

* \_chains (uint256\[], memory): Chain IDs to add/remove
* \_isAdd (bool): True to add, false to remove

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external onlyOwner nonpayable

**Access Control:**

* onlyOwner

**Side Effects:**

* Updates `supportedRefInChains` set

**Emits:**

* [AddSupportedRefCodeInChain](https://docs.cryptolegacy.app/documentation/events-reference#addsupportedrefcodeinchain-ifr1) — `AddSupportedRefCodeInChain(uint256 indexed chainId)`
* [RemoveSupportedRefCodeInChain](https://docs.cryptolegacy.app/documentation/events-reference#removesupportedrefcodeinchain-ifr1) — `RemoveSupportedRefCodeInChain(uint256 indexed chainId)`

**Reverts if:**

* caller is not owner — "Ownable: caller is not the owner"

**Overrides:** None

**Function Calls:**

* [lockFeeRegistryStorage()](#lockfeeregistrystorage-fr1) — FeeRegistry, internal
* `add(uint256)` — `EnumerableSet` (library), internal
* `remove(uint256)` — `EnumerableSet` (library), internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(n) by `_chains.length`

**Example:** Owner calls `setSupportedRefCodeInChains(1,137,42161, true)`.

***

### setFeeBeneficiaries (FR1)

**Contract/Library:** FeeRegistry

**Description:** Sets protocol fee beneficiaries and their shares.

**Detailed Description:** Replaces `feeBeneficiaries` with `_beneficiaries`, checks that the sum of `sharePct` equals [`PCT_BASE`](https://docs.cryptolegacy.app/documentation/data-structures-reference#pct_base-fr1-d1) (10,000), and emits the configuration event.

**Parameters:**

* \_beneficiaries ([FeeBeneficiary](https://docs.cryptolegacy.app/documentation/data-structures-reference#feebeneficiary-ifr1-s3)\[], memory): New beneficiaries and their share percentages

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external onlyOwner nonpayable

**Access Control:**

* onlyOwner

**Side Effects:**

* Deletes and repopulates `feeBeneficiaries` array

**Emits:**

* [SetFeeBeneficiaries](https://docs.cryptolegacy.app/documentation/events-reference#setfeebeneficiaries-ifr1) — `SetFeeBeneficiaries(FeeBeneficiary[] beneficiaries)`

**Reverts if:**

* caller is not owner — "Ownable: caller is not the owner"
* Sum of `_beneficiariesi.sharePct` ≠ [`PCT_BASE`](https://docs.cryptolegacy.app/documentation/data-structures-reference#pct_base-fr1-d1) — [`PctSumDoesntMatchBase()`](https://docs.cryptolegacy.app/documentation/errors-reference#pctsumdoesntmatchbase-ifr1)

**Overrides:** None

**Function Calls:**

* [lockFeeRegistryStorage()](#lockfeeregistrystorage-fr1) — FeeRegistry, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(n) by `_beneficiaries.length`

**Example:** Owner configures revenue split across treasury addresses.

***

### setDefaultPct (FR1)

**Contract/Library:** FeeRegistry

**Description:** Updates global default discount/share percentages.

**Detailed Description:** Loads storage and forwards to [\_setDefaultPct](#_setdefaultpct-fr1) to store new values and emit the event. Does not validate that `_defaultDiscountPct + _defaultSharePct ≤ PCT_BASE` (see [`PCT_BASE`](https://docs.cryptolegacy.app/documentation/data-structures-reference#pct_base-fr1-d1)); invalid values will later make [calculateFee(bytes8,uint256)](#calculatefee-fr1) revert with `TooBigPct()`.

**Parameters:**

* \_defaultDiscountPct (uint32): New default discount bps
* \_defaultSharePct (uint32): New default referrer share bps

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external onlyOwner nonpayable

**Access Control:**

* onlyOwner

**Side Effects:**

* Updates `defaultDiscountPct`
* Updates `defaultSharePct`

**Emits:**

* [SetDefaultPct](https://docs.cryptolegacy.app/documentation/events-reference#setdefaultpct-ifr1) — `SetDefaultPct(uint32 defaultDiscountPct, uint32 defaultSharePct)`

**Reverts if:**

* caller is not owner — "Ownable: caller is not the owner"

**Overrides:** None

**Function Calls:**

* [lockFeeRegistryStorage()](#lockfeeregistrystorage-fr1) — FeeRegistry, internal
* [\_setDefaultPct(FRStorage,uint32,uint32)](#_setdefaultpct-fr1) — FeeRegistry, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Owner calls `setDefaultPct(500, 1000)`.

***

### \_setDefaultPct (FR1)

**Contract/Library:** FeeRegistry

**Description:** Internal setter for default discount/share percentages.

**Detailed Description:** Writes the provided values into storage and emits the update event. Does not validate that `_defaultDiscountPct + _defaultSharePct ≤ PCT_BASE` (see [`PCT_BASE`](https://docs.cryptolegacy.app/documentation/data-structures-reference#pct_base-fr1-d1)); invalid values will later make [calculateFee(bytes8,uint256)](#calculatefee-fr1) revert with `TooBigPct()`.

**Parameters:**

* fs ([FRStorage](https://docs.cryptolegacy.app/documentation/data-structures-reference#frstorage-ifr1-s1), storage): FeeRegistry storage pointer
* \_defaultDiscountPct (uint32): New default discount bps
* \_defaultSharePct (uint32): New default referrer share bps

**Returns:** None

**Modifiers / Visibility / Mutability:**

* internal nonpayable

**Access Control:**

* Internal only

**Side Effects:**

* Updates `defaultDiscountPct`
* Updates `defaultSharePct`

**Emits:**

* [SetDefaultPct](https://docs.cryptolegacy.app/documentation/events-reference#setdefaultpct-ifr1) — `SetDefaultPct(uint32 defaultDiscountPct, uint32 defaultSharePct)`

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:**

* [initialize(address,uint32,uint32,ILifetimeNft,uint64,uint64)](#initialize-fr1) — FeeRegistry
* [setDefaultPct(uint32,uint32)](#setdefaultpct-fr1) — FeeRegistry

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### setRefererSpecificPct (FR1)

**Contract/Library:** FeeRegistry

**Description:** Sets custom discount/share percentages for a referrer’s code.

**Detailed Description:** Ensures `discountPct + sharePct ≤ PCT_BASE` (see [`PCT_BASE`](https://docs.cryptolegacy.app/documentation/data-structures-reference#pct_base-fr1-d1)). Looks up the referrer’s code and updates its discount/share.

**Parameters:**

* \_referrer (address): Referrer owner address
* \_discountPct (uint32): Custom discount bps
* \_sharePct (uint32): Custom referrer share bps

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external onlyOwner nonpayable

**Access Control:**

* onlyOwner

**Side Effects:**

* Updates `refererByCodecode.discountPct`
* Updates `refererByCodecode.sharePct`

**Emits:**

* [SetRefererSpecificPct](https://docs.cryptolegacy.app/documentation/events-reference#setrefererspecificpct-ifr1) — `SetRefererSpecificPct(address indexed referrer, bytes8 indexed code, uint32 discountPct, uint32 sharePct)`

**Reverts if:**

* caller is not owner — "Ownable: caller is not the owner"
* `_discountPct + _sharePct > PCT_BASE` (see [`PCT_BASE`](https://docs.cryptolegacy.app/documentation/data-structures-reference#pct_base-fr1-d1)) — [`TooBigPct()`](https://docs.cryptolegacy.app/documentation/errors-reference#toobigpct-ifr1)

**Overrides:** None

**Function Calls:**

* [lockFeeRegistryStorage()](#lockfeeregistrystorage-fr1) — FeeRegistry, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Owner assigns a premium referrer a higher share.

***

### setContractCaseFee (FR1)

**Contract/Library:** FeeRegistry

**Description:** Sets the fee amount for a (contract, case) pair.

**Detailed Description:** Writes `_fee` into `feeByContractCase_contract_case` and emits the change.

**Parameters:**

* \_contract (address): Source contract address
* \_case (uint8): Case identifier
* \_fee (uint128): Fee in wei

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external onlyOwner nonpayable

**Access Control:**

* onlyOwner

**Side Effects:**

* Updates `feeByContractCase_contract_case`

**Emits:**

* [SetContractCaseFee](https://docs.cryptolegacy.app/documentation/events-reference#setcontractcasefee-ifr1) — `SetContractCaseFee(address indexed sourceContract, uint8 indexed contractCase, uint256 fee)`

**Reverts if:**

* caller is not owner — "Ownable: caller is not the owner"

**Overrides:** None

**Function Calls:**

* [lockFeeRegistryStorage()](#lockfeeregistrystorage-fr1) — FeeRegistry, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Owner updates build/update/lifetime fee schedules.

***

### takeFee (FR1)

**Contract/Library:** FeeRegistry

**Description:** Charges a fee for a contract case and distributes referrer share.

**Detailed Description:** Computes the case fee, applies referral discount/share, enforces sufficient value, accumulates protocol fee, and attempts to transfer the referrer’s share. On transfer failure, the share is accumulated for later withdrawal. Emits detailed accounting events.

**Parameters:**

* \_contract (address): Source contract
* \_case (uint8): Case identifier
* \_code (bytes8): Referral code
* \_mul (uint256): Multiplier for fee amount

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external payable nonReentrant

**Access Control:**

* Unrestricted

**Side Effects:**

* Increases `accumulatedFee` by `fee - share`
* May increase `refererByCode_code.accumulatedFee` if payout fails
* Sends ETH to `shareRecipient` on success

**Emits:**

* [SentFee](https://docs.cryptolegacy.app/documentation/events-reference#sentfee-ifr1) — `SentFee(address indexed referrer, bytes8 indexed code, address indexed recipient, uint256 value)`
* [AccumulateFee](https://docs.cryptolegacy.app/documentation/events-reference#accumulatefee-ifr1) — `AccumulateFee(address indexed referrer, bytes8 indexed code, address indexed recipient, uint256 value, bytes transferResponse)`
* [TakeFee](https://docs.cryptolegacy.app/documentation/events-reference#takefee-ifr1) — `TakeFee(address indexed sourceContract, uint8 indexed contractCase, bytes8 indexed code, uint256 discount, uint256 share, uint256 fee, uint256 value)`

**Reverts if:**

* Reentrant call — "ReentrancyGuard: reentrant call"
* `discountPct + sharePct > PCT_BASE` (see [`PCT_BASE`](https://docs.cryptolegacy.app/documentation/data-structures-reference#pct_base-fr1-d1); via `_calculateFee`) — [`TooBigPct()`](https://docs.cryptolegacy.app/documentation/errors-reference#toobigpct-ifr1)
* `msg.value < fee` or `msg.value - fee > 0.00001 ether` (via `_checkFee`) — [`IncorrectFee(uint256)`](https://docs.cryptolegacy.app/documentation/errors-reference#incorrectfee-ilcg1)

**Overrides:**

* IFeeRegistry (function implementation).

**Function Calls:**

* [lockFeeRegistryStorage()](#lockfeeregistrystorage-fr1) — FeeRegistry, internal
* [\_calculateFee(FRStorage,bytes8,uint256)](#_calculatefee-fr1) — FeeRegistry, internal
* [\_checkFee(uint256)](#_checkfee-lcg1) — LockChainGate, internal
* `call{value: share, gas: 10000}(bytes)` — `address` *(at `shareRecipient`)*, external

**Called by:** None (entry point)

**Gas / Complexity note:** O(1); includes one bounded external call for referrer payout

**Example:** A build manager pays update fee with a referral code; referrer gets instant payout or accrues balance.

***

### withdrawAccumulatedFee (FR1)

**Contract/Library:** FeeRegistry

**Description:** Distributes accumulated protocol fees to configured beneficiaries.

**Detailed Description:** Reads and zeroes `accumulatedFee`, iterates beneficiaries, and pays each proportional share; reverts on any failed transfer.

**Parameters:** None

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external nonReentrant nonpayable

**Access Control:**

* Unrestricted

**Side Effects:**

* Sets `accumulatedFee` to `0`
* Sends ETH to each `feeBeneficiariesi.recipient`

**Emits:**

* [WithdrawFee](https://docs.cryptolegacy.app/documentation/events-reference#withdrawfee-ifr1) — `WithdrawFee(address indexed beneficiary, uint256 value)`

**Reverts if:**

* Reentrant call — "ReentrancyGuard: reentrant call"
* Any beneficiary transfer fails — [`WithdrawAccumulatedFeeFailed(bytes)`](https://docs.cryptolegacy.app/documentation/errors-reference#withdrawaccumulatedfeefailed-ifr1)

**Overrides:** None

**Function Calls:**

* [lockFeeRegistryStorage()](#lockfeeregistrystorage-fr1) — FeeRegistry, internal
* `call{value: feeShare}(bytes)` — `address` *(at `fs.feeBeneficiariesi.recipient`)*, external

**Called by:** None (entry point)

**Gas / Complexity note:** O(n) by number of beneficiaries

**Example:** Treasury agent calls `withdrawAccumulatedFee()` to split collected fees.

***

### withdrawReferralAccumulatedFee (FR1)

**Contract/Library:** FeeRegistry

**Description:** Pays out a referrer’s accumulated unpaid share.

**Detailed Description:** Loads the referrer record for `_code`, zeroes `accumulatedFee`, and transfers it to `recipient`; reverts on failure.

**Parameters:**

* \_code (bytes8): Referral code whose unpaid balance is withdrawn

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external nonReentrant nonpayable

**Access Control:**

* Unrestricted

**Side Effects:**

* Sets `refererByCode_code.accumulatedFee` to `0`
* Sends ETH to `refererByCode_code.recipient`

**Emits:**

* [WithdrawRefFee](https://docs.cryptolegacy.app/documentation/events-reference#withdrawreffee-ifr1) — `WithdrawRefFee(address indexed recipient, uint256 value)`

**Reverts if:**

* Reentrant call — "ReentrancyGuard: reentrant call"
* Transfer to recipient fails — [`WithdrawAccumulatedFeeFailed(bytes)`](https://docs.cryptolegacy.app/documentation/errors-reference#withdrawaccumulatedfeefailed-ifr1)

**Overrides:** None

**Function Calls:**

* [lockFeeRegistryStorage()](#lockfeeregistrystorage-fr1) — FeeRegistry, internal
* `call{value: feeToSend}(bytes)` — `address` *(at `ref.recipient`)*, external

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Referrer collects unpaid shares accumulated from earlier failed payouts.

***

### \_setCustomCode (FR1)

**Contract/Library:** FeeRegistry

**Description:** Internal writer for a custom referral code’s ownership, recipient, and percentages.

**Detailed Description:** Validates non-zero code, re-assigns owner if different (clearing previous mapping), updates recipient and effective percentages in `refererByCode`, and ensures the new owner is not already a referrer.

**Parameters:**

* fs ([FRStorage](https://docs.cryptolegacy.app/documentation/data-structures-reference#frstorage-ifr1-s1), storage): FeeRegistry storage pointer
* \_referrer (address): New owner of the code
* \_recipient (address): Payout recipient
* \_shortCode (bytes8): Custom code
* \_discountPct (uint32): Discount bps
* \_sharePct (uint32): Share bps

**Returns:**

* shortCode (bytes8): The code stored

**Modifiers / Visibility / Mutability:**

* internal nonpayable

**Access Control:**

* Internal only

**Side Effects:**

* Updates `codeByReferrerprevOwner` (delete if needed)
* Updates `codeByReferrer_referrer`
* Updates `refererByCode_shortCode.owner`
* Updates `refererByCode_shortCode.recipient`
* Updates `refererByCode_shortCode.discountPct`
* Updates `refererByCode_shortCode.sharePct`

**Emits:** None

**Reverts if:**

* `_shortCode == bytes8(0)` — [`ZeroCode()`](https://docs.cryptolegacy.app/documentation/errors-reference#zerocode-ifr1)
* `_referrer` already owns a code — [`AlreadyReferrer()`](https://docs.cryptolegacy.app/documentation/errors-reference#alreadyreferrer-ifr1)

**Overrides:** None

**Function Calls:**

* [\_checkCodeNotZero(bytes8)](#_checkcodenotzero-fr1) — FeeRegistry, internal
* [\_checkNewOwnerIsNotReferrer(FRStorage,address)](#_checknewownerisnotreferrer-fr1) — FeeRegistry, internal

**Called by:**

* [\_createCustomCode(FRStorage,address,address,bytes8,uint256,uint32,uint32)](#_createcustomcode-fr1) — FeeRegistry
* [crossUpdateCustomCode(uint256,address,address,bytes8,uint32,uint32)](#crossupdatecustomcode-fr1) — FeeRegistry

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### \_createCustomCode (FR1)

**Contract/Library:** FeeRegistry

**Description:** Internal creator for a new custom referral code.

**Detailed Description:** Ensures code does not exist, emits creation event, and persists the new mapping via [\_setCustomCode](#_setcustomcode-fr1).

**Parameters:**

* fs ([FRStorage](https://docs.cryptolegacy.app/documentation/data-structures-reference#frstorage-ifr1-s1), storage): FeeRegistry storage pointer
* \_referrer (address): Owner of the new code
* \_recipient (address): Payout recipient
* \_shortCode (bytes8): Desired code
* \_fromChain (uint256): Origin chain ID (0 for local creation)
* \_discountPct (uint32): Discount bps
* \_sharePct (uint32): Share bps

**Returns:**

* shortCode (bytes8): The created code

**Modifiers / Visibility / Mutability:**

* internal nonpayable

**Access Control:**

* Internal only

**Side Effects:**

* Updates `codeByReferrer_referrer`
* Updates `refererByCode_shortCode` (owner, recipient, pcts)

**Emits:**

* [CreateCode](https://docs.cryptolegacy.app/documentation/events-reference#createcode-ifr1) — `CreateCode(address indexed codeOperator, address indexed referrer, bytes8 indexed code, address recipient, uint256 fromChain, uint32 discountPct, uint32 sharePct)`

**Reverts if:**

* Code already exists — [`RefAlreadyCreated()`](https://docs.cryptolegacy.app/documentation/errors-reference#refalreadycreated-ifr1)
* `_shortCode == bytes8(0)` — [`ZeroCode()`](https://docs.cryptolegacy.app/documentation/errors-reference#zerocode-ifr1)
* `_referrer` already owns a code — [`AlreadyReferrer()`](https://docs.cryptolegacy.app/documentation/errors-reference#alreadyreferrer-ifr1)

**Overrides:** None

**Function Calls:**

* [\_setCustomCode(FRStorage,address,address,bytes8,uint32,uint32)](#_setcustomcode-fr1) — FeeRegistry, internal

**Called by:**

* [createCustomCode(address,address,bytes8,uint256\[\],uint256\[\])](#createcustomcode-fr1) — FeeRegistry
* [createCode(address,address,uint256\[\],uint256\[\])](#createcode-fr1) — FeeRegistry
* [crossCreateCustomCode(uint256,address,address,bytes8,uint32,uint32)](#crosscreatecustomcode-fr1) — FeeRegistry

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### \_checkCodeNotZero (FR1)

**Contract/Library:** FeeRegistry

**Description:** Validates that a referral code is non-zero.

**Detailed Description:** Reverts when `_shortCode` equals `bytes8(0)`.

**Parameters:**

* \_shortCode (bytes8): Code to validate

**Returns:** None

**Modifiers / Visibility / Mutability:**

* internal pure

**Access Control:**

* Internal only

**Side Effects:** None

**Emits:** None

**Reverts if:**

* `_shortCode == bytes8(0)` — [`ZeroCode()`](https://docs.cryptolegacy.app/documentation/errors-reference#zerocode-ifr1)

**Overrides:** None

**Function Calls:** None

**Called by:**

* [\_setCustomCode(FRStorage,address,address,bytes8,uint32,uint32)](#_setcustomcode-fr1) — FeeRegistry

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### \_checkSenderIsOperator (FR1)

**Contract/Library:** FeeRegistry

**Description:** Ensures caller is an authorized code operator.

**Detailed Description:** Checks membership in `codeOperators`; reverts otherwise.

**Parameters:**

* fs ([FRStorage](https://docs.cryptolegacy.app/documentation/data-structures-reference#frstorage-ifr1-s1), storage): FeeRegistry storage pointer

**Returns:** None

**Modifiers / Visibility / Mutability:**

* internal view

**Access Control:**

* Internal only

**Side Effects:** None

**Emits:** None

**Reverts if:**

* Caller not in `codeOperators` — [`NotOperator()`](https://docs.cryptolegacy.app/documentation/errors-reference#notoperator-ifr1)

**Overrides:** None

**Function Calls:**

* `contains(address)` — `EnumerableSet.AddressSet`, internal

**Called by:**

* [createCustomCode(address,address,bytes8,uint256\[\],uint256\[\])](#createcustomcode-fr1) — FeeRegistry
* [createCode(address,address,uint256\[\],uint256\[\])](#createcode-fr1) — FeeRegistry
* [updateCrossChainsRef(uint256\[\],uint256\[\])](#updatecrosschainsref-fr1) — FeeRegistry

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### createCustomCode (FR1)

**Contract/Library:** FeeRegistry

**Description:** Creates a **custom** referral code and optionally propagates it cross‑chain.

**Detailed Description:** Requires operator role, creates the code locally, sets cross‑chain refs (sending messages/fees per chain), computes total native fee spent, and returns any surplus.

**Parameters:**

* \_referrer (address): Owner of the new code
* \_recipient (address): Payout recipient
* \_shortCode (bytes8): Desired code
* \_chainIds (uint256\[], memory): Destination chain IDs
* \_crossChainFees (uint256\[], memory): Native fee per chain (0 to auto-calc)

**Returns:**

* shortCode (bytes8): Created code
* totalFee (uint256): Total native fee spent for cross-chain ops
* returnValue (uint256): Refunded surplus (if any)

**Modifiers / Visibility / Mutability:**

* external nonReentrant payable

**Access Control:**

* only operator (enforced internally)

**Side Effects:**

* Updates `codeByReferrer_referrer` and `refererByCode_shortCode` (via internal call)
* Transfers native fee to `deBridgeGate` per chain via `_send` when `_chainIds` not empty
* Refunds surplus ETH to `msg.sender`

**Emits:**

* [CreateCode](https://docs.cryptolegacy.app/documentation/events-reference#createcode-ifr1) — `CreateCode(address indexed codeOperator, address indexed referrer, bytes8 indexed code, address recipient, uint256 fromChain, uint32 discountPct, uint32 sharePct)`
* [SendToChain](https://docs.cryptolegacy.app/documentation/events-reference#sendtochain-ilcg1) — `SendToChain(uint256 indexed toChainId, bytes32 indexed submissionId, uint256 value, bytes dstTransactionCall)`
* [SetCrossChainsRef](https://docs.cryptolegacy.app/documentation/events-reference#setcrosschainsref-ifr1) — `SetCrossChainsRef(bytes8 indexed shortCode, bool indexed isCreate, uint256[] toChainIDs, uint256[] crossChainFees)`

**Reverts if:**

* Reentrant call — "ReentrancyGuard: reentrant call"
* Caller is not operator — [`NotOperator()`](https://docs.cryptolegacy.app/documentation/errors-reference#notoperator-ifr1)
* Code already exists — [`RefAlreadyCreated()`](https://docs.cryptolegacy.app/documentation/errors-reference#refalreadycreated-ifr1)
* `_shortCode == bytes8(0)` — [`ZeroCode()`](https://docs.cryptolegacy.app/documentation/errors-reference#zerocode-ifr1)
* `_referrer` already owns a code — [`AlreadyReferrer()`](https://docs.cryptolegacy.app/documentation/errors-reference#alreadyreferrer-ifr1)
* `_chainIds.length != _crossChainFees.length` — [`ArrayLengthMismatch()`](https://docs.cryptolegacy.app/documentation/errors-reference#arraylengthmismatch-ilcg1)
* Destination chain not configured — [`DestinationChainNotSpecified()`](https://docs.cryptolegacy.app/documentation/errors-reference#destinationchainnotspecified-ilcg1)
* `deBridgeGate.globalFixedNativeFee()` — may revert per deBridgeGate implementation (bubbled)
* `deBridgeGate.sendMessage(...)` — may revert per deBridgeGate implementation (bubbled)
* fee check fails (`msg.value < totalFee` or overpayment > 0.00001 ether) — [`IncorrectFee(uint256)`](https://docs.cryptolegacy.app/documentation/errors-reference#incorrectfee-ilcg1)
* refund transfer fails — [`TransferFeeFailed(bytes)`](https://docs.cryptolegacy.app/documentation/errors-reference#transferfeefailed-ilcg1)

**Overrides:**

* IFeeRegistry (function implementation).

**Function Calls:**

* [lockFeeRegistryStorage()](#lockfeeregistrystorage-fr1) — FeeRegistry, internal
* [\_checkSenderIsOperator(FRStorage)](#_checksenderisoperator-fr1) — FeeRegistry, internal
* [\_createCustomCode(FRStorage,address,address,bytes8,uint256,uint32,uint32)](#_createcustomcode-fr1) — FeeRegistry, internal
* [\_setCrossChainsRef(FRStorage,bool,bytes8,uint256\[\],uint256\[\])](#_setcrosschainsref-fr1) — FeeRegistry, internal
* [\_calcAndReturnFee(uint256)](#_calcandreturnfee-lcg1) — LockChainGate, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1) local + O(n) by `_chainIds.length` for cross-chain work

**Example:** Operator mints a vanity code and broadcasts it to additional chains.

***

### createCode (FR1)

**Contract/Library:** FeeRegistry

**Description:** Creates a **generated** referral code and optionally propagates it cross‑chain.

**Detailed Description:** Requires operator role, generates a short code from entropy, stores it, performs cross‑chain propagation, and refunds any surplus value.

**Parameters:**

* \_referrer (address): New code owner
* \_recipient (address): Payout recipient
* \_chainIds (uint256\[], memory): Destination chain IDs
* \_crossChainFees (uint256\[], memory): Native fee per chain (0 to auto-calc)

**Returns:**

* shortCode (bytes8): Generated code
* totalFee (uint256): Total native fee spent for cross-chain ops
* returnValue (uint256): Refunded surplus (if any)

**Modifiers / Visibility / Mutability:**

* external nonReentrant payable

**Access Control:**

* only operator (enforced internally)

**Side Effects:**

* Updates `codeByReferrer_referrer` and `refererByCodeshortCode` (via internal call)
* Transfers native fee to `deBridgeGate` per chain via `_send` when `_chainIds` not empty
* Refunds surplus ETH to `msg.sender`

**Emits:**

* [CreateCode](https://docs.cryptolegacy.app/documentation/events-reference#createcode-ifr1) — `CreateCode(address indexed codeOperator, address indexed referrer, bytes8 indexed code, address recipient, uint256 fromChain, uint32 discountPct, uint32 sharePct)`
* [SendToChain](https://docs.cryptolegacy.app/documentation/events-reference#sendtochain-ilcg1) — `SendToChain(uint256 indexed toChainId, bytes32 indexed submissionId, uint256 value, bytes dstTransactionCall)`
* [SetCrossChainsRef](https://docs.cryptolegacy.app/documentation/events-reference#setcrosschainsref-ifr1) — `SetCrossChainsRef(bytes8 indexed shortCode, bool indexed isCreate, uint256[] toChainIDs, uint256[] crossChainFees)`

**Reverts if:**

* Reentrant call — "ReentrancyGuard: reentrant call"
* Caller is not operator — [`NotOperator()`](https://docs.cryptolegacy.app/documentation/errors-reference#notoperator-ifr1)
* Code already exists — [`RefAlreadyCreated()`](https://docs.cryptolegacy.app/documentation/errors-reference#refalreadycreated-ifr1)
* generated shortCode == bytes8(0) — [`ZeroCode()`](https://docs.cryptolegacy.app/documentation/errors-reference#zerocode-ifr1)
* `_referrer` already owns a code — [`AlreadyReferrer()`](https://docs.cryptolegacy.app/documentation/errors-reference#alreadyreferrer-ifr1)
* `_chainIds.length != _crossChainFees.length` — [`ArrayLengthMismatch()`](https://docs.cryptolegacy.app/documentation/errors-reference#arraylengthmismatch-ilcg1)
* Destination chain not configured — [`DestinationChainNotSpecified()`](https://docs.cryptolegacy.app/documentation/errors-reference#destinationchainnotspecified-ilcg1)
* `deBridgeGate.globalFixedNativeFee()` — may revert per deBridgeGate implementation (bubbled)
* `deBridgeGate.sendMessage(...)` — may revert per deBridgeGate implementation (bubbled)
* fee check fails (`msg.value < totalFee` or overpayment > 0.00001 ether) — [`IncorrectFee(uint256)`](https://docs.cryptolegacy.app/documentation/errors-reference#incorrectfee-ilcg1)
* refund transfer fails — [`TransferFeeFailed(bytes)`](https://docs.cryptolegacy.app/documentation/errors-reference#transferfeefailed-ilcg1)

**Overrides:**

* IFeeRegistry (function implementation).

**Function Calls:**

* [lockFeeRegistryStorage()](#lockfeeregistrystorage-fr1) — FeeRegistry, internal
* [\_checkSenderIsOperator(FRStorage)](#_checksenderisoperator-fr1) — FeeRegistry, internal
* [\_createCustomCode(FRStorage,address,address,bytes8,uint256,uint32,uint32)](#_createcustomcode-fr1) — FeeRegistry, internal
* [\_setCrossChainsRef(FRStorage,bool,bytes8,uint256\[\],uint256\[\])](#_setcrosschainsref-fr1) — FeeRegistry, internal
* [\_calcAndReturnFee(uint256)](#_calcandreturnfee-lcg1) — LockChainGate, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1) local + O(n) by `_chainIds.length`

**Example:** Operator creates a random short code without choosing a specific value.

***

### \_setCrossChainsRef (FR1)

**Contract/Library:** FeeRegistry

**Description:** Internal helper to (create/update) code data across chains.

**Detailed Description:** Validates arrays length, ensures destination chains are enabled, gets deBridge native fees, encodes cross‑chain call (create or update), sends messages to each chain, checks total fee, and emits a summary event.

**Parameters:**

* fs ([FRStorage](https://docs.cryptolegacy.app/documentation/data-structures-reference#frstorage-ifr1-s1), storage): FeeRegistry storage pointer
* \_isCreate (bool): True for create, false for update
* \_shortCode (bytes8): Code to propagate
* \_toChainIDs (uint256\[], memory): Destination chain IDs
* \_crossChainFees (uint256\[], memory): Provided native fees (0 to auto-calc)

**Returns:**

* totalFee (uint256): Total native fee used

**Modifiers / Visibility / Mutability:**

* internal nonpayable

**Access Control:**

* Internal only

**Side Effects:**

* Transfers native fee to `deBridgeGate` per chain via `_send`

**Emits:**

* [SendToChain](https://docs.cryptolegacy.app/documentation/events-reference#sendtochain-ilcg1) — `SendToChain(uint256 indexed toChainId, bytes32 indexed submissionId, uint256 value, bytes dstTransactionCall)`
* [SetCrossChainsRef](https://docs.cryptolegacy.app/documentation/events-reference#setcrosschainsref-ifr1) — `SetCrossChainsRef(bytes8 indexed shortCode, bool indexed isCreate, uint256[] toChainIDs, uint256[] crossChainFees)`

**Reverts if:**

* `_toChainIDs.length != _crossChainFees.length` — [`ArrayLengthMismatch()`](https://docs.cryptolegacy.app/documentation/errors-reference#arraylengthmismatch-ilcg1)
* Destination chain contract not specified — [`DestinationChainNotSpecified()`](https://docs.cryptolegacy.app/documentation/errors-reference#destinationchainnotspecified-ilcg1)
* `deBridgeGate.globalFixedNativeFee()` — may revert per deBridgeGate implementation (bubbled)
* `deBridgeGate.sendMessage(...)` — may revert per deBridgeGate implementation (bubbled)
* fee check fails (`msg.value < totalFee` or overpayment > 0.00001 ether) — [`IncorrectFee(uint256)`](https://docs.cryptolegacy.app/documentation/errors-reference#incorrectfee-ilcg1)

**Overrides:** None

**Function Calls:**

* [lockChainGateStorage()](#lockchaingatestorage-lcg1) — LockChainGate, internal
* [\_checkDestinationLockedChain(LCGStorage,uint256)](#_checkdestinationlockedchain-lcg1) — LockChainGate, internal
* [\_getDeBridgeChainNativeFee(LCGStorage,uint256,uint256)](#_getdebridgechainnativefee-lcg1) — LockChainGate, internal
* [\_encodeCrossCreateCustomCodeCommand(LCGStorage,address,address,bytes8,uint32,uint32)](#_encodecrosscreatecustomcodecommand-fr1) — FeeRegistry, internal
* [\_encodeCrossUpdateCustomCodeCommand(LCGStorage,address,address,bytes8,uint32,uint32)](#_encodecrossupdatecustomcodecommand-fr1) — FeeRegistry, internal
* [\_send(LCGStorage,bytes,uint256,uint256)](#_send-lcg1) — LockChainGate, internal
* [\_checkFee(uint256)](#_checkfee-lcg1) — LockChainGate, internal

**Called by:**

* [createCustomCode(address,address,bytes8,uint256\[\],uint256\[\])](#createcustomcode-fr1) — FeeRegistry
* [createCode(address,address,uint256\[\],uint256\[\])](#createcode-fr1) — FeeRegistry
* [updateCrossChainsRef(uint256\[\],uint256\[\])](#updatecrosschainsref-fr1) — FeeRegistry
* [changeCodeReferrer(bytes8,address,address,uint256\[\],uint256\[\])](#changecodereferrer-fr1) — FeeRegistry
* [changeRecipientReferrer(bytes8,address,uint256\[\],uint256\[\])](#changerecipientreferrer-fr1) — FeeRegistry

**Gas / Complexity note:** O(n) by `_toChainIDs.length`

**Example:** Not applicable

***

### updateCrossChainsRef (FR1)

**Contract/Library:** FeeRegistry

**Description:** Updates cross-chain parameters for an existing referrer's code.

**Detailed Description:** Requires operator role, ensures `_referrer` has a code, runs cross-chain propagation as an update, and refunds any surplus native fee.

**Parameters:**

* \_referrer (address): Existing referrer
* \_chainIds (uint256\[], memory): Destination chain IDs
* \_crossChainFees (uint256\[], memory): Native fees per chain

**Returns:**

* totalFee (uint256): Total native fee used
* returnValue (uint256): Refunded surplus (if any)

**Modifiers / Visibility / Mutability:**

* external payable nonReentrant

**Access Control:**

* only operator (enforced internally)

**Side Effects:**

* Sends cross-chain messages via deBridgeGate for each chain ID
* Transfers ETH refund to msg.sender (if any)

**Emits:**

* [SendToChain](https://docs.cryptolegacy.app/documentation/events-reference#sendtochain-ilcg1) — `SendToChain(uint256 indexed toChainId, bytes32 indexed submissionId, uint256 value, bytes dstTransactionCall)`
* [SetCrossChainsRef](https://docs.cryptolegacy.app/documentation/events-reference#setcrosschainsref-ifr1) — `SetCrossChainsRef(bytes8 indexed shortCode, bool indexed isCreate, uint256[] toChainIDs, uint256[] crossChainFees)`

**Reverts if:**

* Reentrant call — "ReentrancyGuard: reentrant call"
* Caller is not operator — [`NotOperator()`](https://docs.cryptolegacy.app/documentation/errors-reference#notoperator-ifr1)
* `_referrer` has no code — [`CodeNotCreated()`](https://docs.cryptolegacy.app/documentation/errors-reference#codenotcreated-ifr1)
* `_chainIds.length != _crossChainFees.length` — [`ArrayLengthMismatch()`](https://docs.cryptolegacy.app/documentation/errors-reference#arraylengthmismatch-ilcg1)
* Destination chain contract not specified — [`DestinationChainNotSpecified()`](https://docs.cryptolegacy.app/documentation/errors-reference#destinationchainnotspecified-ilcg1)
* `deBridgeGate.globalFixedNativeFee()` — may revert per implementation (bubbled)
* `deBridgeGate.sendMessage(...)` — may revert per implementation (bubbled)
* `msg.value < totalFee` or `msg.value - totalFee > 0.00001 ether` — [`IncorrectFee(uint256)`](https://docs.cryptolegacy.app/documentation/errors-reference#incorrectfee-ilcg1)
* Refund transfer fails — [`TransferFeeFailed(bytes)`](https://docs.cryptolegacy.app/documentation/errors-reference#transferfeefailed-ilcg1)

**Overrides:**

* IFeeRegistry (function implementation).

**Function Calls:**

* [lockFeeRegistryStorage()](#lockfeeregistrystorage-fr1) — FeeRegistry, internal
* [\_checkSenderIsOperator(FRStorage)](#_checksenderisoperator-fr1) — FeeRegistry, internal
* [\_setCrossChainsRef(FRStorage,bool,bytes8,uint256\[\],uint256\[\])](#_setcrosschainsref-fr1) — FeeRegistry, internal
* [\_calcAndReturnFee(uint256)](#_calcandreturnfee-lcg1) — LockChainGate, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(n) by `_chainIds.length`

**Example:** Operator updates remote chain visibility of an existing code.

***

### crossCreateCustomCode (FR1)

**Contract/Library:** FeeRegistry

**Description:** Cross-chain entry to create a custom code.

**Detailed Description:** Validates source chain and cross-chain caller, then creates the code with the provided configuration.

**Parameters:**

* \_fromChainId (uint256): Origin chain id
* \_referrer (address): Owner of the code
* \_recipient (address): Payout recipient
* \_shortCode (bytes8): Code to create
* \_discountPct (uint32): Discount bps
* \_sharePct (uint32): Share bps

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external nonReentrant nonpayable

**Access Control:**

* Restricted to authorized cross-chain messages via deBridge CallProxy

**Side Effects:**

* Writes `refererByCode` and `codeByReferrer` via [\_createCustomCode](#_createcustomcode-fr1)

**Emits:**

* [CreateCode](https://docs.cryptolegacy.app/documentation/events-reference#createcode-ifr1) — `CreateCode(address indexed codeOperator, address indexed referrer, bytes8 indexed code, address recipient, uint256 fromChain, uint32 discountPct, uint32 sharePct)`

**Reverts if:**

* Reentrant call — "ReentrancyGuard: reentrant call"
* Source chain not configured — [`SourceNotSpecified()`](https://docs.cryptolegacy.app/documentation/errors-reference#sourcenotspecified-ilcg1)
* `deBridgeGate.callProxy()` — may revert per implementation (bubbled)
* Caller is not deBridge CallProxy — [`NotCallProxy()`](https://docs.cryptolegacy.app/documentation/errors-reference#notcallproxy-ilcg1)
* `ICallProxy.submissionChainIdFrom()` — may revert per implementation (bubbled)
* Source chain mismatch — [`ChainIdMismatch()`](https://docs.cryptolegacy.app/documentation/errors-reference#chainidmismatch-ilcg1)
* `ICallProxy.submissionNativeSender()` — may revert per implementation (bubbled)
* Sender validation failed — [`NotValidSender()`](https://docs.cryptolegacy.app/documentation/errors-reference#notvalidsender-ilcg1)
* Code already exists — [`RefAlreadyCreated()`](https://docs.cryptolegacy.app/documentation/errors-reference#refalreadycreated-ifr1)
* `_shortCode == bytes8(0)` — [`ZeroCode()`](https://docs.cryptolegacy.app/documentation/errors-reference#zerocode-ifr1)
* `_referrer` already owns a code — [`AlreadyReferrer()`](https://docs.cryptolegacy.app/documentation/errors-reference#alreadyreferrer-ifr1)

**Overrides:**

* IFeeRegistry (function implementation).

**Function Calls:**

* [lockFeeRegistryStorage()](#lockfeeregistrystorage-fr1) — FeeRegistry, internal
* [lockChainGateStorage()](#lockchaingatestorage-lcg1) — LockChainGate, internal
* [\_checkSource(LCGStorage,uint256)](#_checksource-lcg1) — LockChainGate, internal
* [\_onlyCrossChain(LCGStorage,uint256)](#_onlycrosschain-lcg1) — LockChainGate, internal
* [\_createCustomCode(FRStorage,address,address,bytes8,uint256,uint32,uint32)](#_createcustomcode-fr1) — FeeRegistry, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### crossUpdateCustomCode (FR1)

**Contract/Library:** FeeRegistry

**Description:** Cross-chain entry to update code data.

**Detailed Description:** Validates source chain/caller, updates code owner/recipient/percentages locally, and emits the update event.

**Parameters:**

* \_fromChainId (uint256): Origin chain id
* \_referrer (address): Referrer (owner)
* \_recipient (address): Recipient
* \_shortCode (bytes8): Code to update
* \_discountPct (uint32): Discount bps
* \_sharePct (uint32): Share bps

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external nonReentrant nonpayable

**Access Control:**

* Restricted to authorized cross-chain messages via deBridge CallProxy

**Side Effects:**

* Writes `refererByCode` and `codeByReferrer` via [\_setCustomCode](#_setcustomcode-fr1)

**Emits:**

* [UpdateCode](https://docs.cryptolegacy.app/documentation/events-reference#updatecode-ifr1) — `UpdateCode(address indexed codeOperator, address indexed referrer, bytes8 indexed code, address recipient, uint256 fromChain, uint32 discountPct, uint32 sharePct)`

**Reverts if:**

* Reentrant call — "ReentrancyGuard: reentrant call"
* Source chain not configured — [`SourceNotSpecified()`](https://docs.cryptolegacy.app/documentation/errors-reference#sourcenotspecified-ilcg1)
* `deBridgeGate.callProxy()` — may revert per implementation (bubbled)
* Caller is not deBridge CallProxy — [`NotCallProxy()`](https://docs.cryptolegacy.app/documentation/errors-reference#notcallproxy-ilcg1)
* `ICallProxy.submissionChainIdFrom()` — may revert per implementation (bubbled)
* Source chain mismatch — [`ChainIdMismatch()`](https://docs.cryptolegacy.app/documentation/errors-reference#chainidmismatch-ilcg1)
* `ICallProxy.submissionNativeSender()` — may revert per implementation (bubbled)
* Sender validation failed — [`NotValidSender()`](https://docs.cryptolegacy.app/documentation/errors-reference#notvalidsender-ilcg1)
* `_shortCode == bytes8(0)` — [`ZeroCode()`](https://docs.cryptolegacy.app/documentation/errors-reference#zerocode-ifr1)
* `_referrer` already owns a code — [`AlreadyReferrer()`](https://docs.cryptolegacy.app/documentation/errors-reference#alreadyreferrer-ifr1)

**Overrides:** None

**Function Calls:**

* [lockFeeRegistryStorage()](#lockfeeregistrystorage-fr1) — FeeRegistry, internal
* [lockChainGateStorage()](#lockchaingatestorage-lcg1) — LockChainGate, internal
* [\_checkSource(LCGStorage,uint256)](#_checksource-lcg1) — LockChainGate, internal
* [\_onlyCrossChain(LCGStorage,uint256)](#_onlycrosschain-lcg1) — LockChainGate, internal
* [\_setCustomCode(FRStorage,address,address,bytes8,uint32,uint32)](#_setcustomcode-fr1) — FeeRegistry, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### \_encodeCrossCreateCustomCodeCommand (FR1)

**Contract/Library:** FeeRegistry

**Description:** Encodes the cross-chain create code command payload.

**Detailed Description:** Constructs abi-encoded calldata for `crossCreateCustomCode` including the current chain id and parameters.

**Parameters:**

* ls ([LCGStorage](https://docs.cryptolegacy.app/documentation/data-structures-reference#lcgstorage-ilcg1-s1), storage): LockChainGate storage pointer
* \_referrer (address): Owner
* \_recipient (address): Recipient
* \_shortCode (bytes8): Code
* \_discountPct (uint32): Discount bps
* \_sharePct (uint32): Share bps

**Returns:**

* data (bytes, memory): Encoded payload

**Modifiers / Visibility / Mutability:**

* internal view

**Access Control:**

* Internal only

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [\_getChainId(LCGStorage)](#_getchainid-lcg1) — LockChainGate, internal

**Called by:**

* [\_setCrossChainsRef(FRStorage,bool,bytes8,uint256\[\],uint256\[\])](#_setcrosschainsref-fr1) — FeeRegistry

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### \_encodeCrossUpdateCustomCodeCommand (FR1)

**Contract/Library:** FeeRegistry

**Description:** Encodes the cross-chain update code command payload.

**Detailed Description:** Constructs abi-encoded calldata for `crossUpdateCustomCode` including the current chain id and parameters.

**Parameters:**

* ls ([LCGStorage](https://docs.cryptolegacy.app/documentation/data-structures-reference#lcgstorage-ilcg1-s1), storage): LockChainGate storage pointer
* \_referrer (address): Referrer address
* \_recipient (address): Recipient address
* \_shortCode (bytes8): Code
* \_discountPct (uint32): Discount bps
* \_sharePct (uint32): Share bps

**Returns:**

* data (bytes, memory): Encoded payload

**Modifiers / Visibility / Mutability:**

* internal view

**Access Control:**

* Internal only

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [\_getChainId(LCGStorage)](#_getchainid-lcg1) — LockChainGate, internal

**Called by:**

* [\_setCrossChainsRef(FRStorage,bool,bytes8,uint256\[\],uint256\[\])](#_setcrosschainsref-fr1) — FeeRegistry

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### \_checkSenderIsReferrer (FR1)

**Contract/Library:** FeeRegistry

**Description:** Ensures the caller owns the specified referral code.

**Detailed Description:** Checks `codeByReferrermsg.sender == _code` and that `_code != bytes8(0)`; reverts otherwise.

**Parameters:**

* fs ([FRStorage](https://docs.cryptolegacy.app/documentation/data-structures-reference#frstorage-ifr1-s1), storage): FeeRegistry storage pointer
* \_code (bytes8): Code to check ownership of

**Returns:** None

**Modifiers / Visibility / Mutability:**

* internal view

**Access Control:**

* Internal only

**Side Effects:** None

**Emits:** None

**Reverts if:**

* `codeByReferrermsg.sender != _code` — [`NotReferrer()`](https://docs.cryptolegacy.app/documentation/errors-reference#notreferrer-ifr1)
* `_code == bytes8(0)` — [`NotReferrer()`](https://docs.cryptolegacy.app/documentation/errors-reference#notreferrer-ifr1)

**Overrides:** None

**Function Calls:** None

**Called by:**

* [changeCodeReferrer(bytes8,address,address,uint256\[\],uint256\[\])](#changecodereferrer-fr1) — FeeRegistry
* [changeRecipientReferrer(bytes8,address,uint256\[\],uint256\[\])](#changerecipientreferrer-fr1) — FeeRegistry

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### \_checkNewOwnerIsNotReferrer (FR1)

**Contract/Library:** FeeRegistry

**Description:** Prevents assigning a code to an address that already has one.

**Detailed Description:** Ensures `codeByReferrer_newReferer == bytes8(0)`.

**Parameters:**

* fs ([FRStorage](https://docs.cryptolegacy.app/documentation/data-structures-reference#frstorage-ifr1-s1), storage): FeeRegistry storage pointer
* \_newReferer (address): Candidate referrer

**Returns:** None

**Modifiers / Visibility / Mutability:**

* internal view

**Access Control:**

* Internal only

**Side Effects:** None

**Emits:** None

**Reverts if:**

* `codeByReferrer_newReferer != bytes8(0)` — [`AlreadyReferrer()`](https://docs.cryptolegacy.app/documentation/errors-reference#alreadyreferrer-ifr1)

**Overrides:** None

**Function Calls:** None

**Called by:**

* [\_setCustomCode(FRStorage,address,address,bytes8,uint32,uint32)](#_setcustomcode-fr1) — FeeRegistry
* [changeCodeReferrer(bytes8,address,address,uint256\[\],uint256\[\])](#changecodereferrer-fr1) — FeeRegistry

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### changeCodeReferrer (FR1)

**Contract/Library:** FeeRegistry

**Description:** Transfers code ownership to a new referrer and optionally updates cross‑chain.

**Detailed Description:** Checks caller is current referrer and target is not already one, updates owner/recipient mappings, optionally propagates cross-chain updates, refunds surplus, and emits ownership change.

**Parameters:**

* \_code (bytes8): Code to transfer
* \_newReferer (address): New owner
* \_newRecipient (address): New payout recipient
* \_chainIds (uint256\[], memory): Destination chain IDs
* \_crossChainFees (uint256\[], memory): Native fees per chain

**Returns:**

* totalFee (uint256): Total native fee used
* returnValue (uint256): Refunded surplus (if any)

**Modifiers / Visibility / Mutability:**

* external nonReentrant payable

**Access Control:**

* Caller must be current referrer (enforced internally)

**Side Effects:**

* Clears `codeByReferrermsg.sender`
* Updates `refererByCode_code.owner` and `.recipient`
* Updates `codeByReferrer_newReferer`
* Sends native fee to `deBridgeGate` per destination chain via `_send`
* May transfer surplus ETH back to `msg.sender` via `_calcAndReturnFee`

**Emits:**

* [SendToChain](https://docs.cryptolegacy.app/documentation/events-reference#sendtochain-ilcg1) — `SendToChain(uint256 indexed toChainId, bytes32 indexed submissionId, uint256 value, bytes dstTransactionCall)`
* [SetCrossChainsRef](https://docs.cryptolegacy.app/documentation/events-reference#setcrosschainsref-ifr1) — `SetCrossChainsRef(bytes8 indexed shortCode, bool indexed isCreate, uint256[] toChainIDs, uint256[] crossChainFees)`
* [ChangeCode](https://docs.cryptolegacy.app/documentation/events-reference#changecode-ifr1) — `ChangeCode(address indexed oldReferrer, address indexed newReferrer, bytes8 indexed code)`

**Reverts if:**

* Reentrant call — "ReentrancyGuard: reentrant call"
* `codeByReferrermsg.sender != _code` — [`NotReferrer()`](https://docs.cryptolegacy.app/documentation/errors-reference#notreferrer-ifr1)
* `_code == bytes8(0)` — [`NotReferrer()`](https://docs.cryptolegacy.app/documentation/errors-reference#notreferrer-ifr1)
* `codeByReferrer_newReferer != bytes8(0)` — [`AlreadyReferrer()`](https://docs.cryptolegacy.app/documentation/errors-reference#alreadyreferrer-ifr1)
* `_chainIds.length != _crossChainFees.length` — [`ArrayLengthMismatch()`](https://docs.cryptolegacy.app/documentation/errors-reference#arraylengthmismatch-ilcg1)
* Destination chain contract not specified — [`DestinationChainNotSpecified()`](https://docs.cryptolegacy.app/documentation/errors-reference#destinationchainnotspecified-ilcg1)
* `deBridgeGate.globalFixedNativeFee()` — may revert per implementation (bubbled)
* `deBridgeGate.sendMessage(...)` — may revert per deBridgeGate implementation (bubbled)
* `msg.value < totalFee` or `msg.value - totalFee > 0.00001 ether` — [`IncorrectFee(uint256)`](https://docs.cryptolegacy.app/documentation/errors-reference#incorrectfee-ilcg1)
* Refund transfer to `msg.sender` fails — [`TransferFeeFailed(bytes)`](https://docs.cryptolegacy.app/documentation/errors-reference#transferfeefailed-ilcg1)

**Overrides:** None

**Function Calls:**

* [lockFeeRegistryStorage()](#lockfeeregistrystorage-fr1) — FeeRegistry, internal
* [\_checkSenderIsReferrer(FRStorage,bytes8)](#_checksenderisreferrer-fr1) — FeeRegistry, internal
* [\_checkNewOwnerIsNotReferrer(FRStorage,address)](#_checknewownerisnotreferrer-fr1) — FeeRegistry, internal
* [\_setCrossChainsRef(FRStorage,bool,bytes8,uint256\[\],uint256\[\])](#_setcrosschainsref-fr1) — FeeRegistry, internal
* [\_calcAndReturnFee(uint256)](#_calcandreturnfee-lcg1) — LockChainGate, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1) local + O(n) by `_chainIds.length`

**Example:** Referrer moves code ownership to a new address and updates remote chains.

***

### changeRecipientReferrer (FR1)

**Contract/Library:** FeeRegistry

**Description:** Updates the payout recipient for a referral code and optionally propagates cross-chain.

**Detailed Description:** Checks caller is the referrer for `_code`, updates `refererByCode_code.recipient`, propagates cross-chain update, and refunds any surplus fee.

**Parameters:**

* \_code (bytes8): Code to update
* \_newRecipient (address): New payout recipient
* \_chainIds (uint256\[], memory): Destination chain IDs
* \_crossChainFees (uint256\[], memory): Native fees per chain

**Returns:**

* totalFee (uint256): Total native fee used
* returnValue (uint256): Refunded surplus (if any)

**Modifiers / Visibility / Mutability:**

* external nonReentrant payable

**Access Control:**

* Caller must be current referrer (enforced internally)

**Side Effects:**

* Updates `refererByCode_code.recipient`
* Sends native fee to `deBridgeGate` per destination chain via `_send`
* May transfer surplus ETH back to `msg.sender` via `_calcAndReturnFee`

**Emits:**

* [SendToChain](https://docs.cryptolegacy.app/documentation/events-reference#sendtochain-ilcg1) — `SendToChain(uint256 indexed toChainId, bytes32 indexed submissionId, uint256 value, bytes dstTransactionCall)`
* [SetCrossChainsRef](https://docs.cryptolegacy.app/documentation/events-reference#setcrosschainsref-ifr1) — `SetCrossChainsRef(bytes8 indexed shortCode, bool indexed isCreate, uint256[] toChainIDs, uint256[] crossChainFees)`
* [ChangeRecipient](https://docs.cryptolegacy.app/documentation/events-reference#changerecipient-ifr1) — `ChangeRecipient(address indexed referrer, address indexed newRecipient, bytes8 indexed code)`

**Reverts if:**

* Reentrant call — "ReentrancyGuard: reentrant call"
* `codeByReferrermsg.sender != _code` — [`NotReferrer()`](https://docs.cryptolegacy.app/documentation/errors-reference#notreferrer-ifr1)
* `_code == bytes8(0)` — [`NotReferrer()`](https://docs.cryptolegacy.app/documentation/errors-reference#notreferrer-ifr1)
* `_chainIds.length != _crossChainFees.length` — [`ArrayLengthMismatch()`](https://docs.cryptolegacy.app/documentation/errors-reference#arraylengthmismatch-ilcg1)
* Destination chain contract not specified — [`DestinationChainNotSpecified()`](https://docs.cryptolegacy.app/documentation/errors-reference#destinationchainnotspecified-ilcg1)
* `deBridgeGate.globalFixedNativeFee()` — may revert per implementation (bubbled)
* `deBridgeGate.sendMessage(...)` — may revert per deBridgeGate implementation (bubbled)
* `msg.value < totalFee` or `msg.value - totalFee > 0.00001 ether` — [`IncorrectFee(uint256)`](https://docs.cryptolegacy.app/documentation/errors-reference#incorrectfee-ilcg1)
* Refund transfer to `msg.sender` fails — [`TransferFeeFailed(bytes)`](https://docs.cryptolegacy.app/documentation/errors-reference#transferfeefailed-ilcg1)

**Overrides:** None

**Function Calls:**

* [lockFeeRegistryStorage()](#lockfeeregistrystorage-fr1) — FeeRegistry, internal
* [\_checkSenderIsReferrer(FRStorage,bytes8)](#_checksenderisreferrer-fr1) — FeeRegistry, internal
* [\_setCrossChainsRef(FRStorage,bool,bytes8,uint256\[\],uint256\[\])](#_setcrosschainsref-fr1) — FeeRegistry, internal
* [\_calcAndReturnFee(uint256)](#_calcandreturnfee-lcg1) — LockChainGate, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1) local + O(n) by `_chainIds.length`

**Example:** Referrer updates their payout address and syncs it to other chains.

***

### getCodeOperatorsList (FR1)

**Contract/Library:** FeeRegistry

**Description:** Returns the list of authorized code operators.

**Detailed Description:** Reads the enumerable set and materializes it into an array.

**Parameters:** None

**Returns:**

* operators (address\[], memory): Current code operators

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [lockFeeRegistryStorage()](#lockfeeregistrystorage-fr1) — FeeRegistry, internal
* `values()` — `EnumerableSet.AddressSet`, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(n) by number of operators

**Example:** Front-end queries to display operator addresses.

***

### isCodeOperator (FR1)

**Contract/Library:** FeeRegistry

**Description:** Checks whether an address is an authorized code operator.

**Detailed Description:** Queries membership in the `codeOperators` set for `_addr`.

**Parameters:**

* \_addr (address): Address to check

**Returns:**

* isOperator (bool): True if address is an operator

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [lockFeeRegistryStorage()](#lockfeeregistrystorage-fr1) — FeeRegistry, internal
* `contains(address)` — `EnumerableSet.AddressSet`, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### getSupportedRefInChainsList (FR1)

**Contract/Library:** FeeRegistry

**Description:** Lists chain IDs where referral codes are supported.

**Detailed Description:** Returns the contents of `supportedRefInChains` set.

**Parameters:** None

**Returns:**

* chains (uint256\[], memory): Supported chain IDs

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:**

* IFeeRegistry (function implementation).

**Function Calls:**

* [lockFeeRegistryStorage()](#lockfeeregistrystorage-fr1) — FeeRegistry, internal
* `values()` — `EnumerableSet.UintSet`, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(n) by set size

**Example:** Not applicable

***

### isSupportedRefInChain (FR1)

**Contract/Library:** FeeRegistry

**Description:** Checks whether a chain ID supports referral codes.

**Detailed Description:** Queries membership in the `supportedRefInChains` set.

**Parameters:**

* \_chainId (uint256): Chain id to check

**Returns:**

* supported (bool): True if supported

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [lockFeeRegistryStorage()](#lockfeeregistrystorage-fr1) — FeeRegistry, internal
* `contains(uint256)` — `EnumerableSet.UintSet`, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### getFeeBeneficiaries (FR1)

**Contract/Library:** FeeRegistry

**Description:** Returns protocol fee beneficiaries.

**Detailed Description:** Reads and returns the stored array of `(recipient, sharePct)`.

**Parameters:** None

**Returns:**

* beneficiaries ([FeeBeneficiary](https://docs.cryptolegacy.app/documentation/data-structures-reference#feebeneficiary-ifr1-s3)\[], memory): Current fee beneficiaries

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [lockFeeRegistryStorage()](#lockfeeregistrystorage-fr1) — FeeRegistry, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(n) by beneficiaries length

**Example:** Not applicable

***

### getCodePct (FR1)

**Contract/Library:** FeeRegistry

**Description:** Returns effective discount/share percentages for a code.

**Detailed Description:** Returns `(0, 0)` if the code is unset; otherwise returns code-specific values when set, or defaults.

**Parameters:**

* \_code (bytes8): Code whose percentages are requested

**Returns:**

* discountPct (uint32): Effective discount bps
* sharePct (uint32): Effective share bps

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [lockFeeRegistryStorage()](#lockfeeregistrystorage-fr1) — FeeRegistry, internal
* [\_getCodePct(FRStorage,bytes8)](#_getcodepct-fr1) — FeeRegistry, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### \_getCodePct (FR1)

**Contract/Library:** FeeRegistry

**Description:** Internal resolver for a code’s effective percentages.

**Detailed Description:** Returns `(0,0)` if code unset; else returns specific values if present, or fallbacks to defaults.

**Parameters:**

* fs ([FRStorage](https://docs.cryptolegacy.app/documentation/data-structures-reference#frstorage-ifr1-s1), storage): FeeRegistry storage pointer
* \_code (bytes8): Code to resolve

**Returns:**

* discountPct (uint32): Effective discount bps
* sharePct (uint32): Effective share bps

**Modifiers / Visibility / Mutability:**

* internal view

**Access Control:**

* Internal only

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:**

* [getCodePct(bytes8)](#getcodepct-fr1) — FeeRegistry
* [\_calculateFee(FRStorage,bytes8,uint256)](#_calculatefee-fr1) — FeeRegistry
* [\_getReferrerByCode(FRStorage,bytes8)](#_getreferrerbycode-fr1) — FeeRegistry

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### calculateFee (FR1)

**Contract/Library:** FeeRegistry

**Description:** Computes discount, share, and final fee for a code and base fee.

**Detailed Description:** Fetches effective percentages and applies them: `discount = base*discountPct/PCT_BASE`, `share = base*sharePct/PCT_BASE`, `fee = base - discount` (see [`PCT_BASE`](https://docs.cryptolegacy.app/documentation/data-structures-reference#pct_base-fr1-d1)).

**Parameters:**

* \_code (bytes8): Code to apply
* \_fee (uint256): Base fee before discount

**Returns:**

* discount (uint256): Discount amount
* share (uint256): Referrer share amount
* fee (uint256): Fee after discount

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:**

* discountPct + sharePct > [`PCT_BASE`](https://docs.cryptolegacy.app/documentation/data-structures-reference#pct_base-fr1-d1) — [`TooBigPct()`](https://docs.cryptolegacy.app/documentation/errors-reference#toobigpct-ifr1)

**Overrides:** None

**Function Calls:**

* [lockFeeRegistryStorage()](#lockfeeregistrystorage-fr1) — FeeRegistry, internal
* [\_calculateFee(FRStorage,bytes8,uint256)](#_calculatefee-fr1) — FeeRegistry, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### \_calculateFee (FR1)

**Contract/Library:** FeeRegistry

**Description:** Internal computation of discount/share/fee for a code and base amount.

**Detailed Description:** Reads effective percentages via [\_getCodePct](#_getcodepct-fr1), verifies sum ≤ [`PCT_BASE`](https://docs.cryptolegacy.app/documentation/data-structures-reference#pct_base-fr1-d1), then computes amounts.

**Parameters:**

* fs ([FRStorage](https://docs.cryptolegacy.app/documentation/data-structures-reference#frstorage-ifr1-s1), storage): FeeRegistry storage pointer
* \_code (bytes8): Code to apply
* \_fee (uint256): Base fee

**Returns:**

* discount (uint256): Discount amount
* share (uint256): Share amount
* fee (uint256): Final fee after discount

**Modifiers / Visibility / Mutability:**

* internal view

**Access Control:**

* Internal only

**Side Effects:** None

**Emits:** None

**Reverts if:**

* discountPct + sharePct > [`PCT_BASE`](https://docs.cryptolegacy.app/documentation/data-structures-reference#pct_base-fr1-d1) — [`TooBigPct()`](https://docs.cryptolegacy.app/documentation/errors-reference#toobigpct-ifr1)

**Overrides:** None

**Function Calls:**

* [\_getCodePct(FRStorage,bytes8)](#_getcodepct-fr1) — FeeRegistry, internal

**Called by:**

* [takeFee(address,uint8,bytes8,uint256)](#takefee-fr1) — FeeRegistry
* [calculateFee(bytes8,uint256)](#calculatefee-fr1) — FeeRegistry
* [getContractCaseFeeForCode(address,uint8,bytes8)](#getcontractcasefeeforcode-fr1) — FeeRegistry

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### getContractCaseFee (FR1)

**Contract/Library:** FeeRegistry

**Description:** Retrieves the stored fee for a (contract, case) pair.

**Detailed Description:** Returns `feeByContractCase_contract_case`.

**Parameters:**

* \_contract (address): Source contract
* \_case (uint8): Case id

**Returns:**

* fee (uint256): Stored fee amount

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:**

* IFeeRegistry (function implementation).

**Function Calls:**

* [lockFeeRegistryStorage()](#lockfeeregistrystorage-fr1) — FeeRegistry, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### getContractCaseFeeForCode (FR1)

**Contract/Library:** FeeRegistry

**Description:** Retrieves the effective fee for a (contract, case) after applying a code’s discount.

**Detailed Description:** Computes discount/fee using stored base and code’s percentages; returns the effective fee.

**Parameters:**

* \_contract (address): Source contract
* \_case (uint8): Case id
* \_code (bytes8): Referral code

**Returns:**

* fee (uint256): Effective fee after discount

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:**

* discountPct + sharePct > [`PCT_BASE`](https://docs.cryptolegacy.app/documentation/data-structures-reference#pct_base-fr1-d1) — [`TooBigPct()`](https://docs.cryptolegacy.app/documentation/errors-reference#toobigpct-ifr1)

**Overrides:**

* IFeeRegistry (function implementation).

**Function Calls:**

* [lockFeeRegistryStorage()](#lockfeeregistrystorage-fr1) — FeeRegistry, internal
* [\_calculateFee(FRStorage,bytes8,uint256)](#_calculatefee-fr1) — FeeRegistry, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### getReferrerByAddress (FR1)

**Contract/Library:** FeeRegistry

**Description:** Returns referrer metadata by referrer address.

**Detailed Description:** Looks up the short code via `codeByReferrer` and returns the [`Referrer`](https://docs.cryptolegacy.app/documentation/data-structures-reference#referrer-ifr1-s2) struct (with effective percentages applied).

**Parameters:**

* \_referrer (address): Referrer owner address

**Returns:**

* ref ([Referrer](https://docs.cryptolegacy.app/documentation/data-structures-reference#referrer-ifr1-s2), memory): Referrer data (owner, recipient, pcts, accumulated)

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [lockFeeRegistryStorage()](#lockfeeregistrystorage-fr1) — FeeRegistry, internal
* [\_getReferrerByAddress(FRStorage,address)](#_getreferrerbyaddress-fr1) — FeeRegistry, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Call `getReferrerByAddress(alice)` to read the referrer data for an address.

***

### \_getReferrerByAddress (FR1)

**Contract/Library:** FeeRegistry

**Description:** Internal resolver for referrer by address.

**Detailed Description:** Finds a code via `codeByReferrer` and returns the corresponding referrer struct.

**Parameters:**

* fs ([FRStorage](https://docs.cryptolegacy.app/documentation/data-structures-reference#frstorage-ifr1-s1), storage): FeeRegistry storage pointer
* \_referrer (address): Referrer owner

**Returns:**

* ref ([Referrer](https://docs.cryptolegacy.app/documentation/data-structures-reference#referrer-ifr1-s2), memory): Referrer data

**Modifiers / Visibility / Mutability:**

* internal view

**Access Control:**

* Internal only

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [getReferrerByCode(bytes8)](#getreferrerbycode-fr1) — FeeRegistry, internal

**Called by:**

* [getReferrerByAddress(address)](#getreferrerbyaddress-fr1) — FeeRegistry

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### getReferrerByCode (FR1)

**Contract/Library:** FeeRegistry

**Description:** Returns referrer metadata by code.

**Detailed Description:** Calls \_getReferrerByCode, which fetches the stored referrer struct and applies effective percentages from \_getCodePct; if the code is registered, defaults are used when specific pcts are zero, and if not registered, \_getCodePct returns 0/0.

**Parameters:**

* \_code (bytes8): Short referral code

**Returns:**

* ref ([Referrer](https://docs.cryptolegacy.app/documentation/data-structures-reference#referrer-ifr1-s2), memory): Referrer data with effective pcts

**Modifiers / Visibility / Mutability:**

* public view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [lockFeeRegistryStorage()](#lockfeeregistrystorage-fr1) — FeeRegistry, internal
* [\_getReferrerByCode(FRStorage,bytes8)](#_getreferrerbycode-fr1) — FeeRegistry, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Call `getReferrerByCode(refCode)` after code creation to read the referrer data.

***

### \_getReferrerByCode (FR1)

**Contract/Library:** FeeRegistry

**Description:** Internal resolver for referrer by code.

**Detailed Description:** Reads `refererByCode_code` and replaces its discount/share with effective values from [\_getCodePct](#_getcodepct-fr1).

**Parameters:**

* fs ([FRStorage](https://docs.cryptolegacy.app/documentation/data-structures-reference#frstorage-ifr1-s1), storage): FeeRegistry storage pointer
* \_code (bytes8): Short code

**Returns:**

* ref ([Referrer](https://docs.cryptolegacy.app/documentation/data-structures-reference#referrer-ifr1-s2), memory): Referrer data with effective pcts

**Modifiers / Visibility / Mutability:**

* internal view

**Access Control:**

* Internal only

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [\_getCodePct(FRStorage,bytes8)](#_getcodepct-fr1) — FeeRegistry, internal

**Called by:**

* [getReferrerByCode(bytes8)](#getreferrerbycode-fr1) — FeeRegistry

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### defaultSharePct (FR1)

**Contract/Library:** FeeRegistry

**Description:** Returns the default share percentage.

**Detailed Description:** Reads `defaultSharePct` from storage.

**Parameters:** None

**Returns:**

* pct (uint32): Default share bps

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [lockFeeRegistryStorage()](#lockfeeregistrystorage-fr1) — FeeRegistry, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### defaultDiscountPct (FR1)

**Contract/Library:** FeeRegistry

**Description:** Returns the default discount percentage.

**Detailed Description:** Reads `defaultDiscountPct` from storage.

**Parameters:** None

**Returns:**

* pct (uint32): Default discount bps

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [lockFeeRegistryStorage()](#lockfeeregistrystorage-fr1) — FeeRegistry, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### refererByCode (FR1)

**Contract/Library:** FeeRegistry

**Description:** Returns raw referrer record for a code (without effective pcts).

**Detailed Description:** Directly returns `refererByCode_code` from storage.

**Parameters:**

* \_code (bytes8): Short code

**Returns:**

* ref ([Referrer](https://docs.cryptolegacy.app/documentation/data-structures-reference#referrer-ifr1-s2), memory): Raw referrer struct

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [lockFeeRegistryStorage()](#lockfeeregistrystorage-fr1) — FeeRegistry, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### codeByReferrer (FR1)

**Contract/Library:** FeeRegistry

**Description:** Returns the code associated with a referrer address.

**Detailed Description:** Directly returns `codeByReferrer_referrer` from storage.

**Parameters:**

* \_referrer (address): Referrer owner address

**Returns:**

* code (bytes8): Assigned short code (or zero)

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [lockFeeRegistryStorage()](#lockfeeregistrystorage-fr1) — FeeRegistry, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### accumulatedFee (FR1)

**Contract/Library:** FeeRegistry

**Description:** Returns the accumulated protocol fee balance.

**Detailed Description:** Reads `accumulatedFee` from storage.

**Parameters:** None

**Returns:**

* amount (uint128): Accumulated protocol fee

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:**

* IFeeRegistry (function implementation).

**Function Calls:**

* [lockFeeRegistryStorage()](#lockfeeregistrystorage-fr1) — FeeRegistry, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

## LegacyMessenger (LM1)

### constructor (LM1)

**Contract/Library:** LegacyMessenger

**Description:** Initializes the messenger and sets the contract owner.

**Detailed Description:** Transfers ownership to `_owner` during deployment using the inherited `_transferOwnership` helper.

**Parameters:**

* \_owner (address): Address to be set as the initial owner

**Returns:** None

**Modifiers / Visibility / Mutability:**

* constructor nonpayable

**Access Control:**

* Unrestricted (deployment only)

**Side Effects:**

* Sets `owner` (inherited from `Ownable`)

**Emits:**

* [OwnershipTransferred](https://docs.cryptolegacy.app/documentation/events-reference#ownershiptransferred-iclo1) — `OwnershipTransferred(address indexed previousOwner, address indexed newOwner)`

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* `_transferOwnership(address)` — `Ownable`, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Deploy with `new LegacyMessenger(msg.sender)` to set the deployer as the owner.

***

### sendMessagesTo (LM1)

**Contract/Library:** LegacyMessenger

**Description:** Emits per‑recipient message events and records the block number for each recipient.

**Detailed Description:** Verifies the caller and target CryptoLegacy instance via `_checkBuildManagerValid(_cryptoLegacy, msg.sender)`. Iterates over `_recipientList`, and for each index `i` emits `LegacyMessage` and `LegacyMessageCheck` with the corresponding payloads, then appends the current block number to [`messagesGotByBlockNumber`](https://docs.cryptolegacy.app/documentation/data-structures-reference#messagesgotbyblocknumber-lm1-d1)\[\_recipientList\[i]]. Uses L2 Arbitrum block number via `ArbSys(address(100)).arbBlockNumber()` when `block.chainid == 42161`, otherwise `block.number`. Arrays are treated as parallel and must align by index.

**Parameters:**

* \_cryptoLegacy (address): Target CryptoLegacy contract whose owner is authorized to send
* \_recipientList (bytes32\[], memory): Recipient identifiers (hashes) aligned by index
* \_messageHashList (bytes32\[], memory): Message hashes aligned by index
* \_messageList (bytes\[], memory): Raw message payloads aligned by index
* \_messageCheckList (bytes\[], memory): Companion/check payloads aligned by index
* \_messageType (uint256): Application‑specific message type/category

**Returns:** None

**Modifiers / Visibility / Mutability:**

* public nonpayable

**Access Control:**

* Caller must pass `_checkBuildManagerValid(_cryptoLegacy, msg.sender)` (owner of `_cryptoLegacy` and `_cryptoLegacy` built by an allow‑listed build manager).

**Side Effects:**

* Appends to [`messagesGotByBlockNumber`](https://docs.cryptolegacy.app/documentation/data-structures-reference#messagesgotbyblocknumber-lm1-d1)\[\_recipientList\[i]] for each recipient.

**Emits:**

* [LegacyMessage](https://docs.cryptolegacy.app/documentation/events-reference#legacymessage-ilm1) — `LegacyMessage(address indexed legacy, bytes32 indexed toRecipient, bytes32 messageHash, bytes message, uint256 indexed messageType)`
* [LegacyMessageCheck](https://docs.cryptolegacy.app/documentation/events-reference#legacymessagecheck-ilm1) — `LegacyMessageCheck(address indexed legacy, bytes32 indexed toBeneficiary, bytes32 messageHash, bytes message, uint256 indexed messageType)`

**Reverts if:**

* Caller is not the owner of `_cryptoLegacy` — [`NotTheOwnerOfCryptoLegacy()`](https://docs.cryptolegacy.app/documentation/errors-reference#nottheownerofcryptolegacy-ibmo1)
* `_cryptoLegacy` not registered by its build manager — [`CryptoLegacyNotRegistered()`](https://docs.cryptolegacy.app/documentation/errors-reference#cryptolegacynotregistered-ibmo1)
* Build manager not allow-listed — [`BuildManagerNotAdded()`](https://docs.cryptolegacy.app/documentation/errors-reference#buildmanagernotadded-ibmo1)
* Array length mismatch — Panic(0x32)

**Overrides:** None

**Function Calls:**

* [`_checkBuildManagerValid(address,address)`](#_checkbuildmanagervalid-bmo1) — `BuildManagerOwnable`, internal
* `arbBlockNumber()` — `ArbSys` *(at `address(100)`)*, external (staticcall)

**Called by:** None (entry point)

**Gas / Complexity note:** O(n) by `_recipientList.length` — each recipient costs two event emissions and one storage append.

**Example:** Owner of a CryptoLegacy instance calls `sendMessagesTo(cl, recipients, msgHashes, msgs, checks, 1)` to broadcast messages and log the corresponding block numbers.

***

### getMessagesBlockNumbersByRecipient (LM1)

**Contract/Library:** LegacyMessenger

**Description:** Returns the list of block numbers when a given recipient received messages.

**Detailed Description:** Reads and returns the dynamic array stored at [`messagesGotByBlockNumber`](https://docs.cryptolegacy.app/documentation/data-structures-reference#messagesgotbyblocknumber-lm1-d1)\[\_recipient].

**Parameters:**

* \_recipient (bytes32): Recipient identifier (hash)

**Returns:**

* blockNumbers (uint64\[], memory): Array of recorded block numbers for `_recipient`

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:** None (entry point)

**Gas / Complexity note:** O(n) by `blockNumbers.length`.

**Example:** Call `getMessagesBlockNumbersByRecipient(recipientHash)` to obtain all blocks when messages were observed for that recipient.

***

## LifetimeNft (LN1)

### constructor (LN1)

**Contract/Library:** LifetimeNft

**Description:** Initializes the ERC721 token with name, symbol, base URI, and owner.

**Detailed Description:** Sets the metadata base URI via internal `_setBaseUri`, initializes ERC721 name and symbol, then lets `Ownable()` set the initial owner to `msg.sender` before `_transferOwnership(_owner)` transfers control to the final owner. Emits `SetBaseURI` (via `_setBaseUri`) and two `OwnershipTransferred` events for the inherited Ownable handoff.

**Parameters:**

* name\_ (string, memory): Token name
* symbol\_ (string, memory): Token symbol
* baseURI\_ (string, memory): Initial base URI for metadata
* \_owner (address): Initial contract owner

**Returns:** None

**Modifiers / Visibility / Mutability:**

* constructor nonpayable

**Access Control:**

* Unrestricted (deployment only)

**Side Effects:**

* Sets [`baseURI`](https://docs.cryptolegacy.app/documentation/data-structures-reference#baseuri-ln1-d1)
* Sets ERC721 name and symbol
* Sets `owner`

**Emits:**

* [SetBaseURI](https://docs.cryptolegacy.app/documentation/events-reference#setbaseuri-ln1) — `SetBaseURI(string baseURI)`
* [OwnershipTransferred](https://docs.cryptolegacy.app/documentation/events-reference#ownershiptransferred-iclo1) — `OwnershipTransferred(address indexed previousOwner, address indexed newOwner)` (via `Ownable()` constructor)
* [OwnershipTransferred](https://docs.cryptolegacy.app/documentation/events-reference#ownershiptransferred-iclo1) — `OwnershipTransferred(address indexed previousOwner, address indexed newOwner)` (via `Ownable._transferOwnership`)

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [\_setBaseUri(string)](#_setbaseuri-ln1) — LifetimeNft, internal
* \_transferOwnership(address) — OpenZeppelin Ownable, internal
* `ERC721(name_,symbol_)` — ERC721, internal

**Called by:**

None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Deploy with `new LifetimeNft("Lifetime", "LIFE", "https://api.example.com/metadata/", msg.sender)`.

***

### setBaseUri (LN1)

**Contract/Library:** LifetimeNft

**Description:** Updates the collection-wide base URI.

**Detailed Description:** Owner-only setter that forwards to `_setBaseUri` to update storage and emit `SetBaseURI`.

**Parameters:**

* baseURI\_ (string, memory): New base URI string

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external onlyOwner nonpayable

**Access Control:**

* Owner only

**Side Effects:**

* Updates [`baseURI`](https://docs.cryptolegacy.app/documentation/data-structures-reference#baseuri-ln1-d1)

**Emits:**

* [SetBaseURI](https://docs.cryptolegacy.app/documentation/events-reference#setbaseuri-ln1) — `SetBaseURI(string baseURI)`

**Reverts if:**

* Caller is not the owner — "Ownable: caller is not the owner"

**Overrides:** None

**Function Calls:**

* [\_setBaseUri(string)](#_setbaseuri-ln1) — LifetimeNft, internal

**Called by:**

None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Owner calls `setBaseUri("https://cdn.example.com/nft/")` to change metadata base.

***

### \_setBaseUri (LN1)

**Contract/Library:** LifetimeNft

**Description:** Internal helper to set the base URI and emit an event.

**Detailed Description:** Writes [`baseURI`](https://docs.cryptolegacy.app/documentation/data-structures-reference#baseuri-ln1-d1) to storage and emits `SetBaseURI`. Used by the constructor and `setBaseUri`.

**Parameters:**

* baseURI\_ (string, memory): New base URI string

**Returns:** None

**Modifiers / Visibility / Mutability:**

* internal nonpayable

**Access Control:**

* Unrestricted (internal)

**Side Effects:**

* Updates [`baseURI`](https://docs.cryptolegacy.app/documentation/data-structures-reference#baseuri-ln1-d1)

**Emits:**

* [SetBaseURI](https://docs.cryptolegacy.app/documentation/events-reference#setbaseuri-ln1) — `SetBaseURI(string baseURI)` (new base URI)

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:**

* [constructor](#constructor-ln1) — LifetimeNft
* [setBaseUri(string)](#setbaseuri-ln1) — LifetimeNft

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### setMinterOperator (LN1)

**Contract/Library:** LifetimeNft

**Description:** Grants or revokes minting permission for an address.

**Detailed Description:** Owner-only setter for [`minterOperator`](https://docs.cryptolegacy.app/documentation/data-structures-reference#minteroperator-ln1-d2)\[\_minter]. Updates the permission flag and emits `SetMinterOperator`.

**Parameters:**

* \_minter (address): Address to update
* \_isActive (bool): Whether the address is authorized to mint

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external onlyOwner nonpayable

**Access Control:**

* Owner only

**Side Effects:**

* Updates [`minterOperator`](https://docs.cryptolegacy.app/documentation/data-structures-reference#minteroperator-ln1-d2)\[\_minter]

**Emits:**

* [SetMinterOperator](https://docs.cryptolegacy.app/documentation/events-reference#setminteroperator-ln1) — `SetMinterOperator(address indexed minter, bool indexed isActive)`

**Reverts if:**

* Caller is not the owner — "Ownable: caller is not the owner"

**Overrides:** None

**Function Calls:** None

**Called by:**

None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Owner calls `setMinterOperator(minterAddr, true)` to allow `minterAddr` to mint.

***

### mint (LN1)

**Contract/Library:** LifetimeNft

**Description:** Mints a new token to the specified owner.

**Detailed Description:** Requires [`minterOperator`](https://docs.cryptolegacy.app/documentation/data-structures-reference#minteroperator-ln1-d2)\[msg.sender] to be true. Computes `tokenId = totalSupply() + 1`, then `_safeMint` to `_tokenOwner`. Returns the new `tokenId`.

**Parameters:**

* \_tokenOwner (address): Recipient of the newly minted NFT

**Returns:**

* tokenId (uint256): Newly minted token ID

**Modifiers / Visibility / Mutability:**

* external nonpayable

**Access Control:**

* Active minter operator only ([`minterOperator`](https://docs.cryptolegacy.app/documentation/data-structures-reference#minteroperator-ln1-d2)\[msg.sender] == true)

**Side Effects:**

* Mints a new ERC721 token to `_tokenOwner`
* Updates ERC721 ownership/enumeration state
* May invoke `onERC721Received` on `_tokenOwner` if it is a contract

**Emits:**

* OpenZeppelin base-type event (not mirrored in `events-reference.md`): `Transfer(address indexed from, address indexed to, uint256 indexed tokenId)`

**Reverts if:**

* Caller not authorized — [`NotTheMinter()`](https://docs.cryptolegacy.app/documentation/errors-reference#nottheminter-iln1)
* `_tokenOwner` is the zero address — "ERC721: mint to the zero address"
* `_tokenOwner` cannot receive ERC721 tokens — "ERC721: transfer to non ERC721Receiver implementer"

**Overrides:** None

**Function Calls:**

* `totalSupply()` — ERC721Enumerable, internal
* `_safeMint(address,uint256)` — ERC721, internal

**Called by:**

* [\_mintAndLockLifetimeNft](#_mintandlocklifetimenft-clbm1) — CryptoLegacyBuildManager
* [payForMultipleLifetimeNft](#payformultiplelifetimenft-clbm1) — CryptoLegacyBuildManager

**Gas / Complexity note:** O(1) for bookkeeping; `_safeMint` incurs standard ERC721 mint costs

**Example:** An authorized minter calls `mint(user)` to issue a new lifetime NFT to `user`.

***

### \_baseURI (LN1)

**Contract/Library:** LifetimeNft

**Description:** Returns the stored base URI for metadata composition.

**Detailed Description:** Internal view override that exposes the [`baseURI`](https://docs.cryptolegacy.app/documentation/data-structures-reference#baseuri-ln1-d1) storage variable to ERC721 URI logic.

**Parameters:** None

**Returns:**

* uri (string, memory): Current base URI

**Modifiers / Visibility / Mutability:**

* internal view override

**Access Control:**

* Internal only

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:**

* ERC721.\_baseURI()

**Function Calls:** None

**Called by:**

* `tokenURI(uint256)` — ERC721

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### tokensOfOwner (LN1)

**Contract/Library:** LifetimeNft

**Description:** Enumerates all token IDs owned by the given address.

**Detailed Description:** Allocates an array of length `balanceOf(_owner)` and fills it by iterating `tokenOfOwnerByIndex(_owner, i)` for `i` in `0, balance-1`.

**Parameters:**

* \_owner (address): Address to query

**Returns:**

* tokens (uint256\[], memory): Array of token IDs owned by `_owner`

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:**

* `_owner` == address(0) — "ERC721: address zero is not a valid owner"

**Overrides:** None

**Function Calls:**

* `balanceOf(address)` — ERC721, internal
* `tokenOfOwnerByIndex(address,uint256)` — ERC721Enumerable, internal

**Called by:**

None (entry point)

**Gas / Complexity note:** O(n) by `balanceOf(_owner)`

**Example:** Client calls `tokensOfOwner(user)` to list all owned token IDs.

***

### getTier (LN1)

**Contract/Library:** LifetimeNft

**Description:** Computes the tier for a given token ID.

**Detailed Description:** Pure function using fixed thresholds:

* `1–100` → Silicon
* `101–300` → Gallium
* `301–700` → Indium
* `701–1500` → Tantalum
* `1501+` → Based

**Parameters:**

* \_tokenId (uint256): Token ID to classify

**Returns:**

* tier ([Tier](https://docs.cryptolegacy.app/documentation/data-structures-reference#tier-iln1-e1)): Tier enumeration value for `_tokenId`

**Modifiers / Visibility / Mutability:**

* external pure

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:**

None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Call `getTier(275)` to receive the corresponding tier.

***

## LockChainGate (LCG1)

### constructor (LCG1)

**Contract/Library:** LockChainGate

**Description:** Deploy-time constructor that disables initializers and sets the Ownable owner.

**Detailed Description:** Calls `_disableInitializers()` to lock upgradeable initialization and relies on the inherited `Ownable` constructor to assign the deployer as owner.

**Parameters:** None

**Returns:** None

**Modifiers / Visibility / Mutability:**

* constructor nonpayable

**Access Control:**

* Unrestricted (deployment only)

**Side Effects:**

* Locks the `_initialized` flags within `Initializable`
* Sets `owner` (Ownable)

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* \_disableInitializers() — Initializable, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### lockChainGateStorage (LCG1)

**Contract/Library:** LockChainGate

**Description:** Returns the storage pointer for the LockChainGate storage struct.

**Detailed Description:** Uses inline assembly to assign the storage slot at a fixed keccak-256 position to a [`LCGStorage`](https://docs.cryptolegacy.app/documentation/data-structures-reference#lcgstorage-ilcg1-s1) reference.

**Parameters:** None

**Returns:**

* ls ([LCGStorage](https://docs.cryptolegacy.app/documentation/data-structures-reference#lcgstorage-ilcg1-s1), storage): Storage pointer to LockChainGate layout

**Modifiers / Visibility / Mutability:**

* internal pure

**Access Control:**

* Internal only

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:**

* [\_setCrossChainsRef(FRStorage,bool,bytes8,uint256\[\],uint256\[\])](#_setcrosschainsref-fr1) — FeeRegistry
* [crossCreateCustomCode(uint256,address,address,bytes8,uint32,uint32)](#crosscreatecustomcode-fr1) — FeeRegistry
* [crossUpdateCustomCode(uint256,address,address,bytes8,uint32,uint32)](#crossupdatecustomcode-fr1) — FeeRegistry
* [\_initializeLockChainGate(ILifetimeNft,uint64,uint64,address)](#_initializelockchaingate-lcg1) — LockChainGate
* [setLockOperator(address,bool)](#setlockoperator-lcg1) — LockChainGate
* [setDebridgeGate(address)](#setdebridgegate-lcg1) — LockChainGate
* [setDebridgeNativeFee(uint256,uint256)](#setdebridgenativefee-lcg1) — LockChainGate
* [\_setDestinationChainContract(uint256,address)](#_setdestinationchaincontract-lcg1) — LockChainGate
* [\_setSourceChainContract(uint256,address)](#_setsourcechaincontract-lcg1) — LockChainGate
* [setLockPeriod(uint64,uint64)](#setlockperiod-lcg1) — LockChainGate
* [setReferralCode(uint32)](#setreferralcode-lcg1) — LockChainGate
* [setCustomChainId(uint256)](#setcustomchainid-lcg1) — LockChainGate
* [\_writeLockLifetimeNft(address,uint256)](#_writelocklifetimenft-lcg1) — LockChainGate
* [lockLifetimeNft(uint256,address,uint256\[\],uint256\[\])](#locklifetimenft-lcg1) — LockChainGate
* [crossLockLifetimeNft(uint256,uint256,address)](#crosslocklifetimenft-lcg1) — LockChainGate
* [lockLifetimeNftToChains(uint256\[\],uint256\[\])](#locklifetimenfttochains-lcg1) — LockChainGate
* [unlockLifetimeNft(uint256)](#unlocklifetimenft-lcg1) — LockChainGate
* [unlockLifetimeNftFromChain(uint256)](#unlocklifetimenftfromchain-lcg1) — LockChainGate
* [crossUnlockLifetimeNft(uint256,uint256,address)](#crossunlocklifetimenft-lcg1) — LockChainGate
* [crossUpdateNftOwner(uint256,uint256,address)](#crossupdatenftowner-lcg1) — LockChainGate
* [\_deleteTokenData(address,uint256)](#_deletetokendata-lcg1) — LockChainGate
* [approveLifetimeNftTo(uint256,address)](#approvelifetimenftto-lcg1) — LockChainGate
* [transferLifetimeNftTo(uint256,address,uint256\[\],uint256\[\])](#transferlifetimenftto-lcg1) — LockChainGate
* [updateNftOwnerOnChainList(uint256,uint256\[\],uint256\[\])](#updatenftowneronchainlist-lcg1) — LockChainGate
* [\_checkTooEarly(address)](#_checktooearly-lcg1) — LockChainGate
* [getLockedToChainsIdsOfAccount(address)](#getlockedtochainsidsofaccount-lcg1) — LockChainGate
* [getLockedUntil(address)](#getlockeduntil-lcg1) — LockChainGate
* [getLockedToChainsIds(uint256)](#getlockedtochainsids-lcg1) — LockChainGate
* [lockPeriod()](#lockperiod-lcg1) — LockChainGate
* [transferTimeout()](#transfertimeout-lcg1) — LockChainGate
* [referralCode()](#referralcode-lcg1) — LockChainGate
* [ownerOfTokenId(uint256)](#owneroftokenid-lcg1) — LockChainGate
* [lockedNftFromChainId(uint256)](#lockednftfromchainid-lcg1) — LockChainGate
* [lockedNftApprovedTo(uint256)](#lockednftapprovedto-lcg1) — LockChainGate
* [lockedNft(address)](#lockednft-lcg1) — LockChainGate
* [getDeBridgeChainNativeFeeAndCheck(uint256,uint256)](#getdebridgechainnativefeeandcheck-lcg1) — LockChainGate
* [getDeBridgeChainNativeFee(uint256,uint256)](#getdebridgechainnativefee-lcg1) — LockChainGate
* [deBridgeGate()](#debridgegate-lcg1) — LockChainGate
* [lifetimeNft()](#lifetimenft-lcg1) — LockChainGate
* [deBridgeChainConfig(uint256)](#debridgechainconfig-lcg1) — LockChainGate
* [getLockOperatorsList()](#getlockoperatorslist-lcg1) — LockChainGate
* [isLockOperator(address)](#islockoperator-lcg1) — LockChainGate
* [calculateCrossChainCreateRefNativeFee(uint256\[\],uint256\[\])](#calculatecrosschaincreaterefnativefee-lcg1) — LockChainGate
* [isNftLocked(address)](#isnftlocked-lcg1) — LockChainGate
* [isNftLockedAndUpdate(address)](#isnftlockedandupdate-lcg1) — LockChainGate
* [getChainId()](#getchainid-lcg1) — LockChainGate

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### \_initializeLockChainGate (LCG1)

**Contract/Library:** LockChainGate

**Description:** Internal initializer to set Lifetime NFT address, lock config, owner, and reentrancy guard.

**Detailed Description:** Fetches storage, sets [`lifetimeNft`](https://docs.cryptolegacy.app/documentation/data-structures-reference#lifetimenft-clbm1-d4), `lockPeriod`, and `transferTimeout`, emits config event, transfers ownership to `_owner`, and initializes `ReentrancyGuardUpgradeable`.

**Parameters:**

* \_lifetimeNft (ILifetimeNft): Lifetime NFT contract
* \_lockPeriod (uint64): Lock period in seconds
* \_transferTimeout (uint64): Timeout between lock and transfer in seconds
* \_owner (address): New owner

**Returns:** None

**Modifiers / Visibility / Mutability:**

* internal nonpayable initializer

**Access Control:**

* Internal only

**Side Effects:**

* Updates [`lifetimeNft`](https://docs.cryptolegacy.app/documentation/data-structures-reference#lifetimenft-clbm1-d4), `lockPeriod`, `transferTimeout`
* Transfers ownership via `_transferOwnership(_owner)`
* Initializes reentrancy guard counters via `__ReentrancyGuard_init()`

**Emits:**

* [SetLockPeriodConfig](https://docs.cryptolegacy.app/documentation/events-reference#setlockperiodconfig-ilcg1) — `SetLockPeriodConfig(uint256 lockPeriod, uint256 transferTimeout)`

**Reverts if:**

* Called more than once — "Initializable: contract is already initialized"

**Overrides:** None

**Function Calls:**

* [lockChainGateStorage()](#lockchaingatestorage-lcg1) — LockChainGate, internal
* [\_transferOwnership(address)](#_transferownership-clo1) — Ownable, internal
* `__ReentrancyGuard_init()` — ReentrancyGuardUpgradeable, internal

**Called by:**

* [initialize(address,uint32,uint32,ILifetimeNft,uint64,uint64)](#initialize-fr1) — FeeRegistry

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### setLockOperator (LCG1)

**Contract/Library:** LockChainGate

**Description:** Adds or removes an address from the lock operators set.

**Detailed Description:** Loads storage; if `_isAdd` is true, adds `_operator` to `lockOperators`, else removes it. Emits the corresponding event.

**Parameters:**

* \_operator (address): Address to add or remove
* \_isAdd (bool): True to add; false to remove

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external nonpayable onlyOwner

**Access Control:**

* onlyOwner

**Side Effects:**

* Updates `lockOperators` set

**Emits:**

* [AddLockOperator](https://docs.cryptolegacy.app/documentation/events-reference#addlockoperator-ilcg1) — `AddLockOperator(address indexed lockOperator)`
* [RemoveLockOperator](https://docs.cryptolegacy.app/documentation/events-reference#removelockoperator-ilcg1) — `RemoveLockOperator(address indexed lockOperator)`

**Reverts if:**

* caller is not owner — "Ownable: caller is not the owner"

**Overrides:** None

**Function Calls:**

* [lockChainGateStorage()](#lockchaingatestorage-lcg1) — LockChainGate, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Owner calls to authorize a service account as lock operator.

***

### setDebridgeGate (LCG1)

**Contract/Library:** LockChainGate

**Description:** Sets the deBridgeGate contract used for cross-chain messages.

**Detailed Description:** Stores `_deBridgeGate` into `deBridgeGate` in storage and emits an event.

**Parameters:**

* \_deBridgeGate (address): deBridgeGate contract address

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external nonpayable onlyOwner

**Access Control:**

* onlyOwner

**Side Effects:**

* Updates `deBridgeGate`

**Emits:**

* [SetDeBridgeGate](https://docs.cryptolegacy.app/documentation/events-reference#setdebridgegate-ilcg1) — `SetDeBridgeGate(address indexed deBridgeGate)`

**Reverts if:**

* caller is not owner — "Ownable: caller is not the owner"

**Overrides:** None

**Function Calls:**

* [lockChainGateStorage()](#lockchaingatestorage-lcg1) — LockChainGate, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Owner configures deBridgeGate after deployment.

***

### setDebridgeNativeFee (LCG1)

**Contract/Library:** LockChainGate

**Description:** Sets the per-chain native fee used when sending cross-chain messages.

**Detailed Description:** Writes `_nativeFee` to `deBridgeNativeFee_chainId` in storage; emits an event.

**Parameters:**

* \_chainId (uint256): Destination chain ID
* \_nativeFee (uint256): Fee amount in wei

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external nonpayable onlyOwner

**Access Control:**

* onlyOwner

**Side Effects:**

* Updates `deBridgeNativeFee_chainId`

**Emits:**

* [SetDeBridgeNativeFee](https://docs.cryptolegacy.app/documentation/events-reference#setdebridgenativefee-ilcg1) — `SetDeBridgeNativeFee(uint256 indexed chainId, uint256 nativeFee)`

**Reverts if:**

* caller is not owner — "Ownable: caller is not the owner"

**Overrides:** None

**Function Calls:**

* [lockChainGateStorage()](#lockchaingatestorage-lcg1) — LockChainGate, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Owner adjusts fixed fee per remote chain.

***

### \_setDestinationChainContract (LCG1)

**Contract/Library:** LockChainGate

**Description:** Internal setter for the destination chain contract mapping.

**Detailed Description:** Updates `destinationChainContracts_chainId` and emits an event.

**Parameters:**

* \_chainId (uint256): Destination chain ID
* \_chainContract (address): Contract address on destination chain

**Returns:** None

**Modifiers / Visibility / Mutability:**

* internal nonpayable

**Access Control:**

* Internal only

**Side Effects:**

* Updates `destinationChainContracts_chainId`

**Emits:**

* [SetDestinationChainContract](https://docs.cryptolegacy.app/documentation/events-reference#setdestinationchaincontract-ilcg1) — `SetDestinationChainContract(uint256 indexed chainId, address indexed chainContract)`

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [lockChainGateStorage()](#lockchaingatestorage-lcg1) — LockChainGate, internal

**Called by:**

* [setDestinationChainContract(uint256,address)](#setdestinationchaincontract-lcg1) — LockChainGate
* [setSourceAndDestinationChainContract(uint256,address)](#setsourceanddestinationchaincontract-lcg1) — LockChainGate

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### setDestinationChainContract (LCG1)

**Contract/Library:** LockChainGate

**Description:** Public setter for the destination chain contract mapping.

**Detailed Description:** Calls internal `_setDestinationChainContract`.

**Parameters:**

* \_chainId (uint256): Destination chain ID
* \_chainContract (address): Contract address on destination chain

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external nonpayable onlyOwner

**Access Control:**

* onlyOwner

**Side Effects:**

* Updates `destinationChainContracts_chainId` via internal call

**Emits:**

* [SetDestinationChainContract](https://docs.cryptolegacy.app/documentation/events-reference#setdestinationchaincontract-ilcg1) — `SetDestinationChainContract(uint256 indexed chainId, address indexed chainContract)`

**Reverts if:**

* caller is not owner — "Ownable: caller is not the owner"

**Overrides:** None

**Function Calls:**

* [\_setDestinationChainContract(uint256,address)](#_setdestinationchaincontract-lcg1) — LockChainGate, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Owner configures remote recipient contract for a new chain.

***

### \_setSourceChainContract (LCG1)

**Contract/Library:** LockChainGate

**Description:** Internal setter for source chain contract mapping.

**Detailed Description:** Updates `sourceChainsContracts_chainId` and emits an event.

**Parameters:**

* \_chainId (uint256): Source chain ID
* \_chainContract (address): Contract address on source chain

**Returns:** None

**Modifiers / Visibility / Mutability:**

* internal nonpayable

**Access Control:**

* Internal only

**Side Effects:**

* Updates `sourceChainsContracts_chainId`

**Emits:**

* [SetSourceChainContract](https://docs.cryptolegacy.app/documentation/events-reference#setsourcechaincontract-ilcg1) — `SetSourceChainContract(uint256 indexed chainId, address indexed chainContract)`

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [lockChainGateStorage()](#lockchaingatestorage-lcg1) — LockChainGate, internal

**Called by:**

* [setSourceChainContract(uint256,address)](#setsourcechaincontract-lcg1) — LockChainGate
* [setSourceAndDestinationChainContract(uint256,address)](#setsourceanddestinationchaincontract-lcg1) — LockChainGate

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### setSourceChainContract (LCG1)

**Contract/Library:** LockChainGate

**Description:** Public setter for the source chain contract mapping.

**Detailed Description:** Calls internal `_setSourceChainContract`.

**Parameters:**

* \_chainId (uint256): Source chain ID
* \_chainContract (address): Contract address on source chain

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external nonpayable onlyOwner

**Access Control:**

* onlyOwner

**Side Effects:**

* Updates `sourceChainsContracts_chainId` via internal call

**Emits:**

* [SetSourceChainContract](https://docs.cryptolegacy.app/documentation/events-reference#setsourcechaincontract-ilcg1) — `SetSourceChainContract(uint256 indexed chainId, address indexed chainContract)`

**Reverts if:**

* caller is not owner — "Ownable: caller is not the owner"

**Overrides:** None

**Function Calls:**

* [\_setSourceChainContract(uint256,address)](#_setsourcechaincontract-lcg1) — LockChainGate, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Owner configures the authenticated sender for a source chain.

***

### setSourceAndDestinationChainContract (LCG1)

**Contract/Library:** LockChainGate

**Description:** Sets both source and destination contract addresses for a chain.

**Detailed Description:** Calls `_setSourceChainContract` then `_setDestinationChainContract` with the same `_chainContract`.

**Parameters:**

* \_chainId (uint256): Chain ID
* \_chainContract (address): Contract address for both roles

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external nonpayable onlyOwner

**Access Control:**

* onlyOwner

**Side Effects:**

* Updates `sourceChainsContracts_chainId`
* Updates `destinationChainContracts_chainId`

**Emits:**

* [SetSourceChainContract](https://docs.cryptolegacy.app/documentation/events-reference#setsourcechaincontract-ilcg1) — `SetSourceChainContract(uint256 indexed chainId, address indexed chainContract)`
* [SetDestinationChainContract](https://docs.cryptolegacy.app/documentation/events-reference#setdestinationchaincontract-ilcg1) — `SetDestinationChainContract(uint256 indexed chainId, address indexed chainContract)`

**Reverts if:**

* caller is not owner — "Ownable: caller is not the owner"

**Overrides:** None

**Function Calls:**

* [\_setSourceChainContract(uint256,address)](#_setsourcechaincontract-lcg1) — LockChainGate, internal
* [\_setDestinationChainContract(uint256,address)](#_setdestinationchaincontract-lcg1) — LockChainGate, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Owner mirrors the same address for both source and destination on a test net.

***

### setLockPeriod (LCG1)

**Contract/Library:** LockChainGate

**Description:** Updates the NFT lock period and transfer timeout.

**Detailed Description:** Stores new `_lockPeriod` and `_transferTimeout` in storage and emits the configuration event.

**Parameters:**

* \_lockPeriod (uint64): New lock period in seconds
* \_transferTimeout (uint64): New transfer timeout in seconds

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external nonpayable onlyOwner

**Access Control:**

* onlyOwner

**Side Effects:**

* Updates `lockPeriod`, `transferTimeout`

**Emits:**

* [SetLockPeriodConfig](https://docs.cryptolegacy.app/documentation/events-reference#setlockperiodconfig-ilcg1) — `SetLockPeriodConfig(uint256 lockPeriod, uint256 transferTimeout)`

**Reverts if:**

* caller is not owner — "Ownable: caller is not the owner"

**Overrides:** None

**Function Calls:**

* [lockChainGateStorage()](#lockchaingatestorage-lcg1) — LockChainGate, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Owner extends lock duration as a policy change.

***

### setReferralCode (LCG1)

**Contract/Library:** LockChainGate

**Description:** Sets deBridge referral code used in messages.

**Detailed Description:** Stores `_referralCode` in storage and emits event.

**Parameters:**

* \_referralCode (uint32): New referral code

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external nonpayable onlyOwner

**Access Control:**

* onlyOwner

**Side Effects:**

* Updates `referralCode`

**Emits:**

* [SetReferralCode](https://docs.cryptolegacy.app/documentation/events-reference#setreferralcode-ilcg1) — `SetReferralCode(uint32 indexed referralCode)`

**Reverts if:**

* caller is not owner — "Ownable: caller is not the owner"

**Overrides:** None

**Function Calls:**

* [lockChainGateStorage()](#lockchaingatestorage-lcg1) — LockChainGate, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Owner configures partner referral code for deBridge.

***

### setCustomChainId (LCG1)

**Contract/Library:** LockChainGate

**Description:** Overrides the auto-detected chainId with a custom value.

**Detailed Description:** Sets `customChainId` to `_customChainId` (non-zero to override) and emits event.

**Parameters:**

* \_customChainId (uint256): Custom chain id

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external nonpayable onlyOwner

**Access Control:**

* onlyOwner

**Side Effects:**

* Updates `customChainId`

**Emits:**

* [SetCustomChainId](https://docs.cryptolegacy.app/documentation/events-reference#setcustomchainid-ilcg1) — `SetCustomChainId(uint256 indexed customChainId)`

**Reverts if:**

* caller is not owner — "Ownable: caller is not the owner"

**Overrides:** None

**Function Calls:**

* [lockChainGateStorage()](#lockchaingatestorage-lcg1) — LockChainGate, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Owner sets chainId override in L2 environments.

***

### \_writeLockLifetimeNft (LCG1)

**Contract/Library:** LockChainGate

**Description:** Records a newly locked NFT for a holder.

**Detailed Description:** Ensures the holder has no prior lock; sets `lockedNft_holder` with `lockedAt = block.timestamp` and `tokenId`, and maps `ownerOfTokenIdtokenId = _holder`.

**Parameters:**

* \_holder (address): Holder of the locked NFT
* \_tokenId (uint256): Token id being locked

**Returns:** None

**Modifiers / Visibility / Mutability:**

* internal nonpayable

**Access Control:**

* Internal only

**Side Effects:**

* Updates `lockedNft_holder`
* Updates `ownerOfTokenId_tokenId`

**Emits:** None

**Reverts if:**

* holder already has a locked token — [`AlreadyLocked()`](https://docs.cryptolegacy.app/documentation/errors-reference#alreadylocked-ilcg1)

**Overrides:** None

**Function Calls:**

* [lockChainGateStorage()](#lockchaingatestorage-lcg1) — LockChainGate, internal

**Called by:**

* [lockLifetimeNft(uint256,address,uint256\[\],uint256\[\])](#locklifetimenft-lcg1) — LockChainGate
* [crossLockLifetimeNft(uint256,uint256,address)](#crosslocklifetimenft-lcg1) — LockChainGate

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### lockLifetimeNft (LCG1)

**Contract/Library:** LockChainGate

**Description:** Locks a Lifetime NFT and optionally mirrors the lock on specified chains.

**Detailed Description:** Transfers NFT from caller to this contract, records the lock for `_holder`, locks to extra chains via deBridge if provided, returns any surplus ETH to caller, then emits lock event.

**Parameters:**

* \_tokenId (uint256): NFT token id to lock
* \_holder (address): Address to receive lifetime access
* \_lockToChainIds (uint256\[], memory): Chains to mirror lock on
* \_crossChainFees (uint256\[], memory): Per-chain native fees

**Returns:**

* returnValue (uint256): Surplus ETH returned to caller

**Modifiers / Visibility / Mutability:**

* external payable nonReentrant

**Access Control:**

* Unrestricted

**Side Effects:**

* Transfers ERC721 from `msg.sender` to this contract
* Updates `lockedNft`, `ownerOfTokenId`, possibly `lockedToChainsIds`
* Returns ETH to `msg.sender`

**Emits:**

* [LockNft](https://docs.cryptolegacy.app/documentation/events-reference#locknft-ilcg1) — `LockNft(uint256 lockedAt, uint256 indexed tokenId, address indexed holder)`
* [LockToChain](https://docs.cryptolegacy.app/documentation/events-reference#locktochain-ilcg1) — `LockToChain(address indexed sender, uint256 indexed tokenId, uint256 indexed toChainID, bytes32 submissionId)` (via internal calls)
* [SendToChain](https://docs.cryptolegacy.app/documentation/events-reference#sendtochain-ilcg1) — `SendToChain(uint256 indexed toChainId, bytes32 indexed submissionId, uint256 value, bytes dstTransactionCall)` (via internal calls)

**Reverts if:**

* ERC721 transfer — may revert with `"ERC721: transfer from incorrect owner"` or per token implementation
* holder already has a lock — [`AlreadyLocked()`](https://docs.cryptolegacy.app/documentation/errors-reference#alreadylocked-ilcg1)
* `_lockToChainIds.length != _crossChainFees.length` — [`ArrayLengthMismatch()`](https://docs.cryptolegacy.app/documentation/errors-reference#arraylengthmismatch-ilcg1)
* token already cross-chain locked — [`CrossChainLock()`](https://docs.cryptolegacy.app/documentation/errors-reference#crosschainlock-ilcg1)
* destination chain not configured — [`DestinationChainNotSpecified()`](https://docs.cryptolegacy.app/documentation/errors-reference#destinationchainnotspecified-ilcg1)
* token already locked to chain — [`AlreadyLockedToChain()`](https://docs.cryptolegacy.app/documentation/errors-reference#alreadylockedtochain-ilcg1)
* `msg.value` too small or too large vs total fee — [`IncorrectFee(uint256)`](https://docs.cryptolegacy.app/documentation/errors-reference#incorrectfee-ilcg1)
* refund transfer fails — [`TransferFeeFailed(bytes)`](https://docs.cryptolegacy.app/documentation/errors-reference#transferfeefailed-ilcg1)

**Overrides:** None

**Function Calls:**

* [lockChainGateStorage()](#lockchaingatestorage-lcg1) — LockChainGate, internal
* `transferFrom(address,address,uint256)` — IERC721 *(at `address(ls.lifetimeNft)`)*, external
* [\_writeLockLifetimeNft(address,uint256)](#_writelocklifetimenft-lcg1) — LockChainGate, internal
* [\_lockLifetimeNftToChains(LCGStorage,address,uint256\[\],uint256\[\])](#_locklifetimenfttochains-lcg1) — LockChainGate, internal
* [\_calcAndReturnFee(uint256)](#_calcandreturnfee-lcg1) — LockChainGate, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(n) by `_lockToChainIds.length` (plus ERC721 transfer cost).

**Example:** User locks token `#123` for themselves and mirrors on chains `137,10` by supplying corresponding fees.

***

### \_calcAndReturnFee (LCG1)

**Contract/Library:** LockChainGate

**Description:** Computes surplus ETH after fees and returns it to caller.

**Detailed Description:** Calculates `returnValue = msg.value - _totalFee`, then calls [\_returnFee](#_returnfee-lcg1).

**Parameters:**

* \_totalFee (uint256): Total fee amount to deduct

**Returns:**

* returnValue (uint256): Refunded surplus

**Modifiers / Visibility / Mutability:**

* internal nonpayable

**Access Control:**

* Internal only

**Side Effects:**

* May transfer ETH to `msg.sender`

**Emits:** None

**Reverts if:**

* refund transfer fails — [`TransferFeeFailed(bytes)`](https://docs.cryptolegacy.app/documentation/errors-reference#transferfeefailed-ilcg1)

**Overrides:** None

**Function Calls:**

* [\_returnFee(uint256)](#_returnfee-lcg1) — LockChainGate, internal

**Called by:**

* [createCustomCode(address,address,bytes8,uint256\[\],uint256\[\])](#createcustomcode-fr1) — FeeRegistry
* [createCode(address,address,uint256\[\],uint256\[\])](#createcode-fr1) — FeeRegistry
* [updateCrossChainsRef(uint256\[\],uint256\[\])](#updatecrosschainsref-fr1) — FeeRegistry
* [changeCodeReferrer(bytes8,address,address,uint256\[\],uint256\[\])](#changecodereferrer-fr1) — FeeRegistry
* [changeRecipientReferrer(bytes8,address,uint256\[\],uint256\[\])](#changerecipientreferrer-fr1) — FeeRegistry
* [lockLifetimeNft(uint256,address,uint256\[\],uint256\[\])](#locklifetimenft-lcg1) — LockChainGate
* [lockLifetimeNftToChains(uint256\[\],uint256\[\])](#locklifetimenfttochains-lcg1) — LockChainGate

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### \_returnFee (LCG1)

**Contract/Library:** LockChainGate

**Description:** Sends ETH back to `msg.sender` if `_returnValue > 0`.

**Detailed Description:** Performs a low-level `call` with value. Reverts on failure with `TransferFeeFailed`.

**Parameters:**

* \_returnValue (uint256): Amount to return

**Returns:** None

**Modifiers / Visibility / Mutability:**

* internal nonpayable

**Access Control:**

* Internal only

**Side Effects:**

* Transfers ETH to `msg.sender`

**Emits:** None

**Reverts if:**

* low-level send fails — [`TransferFeeFailed(bytes)`](https://docs.cryptolegacy.app/documentation/errors-reference#transferfeefailed-ilcg1)

**Overrides:** None

**Function Calls:** None

**Called by:**

* [\_calcAndReturnFee(uint256)](#_calcandreturnfee-lcg1) — LockChainGate

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### crossLockLifetimeNft (LCG1)

**Contract/Library:** LockChainGate

**Description:** Handles cross-chain lock message to record a lock from a source chain.

**Detailed Description:** Validates caller and source via `_onlyCrossChain`, writes lock for `_holder`, tags token with `lockedNftFromChainId`, and emits cross-lock event.

**Parameters:**

* \_fromChainID (uint256): Source chain id
* \_tokenId (uint256): Token id
* \_holder (address): Holder address

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external nonpayable nonReentrant

**Access Control:**

* Must be invoked via deBridge CallProxy from configured source chain

**Side Effects:**

* Updates `lockedNft`, `ownerOfTokenId`, `lockedNftFromChainId_tokenId`

**Emits:**

* [CrossLockNft](https://docs.cryptolegacy.app/documentation/events-reference#crosslocknft-ilcg1) — `CrossLockNft(uint256 lockedAt, uint256 indexed tokenId, address indexed holder, uint256 indexed fromChainID)`

**Reverts if:**

* invalid caller or source — [`NotCallProxy()`](https://docs.cryptolegacy.app/documentation/errors-reference#notcallproxy-ilcg1) / [`ChainIdMismatch()`](https://docs.cryptolegacy.app/documentation/errors-reference#chainidmismatch-ilcg1) / [`NotValidSender()`](https://docs.cryptolegacy.app/documentation/errors-reference#notvalidsender-ilcg1)
* source chain not configured — [`SourceNotSpecified()`](https://docs.cryptolegacy.app/documentation/errors-reference#sourcenotspecified-ilcg1)
* holder already has a lock — [`AlreadyLocked()`](https://docs.cryptolegacy.app/documentation/errors-reference#alreadylocked-ilcg1)

**Overrides:** None

**Function Calls:**

* [lockChainGateStorage()](#lockchaingatestorage-lcg1) — LockChainGate, internal
* [\_checkSource(LCGStorage,uint256)](#_checksource-lcg1) — LockChainGate, internal
* [\_onlyCrossChain(LCGStorage,uint256)](#_onlycrosschain-lcg1) — LockChainGate, internal
* [\_writeLockLifetimeNft(address,uint256)](#_writelocklifetimenft-lcg1) — LockChainGate, internal

**Called by:**

None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### \_lockLifetimeNftToChains (LCG1)

**Contract/Library:** LockChainGate

**Description:** Locks a token to multiple chains by sending cross-chain messages.

**Detailed Description:** Validates arrays length; checks token status; for each chain, computes fee and calls [\_lockLifetimeNftToChain](#_locklifetimenfttochain-lcg1); sums fees and validates total via [\_checkFee](#_checkfee-lcg1).

**Parameters:**

* ls ([LCGStorage](https://docs.cryptolegacy.app/documentation/data-structures-reference#lcgstorage-ilcg1-s1), storage): Storage pointer
* \_holder (address): Holder address
* \_toChainIDs (uint256\[], memory): Destination chains
* \_crossChainFees (uint256\[], memory): Per-chain fees

**Returns:**

* totalFee (uint256): Total required fee

**Modifiers / Visibility / Mutability:**

* internal nonpayable

**Access Control:**

* Internal only

**Side Effects:**

* May update `lockedToChainsIdstokenId` via internal calls

**Emits:**

* [LockToChain](https://docs.cryptolegacy.app/documentation/events-reference#locktochain-ilcg1) — `LockToChain(address indexed sender, uint256 indexed tokenId, uint256 indexed toChainID, bytes32 submissionId)` (per chain)
* [SendToChain](https://docs.cryptolegacy.app/documentation/events-reference#sendtochain-ilcg1) — `SendToChain(uint256 indexed toChainId, bytes32 indexed submissionId, uint256 value, bytes dstTransactionCall)` (per chain)

**Reverts if:**

* `_toChainIDs.length != _crossChainFees.length` — [`ArrayLengthMismatch()`](https://docs.cryptolegacy.app/documentation/errors-reference#arraylengthmismatch-ilcg1)
* token not locked — [`TokenNotLocked()`](https://docs.cryptolegacy.app/documentation/errors-reference#tokennotlocked-ilcg1)
* cross-chain lock active — [`CrossChainLock()`](https://docs.cryptolegacy.app/documentation/errors-reference#crosschainlock-ilcg1)
* destination chain not configured — [`DestinationChainNotSpecified()`](https://docs.cryptolegacy.app/documentation/errors-reference#destinationchainnotspecified-ilcg1)
* already locked to destination chain — [`AlreadyLockedToChain()`](https://docs.cryptolegacy.app/documentation/errors-reference#alreadylockedtochain-ilcg1)
* fee check fails — [`IncorrectFee(uint256)`](https://docs.cryptolegacy.app/documentation/errors-reference#incorrectfee-ilcg1)

**Overrides:** None

**Function Calls:**

* [\_checkTokenLocked(LCGStorage,address)](#_checktokenlocked-lcg1) — LockChainGate, internal
* [\_checkCrossChainLock(LCGStorage,uint256)](#_checkcrosschainlock-lcg1) — LockChainGate, internal
* [\_getDeBridgeChainNativeFee(LCGStorage,uint256,uint256)](#_getdebridgechainnativefee-lcg1) — LockChainGate, internal
* [\_lockLifetimeNftToChain(LCGStorage,uint256,address,uint256,uint256)](#_locklifetimenfttochain-lcg1) — LockChainGate, internal
* [\_checkFee(uint256)](#_checkfee-lcg1) — LockChainGate, internal

**Called by:**

* [lockLifetimeNft(uint256,address,uint256\[\],uint256\[\])](#locklifetimenft-lcg1) — LockChainGate
* [lockLifetimeNftToChains(uint256\[\],uint256\[\])](#locklifetimenfttochains-lcg1) — LockChainGate

**Gas / Complexity note:** O(n) by `_toChainIDs.length`

**Example:** Not applicable

***

### \_checkFee (LCG1)

**Contract/Library:** LockChainGate

**Description:** Validates that `msg.value` matches the required fee within tolerance.

**Detailed Description:** Reverts if `msg.value < _fee` or if `msg.value - _fee > 0.00001 ether`.

**Parameters:**

* \_fee (uint256): Required fee

**Returns:** None

**Modifiers / Visibility / Mutability:**

* internal nonpayable

**Access Control:**

* Internal only

**Side Effects:** None

**Emits:** None

**Reverts if:**

* `msg.value < _fee` or too much surplus — [`IncorrectFee(uint256)`](https://docs.cryptolegacy.app/documentation/errors-reference#incorrectfee-ilcg1)

**Overrides:** None

**Function Calls:** None

**Called by:**

* [\_lockLifetimeNftToChains(LCGStorage,address,uint256\[\],uint256\[\])](#_locklifetimenfttochains-lcg1) — LockChainGate
* [\_getDeBridgeChainNativeFeeAndCheck(LCGStorage,uint256,uint256)](#_getdebridgechainnativefeeandcheck-lcg1) — LockChainGate
* [\_updateNftOwnerOnChainList(LCGStorage,uint256,uint256\[\],uint256\[\],address)](#_updatenftowneronchainlist-lcg1) — LockChainGate
* [takeFee(address,uint8,bytes8,uint256)](#takefee-fr1) — FeeRegistry
* [\_setCrossChainsRef(FRStorage,bool,bytes8,uint256\[\],uint256\[\])](#_setcrosschainsref-fr1) — FeeRegistry

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### lockLifetimeNftToChains (LCG1)

**Contract/Library:** LockChainGate

**Description:** Mirrors the caller’s existing lock to additional chains.

**Detailed Description:** Calls internal `_lockLifetimeNftToChains` using `msg.sender` as holder, then refunds any surplus via [\_calcAndReturnFee](#_calcandreturnfee-lcg1).

**Parameters:**

* \_toChainIDs (uint256\[], memory): Destination chains
* \_crossChainFees (uint256\[], memory): Per-chain fees

**Returns:**

* returnValue (uint256): Surplus refund

**Modifiers / Visibility / Mutability:**

* external payable nonReentrant

**Access Control:**

* Unrestricted

**Side Effects:**

* May update `lockedToChainsIdstokenId`
* May refund ETH

**Emits:**

* [LockToChain](https://docs.cryptolegacy.app/documentation/events-reference#locktochain-ilcg1) — `LockToChain(address indexed sender, uint256 indexed tokenId, uint256 indexed toChainID, bytes32 submissionId)`
* [SendToChain](https://docs.cryptolegacy.app/documentation/events-reference#sendtochain-ilcg1) — `SendToChain(uint256 indexed toChainId, bytes32 indexed submissionId, uint256 value, bytes dstTransactionCall)`

**Reverts if:**

* arrays length mismatch — [`ArrayLengthMismatch()`](https://docs.cryptolegacy.app/documentation/errors-reference#arraylengthmismatch-ilcg1)
* token not locked — [`TokenNotLocked()`](https://docs.cryptolegacy.app/documentation/errors-reference#tokennotlocked-ilcg1)
* cross-chain lock active — [`CrossChainLock()`](https://docs.cryptolegacy.app/documentation/errors-reference#crosschainlock-ilcg1)
* destination chain not configured — [`DestinationChainNotSpecified()`](https://docs.cryptolegacy.app/documentation/errors-reference#destinationchainnotspecified-ilcg1)
* already locked to destination chain — [`AlreadyLockedToChain()`](https://docs.cryptolegacy.app/documentation/errors-reference#alreadylockedtochain-ilcg1)
* fee mismatch — [`IncorrectFee(uint256)`](https://docs.cryptolegacy.app/documentation/errors-reference#incorrectfee-ilcg1)
* refund transfer fails — [`TransferFeeFailed(bytes)`](https://docs.cryptolegacy.app/documentation/errors-reference#transferfeefailed-ilcg1)

**Overrides:** None

**Function Calls:**

* [\_lockLifetimeNftToChains(LCGStorage,address,uint256\[\],uint256\[\])](#_locklifetimenfttochains-lcg1) — LockChainGate, internal
* [\_calcAndReturnFee(uint256)](#_calcandreturnfee-lcg1) — LockChainGate, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(n) by `_toChainIDs.length`

**Example:** Holder adds chain 42161 to their mirrored lock set.

***

### \_lockLifetimeNftToChain (LCG1)

**Contract/Library:** LockChainGate

**Description:** Sends a cross-chain lock message to a single chain and records mirroring.

**Detailed Description:** Validates destination contract is set; ensures not already mirrored; encodes cross-lock command; sends via deBridge; then records the chain id in `lockedToChainsIds_tokenId` and emits event.

**Parameters:**

* ls ([LCGStorage](https://docs.cryptolegacy.app/documentation/data-structures-reference#lcgstorage-ilcg1-s1), storage): Storage pointer
* \_toChainID (uint256): Destination chain id
* \_holder (address): Holder address
* \_tokenId (uint256): Token id
* \_sendFee (uint256): Fee to send

**Returns:** None

**Modifiers / Visibility / Mutability:**

* internal nonpayable

**Access Control:**

* Internal only

**Side Effects:**

* Updates `lockedToChainsIds_tokenId`
* Sends ETH to `deBridgeGate`

**Emits:**

* [LockToChain](https://docs.cryptolegacy.app/documentation/events-reference#locktochain-ilcg1) — `LockToChain(address holder, uint256 tokenId, uint256 toChainId, bytes32 submissionId)`
* [SendToChain](https://docs.cryptolegacy.app/documentation/events-reference#sendtochain-ilcg1) — `SendToChain(uint256 toChainId, bytes32 submissionId, uint256 value, bytes dstTransactionCall)`

**Reverts if:**

* destination not set — [`DestinationChainNotSpecified()`](https://docs.cryptolegacy.app/documentation/errors-reference#destinationchainnotspecified-ilcg1)
* already mirrored — [`AlreadyLockedToChain()`](https://docs.cryptolegacy.app/documentation/errors-reference#alreadylockedtochain-ilcg1)

**Overrides:** None

**Function Calls:**

* [\_checkDestinationLockedChain(LCGStorage,uint256)](#_checkdestinationlockedchain-lcg1) — LockChainGate, internal
* [\_encodeCrossLockCommand(LCGStorage,uint256,address)](#_encodecrosslockcommand-lcg1) — LockChainGate, internal
* [\_send(LCGStorage,bytes,uint256,uint256)](#_send-lcg1) — LockChainGate, internal

**Called by:**

* [\_lockLifetimeNftToChains(LCGStorage,address,uint256\[\],uint256\[\])](#_locklifetimenfttochains-lcg1) — LockChainGate

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### unlockLifetimeNft (LCG1)

**Contract/Library:** LockChainGate

**Description:** Unlocks a locally locked NFT back to the caller if conditions are satisfied.

**Detailed Description:** Verifies caller is holder or approved; ensures no mirrored chains; checks time lock via `_checkTooEarly`; ensures not cross-chain locked; transfers NFT back; clears storage; emits unlock event.

**Parameters:**

* \_tokenId (uint256): Token id to unlock

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external nonpayable nonReentrant

**Access Control:**

* Holder or approved address

**Side Effects:**

* Transfers ERC721 to caller
* Deletes `lockedNft`, `lockedNftFromChainId`, `lockedNftApprovedTo`, `ownerOfTokenId` entries

**Emits:**

* [UnlockNft](https://docs.cryptolegacy.app/documentation/events-reference#unlocknft-ilcg1) — `UnlockNft(uint256 lockedAt, uint256 indexed tokenId, address indexed holder, address indexed recipient)`

**Reverts if:**

* caller neither holder nor approved — [`NotAvailable()`](https://docs.cryptolegacy.app/documentation/errors-reference#notavailable-ilcg1)
* mirrored chain list not empty — [`LockedToChains()`](https://docs.cryptolegacy.app/documentation/errors-reference#lockedtochains-ilcg1)
* too early relative to lock period — [`TooEarly()`](https://docs.cryptolegacy.app/documentation/errors-reference#tooearly-ilcg1)
* cross-chain lock active — [`CrossChainLock()`](https://docs.cryptolegacy.app/documentation/errors-reference#crosschainlock-ilcg1)
* ERC721 transfer — may revert with `"ERC721: transfer from incorrect owner"` or per token implementation

**Overrides:** None

**Function Calls:**

* [\_checkTooEarly(address)](#_checktooearly-lcg1) — LockChainGate, internal
* [\_checkCrossChainLock(LCGStorage,uint256)](#_checkcrosschainlock-lcg1) — LockChainGate, internal
* `transferFrom(address,address,uint256)` — IERC721 *(at `address(ls.lifetimeNft)`)*, external
* [\_deleteTokenData(address,uint256)](#_deletetokendata-lcg1) — LockChainGate, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1) (plus ERC721 transfer cost)

**Example:** Holder unlocks their NFT after the lock period expires.

***

### unlockLifetimeNftFromChain (LCG1)

**Contract/Library:** LockChainGate

**Description:** Initiates cross-chain unlock to the source chain and clears local lock.

**Detailed Description:** Reads `fromChainID` from storage; checks it’s set; validates destination config; checks time and holder; encodes cross-unlock command; sends it with fee check; deletes token data; emits event.

**Parameters:**

* \_tokenId (uint256): Token id to unlock from source chain

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external payable nonReentrant

**Access Control:**

* Caller must be the current holder recorded in storage

**Side Effects:**

* Sends cross-chain message
* Deletes local lock data

**Emits:**

* [UnlockFromChain](https://docs.cryptolegacy.app/documentation/events-reference#unlockfromchain-ilcg1) — `UnlockFromChain(address indexed sender, uint256 indexed tokenId, uint256 indexed toChainID, bytes32 submissionId)`
* [SendToChain](https://docs.cryptolegacy.app/documentation/events-reference#sendtochain-ilcg1) — `SendToChain(uint256 indexed toChainId, bytes32 indexed submissionId, uint256 value, bytes dstTransactionCall)`

**Reverts if:**

* not locked by chain — [`NotLockedByChain()`](https://docs.cryptolegacy.app/documentation/errors-reference#notlockedbychain-ilcg1)
* destination chain contract not set — [`DestinationChainNotSpecified()`](https://docs.cryptolegacy.app/documentation/errors-reference#destinationchainnotspecified-ilcg1)
* too early — [`TooEarly()`](https://docs.cryptolegacy.app/documentation/errors-reference#tooearly-ilcg1)
* holder mismatch — [`TokenNotLocked()`](https://docs.cryptolegacy.app/documentation/errors-reference#tokennotlocked-ilcg1)
* fee check fails — [`IncorrectFee(uint256)`](https://docs.cryptolegacy.app/documentation/errors-reference#incorrectfee-ilcg1)

**Overrides:** None

**Function Calls:**

* [\_checkDestinationLockedChain(LCGStorage,uint256)](#_checkdestinationlockedchain-lcg1) — LockChainGate, internal
* [\_checkTooEarly(address)](#_checktooearly-lcg1) — LockChainGate, internal
* [\_checkHolderTokenLock(LCGStorage,address,uint256)](#_checkholdertokenlock-lcg1) — LockChainGate, internal
* [\_encodeCrossUnlockCommand(LCGStorage,uint256,address)](#_encodecrossunlockcommand-lcg1) — LockChainGate, internal
* [\_getDeBridgeChainNativeFeeAndCheck(LCGStorage,uint256,uint256)](#_getdebridgechainnativefeeandcheck-lcg1) — LockChainGate, internal
* [\_send(LCGStorage,bytes,uint256,uint256)](#_send-lcg1) — LockChainGate, internal
* [\_deleteTokenData(address,uint256)](#_deletetokendata-lcg1) — LockChainGate, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Holder requests remote unlock back on originating chain, supplying the native fee.

***

### crossUnlockLifetimeNft (LCG1)

**Contract/Library:** LockChainGate

**Description:** Handles cross-chain unlock completion from a source chain.

**Detailed Description:** Validates via `_onlyCrossChain`; verifies holder mapping; removes the source chain from `lockedToChainsIds_tokenId`; emits event.

**Parameters:**

* \_fromChainID (uint256): Source chain id
* \_tokenId (uint256): Token id
* \_holder (address): Holder address

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external nonpayable nonReentrant

**Access Control:**

* Must be invoked via CallProxy from configured source

**Side Effects:**

* Updates `lockedToChainsIds_tokenId` (remove `_fromChainID`)

**Emits:**

* [CrossUnlockNft](https://docs.cryptolegacy.app/documentation/events-reference#crossunlocknft-ilcg1) — `CrossUnlockNft(uint256 lockedAt, uint256 indexed tokenId, address indexed holder, uint256 indexed fromChainID)`

**Reverts if:**

* source chain not configured — [`SourceNotSpecified()`](https://docs.cryptolegacy.app/documentation/errors-reference#sourcenotspecified-ilcg1)
* invalid caller/source — [`NotCallProxy()`](https://docs.cryptolegacy.app/documentation/errors-reference#notcallproxy-ilcg1) / [`ChainIdMismatch()`](https://docs.cryptolegacy.app/documentation/errors-reference#chainidmismatch-ilcg1) / [`NotValidSender()`](https://docs.cryptolegacy.app/documentation/errors-reference#notvalidsender-ilcg1)
* holder-token mismatch — [`TokenNotLocked()`](https://docs.cryptolegacy.app/documentation/errors-reference#tokennotlocked-ilcg1)

**Overrides:** None

**Function Calls:**

* [\_checkSource(LCGStorage,uint256)](#_checksource-lcg1) — LockChainGate, internal
* [\_onlyCrossChain(LCGStorage,uint256)](#_onlycrosschain-lcg1) — LockChainGate, internal
* [\_checkHolderTokenLock(LCGStorage,address,uint256)](#_checkholdertokenlock-lcg1) — LockChainGate, internal

**Called by:**

None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### crossUpdateNftOwner (LCG1)

**Contract/Library:** LockChainGate

**Description:** Updates owner mapping based on cross-chain transfer message.

**Detailed Description:** Loads storage pointer; validates configured source via `_checkSource`; enforces CallProxy origin through `_onlyCrossChain`; hands ownership to `_transferTo` via `_transferLifetimeNftTo`; records `_fromChainID` in `lockedNftFromChainId` and emits events.

**Parameters:**

* \_fromChainID (uint256): Source chain id
* \_tokenId (uint256): Token id
* \_transferTo (address): New owner

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external nonpayable nonReentrant

**Access Control:**

* Must be invoked via CallProxy from configured source

**Side Effects:**

* Updates `ownerOfTokenId_tokenId` and holder records
* Updates `lockedNftFromChainId_tokenId`

**Emits:**

* [TransferNft](https://docs.cryptolegacy.app/documentation/events-reference#transfernft-ilcg1) — `TransferNft(uint256 indexed tokenId, address indexed holder, address indexed transferTo, uint256 fromChainID)`
* [CrossUpdateNftOwner](https://docs.cryptolegacy.app/documentation/events-reference#crossupdatenftowner-ilcg1) — `CrossUpdateNftOwner(uint256 indexed fromChainID, uint256 indexed tokenId, address indexed transferTo)`

**Reverts if:**

* source chain contract not configured — [`SourceNotSpecified()`](https://docs.cryptolegacy.app/documentation/errors-reference#sourcenotspecified-ilcg1)
* caller not CallProxy — [`NotCallProxy()`](https://docs.cryptolegacy.app/documentation/errors-reference#notcallproxy-ilcg1)
* chain identifier mismatch — [`ChainIdMismatch()`](https://docs.cryptolegacy.app/documentation/errors-reference#chainidmismatch-ilcg1)
* native sender mismatch — [`NotValidSender()`](https://docs.cryptolegacy.app/documentation/errors-reference#notvalidsender-ilcg1)
* `_transferTo` equals current holder — [`SameAddress()`](https://docs.cryptolegacy.app/documentation/errors-reference#sameaddress-ilcg1)
* `_transferTo` already holds a locked token — [`RecipientLocked()`](https://docs.cryptolegacy.app/documentation/errors-reference#recipientlocked-ilcg1)
* transfer cooldown not elapsed — [`TransferLockTimeout()`](https://docs.cryptolegacy.app/documentation/errors-reference#transferlocktimeout-ilcg1)

**Overrides:** None

**Function Calls:**

* [lockChainGateStorage()](#lockchaingatestorage-lcg1) — LockChainGate, internal
* [\_checkSource(LCGStorage,uint256)](#_checksource-lcg1) — LockChainGate, internal
* [\_onlyCrossChain(LCGStorage,uint256)](#_onlycrosschain-lcg1) — LockChainGate, internal
* [\_transferLifetimeNftTo(LCGStorage,uint256,address,address,uint256)](#_transferlifetimenftto-lcg1) — LockChainGate, internal

**Called by:**

None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### \_deleteTokenData (LCG1)

**Contract/Library:** LockChainGate

**Description:** Clears all lock-related mappings for a token and holder.

**Detailed Description:** Deletes `lockedNft_holder`, `lockedNftFromChainId_tokenId`, `lockedNftApprovedTo_tokenId`, and `ownerOfTokenId_tokenId`.

**Parameters:**

* \_holder (address): Holder address
* \_tokenId (uint256): Token id

**Returns:** None

**Modifiers / Visibility / Mutability:**

* internal nonpayable

**Access Control:**

* Internal only

**Side Effects:**

* Deletes several storage entries for the token/holder

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [lockChainGateStorage()](#lockchaingatestorage-lcg1) — LockChainGate, internal

**Called by:**

* [unlockLifetimeNft(uint256)](#unlocklifetimenft-lcg1) — LockChainGate
* [unlockLifetimeNftFromChain(uint256)](#unlocklifetimenftfromchain-lcg1) — LockChainGate

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### \_onlyCrossChain (LCG1)

**Contract/Library:** LockChainGate

**Description:** Ensures the function is called by deBridge CallProxy from the expected source chain and contract.

**Detailed Description:** Reads CallProxy from `deBridgeGate`; checks `msg.sender` is CallProxy; validates `submissionChainIdFrom()` equals `_fromChainID`; compares `submissionNativeSender()` to configured `sourceChainsContracts`.

**Parameters:**

* ls ([LCGStorage](https://docs.cryptolegacy.app/documentation/data-structures-reference#lcgstorage-ilcg1-s1), storage): Storage pointer
* \_fromChainID (uint256): Expected source chain id

**Returns:** None

**Modifiers / Visibility / Mutability:**

* internal nonpayable

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:**

* caller not CallProxy — [`NotCallProxy()`](https://docs.cryptolegacy.app/documentation/errors-reference#notcallproxy-ilcg1)
* chainId mismatch — [`ChainIdMismatch()`](https://docs.cryptolegacy.app/documentation/errors-reference#chainidmismatch-ilcg1)
* native sender mismatch — [`NotValidSender()`](https://docs.cryptolegacy.app/documentation/errors-reference#notvalidsender-ilcg1)

**Overrides:** None

**Function Calls:**

* `callProxy()` — `IDeBridgeGate` *(at `address(ls.deBridgeGate)`)*, external (staticcall)
* `submissionChainIdFrom()` — `ICallProxy` *(at `address(callProxy)`)*, external (staticcall)
* `submissionNativeSender()` — `ICallProxy` *(at `address(callProxy)`)*, external (staticcall)

**Called by:**

* [crossLockLifetimeNft(uint256,uint256,address)](#crosslocklifetimenft-lcg1) — LockChainGate
* [crossUnlockLifetimeNft(uint256,uint256,address)](#crossunlocklifetimenft-lcg1) — LockChainGate
* [crossUpdateNftOwner(uint256,uint256,address)](#crossupdatenftowner-lcg1) — LockChainGate
* [crossCreateCustomCode(uint256,address,address,bytes8,uint32,uint32)](#crosscreatecustomcode-fr1) — FeeRegistry
* [crossUpdateCustomCode(uint256,address,address,bytes8,uint32,uint32)](#crossupdatecustomcode-fr1) — FeeRegistry

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### \_send (LCG1)

**Contract/Library:** LockChainGate

**Description:** Sends a cross-chain message via deBridge with flags set.

**Detailed Description:** Builds flags to revert on external fail and proxy with sender; calls `deBridgeGate.sendMessage` with value `_value`. Emits `SendToChain`.

**Parameters:**

* ls ([LCGStorage](https://docs.cryptolegacy.app/documentation/data-structures-reference#lcgstorage-ilcg1-s1), storage): Storage pointer
* \_dstTransactionCall (bytes, memory): Encoded target call
* \_toChainId (uint256): Destination chain id
* \_value (uint256): Native fee to send

**Returns:**

* submissionId (bytes32): deBridge submission id

**Modifiers / Visibility / Mutability:**

* internal nonpayable

**Access Control:**

* Unrestricted

**Side Effects:**

* Sends ETH to `deBridgeGate`

**Emits:**

* [SendToChain](https://docs.cryptolegacy.app/documentation/events-reference#sendtochain-ilcg1) — `SendToChain(uint256 indexed toChainId, bytes32 indexed submissionId, uint256 value, bytes dstTransactionCall)`

**Reverts if:**

* `IDeBridgeGate.sendMessage(uint256,bytes,bytes,uint256,uint32)` — may revert per deBridge implementation (bubbled)

**Overrides:** None

**Function Calls:**

* `sendMessage(uint256,bytes,bytes,uint256,uint32)` — IDeBridgeGate *(at `address(ls.deBridgeGate)`)*, external

**Called by:**

* [\_setCrossChainsRef(FRStorage,bool,bytes8,uint256\[\],uint256\[\])](#_setcrosschainsref-fr1) — FeeRegistry
* [\_lockLifetimeNftToChain(LCGStorage,uint256,address,uint256,uint256)](#_locklifetimenfttochain-lcg1) — LockChainGate
* [unlockLifetimeNftFromChain(uint256)](#unlocklifetimenftfromchain-lcg1) — LockChainGate
* [\_updateLifetimeNftOwnerOnChain(LCGStorage,uint256,uint256,address,uint256)](#_updatelifetimenftowneronchain-lcg1) — LockChainGate

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### approveLifetimeNftTo (LCG1)

**Contract/Library:** LockChainGate

**Description:** Approves an address to unlock or transfer a locked NFT.

**Detailed Description:** Loads storage pointer; confirms caller is current holder through `_checkHolderTokenLock`; ensures token is not cross-chain locked via `_checkCrossChainLock`; records `_approveTo` in `lockedNftApprovedTo` and emits `ApproveNft`.

**Parameters:**

* \_tokenId (uint256): Token id
* \_approveTo (address): Address to approve

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external nonpayable nonReentrant

**Access Control:**

* Holder of `_tokenId`

**Side Effects:**

* Updates `lockedNftApprovedTo_tokenId`

**Emits:**

* [ApproveNft](https://docs.cryptolegacy.app/documentation/events-reference#approvenft-ilcg1) — `ApproveNft(uint256 indexed tokenId, address indexed holder, address indexed approveTo)`

**Reverts if:**

* caller not holder — [`TokenNotLocked()`](https://docs.cryptolegacy.app/documentation/errors-reference#tokennotlocked-ilcg1)
* cross-chain lock active — [`CrossChainLock()`](https://docs.cryptolegacy.app/documentation/errors-reference#crosschainlock-ilcg1)

**Overrides:** None

**Function Calls:**

* [lockChainGateStorage()](#lockchaingatestorage-lcg1) — LockChainGate, internal
* [\_checkHolderTokenLock(LCGStorage,address,uint256)](#_checkholdertokenlock-lcg1) — LockChainGate, internal
* [\_checkCrossChainLock(LCGStorage,uint256)](#_checkcrosschainlock-lcg1) — LockChainGate, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Holder delegates unlock permission to a trusted address.

***

### \_transferLifetimeNftTo (LCG1)

**Contract/Library:** LockChainGate

**Description:** Internal mapping-only transfer of a locked NFT between holders.

**Detailed Description:** Validates `_holder != _transferTo`, recipient not already locked, and `transferTimeout` elapsed since `_holder` locked; updates ownership mappings; clears approvals; emits `TransferNft`.

**Parameters:**

* ls ([LCGStorage](https://docs.cryptolegacy.app/documentation/data-structures-reference#lcgstorage-ilcg1-s1), storage): Storage pointer
* \_tokenId (uint256): Token id
* \_holder (address): Current holder
* \_transferTo (address): New holder
* \_fromChain (uint256): Originating chain id (0 if local)

**Returns:** None

**Modifiers / Visibility / Mutability:**

* internal nonpayable

**Access Control:**

* Unrestricted

**Side Effects:**

* Updates `ownerOfTokenId_tokenId`, `lockedNft` for both holders
* Clears `lockedNftApprovedTo_tokenId`

**Emits:**

* [TransferNft](https://docs.cryptolegacy.app/documentation/events-reference#transfernft-ilcg1) — `TransferNft(uint256 indexed tokenId, address indexed holder, address indexed transferTo, uint256 fromChainID)`

**Reverts if:**

* `_holder == _transferTo` — [`SameAddress()`](https://docs.cryptolegacy.app/documentation/errors-reference#sameaddress-ilcg1)
* recipient already has locked token — [`RecipientLocked()`](https://docs.cryptolegacy.app/documentation/errors-reference#recipientlocked-ilcg1)
* transfer timeout not elapsed — [`TransferLockTimeout()`](https://docs.cryptolegacy.app/documentation/errors-reference#transferlocktimeout-ilcg1)

**Overrides:** None

**Function Calls:** None

**Called by:**

* [crossUpdateNftOwner(uint256,uint256,address)](#crossupdatenftowner-lcg1) — LockChainGate
* [transferLifetimeNftTo(uint256,address,uint256\[\],uint256\[\])](#transferlifetimenftto-lcg1) — LockChainGate

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### transferLifetimeNftTo (LCG1)

**Contract/Library:** LockChainGate

**Description:** Transfers a locked NFT to a new holder locally and updates remote chains.

**Detailed Description:** Checks no cross-chain lock; verifies caller is holder or approved; verifies holder-token match; calls internal transfer; then updates owner on provided chains via [\_updateNftOwnerOnChainList](#_updatenftowneronchainlist-lcg1).

**Parameters:**

* \_tokenId (uint256): Token id
* \_transferTo (address): Recipient holder
* \_toChainIDs (uint256\[], memory): Chains to update
* \_crossChainFees (uint256\[], memory): Per-chain fees

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external payable nonReentrant

**Access Control:**

* Holder or approved address

**Side Effects:**

* Updates holder mappings
* Sends cross-chain owner-update messages

**Emits:**

* [TransferNft](https://docs.cryptolegacy.app/documentation/events-reference#transfernft-ilcg1) — `TransferNft(uint256 indexed tokenId, address indexed holder, address indexed transferTo, uint256 fromChainID)`
* [UpdateLockToChain](https://docs.cryptolegacy.app/documentation/events-reference#updatelocktochain-ilcg1) — `UpdateLockToChain(address indexed sender, uint256 indexed tokenId, uint256 indexed toChainID, bytes32 submissionId)`
* [SendToChain](https://docs.cryptolegacy.app/documentation/events-reference#sendtochain-ilcg1) — `SendToChain(uint256 indexed toChainId, bytes32 indexed submissionId, uint256 value, bytes dstTransactionCall)`

**Reverts if:**

* cross-chain lock active — [`CrossChainLock()`](https://docs.cryptolegacy.app/documentation/errors-reference#crosschainlock-ilcg1)
* caller neither holder nor approved — [`NotAvailable()`](https://docs.cryptolegacy.app/documentation/errors-reference#notavailable-ilcg1)
* holder-token mismatch — [`TokenNotLocked()`](https://docs.cryptolegacy.app/documentation/errors-reference#tokennotlocked-ilcg1)
* same address — [`SameAddress()`](https://docs.cryptolegacy.app/documentation/errors-reference#sameaddress-ilcg1)
* recipient already has locked token — [`RecipientLocked()`](https://docs.cryptolegacy.app/documentation/errors-reference#recipientlocked-ilcg1)
* transfer timeout not elapsed — [`TransferLockTimeout()`](https://docs.cryptolegacy.app/documentation/errors-reference#transferlocktimeout-ilcg1)
* arrays length mismatch — [`ArrayLengthMismatch()`](https://docs.cryptolegacy.app/documentation/errors-reference#arraylengthmismatch-ilcg1)
* fee mismatch — [`IncorrectFee(uint256)`](https://docs.cryptolegacy.app/documentation/errors-reference#incorrectfee-ilcg1)
* destination chain not configured — [`DestinationChainNotSpecified()`](https://docs.cryptolegacy.app/documentation/errors-reference#destinationchainnotspecified-ilcg1)
* token mismatch after transfer — [`TokenIdMismatch(uint256)`](https://docs.cryptolegacy.app/documentation/errors-reference#tokenidmismatch-ilcg1)

**Overrides:** None

**Function Calls:**

* [lockChainGateStorage()](#lockchaingatestorage-lcg1) — LockChainGate, internal
* [\_checkCrossChainLock(LCGStorage,uint256)](#_checkcrosschainlock-lcg1) — LockChainGate, internal
* [\_checkHolderTokenLock(LCGStorage,address,uint256)](#_checkholdertokenlock-lcg1) — LockChainGate, internal
* [\_transferLifetimeNftTo(LCGStorage,uint256,address,address,uint256)](#_transferlifetimenftto-lcg1) — LockChainGate, internal
* [\_updateNftOwnerOnChainList(LCGStorage,uint256,uint256\[\],uint256\[\],address)](#_updatenftowneronchainlist-lcg1) — LockChainGate, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(n) by `_toChainIDs.length`

**Example:** Holder transfers locked rights to a new address and propagates change to chains `56,137`.

***

### updateNftOwnerOnChainList (LCG1)

**Contract/Library:** LockChainGate

**Description:** Sends owner-update messages for the caller’s locked NFT to specified chains.

**Detailed Description:** Checks no cross-chain lock; requires caller to be the current holder; delegates to internal owner-update routine.

**Parameters:**

* \_tokenId (uint256): Token id
* \_toChainIDs (uint256\[], memory): Chains to update
* \_crossChainFees (uint256\[], memory): Per-chain fees

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external payable nonReentrant

**Access Control:**

* Current holder only

**Side Effects:**

* Sends cross-chain owner-update messages
* Updates `lockedToChainsIds_tokenId`

**Emits:**

* [UpdateLockToChain](https://docs.cryptolegacy.app/documentation/events-reference#updatelocktochain-ilcg1) — `UpdateLockToChain(address indexed sender, uint256 indexed tokenId, uint256 indexed toChainID, bytes32 submissionId)`
* [SendToChain](https://docs.cryptolegacy.app/documentation/events-reference#sendtochain-ilcg1) — `SendToChain(uint256 indexed toChainId, bytes32 indexed submissionId, uint256 value, bytes dstTransactionCall)`

**Reverts if:**

* cross-chain lock active — [`CrossChainLock()`](https://docs.cryptolegacy.app/documentation/errors-reference#crosschainlock-ilcg1)
* caller not current holder — [`NotAvailable()`](https://docs.cryptolegacy.app/documentation/errors-reference#notavailable-ilcg1)
* arrays length mismatch — [`ArrayLengthMismatch()`](https://docs.cryptolegacy.app/documentation/errors-reference#arraylengthmismatch-ilcg1)
* fee mismatch — [`IncorrectFee(uint256)`](https://docs.cryptolegacy.app/documentation/errors-reference#incorrectfee-ilcg1)
* destination chain not configured — [`DestinationChainNotSpecified()`](https://docs.cryptolegacy.app/documentation/errors-reference#destinationchainnotspecified-ilcg1)
* token mismatch — [`TokenIdMismatch(uint256)`](https://docs.cryptolegacy.app/documentation/errors-reference#tokenidmismatch-ilcg1)
* caller has no locked token — [`TokenNotLocked()`](https://docs.cryptolegacy.app/documentation/errors-reference#tokennotlocked-ilcg1)

**Overrides:** None

**Function Calls:**

* [lockChainGateStorage()](#lockchaingatestorage-lcg1) — LockChainGate, internal
* [\_checkCrossChainLock(LCGStorage,uint256)](#_checkcrosschainlock-lcg1) — LockChainGate, internal
* [\_updateNftOwnerOnChainList(LCGStorage,uint256,uint256\[\],uint256\[\],address)](#_updatenftowneronchainlist-lcg1) — LockChainGate, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(n) by `_toChainIDs.length`

**Example:** Holder re-broadcasts ownership to synchronize multiple chains.

***

### \_updateNftOwnerOnChainList (LCG1)

**Contract/Library:** LockChainGate

**Description:** Internal routine to update NFT owner on a list of chains.

**Detailed Description:** Validates arrays; iterates chains, computes fee, calls per-chain updater; sums and checks total fee.

**Parameters:**

* ls ([LCGStorage](https://docs.cryptolegacy.app/documentation/data-structures-reference#lcgstorage-ilcg1-s1), storage): Storage pointer
* \_tokenId (uint256): Token id
* \_toChainIDs (uint256\[], memory): Chains
* \_crossChainFees (uint256\[], memory): Per-chain fees
* \_holder (address): Current holder

**Returns:** None

**Modifiers / Visibility / Mutability:**

* internal nonpayable

**Access Control:**

* Unrestricted

**Side Effects:**

* Updates `lockedToChainsIds_tokenId`

**Emits:**

* [UpdateLockToChain](https://docs.cryptolegacy.app/documentation/events-reference#updatelocktochain-ilcg1) — `UpdateLockToChain(address indexed sender, uint256 indexed tokenId, uint256 indexed toChainID, bytes32 submissionId)`
* [SendToChain](https://docs.cryptolegacy.app/documentation/events-reference#sendtochain-ilcg1) — `SendToChain(uint256 indexed toChainId, bytes32 indexed submissionId, uint256 value, bytes dstTransactionCall)`

**Reverts if:**

* arrays length mismatch — [`ArrayLengthMismatch()`](https://docs.cryptolegacy.app/documentation/errors-reference#arraylengthmismatch-ilcg1)
* fee mismatch — [`IncorrectFee(uint256)`](https://docs.cryptolegacy.app/documentation/errors-reference#incorrectfee-ilcg1)
* destination not set — [`DestinationChainNotSpecified()`](https://docs.cryptolegacy.app/documentation/errors-reference#destinationchainnotspecified-ilcg1)
* token mismatch — [`TokenIdMismatch(uint256)`](https://docs.cryptolegacy.app/documentation/errors-reference#tokenidmismatch-ilcg1)
* token not locked for `_holder` — [`TokenNotLocked()`](https://docs.cryptolegacy.app/documentation/errors-reference#tokennotlocked-ilcg1)

**Overrides:** None

**Function Calls:**

* [lockChainGateStorage()](#lockchaingatestorage-lcg1) — LockChainGate, internal
* [\_getDeBridgeChainNativeFee(LCGStorage,uint256,uint256)](#_getdebridgechainnativefee-lcg1) — LockChainGate, internal
* [\_updateLifetimeNftOwnerOnChain(LCGStorage,uint256,uint256,address,uint256)](#_updatelifetimenftowneronchain-lcg1) — LockChainGate, internal
* [\_checkFee(uint256)](#_checkfee-lcg1) — LockChainGate, internal

**Called by:**

* [transferLifetimeNftTo(uint256,address,uint256\[\],uint256\[\])](#transferlifetimenftto-lcg1) — LockChainGate
* [updateNftOwnerOnChainList(uint256,uint256\[\],uint256\[\])](#updatenftowneronchainlist-lcg1) — LockChainGate

**Gas / Complexity note:** O(n) by `_toChainIDs.length`

**Example:** Not applicable

***

### \_updateLifetimeNftOwnerOnChain (LCG1)

**Contract/Library:** LockChainGate

**Description:** Sends owner-update for a single chain and records mirroring.

**Detailed Description:** Checks current token id for `_holder`; validates destination; ensures token id matches; encodes update command; sends via deBridge; records chain id in set; emits event.

**Parameters:**

* ls ([LCGStorage](https://docs.cryptolegacy.app/documentation/data-structures-reference#lcgstorage-ilcg1-s1), storage): Storage pointer
* \_tokenId (uint256): Token id
* \_toChainID (uint256): Destination chain id
* \_holder (address): Holder
* \_sendFee (uint256): Fee

**Returns:**

* submissionId (bytes32): deBridge submission id

**Modifiers / Visibility / Mutability:**

* internal nonpayable

**Access Control:**

* Unrestricted

**Side Effects:**

* Updates `lockedToChainsIds_tokenId`

**Emits:**

* [UpdateLockToChain](https://docs.cryptolegacy.app/documentation/events-reference#updatelocktochain-ilcg1) — `UpdateLockToChain(address indexed sender, uint256 indexed tokenId, uint256 indexed toChainID, bytes32 submissionId)`
* [SendToChain](https://docs.cryptolegacy.app/documentation/events-reference#sendtochain-ilcg1) — `SendToChain(uint256 indexed toChainId, bytes32 indexed submissionId, uint256 value, bytes dstTransactionCall)`

**Reverts if:**

* destination not set — [`DestinationChainNotSpecified()`](https://docs.cryptolegacy.app/documentation/errors-reference#destinationchainnotspecified-ilcg1)
* token mismatch — [`TokenIdMismatch(uint256)`](https://docs.cryptolegacy.app/documentation/errors-reference#tokenidmismatch-ilcg1)
* token not locked for `_holder` — [`TokenNotLocked()`](https://docs.cryptolegacy.app/documentation/errors-reference#tokennotlocked-ilcg1)

**Overrides:** None

**Function Calls:**

* [\_checkTokenLocked(LCGStorage,address)](#_checktokenlocked-lcg1) — LockChainGate, internal
* [\_checkDestinationLockedChain(LCGStorage,uint256)](#_checkdestinationlockedchain-lcg1) — LockChainGate, internal
* [\_encodeCrossUpdateOwnerCommand(LCGStorage,uint256,address)](#_encodecrossupdateownercommand-lcg1) — LockChainGate, internal
* [\_send(LCGStorage,bytes,uint256,uint256)](#_send-lcg1) — LockChainGate, internal

**Called by:**

* [\_updateNftOwnerOnChainList(LCGStorage,uint256,uint256\[\],uint256\[\],address)](#_updatenftowneronchainlist-lcg1) — LockChainGate

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### \_encodeCrossLockCommand (LCG1)

**Contract/Library:** LockChainGate

**Description:** Encodes the cross-chain lock command calldata.

**Detailed Description:** ABI-encodes selector `crossLockLifetimeNft(uint256,uint256,address)` with current chain id, `_tokenId`, and `_holder`.

**Parameters:**

* ls ([LCGStorage](https://docs.cryptolegacy.app/documentation/data-structures-reference#lcgstorage-ilcg1-s1), storage): Storage pointer
* \_tokenId (uint256): Token id
* \_holder (address): Holder

**Returns:**

* encodedCalldata (bytes, memory): Encoded calldata

**Modifiers / Visibility / Mutability:**

* internal view

**Access Control:**

* Internal only

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [\_getChainId(LCGStorage)](#_getchainid-lcg1) — LockChainGate, internal

**Called by:**

* [\_lockLifetimeNftToChain(LCGStorage,uint256,address,uint256,uint256)](#_locklifetimenfttochain-lcg1) — LockChainGate

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### \_encodeCrossUnlockCommand (LCG1)

**Contract/Library:** LockChainGate

**Description:** Encodes the cross-chain unlock command calldata.

**Detailed Description:** ABI-encodes selector `crossUnlockLifetimeNft(uint256,uint256,address)` with current chain id, `_tokenId`, and `_holder`.

**Parameters:**

* ls ([LCGStorage](https://docs.cryptolegacy.app/documentation/data-structures-reference#lcgstorage-ilcg1-s1), storage): Storage pointer
* \_tokenId (uint256): Token id
* \_holder (address): Holder

**Returns:**

* encodedCalldata (bytes, memory): Encoded calldata

**Modifiers / Visibility / Mutability:**

* internal view

**Access Control:**

* Internal only

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [\_getChainId(LCGStorage)](#_getchainid-lcg1) — LockChainGate, internal

**Called by:**

* [unlockLifetimeNftFromChain(uint256)](#unlocklifetimenftfromchain-lcg1) — LockChainGate

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### \_encodeCrossUpdateOwnerCommand (LCG1)

**Contract/Library:** LockChainGate

**Description:** Encodes the cross-chain update-owner command calldata.

**Detailed Description:** ABI-encodes selector `crossUpdateNftOwner(uint256,uint256,address)` with current chain id, `_tokenId`, and `_transferTo`.

**Parameters:**

* ls ([LCGStorage](https://docs.cryptolegacy.app/documentation/data-structures-reference#lcgstorage-ilcg1-s1), storage): Storage pointer
* \_tokenId (uint256): Token id
* \_transferTo (address): New owner

**Returns:**

* encodedCalldata (bytes, memory): Encoded calldata

**Modifiers / Visibility / Mutability:**

* internal view

**Access Control:**

* Internal only

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [\_getChainId(LCGStorage)](#_getchainid-lcg1) — LockChainGate, internal

**Called by:**

* [\_updateLifetimeNftOwnerOnChain(LCGStorage,uint256,uint256,address,uint256)](#_updatelifetimenftowneronchain-lcg1) — LockChainGate

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### \_checkDestinationLockedChain (LCG1)

**Contract/Library:** LockChainGate

**Description:** Ensures destination chain contract is configured.

**Detailed Description:** Reads `destinationChainContracts_toChainID` and reverts if zero address.

**Parameters:**

* ls ([LCGStorage](https://docs.cryptolegacy.app/documentation/data-structures-reference#lcgstorage-ilcg1-s1), storage): Storage pointer
* \_toChainID (uint256): Destination chain id

**Returns:** None

**Modifiers / Visibility / Mutability:**

* internal view

**Access Control:**

* Internal only

**Side Effects:** None

**Emits:** None

**Reverts if:**

* destination not set — [`DestinationChainNotSpecified()`](https://docs.cryptolegacy.app/documentation/errors-reference#destinationchainnotspecified-ilcg1)

**Overrides:** None

**Function Calls:** None

**Called by:**

* [\_setCrossChainsRef(FRStorage,bool,bytes8,uint256\[\],uint256\[\])](#_setcrosschainsref-fr1) — FeeRegistry
* [\_lockLifetimeNftToChain(LCGStorage,uint256,address,uint256,uint256)](#_locklifetimenfttochain-lcg1) — LockChainGate
* [unlockLifetimeNftFromChain(uint256)](#unlocklifetimenftfromchain-lcg1) — LockChainGate
* [\_updateLifetimeNftOwnerOnChain(LCGStorage,uint256,uint256,address,uint256)](#_updatelifetimenftowneronchain-lcg1) — LockChainGate

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### \_checkTokenLocked (LCG1)

**Contract/Library:** LockChainGate

**Description:** Validates that a holder currently has a locked token and returns its id.

**Detailed Description:** Reads `lockedNft_holder.tokenId`; reverts if zero.

**Parameters:**

* ls ([LCGStorage](https://docs.cryptolegacy.app/documentation/data-structures-reference#lcgstorage-ilcg1-s1), storage): Storage pointer
* \_holder (address): Holder address

**Returns:**

* tokenId (uint256): Locked token id

**Modifiers / Visibility / Mutability:**

* internal view

**Access Control:**

* Internal only

**Side Effects:** None

**Emits:** None

**Reverts if:**

* no token locked — [`TokenNotLocked()`](https://docs.cryptolegacy.app/documentation/errors-reference#tokennotlocked-ilcg1)

**Overrides:** None

**Function Calls:** None

**Called by:**

* [\_lockLifetimeNftToChains(LCGStorage,address,uint256\[\],uint256\[\])](#_locklifetimenfttochains-lcg1) — LockChainGate
* [\_updateLifetimeNftOwnerOnChain(LCGStorage,uint256,uint256,address,uint256)](#_updatelifetimenftowneronchain-lcg1) — LockChainGate

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### \_checkCrossChainLock (LCG1)

**Contract/Library:** LockChainGate

**Description:** Ensures the token is not currently locked via cross-chain lock source id.

**Detailed Description:** Reads `lockedNftFromChainId_tokenId`; reverts if non-zero.

**Parameters:**

* ls ([LCGStorage](https://docs.cryptolegacy.app/documentation/data-structures-reference#lcgstorage-ilcg1-s1), storage): Storage pointer
* \_tokenId (uint256): Token id

**Returns:** None

**Modifiers / Visibility / Mutability:**

* internal view

**Access Control:**

* Unrestricted (internal)

**Side Effects:** None

**Emits:** None

**Reverts if:**

* cross-chain lock active — [`CrossChainLock()`](https://docs.cryptolegacy.app/documentation/errors-reference#crosschainlock-ilcg1)

**Overrides:** None

**Function Calls:** None

**Called by:**

* [\_lockLifetimeNftToChains(LCGStorage,address,uint256\[\],uint256\[\])](#_locklifetimenfttochains-lcg1) — LockChainGate
* [unlockLifetimeNft(uint256)](#unlocklifetimenft-lcg1) — LockChainGate
* [approveLifetimeNftTo(uint256,address)](#approvelifetimenftto-lcg1) — LockChainGate
* [transferLifetimeNftTo(uint256,address,uint256\[\],uint256\[\])](#transferlifetimenftto-lcg1) — LockChainGate
* [updateNftOwnerOnChainList(uint256,uint256\[\],uint256\[\])](#updatenftowneronchainlist-lcg1) — LockChainGate

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### \_checkTooEarly (LCG1)

**Contract/Library:** LockChainGate

**Description:** Enforces that the lock period has elapsed for a holder.

**Detailed Description:** Computes `lockedAt + lockPeriod` and compares to `block.timestamp`; reverts if still locked.

**Parameters:**

* \_holder (address): Holder address

**Returns:** None

**Modifiers / Visibility / Mutability:**

* internal view

**Access Control:**

* Unrestricted (internal)

**Side Effects:** None

**Emits:** None

**Reverts if:**

* current time < unlock time — [`TooEarly()`](https://docs.cryptolegacy.app/documentation/errors-reference#tooearly-ilcg1)

**Overrides:** None

**Function Calls:**

* [lockChainGateStorage()](#lockchaingatestorage-lcg1) — LockChainGate, internal
* [\_getLockedUntil(LCGStorage,address)](#_getlockeduntil-lcg1) — LockChainGate, internal

**Called by:**

* [unlockLifetimeNft(uint256)](#unlocklifetimenft-lcg1) — LockChainGate
* [unlockLifetimeNftFromChain(uint256)](#unlocklifetimenftfromchain-lcg1) — LockChainGate

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### \_checkSource (LCG1)

**Contract/Library:** LockChainGate

**Description:** Ensures source chain contract is configured.

**Detailed Description:** Checks `sourceChainsContracts_fromChainID` non-zero; otherwise reverts.

**Parameters:**

* ls ([LCGStorage](https://docs.cryptolegacy.app/documentation/data-structures-reference#lcgstorage-ilcg1-s1), storage): Storage pointer
* \_fromChainID (uint256): Source chain id

**Returns:** None

**Modifiers / Visibility / Mutability:**

* internal view

**Access Control:**

* Unrestricted (internal)

**Side Effects:** None

**Emits:** None

**Reverts if:**

* source not specified — [`SourceNotSpecified()`](https://docs.cryptolegacy.app/documentation/errors-reference#sourcenotspecified-ilcg1)

**Overrides:** None

**Function Calls:** None

**Called by:**

* [crossLockLifetimeNft(uint256,uint256,address)](#crosslocklifetimenft-lcg1) — LockChainGate
* [crossUnlockLifetimeNft(uint256,uint256,address)](#crossunlocklifetimenft-lcg1) — LockChainGate
* [crossUpdateNftOwner(uint256,uint256,address)](#crossupdatenftowner-lcg1) — LockChainGate
* [crossCreateCustomCode(uint256,address,address,bytes8,uint32,uint32)](#crosscreatecustomcode-fr1) — FeeRegistry
* [crossUpdateCustomCode(uint256,address,address,bytes8,uint32,uint32)](#crossupdatecustomcode-fr1) — FeeRegistry

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### \_checkHolderTokenLock (LCG1)

**Contract/Library:** LockChainGate

**Description:** Verifies that `_holder` is recorded as the holder of `_tokenId`.

**Detailed Description:** Checks `lockedNft_holder.tokenId == _tokenId`; reverts if mismatch.

**Parameters:**

* ls ([LCGStorage](https://docs.cryptolegacy.app/documentation/data-structures-reference#lcgstorage-ilcg1-s1), storage): Storage pointer
* \_holder (address): Holder address
* \_tokenId (uint256): Token id

**Returns:** None

**Modifiers / Visibility / Mutability:**

* internal view

**Access Control:**

* Unrestricted (internal)

**Side Effects:** None

**Emits:** None

**Reverts if:**

* mismatch — [`TokenNotLocked()`](https://docs.cryptolegacy.app/documentation/errors-reference#tokennotlocked-ilcg1)

**Overrides:** None

**Function Calls:** None

**Called by:**

* [unlockLifetimeNftFromChain(uint256)](#unlocklifetimenftfromchain-lcg1) — LockChainGate
* [approveLifetimeNftTo(uint256,address)](#approvelifetimenftto-lcg1) — LockChainGate
* [transferLifetimeNftTo(uint256,address,uint256\[\],uint256\[\])](#transferlifetimenftto-lcg1) — LockChainGate
* [crossUnlockLifetimeNft(uint256,uint256,address)](#crossunlocklifetimenft-lcg1) — LockChainGate

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### getLockedToChainsIdsOfAccount (LCG1)

**Contract/Library:** LockChainGate

**Description:** Returns destination chain ids where the account’s token is mirrored.

**Detailed Description:** Fetches token id for `_holder` and returns the values of its `lockedToChainsIds` set.

**Parameters:**

* \_holder (address): Account address

**Returns:**

* chainIds (uint256\[], memory): List of chain ids

**Modifiers / Visibility / Mutability:**

* external virtual view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [lockChainGateStorage()](#lockchaingatestorage-lcg1) — LockChainGate, internal
* [\_getLockedToChainsIdsOfAccount(LCGStorage,address)](#_getlockedtochainsidsofaccount-lcg1) — LockChainGate, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(k) where k is number of mirrored chains

**Example:** Query mirrored chains for a holder.

***

### \_getLockedToChainsIdsOfAccount (LCG1)

**Contract/Library:** LockChainGate

**Description:** Internal getter for mirrored chain ids of `_holder`.

**Detailed Description:** Uses the holder’s token id to look up and return the set values.

**Parameters:**

* ls ([LCGStorage](https://docs.cryptolegacy.app/documentation/data-structures-reference#lcgstorage-ilcg1-s1), storage): Storage pointer
* \_holder (address): Holder

**Returns:**

* chainIds (uint256\[], memory): Chain ids

**Modifiers / Visibility / Mutability:**

* internal view

**Access Control:**

* Unrestricted (internal)

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:**

* [getLockedToChainsIdsOfAccount(address)](#getlockedtochainsidsofaccount-lcg1) — LockChainGate

**Gas / Complexity note:** O(k)

**Example:** Not applicable

***

### getLockedUntil (LCG1)

**Contract/Library:** LockChainGate

**Description:** Returns the timestamp when \_holder can unlock.

**Detailed Description:** Computes and returns `lockedAt + lockPeriod` for \_holder.

**Parameters:**

* \_holder (address): Holder address

**Returns:**

* lockedUntil (uint256): Unlock timestamp

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [lockChainGateStorage()](#lockchaingatestorage-lcg1) — LockChainGate, internal
* [\_getLockedUntil(LCGStorage,address)](#_getlockeduntil-lcg1) — LockChainGate, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Front-end displays when a lock expires.

***

### \_getLockedUntil (LCG1)

**Contract/Library:** LockChainGate

**Description:** Internal computation of unlock timestamp.

**Detailed Description:** Returns `ls.lockedNft_holder.lockedAt + ls.lockPeriod`.

**Parameters:**

* ls ([LCGStorage](https://docs.cryptolegacy.app/documentation/data-structures-reference#lcgstorage-ilcg1-s1), storage): Storage pointer
* \_holder (address): Holder

**Returns:**

* lockedUntil (uint256): Unlock timestamp

**Modifiers / Visibility / Mutability:**

* internal view

**Access Control:**

* Unrestricted (internal)

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:**

* [\_checkTooEarly(address)](#_checktooearly-lcg1) — LockChainGate
* [isNftLockedAndUpdate(address)](#isnftlockedandupdate-lcg1) — LockChainGate
* [getLockedUntil(address)](#getlockeduntil-lcg1) — LockChainGate

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### getLockedToChainsIds (LCG1)

**Contract/Library:** LockChainGate

**Description:** Returns mirrored chain ids for a given token id.

**Detailed Description:** Reads the enumerable set for \_tokenId and returns values.

**Parameters:**

* \_tokenId (uint256): Token id

**Returns:**

* chainIds (uint256\[], memory): Chain ids

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [lockChainGateStorage()](#lockchaingatestorage-lcg1) — LockChainGate, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(k)

**Example:** Caller inspects which chains mirror token lock.

***

### lockPeriod (LCG1)

**Contract/Library:** LockChainGate

**Description:** Getter for current lock period.

**Detailed Description:** Returns `lockPeriod` from storage.

**Parameters:** None

**Returns:**

* lockPeriod (uint256): Lock period in seconds

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [lockChainGateStorage()](#lockchaingatestorage-lcg1) — LockChainGate, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### transferTimeout (LCG1)

**Contract/Library:** LockChainGate

**Description:** Getter for transfer timeout.

**Detailed Description:** Returns `transferTimeout` from storage.

**Parameters:** None

**Returns:**

* transferTimeout (uint256): Transfer timeout in seconds

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [lockChainGateStorage()](#lockchaingatestorage-lcg1) — LockChainGate, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### referralCode (LCG1)

**Contract/Library:** LockChainGate

**Description:** Getter for deBridge referral code.

**Detailed Description:** Returns `referralCode` from storage.

**Parameters:** None

**Returns:**

* referralCode (uint256): Referral code

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [lockChainGateStorage()](#lockchaingatestorage-lcg1) — LockChainGate, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### ownerOfTokenId (LCG1)

**Contract/Library:** LockChainGate

**Description:** Returns owner address recorded for a locked token.

**Detailed Description:** Fetches `ownerOfTokenId_tokenId` from storage.

**Parameters:**

* \_tokenId (uint256): Token id

**Returns:**

* owner (address): Owner address

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [lockChainGateStorage()](#lockchaingatestorage-lcg1) — LockChainGate, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### lockedNftFromChainId (LCG1)

**Contract/Library:** LockChainGate

**Description:** Returns the source chain id that locked a token, if any.

**Detailed Description:** Reads `lockedNftFromChainId_tokenId`.

**Parameters:**

* \_tokenId (uint256): Token id

**Returns:**

* sourceChainId (uint256): Source chain id (0 if local)

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [lockChainGateStorage()](#lockchaingatestorage-lcg1) — LockChainGate, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### lockedNftApprovedTo (LCG1)

**Contract/Library:** LockChainGate

**Description:** Returns the address approved for a locked NFT.

**Detailed Description:** Reads `lockedNftApprovedTo_tokenId`.

**Parameters:**

* \_tokenId (uint256): Token id

**Returns:**

* approvedTo (address): Approved address

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [lockChainGateStorage()](#lockchaingatestorage-lcg1) — LockChainGate, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### lockedNft (LCG1)

**Contract/Library:** LockChainGate

**Description:** Returns the [`LockedNft`](https://docs.cryptolegacy.app/documentation/data-structures-reference#lockednft-ilcg1-s2) record for a holder.

**Detailed Description:** Reads `lockedNft_holder` struct from storage.

**Parameters:**

* \_holder (address): Holder address

**Returns:**

* lockInfo ([LockedNft](https://docs.cryptolegacy.app/documentation/data-structures-reference#lockednft-ilcg1-s2), memory): Lock record {lockedAt, tokenId}

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [lockChainGateStorage()](#lockchaingatestorage-lcg1) — LockChainGate, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### getDeBridgeChainNativeFeeAndCheck (LCG1)

**Contract/Library:** LockChainGate

**Description:** Returns required native fee for a chain and verifies `msg.value` matches policy.

**Detailed Description:** Calculates required fee by delegating to internal getter; then checks `msg.value` via [\_checkFee](#_checkfee-lcg1); returns the fee.

**Parameters:**

* \_chainId (uint256): Chain id
* \_userValue (uint256): User-specified value

**Returns:**

* nativeFee (uint256): Required fee

**Modifiers / Visibility / Mutability:**

* external payable

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:**

* fee check fails — [`IncorrectFee(uint256)`](https://docs.cryptolegacy.app/documentation/errors-reference#incorrectfee-ilcg1)
* `globalFixedNativeFee()` call fails — may revert per deBridge implementation (bubbled)

**Overrides:** None

**Function Calls:**

* [lockChainGateStorage()](#lockchaingatestorage-lcg1) — LockChainGate, internal
* [\_getDeBridgeChainNativeFeeAndCheck(LCGStorage,uint256,uint256)](#_getdebridgechainnativefeeandcheck-lcg1) — LockChainGate, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Front-end pre-check for fee sufficiency before sending cross-chain tx.

***

### \_getDeBridgeChainNativeFeeAndCheck (LCG1)

**Contract/Library:** LockChainGate

**Description:** Internal compute-and-check fee helper.

**Detailed Description:** Calls internal fee getter and then runs [\_checkFee](#_checkfee-lcg1); returns computed fee.

**Parameters:**

* ls ([LCGStorage](https://docs.cryptolegacy.app/documentation/data-structures-reference#lcgstorage-ilcg1-s1), storage): Storage pointer
* \_chainId (uint256): Chain id
* \_userValue (uint256): User value

**Returns:**

* nativeFee (uint256): Required fee

**Modifiers / Visibility / Mutability:**

* internal nonpayable

**Access Control:**

* Unrestricted (internal)

**Side Effects:** None

**Emits:** None

**Reverts if:**

* fee check fails — [`IncorrectFee(uint256)`](https://docs.cryptolegacy.app/documentation/errors-reference#incorrectfee-ilcg1)
* `globalFixedNativeFee()` call fails — may revert per deBridge implementation (bubbled)

**Overrides:** None

**Function Calls:**

* [\_getDeBridgeChainNativeFee(LCGStorage,uint256,uint256)](#_getdebridgechainnativefee-lcg1) — LockChainGate, internal
* [\_checkFee(uint256)](#_checkfee-lcg1) — LockChainGate, internal

**Called by:**

* [unlockLifetimeNftFromChain(uint256)](#unlocklifetimenftfromchain-lcg1) — LockChainGate
* [getDeBridgeChainNativeFeeAndCheck(uint256,uint256)](#getdebridgechainnativefeeandcheck-lcg1) — LockChainGate

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### getDeBridgeChainNativeFee (LCG1)

**Contract/Library:** LockChainGate

**Description:** View function to compute native fee for a chain.

**Detailed Description:** Returns `deBridgeNativeFee_chainId` if set; otherwise queries `deBridgeGate.globalFixedNativeFee()`. If `_userValue` exceeds computed fee, returns `_userValue`.

**Parameters:**

* \_chainId (uint256): Chain id
* \_userValue (uint256): User value

**Returns:**

* nativeFee (uint256): Computed native fee

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:**

* `globalFixedNativeFee()` call fails — may revert per deBridge implementation (bubbled)

**Overrides:** None

**Function Calls:**

* [lockChainGateStorage()](#lockchaingatestorage-lcg1) — LockChainGate, internal
* [\_getDeBridgeChainNativeFee(LCGStorage,uint256,uint256)](#_getdebridgechainnativefee-lcg1) — LockChainGate, internal

**Called by:**

None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Front-end estimates fee to supply.

***

### \_getDeBridgeChainNativeFee (LCG1)

**Contract/Library:** LockChainGate

**Description:** Internal fee computation for a chain.

**Detailed Description:** If mapping value is zero, reads `globalFixedNativeFee()` from deBridge; then maxes with `_userValue`.

**Parameters:**

* ls ([LCGStorage](https://docs.cryptolegacy.app/documentation/data-structures-reference#lcgstorage-ilcg1-s1), storage): Storage pointer
* \_chainId (uint256): Chain id
* \_userValue (uint256): User value

**Returns:**

* nativeFee (uint256): Fee

**Modifiers / Visibility / Mutability:**

* internal view

**Access Control:**

* Unrestricted (internal)

**Side Effects:** None

**Emits:** None

**Reverts if:**

* `globalFixedNativeFee()` call fails — may revert per deBridge implementation (bubbled)

**Overrides:** None

**Function Calls:**

* `globalFixedNativeFee()` — `IDeBridgeGate` *(at `address(ls.deBridgeGate)`)*, external (staticcall)

**Called by:**

* [\_lockLifetimeNftToChains(LCGStorage,address,uint256\[\],uint256\[\])](#_locklifetimenfttochains-lcg1) — LockChainGate
* [\_updateNftOwnerOnChainList(LCGStorage,uint256,uint256\[\],uint256\[\],address)](#_updatenftowneronchainlist-lcg1) — LockChainGate
* [\_getDeBridgeChainNativeFeeAndCheck(LCGStorage,uint256,uint256)](#_getdebridgechainnativefeeandcheck-lcg1) — LockChainGate
* [getDeBridgeChainNativeFee(uint256,uint256)](#getdebridgechainnativefee-lcg1) — LockChainGate
* [calculateCrossChainCreateRefNativeFee(uint256\[\],uint256\[\])](#calculatecrosschaincreaterefnativefee-lcg1) — LockChainGate
* [\_setCrossChainsRef(FRStorage,bool,bytes8,uint256\[\],uint256\[\])](#_setcrosschainsref-fr1) — FeeRegistry

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### deBridgeGate (LCG1)

**Contract/Library:** LockChainGate

**Description:** Returns the configured deBridgeGate address.

**Detailed Description:** Casts and returns `ls.deBridgeGate`.

**Parameters:** None

**Returns:**

* deBridgeGate (address): deBridgeGate address

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [lockChainGateStorage()](#lockchaingatestorage-lcg1) — LockChainGate, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### lifetimeNft (LCG1)

**Contract/Library:** LockChainGate

**Description:** Returns the associated LifetimeNft address.

**Detailed Description:** Casts and returns [`ls.lifetimeNft`](https://docs.cryptolegacy.app/documentation/data-structures-reference#lifetimenft-clbm1-d4).

**Parameters:** None

**Returns:**

* lifetimeNft (address): LifetimeNft address

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [lockChainGateStorage()](#lockchaingatestorage-lcg1) — LockChainGate, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### deBridgeChainConfig (LCG1)

**Contract/Library:** LockChainGate

**Description:** Returns cross-chain configuration for a chain id.

**Detailed Description:** Returns tuple of `(nativeFee, destinationChain, sourceChain)` from storage.

**Parameters:**

* \_chainId (uint256): Chain id

**Returns:**

* nativeFee (uint256): Native fee
* destinationChain (address): Destination contract
* sourceChain (address): Source contract

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [lockChainGateStorage()](#lockchaingatestorage-lcg1) — LockChainGate, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** UI displays remote config for a chain.

***

### getLockOperatorsList (LCG1)

**Contract/Library:** LockChainGate

**Description:** Returns all lock operator addresses.

**Detailed Description:** Returns the values of the `lockOperators` set.

**Parameters:** None

**Returns:**

* operators (address\[], memory): Operators

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [lockChainGateStorage()](#lockchaingatestorage-lcg1) — LockChainGate, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(m) where m is number of operators

**Example:** Admin audits current operators.

***

### isLockOperator (LCG1)

**Contract/Library:** LockChainGate

**Description:** Checks whether an address is a lock operator.

**Detailed Description:** Returns membership test in `lockOperators` set.

**Parameters:**

* \_addr (address): Address to check

**Returns:**

* isOperator (bool): True if operator

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [lockChainGateStorage()](#lockchaingatestorage-lcg1) — LockChainGate, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### calculateCrossChainCreateRefNativeFee (LCG1)

**Contract/Library:** LockChainGate

**Description:** Computes total native fee for cross-chain referral creation.

**Detailed Description:** Sums per-chain fees using internal native fee getter for each provided id.

**Parameters:**

* \_chainIds (uint256\[], memory): Chain ids
* \_crossChainFees (uint256\[], memory): User-provided fees

**Returns:**

* totalNativeFee (uint256): Total native fee

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:**

* `_crossChainFees.length < _chainIds.length` — `Panic(0x32)`
* `globalFixedNativeFee()` call fails — may revert per deBridge implementation (bubbled)

**Overrides:** None

**Function Calls:**

* [lockChainGateStorage()](#lockchaingatestorage-lcg1) — LockChainGate, internal
* [\_getDeBridgeChainNativeFee(LCGStorage,uint256,uint256)](#_getdebridgechainnativefee-lcg1) — LockChainGate, internal

**Called by:**

* [calculateCrossChainCreateRefFee(uint256\[\],uint256\[\])](#calculatecrosschaincreatereffee-clbm1) — CryptoLegacyBuildManager

**Gas / Complexity note:** O(n) by `_chainIds.length`

**Example:** Used by FeeRegistry to pre-aggregate native fees.

***

### isNftLocked (LCG1)

**Contract/Library:** LockChainGate

**Description:** Returns whether a holder has a locked NFT.

**Detailed Description:** Delegates to internal `_isNftLocked`.

**Parameters:**

* \_holder (address): Holder address

**Returns:**

* locked (bool): True if locked

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [lockChainGateStorage()](#lockchaingatestorage-lcg1) — LockChainGate, internal
* [\_isNftLocked(LCGStorage,address)](#_isnftlocked-lcg1) — LockChainGate, internal

**Called by:**

* [isLifetimeNftLocked(address)](#islifetimenftlocked-clbm1) — CryptoLegacyBuildManager

**Gas / Complexity note:** O(1)

**Example:** UI badge shows lifetime status.

***

### \_isNftLocked (LCG1)

**Contract/Library:** LockChainGate

**Description:** Internal check if a holder has a locked token id.

**Detailed Description:** Returns `ls.lockedNft_holder.tokenId != 0`.

**Parameters:**

* ls ([LCGStorage](https://docs.cryptolegacy.app/documentation/data-structures-reference#lcgstorage-ilcg1-s1), storage): Storage pointer
* \_holder (address): Holder

**Returns:**

* locked (bool): True if locked

**Modifiers / Visibility / Mutability:**

* internal view

**Access Control:**

* Unrestricted (internal)

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:**

* [isNftLocked(address)](#isnftlocked-lcg1) — LockChainGate
* [isNftLockedAndUpdate(address)](#isnftlockedandupdate-lcg1) — LockChainGate

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### isNftLockedAndUpdate (LCG1)

**Contract/Library:** LockChainGate

**Description:** Returns whether the holder has a locked NFT and refreshes lock time if expired.

**Detailed Description:** If no token locked, returns false. Otherwise ensures caller is a lock operator, the holder, or approved; if current time beyond unlock time, rewrites `lockedAt = block.timestamp`. Returns true.

**Parameters:**

* \_holder (address): Holder address

**Returns:**

* locked (bool): True if NFT locked

**Modifiers / Visibility / Mutability:**

* external nonpayable

**Access Control:**

* Lock operator, holder, or approved on token

**Side Effects:**

* May update `lockedNft_holder.lockedAt`

**Emits:** None

**Reverts if:**

* unauthorized caller — [`NotAllowed()`](https://docs.cryptolegacy.app/documentation/errors-reference#notallowed-ilcg1)

**Overrides:** None

**Function Calls:**

* [lockChainGateStorage()](#lockchaingatestorage-lcg1) — LockChainGate, internal
* [\_isNftLocked(LCGStorage,address)](#_isnftlocked-lcg1) — LockChainGate, internal
* [\_getLockedUntil(LCGStorage,address)](#_getlockeduntil-lcg1) — LockChainGate, internal

**Called by:**

* [\_getAndPayBuildFee(bytes8,uint256,uint256\[\],uint256\[\])](#_getandpaybuildfee-clbm1) — CryptoLegacyBuildManager
* [isLifetimeNftLockedAndUpdate(address)](#islifetimenftlockedandupdate-clbm1) — CryptoLegacyBuildManager

**Gas / Complexity note:** O(1)

**Example:** Called by operators to keep lifetime status fresh.

***

### getChainId (LCG1)

**Contract/Library:** LockChainGate

**Description:** Returns the effective chain id (custom or EVM).

**Detailed Description:** If `customChainId` set, returns it; else returns `chainid()` opcode value.

**Parameters:** None

**Returns:**

* cid (uint256): Effective chain id

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [lockChainGateStorage()](#lockchaingatestorage-lcg1) — LockChainGate, internal
* [\_getChainId(LCGStorage)](#_getchainid-lcg1) — LockChainGate, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Front-end detects environment.

***

### \_getChainId (LCG1)

**Contract/Library:** LockChainGate

**Description:** Internal effective chain id getter.

**Detailed Description:** Returns `ls.customChainId` if non-zero; otherwise uses inline assembly to read `chainid`.

**Parameters:**

* ls ([LCGStorage](https://docs.cryptolegacy.app/documentation/data-structures-reference#lcgstorage-ilcg1-s1), storage): Storage pointer

**Returns:**

* cid (uint256): Effective chain id

**Modifiers / Visibility / Mutability:**

* internal view

**Access Control:**

* Unrestricted (internal)

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:**

* [\_encodeCrossCreateCustomCodeCommand(LCGStorage,address,address,bytes8,uint32,uint32)](#_encodecrosscreatecustomcodecommand-fr1) — FeeRegistry
* [\_encodeCrossUpdateCustomCodeCommand(LCGStorage,address,address,bytes8,uint32,uint32)](#_encodecrossupdatecustomcodecommand-fr1) — FeeRegistry
* [\_encodeCrossLockCommand(LCGStorage,uint256,address)](#_encodecrosslockcommand-lcg1) — LockChainGate
* [\_encodeCrossUnlockCommand(LCGStorage,uint256,address)](#_encodecrossunlockcommand-lcg1) — LockChainGate
* [\_encodeCrossUpdateOwnerCommand(LCGStorage,uint256,address)](#_encodecrossupdateownercommand-lcg1) — LockChainGate
* [getChainId()](#getchainid-lcg1) — LockChainGate

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

## MultiPermit (MP1)

### constructor (MP1)

**Contract/Library:** MultiPermit

**Description:** Deploys the MultiPermit helper contract.

**Detailed Description:** Initializes the contract with no state to set.

**Parameters:** None

**Returns:** None

**Modifiers / Visibility / Mutability:**

* constructor nonpayable

**Access Control:**

* Unrestricted (deployment only)

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Deploy with `new MultiPermit()`.

***

### approveTreasuryTokensToLegacy (MP1)

**Contract/Library:** MultiPermit

**Description:** Executes multiple ERC‑2612 `permit` approvals in a single transaction.

**Detailed Description:** Iterates over the provided array of [`PermitData`](https://docs.cryptolegacy.app/documentation/data-structures-reference#permitdata-mp1-s1) and for each entry calls the corresponding token’s `permit` method, authorizing `spender` to spend `value` from `owner` until `deadline` using the ECDSA signature `(v,r,s)`. The function does not persist any state in this contract and relies on each token’s ERC‑2612 implementation.

**Parameters:**

* \_permits ([PermitData](https://docs.cryptolegacy.app/documentation/data-structures-reference#permitdata-mp1-s1)\[], memory): Array of permit parameters, one per token approval to execute

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external nonpayable

**Access Control:**

* Unrestricted

**Side Effects:**

* For each item in \_permits, may update allowances in the respective ERC20 token contracts via `permit`

**Emits:** None

**Reverts if:**

* External call to `IERC20Permit(token).permit(owner, spender, value, deadline, v, r, s)` — may revert per token implementation (bubbled)

**Overrides:** None

**Function Calls:**

* `permit(address,address,uint256,uint256,uint8,bytes32,bytes32)` — `IERC20Permit` *(at `p.token`)*, external

**Called by:** None (entry point)

**Gas / Complexity note:** O(n) by \_permits.length

**Example:** User gathers signed permits for several tokens off‑chain, then calls `approveTreasuryTokensToLegacy(permits)` to set all allowances in one transaction.

***

## PluginsRegistry (PR1)

### constructor (PR1)

**Contract/Library:** PluginsRegistry

**Description:** Initializes ownership and sets the provided \_owner as the contract owner.

**Detailed Description:** Runs once at deployment. `Ownable()` first sets the owner to `msg.sender` and emits `OwnershipTransferred(address(0), msg.sender)`, then explicit `_transferOwnership(_owner)` hands control to the configured owner and emits `OwnershipTransferred(msg.sender, _owner)`. Cannot be called again post-deployment.

**Parameters:**

* \_owner (address): Address that will become the owner

**Returns:** None

**Modifiers / Visibility / Mutability:**

* constructor nonpayable

**Access Control:**

* Unrestricted (deployment only)

**Side Effects:**

* Sets `owner`

**Emits:**

* [OwnershipTransferred](https://docs.cryptolegacy.app/documentation/events-reference#ownershiptransferred-iclo1) — `OwnershipTransferred(address indexed previousOwner, address indexed newOwner)` (via `Ownable()` constructor)
* [OwnershipTransferred](https://docs.cryptolegacy.app/documentation/events-reference#ownershiptransferred-iclo1) — `OwnershipTransferred(address indexed previousOwner, address indexed newOwner)` (via `Ownable._transferOwnership`)

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* \_transferOwnership(address) — `Ownable`, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Deploy with `new PluginsRegistry(msg.sender)`.

***

### addPlugin (PR1)

**Contract/Library:** PluginsRegistry

**Description:** Registers a plugin and records a description block number, then emits `AddPlugin`.

**Detailed Description:** Adds \_plugin into an internal `EnumerableSet` for uniqueness; appends the current L2/L1 block number to [`pluginDescriptionBlockNumbers`](https://docs.cryptolegacy.app/documentation/data-structures-reference#plugindescriptionblocknumbers-pr1-d2)\[\_plugin] (uses `ArbSys.arbBlockNumber()` when `chainid == 42161`, else `block.number`); finally emits the registry event with the provided description.

**Parameters:**

* \_plugin (address): Plugin contract address to register
* \_description (string, memory): Human‑readable description attached at registration time

**Returns:** None

**Modifiers / Visibility / Mutability:**

* public nonpayable onlyOwner

**Access Control:**

* onlyOwner

**Side Effects:**

* Inserts \_plugin into [`pluginsList`](https://docs.cryptolegacy.app/documentation/data-structures-reference#pluginslist-pr1-d1)
* Appends a `uint64` block number to [`pluginDescriptionBlockNumbers`](https://docs.cryptolegacy.app/documentation/data-structures-reference#plugindescriptionblocknumbers-pr1-d2)\[\_plugin]

**Emits:**

* [AddPlugin](https://docs.cryptolegacy.app/documentation/events-reference#addplugin-ipr1) — `AddPlugin(address indexed plugin, string description)`.

**Reverts if:**

* caller is not owner — "Ownable: caller is not the owner"

**Overrides:** None

**Function Calls:**

* `add(address)` — `EnumerableSet.AddressSet`, internal
* [`arbBlockNumber()`](#arbblocknumber-as1) — `ArbSys` *(at `address(100)`)*, external (staticcall)

**Called by:** None (entry point)

**Gas / Complexity note:** O(1) for set insert and array push; plus log emission and minimal conditional L2/L1 block read.

**Example:** Owner calls `addPlugin(0xPlugin, "Vesting plugin v1")` to register a new plugin with an initial description.

***

### addPluginDescription (PR1)

**Contract/Library:** PluginsRegistry

**Description:** Appends a new description block number for an existing plugin and emits `AddPluginDescription`.

**Detailed Description:** Pushes the current L2/L1 block number (Arbitrum-specific `ArbSys.arbBlockNumber()` if `chainid == 42161`, else `block.number`) to [`pluginDescriptionBlockNumbers`](https://docs.cryptolegacy.app/documentation/data-structures-reference#plugindescriptionblocknumbers-pr1-d2)\[\_plugin], preserving a history of description updates; emits the corresponding event with the supplied \_description.

**Parameters:**

* \_plugin (address): Plugin contract address whose description history is extended
* \_description (string, memory): New description text to record

**Returns:** None

**Modifiers / Visibility / Mutability:**

* public nonpayable onlyOwner

**Access Control:**

* onlyOwner

**Side Effects:**

* Appends a `uint64` block number to [`pluginDescriptionBlockNumbers`](https://docs.cryptolegacy.app/documentation/data-structures-reference#plugindescriptionblocknumbers-pr1-d2)\[\_plugin]

**Emits:**

* [AddPluginDescription](https://docs.cryptolegacy.app/documentation/events-reference#addplugindescription-ipr1) — `AddPluginDescription(address indexed plugin, string description)`.

**Reverts if:**

* caller is not owner — "Ownable: caller is not the owner"

**Overrides:** None

**Function Calls:**

* [`arbBlockNumber()`](#arbblocknumber-as1) — `ArbSys` *(at `address(100)`)*, external (staticcall)

**Called by:** None (entry point)

**Gas / Complexity note:** O(1) for array push; plus event emission and conditional L2/L1 block read.

**Example:** Owner calls `addPluginDescription(0xPlugin, "Upgraded to support EIP-712 signatures")`.

***

### removePlugin (PR1)

**Contract/Library:** PluginsRegistry

**Description:** Unregisters a plugin and emits `RemovePlugin`.

**Detailed Description:** Removes \_plugin from the [`pluginsList`](https://docs.cryptolegacy.app/documentation/data-structures-reference#pluginslist-pr1-d1) set; historical [`pluginDescriptionBlockNumbers`](https://docs.cryptolegacy.app/documentation/data-structures-reference#plugindescriptionblocknumbers-pr1-d2)\[\_plugin] are preserved for auditability. Emits the removal event.

**Parameters:**

* \_plugin (address): Plugin contract address to remove

**Returns:** None

**Modifiers / Visibility / Mutability:**

* public nonpayable onlyOwner

**Access Control:**

* onlyOwner

**Side Effects:**

* Removes \_plugin from [`pluginsList`](https://docs.cryptolegacy.app/documentation/data-structures-reference#pluginslist-pr1-d1)

**Emits:**

* [RemovePlugin](https://docs.cryptolegacy.app/documentation/events-reference#removeplugin-ipr1) — `RemovePlugin(address indexed plugin)`.

**Reverts if:**

* caller is not owner — "Ownable: caller is not the owner"

**Overrides:** None

**Function Calls:**

* `remove(address)` — `EnumerableSet.AddressSet`, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1) average for set removal.

**Example:** Owner calls `removePlugin(0xPlugin)` to unregister an obsolete plugin.

***

### isPluginRegistered (PR1)

**Contract/Library:** PluginsRegistry

**Description:** Returns whether \_plugin is currently registered.

**Detailed Description:** Performs a constant‑time membership check in the internal `EnumerableSet` of plugin addresses.

**Parameters:**

* \_plugin (address): Plugin address to test

**Returns:**

* result (bool): True if \_plugin exists in the registry set; otherwise false

**Modifiers / Visibility / Mutability:**

* public view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* `contains(address)` — `EnumerableSet.AddressSet`, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1).

**Example:** UI or other contract calls `isPluginRegistered(0xPlugin)` to check inclusion.

***

### getPluginMetadata (PR1)

**Contract/Library:** PluginsRegistry

**Description:** Reads a plugin’s `name`, `version`, and its description block numbers.

**Detailed Description:** Queries the plugin contract for its human‑readable name and semantic version via `ICryptoLegacyPlugin`, and returns the stored [`pluginDescriptionBlockNumbers`](https://docs.cryptolegacy.app/documentation/data-structures-reference#plugindescriptionblocknumbers-pr1-d2)\[\_plugin]. Does not mutate state.

**Parameters:**

* \_plugin (address): Target plugin contract to query

**Returns:**

* name (string, memory): Plugin name returned by the plugin itself
* version (uint16): Plugin version returned by the plugin itself
* descriptionBlockNumbers (uint64\[], memory): Recorded block numbers when descriptions were added in this registry

**Modifiers / Visibility / Mutability:**

* public view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:**

* ICryptoLegacyPlugin(\_plugin).getPluginName() — may revert per plugin implementation (bubbled)
* ICryptoLegacyPlugin(\_plugin).getPluginVer() — may revert per plugin implementation (bubbled)

**Overrides:** None

**Function Calls:**

* `getPluginName()` — `ICryptoLegacyPlugin` *(at \_plugin)*, external (staticcall)
* `getPluginVer()` — `ICryptoLegacyPlugin` *(at \_plugin)*, external (staticcall)

**Called by:**

* [getPluginInfoList()](#getplugininfolist-pr1) — PluginsRegistry

**Gas / Complexity note:** O(1) for registry reads; plus two external (staticcall) reads to the plugin.

**Example:** Front‑end calls `getPluginMetadata(0xPlugin)` to display plugin name/version alongside description history.

***

### getPluginDescriptionBlockNumbers (PR1)

**Contract/Library:** PluginsRegistry

**Description:** Returns the full array of description block numbers for \_plugin.

**Detailed Description:** Reads and returns the `uint64[]` history of block numbers at which descriptions were recorded for the given plugin address.

**Parameters:**

* \_plugin (address): Plugin whose description timeline is requested

**Returns:**

* blockNumbers (uint64\[], memory): Array of L2/L1 block numbers corresponding to description additions

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:** None (entry point)

**Gas / Complexity note:** O(n) by [`pluginDescriptionBlockNumbers`](https://docs.cryptolegacy.app/documentation/data-structures-reference#plugindescriptionblocknumbers-pr1-d2)\[\_plugin].length to allocate and return the array.

**Example:** Indexers call `getPluginDescriptionBlockNumbers(0xPlugin)` to rebuild a description change timeline.

***

### getPluginAddressList (PR1)

**Contract/Library:** PluginsRegistry

**Description:** Returns an array of all registered plugin addresses.

**Detailed Description:** Enumerates the internal set and returns a copy as a dynamic array for off‑chain consumption or iteration by callers.

**Parameters:** None

**Returns:**

* plugins (address\[], memory): Array of registered plugin addresses

**Modifiers / Visibility / Mutability:**

* public view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* `values()` — `EnumerableSet.AddressSet`, internal

**Called by:**

* [getPluginInfoList()](#getplugininfolist-pr1) — PluginsRegistry

**Gas / Complexity note:** O(n) by number of registered plugins (copying set contents).

**Example:** Explorer calls `getPluginAddressList()` to show all plugins on a dashboard.

***

### getPluginInfoList (PR1)

**Contract/Library:** PluginsRegistry

**Description:** Aggregates metadata for all registered plugins into an array of [`PluginInfo`](https://docs.cryptolegacy.app/documentation/data-structures-reference#plugininfo-ipr1-s1).

**Detailed Description:** Fetches the address list via `getPluginAddressList()`, then for each address calls `getPluginMetadata(address)` to collect `(name, version, descriptionBlockNumbers)` and builds an array of [`PluginInfo`](https://docs.cryptolegacy.app/documentation/data-structures-reference#plugininfo-ipr1-s1). Returns the assembled list.

**Parameters:** None

**Returns:**

* plugins ([PluginInfo](https://docs.cryptolegacy.app/documentation/data-structures-reference#plugininfo-ipr1-s1)\[], memory): Array of plugin info entries

**Modifiers / Visibility / Mutability:**

* public view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:**

* `ICryptoLegacyPlugin.getPluginName()` — may revert per plugin implementation (bubbled via `getPluginMetadata`)
* `ICryptoLegacyPlugin.getPluginVer()` — may revert per plugin implementation (bubbled via `getPluginMetadata`)

**Overrides:** None

**Function Calls:**

* [getPluginAddressList()](#getpluginaddresslist-pr1) — PluginsRegistry, internal
* [getPluginMetadata(address)](#getpluginmetadata-pr1) — PluginsRegistry, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(n) by the number of registered plugins; additionally performs 2 external (staticcall) reads per plugin via `getPluginMetadata`.

**Example:** Front‑end queries `getPluginInfoList()` to render a full plugin directory with names, versions, and update timelines.

***

## ProxyBuilder (PB1)

### constructor (PB1)

**Contract/Library:** ProxyBuilder

**Description:** Initializes the builder with an optional ProxyAdmin and sets the owner.

**Detailed Description:** If \_proxyAdmin is not the zero address, stores it as the [`proxyAdmin`](https://docs.cryptolegacy.app/documentation/data-structures-reference#proxyadmin-pb1-d1). `Ownable()` first sets the owner to `msg.sender` and emits `OwnershipTransferred(address(0), msg.sender)`, then explicit `_transferOwnership(_owner)` hands control to the configured owner and emits `OwnershipTransferred(msg.sender, _owner)`. Designed to set up upgradeable proxy deployments managed by `ProxyAdmin`.

**Parameters:**

* \_owner (address): Address to receive contract ownership
* \_proxyAdmin (address): Optional ProxyAdmin contract to control proxies

**Returns:** None

**Modifiers / Visibility / Mutability:**

* constructor nonpayable

**Access Control:**

* Unrestricted (deployment only)

**Side Effects:**

* Sets [`proxyAdmin`](https://docs.cryptolegacy.app/documentation/data-structures-reference#proxyadmin-pb1-d1) (only when \_proxyAdmin is non-zero)
* Sets `owner`

**Emits:**

* [OwnershipTransferred](https://docs.cryptolegacy.app/documentation/events-reference#ownershiptransferred-iclo1) — `OwnershipTransferred(address indexed previousOwner, address indexed newOwner)` (via `Ownable()` constructor)
* [OwnershipTransferred](https://docs.cryptolegacy.app/documentation/events-reference#ownershiptransferred-iclo1) — `OwnershipTransferred(address indexed previousOwner, address indexed newOwner)` (via `Ownable._transferOwnership`)

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* \_transferOwnership(address) — `Ownable`, internal

**Called by:**

None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Deploy with `new ProxyBuilder(deployer, proxyAdminAddr)`.

***

### setProxyAdmin (PB1)

**Contract/Library:** ProxyBuilder

**Description:** Updates the ProxyAdmin controller address.

**Detailed Description:** Sets the [`proxyAdmin`](https://docs.cryptolegacy.app/documentation/data-structures-reference#proxyadmin-pb1-d1) used for newly built proxies and emits an event for off-chain tracking.

**Parameters:**

* \_proxyAdmin (address): New ProxyAdmin contract address

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external nonpayable onlyOwner

**Access Control:**

* onlyOwner

**Side Effects:**

* Updates [`proxyAdmin`](https://docs.cryptolegacy.app/documentation/data-structures-reference#proxyadmin-pb1-d1)

**Emits:**

* [SetProxyAdmin](https://docs.cryptolegacy.app/documentation/events-reference#setproxyadmin-pb1) — `SetProxyAdmin(address proxyAdmin)`

**Reverts if:**

* Caller is not the owner — "Ownable: caller is not the owner"

**Overrides:** None

**Function Calls:** None

**Called by:**

None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Owner calls `setProxyAdmin(newAdmin)` to rotate proxy admin control.

***

### build (PB1)

**Contract/Library:** ProxyBuilder

**Description:** Deploys a `TransparentUpgradeableProxy` deterministically via CREATE3.

**Detailed Description:** Constructs proxy creation bytecode with the provided implementation and initializer data, deploys it to a deterministic address using `LibCreate3.create3`, verifies the deployed address equals \_create3Address, emits `Build`, and returns the proxy address.

**Parameters:**

* \_create3Address (address): Expected deterministic proxy address
* \_create3Salt (bytes32): Salt used with CREATE3
* \_implementation (address): Initial implementation logic contract
* \_initData (bytes, calldata): Initialization calldata to execute in proxy constructor

**Returns:**

* proxy (address): Address of the deployed `TransparentUpgradeableProxy`

**Modifiers / Visibility / Mutability:**

* external nonpayable onlyOwner

**Access Control:**

* onlyOwner

**Side Effects:**

* Deploys a new `TransparentUpgradeableProxy` using CREATE3

**Emits:**

* [Build](https://docs.cryptolegacy.app/documentation/events-reference#build-pb1) — `Build(address proxy, address implementation)`

**Reverts if:**

* Caller is not the owner — "Ownable: caller is not the owner"
* Deployed address differs from \_create3Address — [`AddressMismatch()`](https://docs.cryptolegacy.app/documentation/errors-reference#addressmismatch-pb1)
* CREATE3 proxy creation fails — [`LibCreate3.ErrorCreatingProxy()`](https://docs.cryptolegacy.app/documentation/errors-reference#errorcreatingproxy-lc31) (bubbled)
* Target address already exists for the given salt — [`LibCreate3.TargetAlreadyExists()`](https://docs.cryptolegacy.app/documentation/errors-reference#targetalreadyexists-lc31) (bubbled)
* Child contract creation fails — [`LibCreate3.ErrorCreatingContract()`](https://docs.cryptolegacy.app/documentation/errors-reference#errorcreatingcontract-lc31) (bubbled)

**Overrides:** None

**Function Calls:**

* [proxyBytecode(address,bytes)](#proxybytecode-pb1) — `ProxyBuilder`, internal
* [create3(bytes32,bytes)](#create3bytes32bytes-lc31) — `LibCreate3`, internal

**Called by:**

None (entry point)

**Gas / Complexity note:** O(n) by creation bytecode size and \_initData.length; CREATE3 deployment dominates cost.

**Example:**

1. Compute predicted address with [computeAddress(bytes32)](#computeaddress-pb1) → `pred`.
2. Owner calls `build(pred, salt, impl, initCalldata)` to deploy the proxy at `pred`.

***

### proxyBytecode (PB1)

**Contract/Library:** ProxyBuilder

**Description:** Produces creation bytecode for `TransparentUpgradeableProxy`.

**Detailed Description:** Concatenates the proxy’s `creationCode` with ABI-encoded constructor args: `(implementation, proxyAdmin, initData)`. Used by [build](#build-pb1).

**Parameters:**

* \_implementation (address): Implementation logic contract
* \_data (bytes, memory): Initialization calldata for proxy constructor

**Returns:**

* bytecode (bytes, memory): Fully encoded creation bytecode for deployment

**Modifiers / Visibility / Mutability:**

* public view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:**

* [build(address,bytes32,address,bytes)](#build-pb1) — ProxyBuilder

**Gas / Complexity note:** O(n) by \_data.length (encoding cost).

**Example:** Not applicable

***

### computeAddress (PB1)

**Contract/Library:** ProxyBuilder

**Description:** Computes the deterministic CREATE3 address for a given salt.

**Detailed Description:** Returns the address that `LibCreate3.create3` would deploy to for \_salt, useful for precomputing target proxy addresses.

**Parameters:**

* \_salt (bytes32): Salt used for address computation

**Returns:**

* predicted (address): Deterministic address derived from \_salt

**Modifiers / Visibility / Mutability:**

* public view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [addressOf(bytes32)](#addressof-lc31) — `LibCreate3`, internal

**Called by:**

None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

## ProxyBuilderAdmin (PBA1)

### constructor (PBA1)

**Contract/Library:** ProxyBuilderAdmin

**Description:** Initializes the ProxyBuilderAdmin and sets the initial owner.

**Detailed Description:** Executed once at deployment. Calls the inherited \_transferOwnership to set the initial owner address, which governs future admin actions. Emits `OwnershipTransferred` from the OpenZeppelin `Ownable` base.

**Parameters:**

* \_owner (address): Address to receive ownership of the ProxyBuilderAdmin

**Returns:** None

**Modifiers / Visibility / Mutability:**

* constructor nonpayable

**Access Control:**

* Unrestricted (deployment only)

**Side Effects:**

* Sets `owner` (from `Ownable`)

**Emits:**

* [OwnershipTransferred](https://docs.cryptolegacy.app/documentation/events-reference#ownershiptransferred-iclo1) — `OwnershipTransferred(address indexed previousOwner, address indexed newOwner)`

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* \_transferOwnership(address) — `Ownable`, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Deploy with `new ProxyBuilderAdmin(msg.sender)`.

***

## SignatureRoleTimelock (SRT1)

### constructor (SRT1)

**Contract/Library:** SignatureRoleTimelock

**Description:** Initializes admin role, seeds role accounts, and installs initial signature roles with timelocks.

**Detailed Description:** Grants [`ADMIN_ROLE`](https://docs.cryptolegacy.app/documentation/data-structures-reference#admin_role-srt1-d1) to \_adminAccount via internal role helper. Registers signature roles (with \_adminTimelock) for privileged self-managed functions: `setRoleAccounts`, `addSignatureRoleList`, `removeSignatureRoleList`, and `setMaxExecutionPeriod`. Iterates \_roles to add initial role accounts and \_sigs to configure target signatures with required roles and timelocks.

**Parameters:**

* \_adminTimelock (uint128): Timelock (seconds) applied to admin-managed functions
* \_roles ([ISignatureRoleTimelock.AddressRoleInput](https://docs.cryptolegacy.app/documentation/data-structures-reference#addressroleinput-isrt1-s2)\[], memory): Initial role account assignments
* \_sigs ([SignatureToAdd](https://docs.cryptolegacy.app/documentation/data-structures-reference#signaturetoadd-isrt1-s4)\[], memory): Initial signature-role bindings to add
* \_adminAccount (address): Account to grant [`ADMIN_ROLE`](https://docs.cryptolegacy.app/documentation/data-structures-reference#admin_role-srt1-d1)

**Returns:** None

**Modifiers / Visibility / Mutability:**

* constructor nonpayable

**Access Control:**

* Unrestricted (deployment only)

**Side Effects:**

* Grants [`ADMIN_ROLE`](https://docs.cryptolegacy.app/documentation/data-structures-reference#admin_role-srt1-d1)
* Updates [`roleAccounts`](https://docs.cryptolegacy.app/documentation/data-structures-reference#roleaccounts-srt1-d6)
* Updates [`signatureRoles`](https://docs.cryptolegacy.app/documentation/data-structures-reference#signatureroles-srt1-d7), [`targetSigs`](https://docs.cryptolegacy.app/documentation/data-structures-reference#targetsigs-srt1-d8), [`targets`](https://docs.cryptolegacy.app/documentation/data-structures-reference#targets-srt1-d9)

**Emits:**

* [AddRoleAccount](https://docs.cryptolegacy.app/documentation/events-reference#addroleaccount-isrt1) — `AddRoleAccount(bytes32 indexed role, address indexed account)`
* [AddSignatureRole](https://docs.cryptolegacy.app/documentation/events-reference#addsignaturerole-isrt1) — `AddSignatureRole(address indexed target, bytes4 indexed signature, bytes32 indexed role, uint256 timelock)`
* [AddTarget](https://docs.cryptolegacy.app/documentation/events-reference#addtarget-isrt1) — `AddTarget(address indexed target)`

**Reverts if:**

* \_adminAccount already holds [`ADMIN_ROLE`](https://docs.cryptolegacy.app/documentation/data-structures-reference#admin_role-srt1-d1) — [`AlreadyHaveRole()`](https://docs.cryptolegacy.app/documentation/errors-reference#alreadyhaverole-isrt1)
* \_adminTimelock > [`MAX_TIMELOCK_DURATION`](https://docs.cryptolegacy.app/documentation/data-structures-reference#max_timelock_duration-srt1-d2) — [`OutOfTimelockBounds(uint256)`](https://docs.cryptolegacy.app/documentation/errors-reference#outoftimelockbounds-isrt1)
* \_rolesi.newAccount already assigned to \_rolesi.role — [`AlreadyHaveRole()`](https://docs.cryptolegacy.app/documentation/errors-reference#alreadyhaverole-isrt1)
* \_sigsi.role has no members (was not provisioned via \_roles) — [`RoleDontExist()`](https://docs.cryptolegacy.app/documentation/errors-reference#roledontexist-isrt1)
* Signature binding for \_sigsi.target/\_sigsi.signature already exists — [`SignatureAlreadyExists()`](https://docs.cryptolegacy.app/documentation/errors-reference#signaturealreadyexists-isrt1)
* \_sigsi.timelock > [`MAX_TIMELOCK_DURATION`](https://docs.cryptolegacy.app/documentation/data-structures-reference#max_timelock_duration-srt1-d2) — [`OutOfTimelockBounds(uint256)`](https://docs.cryptolegacy.app/documentation/errors-reference#outoftimelockbounds-isrt1)

**Overrides:** None

**Function Calls:**

* [\_addRoleAccount(bytes32,address)](#_addroleaccount-srt1) — SignatureRoleTimelock, internal
* [\_addSignatureRole(address,bytes4,bytes32,uint128)](#_addsignaturerole-srt1) — SignatureRoleTimelock, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(n\_roles + n\_sigs)

**Example:** Deploy with initial roles and signatures configured.

***

### modifier onlyCurrentAddress (SRT1)

**Contract/Library:** SignatureRoleTimelock

**Description:** Restricts execution to calls initiated by the contract itself.

**Detailed Description:** Ensures `msg.sender == address(this)` for functions guarded by this modifier, enforcing that such functions can only be reached via a scheduled self-call.

**Parameters:** None

**Returns:** None

**Modifiers / Visibility / Mutability:**

* modifier nonpayable

**Access Control:**

* Enforced by the modifier itself

**Side Effects:** None

**Emits:** None

**Reverts if:**

* `msg.sender != address(this)` — [`CallerNotCurrentAddress()`](https://docs.cryptolegacy.app/documentation/errors-reference#callernotcurrentaddress-isrt1)

**Overrides:** None

**Function Calls:** None

**Called by:**

* [setMaxExecutionPeriod](#setmaxexecutionperiod-srt1) — SignatureRoleTimelock
* [setRoleAccounts](#setroleaccounts-srt1) — SignatureRoleTimelock
* [addSignatureRoleList](#addsignaturerolelist-srt1) — SignatureRoleTimelock
* [removeSignatureRoleList](#removesignaturerolelist-srt1) — SignatureRoleTimelock

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### setMaxExecutionPeriod (SRT1)

**Contract/Library:** SignatureRoleTimelock

**Description:** Updates the maximum allowed execution window after timelock expiry.

**Detailed Description:** Sets [`maxExecutionPeriod`](https://docs.cryptolegacy.app/documentation/data-structures-reference#maxexecutionperiod-srt1-d5) to \_maxExecutionPeriod when invoked via self-call. Ensures the value lies within [`MAX_EXECUTION_PERIOD_LOWER_BOUND`](https://docs.cryptolegacy.app/documentation/data-structures-reference#max_execution_period_lower_bound-srt1-d3), [`MAX_EXECUTION_PERIOD_UPPER_BOUND`](https://docs.cryptolegacy.app/documentation/data-structures-reference#max_execution_period_upper_bound-srt1-d4) and emits an event.

**Parameters:**

* \_maxExecutionPeriod (uint128): Max seconds after `executeAfter` during which a call remains valid

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external nonpayable onlyCurrentAddress

**Access Control:**

* Only self-call (enforced by `onlyCurrentAddress`)

**Side Effects:**

* Updates [`maxExecutionPeriod`](https://docs.cryptolegacy.app/documentation/data-structures-reference#maxexecutionperiod-srt1-d5)

**Emits:**

* [SetMaxExecutionPeriod](https://docs.cryptolegacy.app/documentation/events-reference#setmaxexecutionperiod-isrt1) — `SetMaxExecutionPeriod(uint128 indexed maxExecutionPeriod)`

**Reverts if:**

* `msg.sender != address(this)` — [`CallerNotCurrentAddress()`](https://docs.cryptolegacy.app/documentation/errors-reference#callernotcurrentaddress-isrt1)
* \_maxExecutionPeriod outside bounds — [`OutOfMaxExecutionPeriodBounds(uint256,uint256)`](https://docs.cryptolegacy.app/documentation/errors-reference#outofmaxexecutionperiodbounds-isrt1)

**Overrides:** None

**Function Calls:** None

**Called by:**

* [\_executeCall(bytes32)](#_executecall-srt1) — SignatureRoleTimelock

**Gas / Complexity note:** O(1)

**Example:** Schedule-and-execute a self-call to adjust the execution window.

***

### setRoleAccounts (SRT1)

**Contract/Library:** SignatureRoleTimelock

**Description:** Batch adds, removes, or replaces role accounts.

**Detailed Description:** For each [`AddressRoleInput`](https://docs.cryptolegacy.app/documentation/data-structures-reference#addressroleinput-isrt1-s2) in \_list: if `prevAccount == address(0)` adds `newAccount`; else if `newAccount == address(0)` removes `prevAccount`; otherwise replaces `prevAccount` with `newAccount`. Emits corresponding add/remove events. Self-call only.

**Parameters:**

* \_list ([AddressRoleInput](https://docs.cryptolegacy.app/documentation/data-structures-reference#addressroleinput-isrt1-s2)\[], memory): Role account mutations (add/remove/replace)

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external nonpayable onlyCurrentAddress

**Access Control:**

* Only self-call (enforced by `onlyCurrentAddress`)

**Side Effects:**

* Updates [`roleAccounts`](https://docs.cryptolegacy.app/documentation/data-structures-reference#roleaccounts-srt1-d6)
* Updates AccessControl roles (grant/revoke)

**Emits:**

* [AddRoleAccount](https://docs.cryptolegacy.app/documentation/events-reference#addroleaccount-isrt1) — `AddRoleAccount(bytes32 indexed role, address indexed account)`
* [RemoveRoleAccount](https://docs.cryptolegacy.app/documentation/events-reference#removeroleaccount-isrt1) — `RemoveRoleAccount(bytes32 indexed role, address indexed account)`

**Reverts if:**

* `msg.sender != address(this)` — [`CallerNotCurrentAddress()`](https://docs.cryptolegacy.app/documentation/errors-reference#callernotcurrentaddress-isrt1)
* Adding an existing account — [`AlreadyHaveRole()`](https://docs.cryptolegacy.app/documentation/errors-reference#alreadyhaverole-isrt1)
* Removing a non-member — [`DoesntHaveRole()`](https://docs.cryptolegacy.app/documentation/errors-reference#doesnthaverole-isrt1)
* Removal index mismatch — [`IncorrectRoleIndex()`](https://docs.cryptolegacy.app/documentation/errors-reference#incorrectroleindex-isrt1)

**Overrides:** None

**Function Calls:**

* [\_addRoleAccount(bytes32,address)](#_addroleaccount-srt1) — SignatureRoleTimelock, internal
* [\_removeRoleAccount(bytes32,address)](#_removeroleaccount-srt1) — SignatureRoleTimelock, internal

**Called by:**

* [\_executeCall(bytes32)](#_executecall-srt1) — SignatureRoleTimelock

**Gas / Complexity note:** O(n) by \_list.length

**Example:** Schedule setRoleAccounts({role: [`ADMIN_ROLE`](https://docs.cryptolegacy.app/documentation/data-structures-reference#admin_role-srt1-d1), prevAccount: old, newAccount: neu}) for timed replacement.

***

### \_addRoleAccount (SRT1)

**Contract/Library:** SignatureRoleTimelock

**Description:** Adds an account to a role and grants it in AccessControl.

**Detailed Description:** Reverts if the account already has the role. Appends to [`roleAccounts`](https://docs.cryptolegacy.app/documentation/data-structures-reference#roleaccounts-srt1-d6)\[\_role] and calls \_grantRole. Emits `AddRoleAccount`.

**Parameters:**

* \_role (bytes32): Role identifier
* \_account (address): Account to add

**Returns:** None

**Modifiers / Visibility / Mutability:**

* internal nonpayable

**Access Control:**

* Internal helper used exclusively by this plugin

**Side Effects:**

* Updates [`roleAccounts`](https://docs.cryptolegacy.app/documentation/data-structures-reference#roleaccounts-srt1-d6)\[\_role]
* Grants AccessControl role

**Emits:**

* [AddRoleAccount](https://docs.cryptolegacy.app/documentation/events-reference#addroleaccount-isrt1) — `AddRoleAccount(bytes32 indexed role, address indexed account)`

**Reverts if:**

* hasRole(\_role, \_account) — [`AlreadyHaveRole()`](https://docs.cryptolegacy.app/documentation/errors-reference#alreadyhaverole-isrt1)

**Overrides:** None

**Function Calls:**

* \_grantRole(bytes32,address) — AccessControl, internal

**Called by:**

* [constructor](#constructor-srt1) — SignatureRoleTimelock
* [setRoleAccounts](#setroleaccounts-srt1) — SignatureRoleTimelock

**Gas / Complexity note:** O(1) amortized

**Example:** Not applicable

***

### \_getAddressIndex (SRT1)

**Contract/Library:** SignatureRoleTimelock

**Description:** Finds index of address in array or returns `type(uint256).max`.

**Detailed Description:** Linear scan over \_list to locate \_addr. Used by role/target removal helpers.

**Parameters:**

* \_list (address\[], memory): Address list to search
* \_addr (address): Address to find

**Returns:**

* index (uint): Found index or `type(uint256).max`

**Modifiers / Visibility / Mutability:**

* internal pure

**Access Control:**

* Unrestricted (internal)

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:**

* [\_removeRoleAccount](#_removeroleaccount-srt1) — SignatureRoleTimelock
* [\_removeSignatureRole](#_removesignaturerole-srt1) — SignatureRoleTimelock
* [\_addSignatureRole(address,bytes4,bytes32,uint128)](#_addsignaturerole-srt1) — SignatureRoleTimelock

**Gas / Complexity note:** O(n)

**Example:** Not applicable

***

### \_getBytes4Index (SRT1)

**Contract/Library:** SignatureRoleTimelock

**Description:** Finds index of bytes4 selector in array or returns `type(uint256).max`.

**Detailed Description:** Linear scan over \_list to locate \_hash. Used when removing signature selectors.

**Parameters:**

* \_list (bytes4\[], memory): Selector list to search
* \_hash (bytes4): Selector to find

**Returns:**

* index (uint): Found index or `type(uint256).max`

**Modifiers / Visibility / Mutability:**

* internal pure

**Access Control:**

* Unrestricted (internal)

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:**

* [\_removeSignatureRole](#_removesignaturerole-srt1) — SignatureRoleTimelock

**Gas / Complexity note:** O(n)

**Example:** Not applicable

***

### \_removeRoleAccount (SRT1)

**Contract/Library:** SignatureRoleTimelock

**Description:** Removes an account from a role and revokes it in AccessControl.

**Detailed Description:** Checks membership, finds index, swaps with last and pops. Calls \_revokeRole and emits `RemoveRoleAccount`.

**Parameters:**

* \_role (bytes32): Role identifier
* \_account (address): Account to remove

**Returns:** None

**Modifiers / Visibility / Mutability:**

* internal nonpayable

**Access Control:**

* Unrestricted (internal)

**Side Effects:**

* Updates [`roleAccounts`](https://docs.cryptolegacy.app/documentation/data-structures-reference#roleaccounts-srt1-d6)\[\_role]
* Revokes AccessControl role

**Emits:**

* [RemoveRoleAccount](https://docs.cryptolegacy.app/documentation/events-reference#removeroleaccount-isrt1) — `RemoveRoleAccount(bytes32 indexed role, address indexed account)`

**Reverts if:**

* !hasRole(\_role, \_account) — [`DoesntHaveRole()`](https://docs.cryptolegacy.app/documentation/errors-reference#doesnthaverole-isrt1)
* Index check fails — [`IncorrectRoleIndex()`](https://docs.cryptolegacy.app/documentation/errors-reference#incorrectroleindex-isrt1)

**Overrides:** None

**Function Calls:**

* [\_getAddressIndex(address\[\],address)](#_getaddressindex-srt1) — SignatureRoleTimelock, internal
* \_revokeRole(bytes32,address) — AccessControl, internal

**Called by:**

* [setRoleAccounts](#setroleaccounts-srt1) — SignatureRoleTimelock

**Gas / Complexity note:** O(n) by [`roleAccounts`](https://docs.cryptolegacy.app/documentation/data-structures-reference#roleaccounts-srt1-d6)\[\_role].length

**Example:** Not applicable

***

### renounceRole (SRT1)

**Contract/Library:** SignatureRoleTimelock

**Description:** Disabled AccessControl function; always reverts.

**Detailed Description:** Overrides `AccessControl.renounceRole` to hard-disable it, enforcing role changes through scheduled admin actions only.

**Parameters:**

* \_role (bytes32): Role identifier
* \_account (address): Account

**Returns:** None

**Modifiers / Visibility / Mutability:**

* public pure override

**Access Control:**

* Not applicable

**Side Effects:** None

**Emits:** None

**Reverts if:**

* Always — [`DisabledFunction()`](https://docs.cryptolegacy.app/documentation/errors-reference#disabledfunction-isrt1)

**Overrides:**

* `AccessControl.renounceRole`

**Function Calls:** None

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### addSignatureRoleList (SRT1)

**Contract/Library:** SignatureRoleTimelock

**Description:** Batch-assigns signature roles to target functions.

**Detailed Description:** Self-call only. For each [`SignatureToAdd`](https://docs.cryptolegacy.app/documentation/data-structures-reference#signaturetoadd-isrt1-s4), validates role existence and timelock bounds, then adds binding of `(target, selector) → (role, timelock)`. Adds `target` to the global list on first binding. Emits for every entry.

**Parameters:**

* \_sigs ([SignatureToAdd](https://docs.cryptolegacy.app/documentation/data-structures-reference#signaturetoadd-isrt1-s4)\[], memory): List of `{target, signature, role, timelock}` entries to add

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external nonpayable onlyCurrentAddress

**Access Control:**

* Only self-call (enforced by `onlyCurrentAddress`)

**Side Effects:**

* Updates [`signatureRoles`](https://docs.cryptolegacy.app/documentation/data-structures-reference#signatureroles-srt1-d7), [`targetSigs`](https://docs.cryptolegacy.app/documentation/data-structures-reference#targetsigs-srt1-d8), [`targets`](https://docs.cryptolegacy.app/documentation/data-structures-reference#targets-srt1-d9)

**Emits:**

* [AddSignatureRole](https://docs.cryptolegacy.app/documentation/events-reference#addsignaturerole-isrt1) — `AddSignatureRole(address indexed target, bytes4 indexed signature, bytes32 indexed role, uint256 timelock)`
* [AddTarget](https://docs.cryptolegacy.app/documentation/events-reference#addtarget-isrt1) — `AddTarget(address indexed target)` (when first selector for target)

**Reverts if:**

* `msg.sender != address(this)` — [`CallerNotCurrentAddress()`](https://docs.cryptolegacy.app/documentation/errors-reference#callernotcurrentaddress-isrt1)
* Role has no accounts — [`RoleDontExist()`](https://docs.cryptolegacy.app/documentation/errors-reference#roledontexist-isrt1)
* Binding exists — [`SignatureAlreadyExists()`](https://docs.cryptolegacy.app/documentation/errors-reference#signaturealreadyexists-isrt1)
* \_timelock > [`MAX_TIMELOCK_DURATION`](https://docs.cryptolegacy.app/documentation/data-structures-reference#max_timelock_duration-srt1-d2) — [`OutOfTimelockBounds(uint256)`](https://docs.cryptolegacy.app/documentation/errors-reference#outoftimelockbounds-isrt1)

**Overrides:** None

**Function Calls:**

* [\_addSignatureRole(address,bytes4,bytes32,uint128)](#_addsignaturerole-srt1) — SignatureRoleTimelock, internal

**Called by:**

* [\_executeCall(bytes32)](#_executecall-srt1) — SignatureRoleTimelock

**Gas / Complexity note:** O(n) by \_sigs.length

**Example:** Schedule a batch to authorize admin-controlled selectors on an external target.

***

### \_addSignatureRole (SRT1)

**Contract/Library:** SignatureRoleTimelock

**Description:** Adds a single `(target, selector)` signature role binding.

**Detailed Description:** Verifies role existence and uniqueness; clamps \_timelock to `1` if `0`; writes [`signatureRoles`](https://docs.cryptolegacy.app/documentation/data-structures-reference#signatureroles-srt1-d7)\[targetSignature], updates [`targetSigs`](https://docs.cryptolegacy.app/documentation/data-structures-reference#targetsigs-srt1-d8)\[target], and appends new `target` to [`targets`](https://docs.cryptolegacy.app/documentation/data-structures-reference#targets-srt1-d9) if needed. Emits events.

**Parameters:**

* \_target (address): Target contract
* \_signature (bytes4): Function selector
* \_role (bytes32): Required role
* \_timelock (uint128): Per-signature timelock

**Returns:** None

**Modifiers / Visibility / Mutability:**

* internal nonpayable

**Access Control:**

* Unrestricted (internal)

**Side Effects:**

* Updates [`signatureRoles`](https://docs.cryptolegacy.app/documentation/data-structures-reference#signatureroles-srt1-d7), [`targetSigs`](https://docs.cryptolegacy.app/documentation/data-structures-reference#targetsigs-srt1-d8), [`targets`](https://docs.cryptolegacy.app/documentation/data-structures-reference#targets-srt1-d9)

**Emits:**

* [AddSignatureRole](https://docs.cryptolegacy.app/documentation/events-reference#addsignaturerole-isrt1) — `AddSignatureRole(address indexed target, bytes4 indexed signature, bytes32 indexed role, uint256 timelock)`
* [AddTarget](https://docs.cryptolegacy.app/documentation/events-reference#addtarget-isrt1) — `AddTarget(address indexed target)` (when first selector for target)

**Reverts if:**

* Role absent — [`RoleDontExist()`](https://docs.cryptolegacy.app/documentation/errors-reference#roledontexist-isrt1)
* Binding exists — [`SignatureAlreadyExists()`](https://docs.cryptolegacy.app/documentation/errors-reference#signaturealreadyexists-isrt1)
* \_timelock > [`MAX_TIMELOCK_DURATION`](https://docs.cryptolegacy.app/documentation/data-structures-reference#max_timelock_duration-srt1-d2) — [`OutOfTimelockBounds(uint256)`](https://docs.cryptolegacy.app/documentation/errors-reference#outoftimelockbounds-isrt1)

**Overrides:** None

**Function Calls:**

* [\_getAddressIndex(address\[\],address)](#_getaddressindex-srt1) — SignatureRoleTimelock, internal

**Called by:**

* [constructor](#constructor-srt1) — SignatureRoleTimelock
* [addSignatureRoleList](#addsignaturerolelist-srt1) — SignatureRoleTimelock

**Gas / Complexity note:** O(1) amortized (plus O(t) scan for first-target detection)

**Example:** Not applicable

***

### removeSignatureRoleList (SRT1)

**Contract/Library:** SignatureRoleTimelock

**Description:** Batch-removes signature role bindings.

**Detailed Description:** Self-call only. For each entry, drops the `(target, selector)` binding; when a target has no remaining selectors, removes it from [`targets`](https://docs.cryptolegacy.app/documentation/data-structures-reference#targets-srt1-d9). Emits corresponding events.

**Parameters:**

* \_sigsToRemove ([SignatureToRemove](https://docs.cryptolegacy.app/documentation/data-structures-reference#signaturetoremove-isrt1-s5)\[], memory): List of `{target, signature}` entries to remove

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external nonpayable onlyCurrentAddress

**Access Control:**

* Only self-call (enforced by `onlyCurrentAddress`)

**Side Effects:**

* Updates [`signatureRoles`](https://docs.cryptolegacy.app/documentation/data-structures-reference#signatureroles-srt1-d7), [`targetSigs`](https://docs.cryptolegacy.app/documentation/data-structures-reference#targetsigs-srt1-d8), [`targets`](https://docs.cryptolegacy.app/documentation/data-structures-reference#targets-srt1-d9)

**Emits:**

* [RemoveSignatureRole](https://docs.cryptolegacy.app/documentation/events-reference#removesignaturerole-isrt1) — `RemoveSignatureRole(address indexed target, bytes4 indexed signature)`
* [RemoveTarget](https://docs.cryptolegacy.app/documentation/events-reference#removetarget-isrt1) — `RemoveTarget(address indexed target)` (when last selector removed)

**Reverts if:**

* `msg.sender != address(this)` — [`CallerNotCurrentAddress()`](https://docs.cryptolegacy.app/documentation/errors-reference#callernotcurrentaddress-isrt1)
* Target has no matching selector — `Panic(0x32)` (array out-of-bounds)
* Index check fails — [`IncorrectSignatureIndex()`](https://docs.cryptolegacy.app/documentation/errors-reference#incorrectsignatureindex-isrt1)

**Overrides:** None

**Function Calls:**

* [\_removeSignatureRole(address,bytes4)](#_removesignaturerole-srt1) — SignatureRoleTimelock, internal

**Called by:**

* [\_executeCall(bytes32)](#_executecall-srt1) — SignatureRoleTimelock

**Gas / Complexity note:** O(n) by \_sigsToRemove.length

**Example:** Schedule removal of obsolete selectors from a target.

***

### \_removeSignatureRole (SRT1)

**Contract/Library:** SignatureRoleTimelock

**Description:** Removes a single `(target, selector)` signature role binding.

**Detailed Description:** Deletes [`signatureRoles`](https://docs.cryptolegacy.app/documentation/data-structures-reference#signatureroles-srt1-d7)\[targetSignature], removes selector from [`targetSigs`](https://docs.cryptolegacy.app/documentation/data-structures-reference#targetsigs-srt1-d8)\[target], and if empty, removes `target` from [`targets`](https://docs.cryptolegacy.app/documentation/data-structures-reference#targets-srt1-d9). Emits corresponding events.

**Parameters:**

* \_target (address): Target contract
* \_signature (bytes4): Function selector to remove

**Returns:** None

**Modifiers / Visibility / Mutability:**

* internal nonpayable

**Access Control:**

* Unrestricted (internal)

**Side Effects:**

* Updates [`signatureRoles`](https://docs.cryptolegacy.app/documentation/data-structures-reference#signatureroles-srt1-d7), [`targetSigs`](https://docs.cryptolegacy.app/documentation/data-structures-reference#targetsigs-srt1-d8), [`targets`](https://docs.cryptolegacy.app/documentation/data-structures-reference#targets-srt1-d9)

**Emits:**

* [RemoveSignatureRole](https://docs.cryptolegacy.app/documentation/events-reference#removesignaturerole-isrt1) — `RemoveSignatureRole(address indexed target, bytes4 indexed signature)`
* [RemoveTarget](https://docs.cryptolegacy.app/documentation/events-reference#removetarget-isrt1) — `RemoveTarget(address indexed target)` (when last selector removed)

**Reverts if:**

* Target has no signatures or selector missing — `Panic(0x32)` (array out-of-bounds)
* Selector index mismatch — [`IncorrectSignatureIndex()`](https://docs.cryptolegacy.app/documentation/errors-reference#incorrectsignatureindex-isrt1)

**Overrides:** None

**Function Calls:**

* [\_getBytes4Index(bytes4\[\],bytes4)](#_getbytes4index-srt1) — SignatureRoleTimelock, internal
* [\_getAddressIndex(address\[\],address)](#_getaddressindex-srt1) — SignatureRoleTimelock, internal

**Called by:**

* [removeSignatureRoleList](#removesignaturerolelist-srt1) — SignatureRoleTimelock

**Gas / Complexity note:** O(n) by [`targetSigs`](https://docs.cryptolegacy.app/documentation/data-structures-reference#targetsigs-srt1-d8)\[target].length

**Example:** Not applicable

***

### scheduleCallList (SRT1)

**Contract/Library:** SignatureRoleTimelock

**Description:** Schedules a batch of authorized calls with per-signature timelocks.

**Detailed Description:** For each entry, extracts selector from calldata prefix and invokes internal scheduler. The scheduler enforces that the caller holds the required role for that `(target, selector)` and that a timelock is configured. Returns an array of computed call IDs.

**Parameters:**

* \_calls ([CallToAdd](https://docs.cryptolegacy.app/documentation/data-structures-reference#calltoadd-isrt1-s6)\[], calldata): `{target, data}` calls to schedule

**Returns:**

* callIds (bytes32\[], memory): Identifiers of scheduled calls

**Modifiers / Visibility / Mutability:**

* external nonpayable nonReentrant

**Access Control:**

* Requires appropriate role per signature (validated within scheduler)

**Side Effects:**

* Updates [`pendingCalls`](https://docs.cryptolegacy.app/documentation/data-structures-reference#pendingcalls-srt1-d10) and [`callsIds`](https://docs.cryptolegacy.app/documentation/data-structures-reference#callsids-srt1-d11) (via scheduler)

**Emits:**

* [CallScheduled](https://docs.cryptolegacy.app/documentation/events-reference#callscheduled-isrt1) — `CallScheduled(bytes32 indexed callId, address indexed caller, address indexed target, bytes4 signature, uint256 executeAfter)` (via scheduler)

**Reverts if:**

* Reentrant call — "ReentrancyGuard: reentrant call"
* Call payload shorter than 4 bytes — `Panic(0x32)` (slice out-of-bounds)
* No timelock configured — [`SignatureTimeLockNotSet(bytes4)`](https://docs.cryptolegacy.app/documentation/errors-reference#signaturetimelocknotset-isrt1)
* Caller lacks required role — [`CallerHaveNoRequiredRole(bytes32)`](https://docs.cryptolegacy.app/documentation/errors-reference#callerhavenorequiredrole-isrt1)
* Call already scheduled — [`CallAlreadyScheduled()`](https://docs.cryptolegacy.app/documentation/errors-reference#callalreadyscheduled-isrt1)

**Overrides:** None

**Function Calls:**

* [\_scheduleCall(address,bytes4,bytes)](#_schedulecall-srt1) — SignatureRoleTimelock, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(n) by \_calls.length

**Example:** Schedule upgrades or admin ops across multiple targets in one transaction.

***

### \_checkRole (SRT1)

**Contract/Library:** SignatureRoleTimelock

**Description:** AccessControl hook override to enforce role checks with custom error.

**Detailed Description:** Overrides OZ’s \_checkRole to revert with `CallerHaveNoRequiredRole(requiredRole)` when the caller lacks the role. Applies both to the internal scheduler and to any `onlyRole`-guarded entry points (e.g., `cancelCallList`).

**Parameters:**

* \_role (bytes32): Required role

**Returns:** None

**Modifiers / Visibility / Mutability:**

* internal view override

**Access Control:**

* Unrestricted (internal)

**Side Effects:** None

**Emits:** None

**Reverts if:**

* Caller lacks \_role — [`CallerHaveNoRequiredRole(bytes32)`](https://docs.cryptolegacy.app/documentation/errors-reference#callerhavenorequiredrole-isrt1)

**Overrides:**

* AccessControl.\_checkRole

**Function Calls:**

* hasRole(bytes32,address) — `AccessControl`, internal

**Called by:**

* [\_scheduleCall](#_schedulecall-srt1) — SignatureRoleTimelock
* [cancelCallList](#cancelcalllist-srt1) — SignatureRoleTimelock

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### \_scheduleCall (SRT1)

**Contract/Library:** SignatureRoleTimelock

**Description:** Schedules a single authorized call with timelock and execution window.

**Detailed Description:** Validates that a signature timelock is configured and that the caller has the required role. Computes `executeAfter = now + timelock`, then `executeBefore = executeAfter + maxExecutionPeriod` where [`maxExecutionPeriod`](https://docs.cryptolegacy.app/documentation/data-structures-reference#maxexecutionperiod-srt1-d5) is the configured window. Computes `callId = keccak256(target, data, caller, executeAfter)`, ensures it’s unique, stores [`CallRequest`](https://docs.cryptolegacy.app/documentation/data-structures-reference#callrequest-isrt1-s1), pushes `callId` to [`callsIds`](https://docs.cryptolegacy.app/documentation/data-structures-reference#callsids-srt1-d11), and emits `CallScheduled`.

**Parameters:**

* \_target (address): Call target
* \_sig (bytes4): Function selector
* \_data (bytes, memory): ABI-encoded calldata

**Returns:**

* callId (bytes32): Scheduled call identifier

**Modifiers / Visibility / Mutability:**

* internal nonpayable

**Access Control:**

* Requires caller to hold the bound role for \_sig on \_target

**Side Effects:**

* Writes [`pendingCalls`](https://docs.cryptolegacy.app/documentation/data-structures-reference#pendingcalls-srt1-d10)\[callId]
* Appends to [`callsIds`](https://docs.cryptolegacy.app/documentation/data-structures-reference#callsids-srt1-d11)

**Emits:**

* [CallScheduled](https://docs.cryptolegacy.app/documentation/events-reference#callscheduled-isrt1) — `CallScheduled(bytes32 indexed callId, address indexed caller, address indexed target, bytes4 signature, uint256 executeAfter)`

**Reverts if:**

* No timelock configured — [`SignatureTimeLockNotSet(bytes4)`](https://docs.cryptolegacy.app/documentation/errors-reference#signaturetimelocknotset-isrt1)
* Caller lacks role — [`CallerHaveNoRequiredRole(bytes32)`](https://docs.cryptolegacy.app/documentation/errors-reference#callerhavenorequiredrole-isrt1)
* Call already scheduled — [`CallAlreadyScheduled()`](https://docs.cryptolegacy.app/documentation/errors-reference#callalreadyscheduled-isrt1)

**Overrides:** None

**Function Calls:**

* [\_checkRole(bytes32)](#_checkrole-srt1) — SignatureRoleTimelock, internal

**Called by:**

* [scheduleCallList](#schedulecalllist-srt1) — SignatureRoleTimelock

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### executeCallList (SRT1)

**Contract/Library:** SignatureRoleTimelock

**Description:** Executes a batch of scheduled calls after their timelocks expire.

**Detailed Description:** Iterates over \_callIds and delegates to the internal executor. Each call must be pending, within its execution window, and will be performed via a low-level call to its target with stored calldata.

**Parameters:**

* \_callIds (bytes32\[], memory): Scheduled call IDs to execute

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external nonpayable nonReentrant

**Access Control:**

* Unrestricted

**Side Effects:**

* Marks executed calls as not pending

**Emits:**

* [CallExecuted](https://docs.cryptolegacy.app/documentation/events-reference#callexecuted-isrt1) — `CallExecuted(bytes32 indexed callId, address indexed msgSender, bytes returnData)` (per executed call)

**Reverts if:**

* Reentrant call — "ReentrancyGuard: reentrant call"
* Call not scheduled — [`CallNotScheduled()`](https://docs.cryptolegacy.app/documentation/errors-reference#callnotscheduled-isrt1)
* Already executed/canceled — [`NotPending()`](https://docs.cryptolegacy.app/documentation/errors-reference#notpending-isrt1)
* Timelock still active — [`TimelockActive()`](https://docs.cryptolegacy.app/documentation/errors-reference#timelockactive-isrt1)
* Execution window expired — [`TimelockExpired()`](https://docs.cryptolegacy.app/documentation/errors-reference#timelockexpired-isrt1)
* Target call failed — [`CallFailed(bytes)`](https://docs.cryptolegacy.app/documentation/errors-reference#callfailed-isrt1)

**Overrides:** None

**Function Calls:**

* [\_executeCall(bytes32)](#_executecall-srt1) — SignatureRoleTimelock, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(n) by \_callIds.length

**Example:** Execute multiple approved admin operations after timelock.

***

### \_executeCall (SRT1)

**Contract/Library:** SignatureRoleTimelock

**Description:** Executes an individual scheduled call when permitted by time window.

**Detailed Description:** Requires that the call is scheduled and pending, current time ≥ `executeAfter` and ≤ `executeBefore`. Clears `pending`, performs `target.call(data)`, and on success emits `CallExecuted`; otherwise reverts with `CallFailed(returnData)`.

**Parameters:**

* callId (bytes32): Identifier of the scheduled call

**Returns:** None

**Modifiers / Visibility / Mutability:**

* internal nonpayable

**Access Control:**

* Unrestricted (internal)

**Side Effects:**

* Updates [`pendingCalls`](https://docs.cryptolegacy.app/documentation/data-structures-reference#pendingcalls-srt1-d10)\[callId].pending

**Emits:**

* [CallExecuted](https://docs.cryptolegacy.app/documentation/events-reference#callexecuted-isrt1) — `CallExecuted(bytes32 indexed callId, address indexed msgSender, bytes returnData)`

**Reverts if:**

* Not scheduled — [`CallNotScheduled()`](https://docs.cryptolegacy.app/documentation/errors-reference#callnotscheduled-isrt1)
* Already executed/canceled — [`NotPending()`](https://docs.cryptolegacy.app/documentation/errors-reference#notpending-isrt1)
* Timelock not yet elapsed — [`TimelockActive()`](https://docs.cryptolegacy.app/documentation/errors-reference#timelockactive-isrt1)
* Execution window expired — [`TimelockExpired()`](https://docs.cryptolegacy.app/documentation/errors-reference#timelockexpired-isrt1)
* Target call failed — [`CallFailed(bytes)`](https://docs.cryptolegacy.app/documentation/errors-reference#callfailed-isrt1)

**Overrides:** None

**Function Calls:**

* `target.call(bytes)` — `target`, external

**Called by:**

* [executeCallList](#executecalllist-srt1) — SignatureRoleTimelock

**Gas / Complexity note:** O(1) for executor; target call cost dominates

**Example:** Not applicable

***

### cancelCallList (SRT1)

**Contract/Library:** SignatureRoleTimelock

**Description:** Cancels pending scheduled calls (admin-only).

**Detailed Description:** Restricted to [`ADMIN_ROLE`](https://docs.cryptolegacy.app/documentation/data-structures-reference#admin_role-srt1-d1). Iterates over call IDs and cancels each if scheduled and pending.

**Parameters:**

* \_callIds (bytes32\[], memory): Call IDs to cancel

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external nonpayable onlyRole(ADMIN\_ROLE) nonReentrant

**Access Control:**

* Only [`ADMIN_ROLE`](https://docs.cryptolegacy.app/documentation/data-structures-reference#admin_role-srt1-d1) (AccessControl)

**Side Effects:**

* Updates [`pendingCalls`](https://docs.cryptolegacy.app/documentation/data-structures-reference#pendingcalls-srt1-d10)\[callId].pending to `false`

**Emits:**

* [CallCanceled](https://docs.cryptolegacy.app/documentation/events-reference#callcanceled-isrt1) — `CallCanceled(bytes32 indexed callId, address indexed msgSender)`

**Reverts if:**

* Caller lacks role — [`CallerHaveNoRequiredRole(bytes32)`](https://docs.cryptolegacy.app/documentation/errors-reference#callerhavenorequiredrole-isrt1)
* Reentrant call — "ReentrancyGuard: reentrant call"
* Call not scheduled — [`CallNotScheduled()`](https://docs.cryptolegacy.app/documentation/errors-reference#callnotscheduled-isrt1)
* Already executed/canceled — [`NotPending()`](https://docs.cryptolegacy.app/documentation/errors-reference#notpending-isrt1)

**Overrides:** None

**Function Calls:**

* [\_cancelCall(bytes32)](#_cancelcall-srt1) — SignatureRoleTimelock, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(n) by \_callIds.length

**Example:** Cancel outdated or invalidated scheduled calls.

***

### \_cancelCall (SRT1)

**Contract/Library:** SignatureRoleTimelock

**Description:** Cancels a single scheduled call if still pending.

**Detailed Description:** Verifies that the call exists and is pending; marks it not pending and emits `CallCanceled`.

**Parameters:**

* callId (bytes32): Identifier of the scheduled call

**Returns:** None

**Modifiers / Visibility / Mutability:**

* internal nonpayable

**Access Control:**

* Unrestricted (internal)

**Side Effects:**

* Updates [`pendingCalls`](https://docs.cryptolegacy.app/documentation/data-structures-reference#pendingcalls-srt1-d10)\[callId].pending

**Emits:**

* [CallCanceled](https://docs.cryptolegacy.app/documentation/events-reference#callcanceled-isrt1) — `CallCanceled(bytes32 indexed callId, address indexed msgSender)`

**Reverts if:**

* Not scheduled — [`CallNotScheduled()`](https://docs.cryptolegacy.app/documentation/errors-reference#callnotscheduled-isrt1)
* Already executed/canceled — [`NotPending()`](https://docs.cryptolegacy.app/documentation/errors-reference#notpending-isrt1)

**Overrides:** None

**Function Calls:** None

**Called by:**

* [cancelCallList](#cancelcalllist-srt1) — SignatureRoleTimelock

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### getRoleAccounts (SRT1)

**Contract/Library:** SignatureRoleTimelock

**Description:** Returns accounts that hold a given role.

**Detailed Description:** Reads and returns the [`roleAccounts`](https://docs.cryptolegacy.app/documentation/data-structures-reference#roleaccounts-srt1-d6) array for \_role.

**Parameters:**

* \_role (bytes32): Role identifier

**Returns:**

* accounts (address\[], memory): Role members

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:** None (entry point)

**Gas / Complexity note:** O(n) by number of accounts

**Example:** Query current admins.

***

### getTargets (SRT1)

**Contract/Library:** SignatureRoleTimelock

**Description:** Lists all targets that have signature role bindings.

**Detailed Description:** Returns the [`targets`](https://docs.cryptolegacy.app/documentation/data-structures-reference#targets-srt1-d9) array.

**Parameters:** None

**Returns:**

* result (address\[], memory): Target addresses

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:** None (entry point)

**Gas / Complexity note:** O(targets.length)

**Example:** Enumerate configured targets.

***

### getTargetSigs (SRT1)

**Contract/Library:** SignatureRoleTimelock

**Description:** Returns signature role details for a given target.

**Detailed Description:** Builds [`TargetSigRes[]`](https://docs.cryptolegacy.app/documentation/data-structures-reference#targetsigres-isrt1-s7) by iterating [`targetSigs`](https://docs.cryptolegacy.app/documentation/data-structures-reference#targetsigs-srt1-d8)\[\_target] and pairing each selector with its `role` and `timelock` from [`signatureRoles`](https://docs.cryptolegacy.app/documentation/data-structures-reference#signatureroles-srt1-d7).

**Parameters:**

* \_target (address): Target contract

**Returns:**

* result ([TargetSigRes](https://docs.cryptolegacy.app/documentation/data-structures-reference#targetsigres-isrt1-s7)\[], memory): Selector → (role, timelock)

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:** None (entry point)

**Gas / Complexity note:** O(n) by [`targetSigs`](https://docs.cryptolegacy.app/documentation/data-structures-reference#targetsigs-srt1-d8)\[\_target].length

**Example:** Inspect roles/timelocks for a managed contract.

***

### getCallId (SRT1)

**Contract/Library:** SignatureRoleTimelock

**Description:** Computes a deterministic call ID for a pending call.

**Detailed Description:** Pure function returning `keccak256(abi.encode(target, data, caller, executeAfter))`.

**Parameters:**

* target (address): Target contract
* data (bytes, calldata): ABI-encoded calldata
* caller (address): Scheduler account
* executeAfter (uint256): Unlock timestamp

**Returns:**

* callId (bytes32): Computed call identifier

**Modifiers / Visibility / Mutability:**

* public pure

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Use to precompute `callId` off-chain.

***

### getCall (SRT1)

**Contract/Library:** SignatureRoleTimelock

**Description:** Returns details of a scheduled call.

**Detailed Description:** Fetches [`pendingCalls`](https://docs.cryptolegacy.app/documentation/data-structures-reference#pendingcalls-srt1-d10)\[\_callId].

**Parameters:**

* \_callId (bytes32): Scheduled call ID

**Returns:**

* request ([CallRequest](https://docs.cryptolegacy.app/documentation/data-structures-reference#callrequest-isrt1-s1), memory): Call metadata

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Read a pending call’s window.

***

### getCallsList (SRT1)

**Contract/Library:** SignatureRoleTimelock

**Description:** Paginates scheduled call IDs and their details.

**Detailed Description:** Returns two parallel arrays of length \_limit: IDs starting at \_offset and their [`CallRequest`](https://docs.cryptolegacy.app/documentation/data-structures-reference#callrequest-isrt1-s1) records.

**Parameters:**

* \_offset (uint256): Starting index in [`callsIds`](https://docs.cryptolegacy.app/documentation/data-structures-reference#callsids-srt1-d11)
* \_limit (uint256): Number of items to return

**Returns:**

* ids (bytes32\[], memory): Selected call IDs
* resCalls ([CallRequest](https://docs.cryptolegacy.app/documentation/data-structures-reference#callrequest-isrt1-s1)\[], memory): Corresponding call metadata

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:**

* \_offset + \_limit > [`callsIds`](https://docs.cryptolegacy.app/documentation/data-structures-reference#callsids-srt1-d11).length — `Panic(0x32)`

**Overrides:** None

**Function Calls:** None

**Called by:** None (entry point)

**Gas / Complexity note:** O(\_limit)

**Example:** Fetch a page of pending calls for UI.

***

### getCallIds (SRT1)

**Contract/Library:** SignatureRoleTimelock

**Description:** Returns all scheduled call IDs.

**Detailed Description:** Reads and returns the [`callsIds`](https://docs.cryptolegacy.app/documentation/data-structures-reference#callsids-srt1-d11) array.

**Parameters:** None

**Returns:**

* ids (bytes32\[], memory): All call IDs

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:** None (entry point)

**Gas / Complexity note:** O(n) by [`callsIds`](https://docs.cryptolegacy.app/documentation/data-structures-reference#callsids-srt1-d11).length (copy cost)

**Example:** Enumerate all scheduled calls.

***

### getCallsLength (SRT1)

**Contract/Library:** SignatureRoleTimelock

**Description:** Returns the number of scheduled calls.

**Detailed Description:** Returns [`callsIds`](https://docs.cryptolegacy.app/documentation/data-structures-reference#callsids-srt1-d11).length.

**Parameters:** None

**Returns:**

* count (uint256): Number of scheduled call IDs

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

## BeneficiaryAaveV3SupplyPlugin (BALP1)

### constructor (BALP1)

**Contract/Library:** BeneficiaryAaveV3SupplyPlugin

**Description:** Stores the Aave V3 and StataToken integration addresses used by the beneficiary plugin.

**Detailed Description:** Initializes the plugin with the Aave Pool, PoolDataProvider, StataTokenFactory, and fallback referral code that power the supply, withdraw, and wrapping flows exposed by the facet.

**Parameters:**

* \_pool (address): Aave V3 Pool contract used for supply and withdraw actions
* \_poolDataProvider (address): PoolDataProvider used to resolve reserve-token addresses
* \_stataTokenFactory (address): StataTokenFactory used to resolve wrapper vaults
* \_defaultReferralCode (uint16): Default Aave referral code used when callers pass `0`

**Returns:** None

**Modifiers / Visibility / Mutability:**

* constructor nonpayable

**Access Control:**

* Unrestricted at deployment time

**Side Effects:**

* Sets [`POOL (BALP-D2)`](https://docs.cryptolegacy.app/documentation/data-structures-reference#pool-balp1-d2), [`POOL_DATA_PROVIDER (BALP-D3)`](https://docs.cryptolegacy.app/documentation/data-structures-reference#pool_data_provider-balp1-d3), [`STATA_TOKEN_FACTORY (BALP-D4)`](https://docs.cryptolegacy.app/documentation/data-structures-reference#stata_token_factory-balp1-d4), and [`DEFAULT_REFERRAL_CODE (BALP-D5)`](https://docs.cryptolegacy.app/documentation/data-structures-reference#default_referral_code-balp1-d5) once as immutable configuration

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:** None (deployment only)

**Gas / Complexity note:** O(1)

**Example:** `new BeneficiaryAaveV3SupplyPlugin(pool, poolDataProvider, stataFactory, referralCode);`

***

### getSigs (BALP1)

**Contract/Library:** BeneficiaryAaveV3SupplyPlugin

**Description:** Returns the selectors exposed by the Aave beneficiary plugin.

**Detailed Description:** Builds the 14-selector array used by the diamond to register the plugin's multisig-management getters and the six Aave/StataToken execution entry points.

**Parameters:** None

**Returns:**

* sigs (bytes4\[], memory): Selector array covering the plugin's public surface

**Modifiers / Visibility / Mutability:**

* external pure

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:** None (entry point)

**Gas / Complexity note:** O(1) — fixed-length selector assembly

**Example:** Facet-registration tooling reads `getSigs()` before wiring the plugin into the diamond.

***

### getSetupSigs (BALP1)

**Contract/Library:** BeneficiaryAaveV3SupplyPlugin

**Description:** Returns the setup-time selectors required by the Aave beneficiary plugin.

**Detailed Description:** Returns an empty array, confirming that the plugin does not require any dedicated setup selectors during installation.

**Parameters:** None

**Returns:**

* sigs (bytes4\[], memory): Always an empty selector array

**Modifiers / Visibility / Mutability:**

* external pure

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Install flow checks `getSetupSigs()` and skips extra setup calls because the array is empty.

***

### getMultisigAllowedMethods (BALP1)

**Contract/Library:** BeneficiaryAaveV3SupplyPlugin

**Description:** Lists selectors that beneficiary multisig proposals are allowed to execute.

**Detailed Description:** Returns the six execution selectors that the beneficiary multisig may schedule: supply, withdraw, aToken-to-Stata wrapping, Stata-to-aToken unwrapping, direct Stata deposits, and direct Stata redemptions.

**Parameters:** None

**Returns:**

* sigs (bytes4\[], memory): Allowed multisig method selectors

**Modifiers / Visibility / Mutability:**

* public pure

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:**

* [baavesPropose(bytes4,bytes)](#baavespropose-balp1) — BeneficiaryAaveV3SupplyPlugin

**Gas / Complexity note:** O(1)

**Example:** `baavesPropose` reads `getMultisigAllowedMethods()` before accepting a new proposal.

***

### getPluginName (BALP1)

**Contract/Library:** BeneficiaryAaveV3SupplyPlugin

**Description:** Returns the unique plugin name string.

**Detailed Description:** Supplies the stable identifier `"beneficiary_aave_v3_supply"` for registry displays, tooling, and plugin metadata views.

**Parameters:** None

**Returns:**

* name (string, memory): Static plugin name `"beneficiary_aave_v3_supply"`

**Modifiers / Visibility / Mutability:**

* public pure

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Front-end uses `getPluginName()` to label the facet in the installed-plugin list.

***

### getPluginVer (BALP1)

**Contract/Library:** BeneficiaryAaveV3SupplyPlugin

**Description:** Returns the semantic version for the Aave beneficiary plugin.

**Detailed Description:** Exposes the hard-coded version `1` so deployment and upgrade tooling can compare the installed facet against the expected release.

**Parameters:** None

**Returns:**

* version (uint16): Static plugin version `1`

**Modifiers / Visibility / Mutability:**

* external pure

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Upgrade scripts compare `getPluginVer()` before replacing the facet.

***

### modifier onlyDistributionReady (BALP1)

**Contract/Library:** BeneficiaryAaveV3SupplyPlugin

**Description:** Restricts execution to phases where beneficiary distribution is already active.

**Detailed Description:** Loads CryptoLegacy storage and forwards it to `LibCryptoLegacy._checkDistributionReady(...)`, requiring the distribution-start timestamp to be set and already reached before the wrapped function proceeds.

**Parameters:** None

**Returns:** None

**Modifiers / Visibility / Mutability:**

* modifier nonpayable

**Access Control:**

* Distribution must already be active

**Side Effects:** None

**Emits:** None

**Reverts if:**

* Distribution not yet ready — [`TooEarly()`](https://docs.cryptolegacy.app/documentation/errors-reference#tooearly-icl1)

**Overrides:** None

**Function Calls:**

* [LibCryptoLegacy.getCryptoLegacyStorage()](#getcryptolegacystorage-lcl1) — LibCryptoLegacy, internal
* [LibCryptoLegacy.\_checkDistributionReady(ICryptoLegacy.CryptoLegacyStorage)](#_checkdistributionready-lcl1) — LibCryptoLegacy, internal

**Called by:**

* [baavesPropose(bytes4,bytes)](#baavespropose-balp1) — BeneficiaryAaveV3SupplyPlugin
* [baavesConfirm(uint256)](#baavesconfirm-balp1) — BeneficiaryAaveV3SupplyPlugin
* [baavesCancel(uint256)](#baavescancel-balp1) — BeneficiaryAaveV3SupplyPlugin
* [baavesSupply(address,uint256,uint16)](#baavessupply-balp1) — BeneficiaryAaveV3SupplyPlugin
* [baavesWithdraw(address,uint256)](#baaveswithdraw-balp1) — BeneficiaryAaveV3SupplyPlugin
* [baavesWrapATokenToStataToken(address,uint256)](#baaveswrapatokentostatatoken-balp1) — BeneficiaryAaveV3SupplyPlugin
* [baavesUnwrapStataTokenToAToken(address,uint256)](#baavesunwrapstatatokentoatoken-balp1) — BeneficiaryAaveV3SupplyPlugin
* [baavesDepositToStataToken(address,uint256)](#baavesdeposittostatatoken-balp1) — BeneficiaryAaveV3SupplyPlugin
* [baavesRedeemFromStataToken(address,uint256)](#baavesredeemfromstatatoken-balp1) — BeneficiaryAaveV3SupplyPlugin

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### getPluginMultisigStorage (BALP1)

**Contract/Library:** BeneficiaryAaveV3SupplyPlugin

**Description:** Retrieves the plugin-specific multisig storage slot.

**Detailed Description:** Uses inline assembly to reinterpret [`PLUGIN_MULTISIG_POSITION (BALP-D1)`](https://docs.cryptolegacy.app/documentation/data-structures-reference#plugin_multisig_position-balp1-d1) as an `ISafeMinimalMultisig.Storage` reference shared by the plugin's multisig helpers and view methods.

**Parameters:** None

**Returns:**

* storageStruct (ISafeMinimalMultisig.Storage, storage): Multisig storage layout for this plugin

**Modifiers / Visibility / Mutability:**

* internal pure

**Access Control:**

* Internal helper used only by this plugin

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:**

* [baavesSetMultisigConfig(uint128)](#baavessetmultisigconfig-balp1) — BeneficiaryAaveV3SupplyPlugin
* [baavesPropose(bytes4,bytes)](#baavespropose-balp1) — BeneficiaryAaveV3SupplyPlugin
* [baavesConfirm(uint256)](#baavesconfirm-balp1) — BeneficiaryAaveV3SupplyPlugin
* [baavesCancel(uint256)](#baavescancel-balp1) — BeneficiaryAaveV3SupplyPlugin
* [baavesGetInitializationStatus()](#baavesgetinitializationstatus-balp1) — BeneficiaryAaveV3SupplyPlugin
* [baavesGetVotersAndConfirmations()](#baavesgetvotersandconfirmations-balp1) — BeneficiaryAaveV3SupplyPlugin
* [baavesGetProposalWithStatus(uint256)](#baavesgetproposalwithstatus-balp1) — BeneficiaryAaveV3SupplyPlugin
* [baavesGetProposalListWithStatuses()](#baavesgetproposallistwithstatuses-balp1) — BeneficiaryAaveV3SupplyPlugin

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### baavesSetMultisigConfig (BALP1)

**Contract/Library:** BeneficiaryAaveV3SupplyPlugin

**Description:** Updates the beneficiary multisig confirmation threshold for the plugin.

**Detailed Description:** If called by the contract itself, the function rechecks distribution readiness; otherwise it enforces owner authority. It then loads the current beneficiary set and forwards the new threshold to `LibSafeMinimalBeneficiaryMultisig._setConfirmations(...)`.

**Parameters:**

* \_requiredConfirmations (uint128): Desired confirmation threshold

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external nonpayable

**Access Control:**

* Owner when called externally; `address(this)` may call it once distribution is ready

**Side Effects:**

* Updates `requiredConfirmations` inside plugin multisig storage

**Emits:**

* [SetConfirmations](https://docs.cryptolegacy.app/documentation/events-reference#setconfirmations-ism1) — `SetConfirmations(uint128 requiredConfirmations)`

**Reverts if:**

* Distribution already started on the owner path — [`DistributionStarted()`](https://docs.cryptolegacy.app/documentation/errors-reference#distributionstarted-icl1)
* Initial fee unpaid on the owner path — [`InitialFeeNotPaid()`](https://docs.cryptolegacy.app/documentation/errors-reference#initialfeenotpaid-icl1)
* Caller is not owner on the owner path — [`NotTheOwner()`](https://docs.cryptolegacy.app/documentation/errors-reference#nottheowner-icl1)
* Distribution not yet ready on the self-call path — [`TooEarly()`](https://docs.cryptolegacy.app/documentation/errors-reference#tooearly-icl1)
* Invalid threshold for the current beneficiary set — [`MultisigIncorrectRequiredConfirmations()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisigincorrectrequiredconfirmations-ism1)

**Overrides:** None

**Function Calls:**

* [LibCryptoLegacy.getCryptoLegacyStorage()](#getcryptolegacystorage-lcl1) — LibCryptoLegacy, internal
* [LibCryptoLegacy.\_checkDistributionReady(ICryptoLegacy.CryptoLegacyStorage)](#_checkdistributionready-lcl1) — LibCryptoLegacy, internal
* [LibCryptoLegacy.\_checkOwner()](#_checkowner-lcl1) — LibCryptoLegacy, internal
* [getPluginMultisigStorage()](#getpluginmultisigstorage-balp1) — BeneficiaryAaveV3SupplyPlugin, internal
* [LibSafeMinimalBeneficiaryMultisig.\_setConfirmations(...)](#_setconfirmations-lsmb1) — LibSafeMinimalBeneficiaryMultisig, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(b) by number of beneficiaries

**Example:** Owner raises the number of beneficiary confirmations required for Aave actions.

***

### baavesPropose (BALP1)

**Contract/Library:** BeneficiaryAaveV3SupplyPlugin

**Description:** Creates a multisig proposal for an allowed Aave beneficiary action.

**Detailed Description:** Requires distribution to be active, validates the caller as an allowed beneficiary voter, checks the requested selector against the plugin allowlist, and records a proposal that may execute immediately if only one confirmation is required.

**Parameters:**

* \_selector (bytes4): Target function selector
* \_params (bytes, memory): ABI-encoded arguments for the target call

**Returns:**

* proposalId (uint256): Newly created proposal index

**Modifiers / Visibility / Mutability:**

* external payable nonReentrant onlyDistributionReady

**Access Control:**

* Caller must be an authorized beneficiary voter

**Side Effects:**

* Appends a proposal to plugin multisig storage
* Records the proposer's confirmation and may execute immediately
* Credits held ETH when execution leaves surplus native value behind

**Emits:**

* [CreateSafeMinimalMultisigProposal](https://docs.cryptolegacy.app/documentation/events-reference#createsafeminimalmultisigproposal-ism1) — `CreateSafeMinimalMultisigProposal(uint256 proposalId, bytes32 voter, uint128 reqConfirmations)`
* [ExecuteSafeMinimalMultisigProposal](https://docs.cryptolegacy.app/documentation/events-reference#executesafeminimalmultisigproposal-ism1) — `ExecuteSafeMinimalMultisigProposal(uint256 proposalId, bytes32 voter, bool executed, bytes returnData)` (when quorum is reached immediately)
* [AddHeldEth](https://docs.cryptolegacy.app/documentation/events-reference#addheldeth-ism1) — `AddHeldEth(bytes32 voter, uint256 value)` (when ETH is retained)

**Reverts if:**

* Distribution not yet ready — [`TooEarly()`](https://docs.cryptolegacy.app/documentation/errors-reference#tooearly-icl1)
* Reentrant call — "ReentrancyGuard: reentrant call"
* Caller is not an allowed voter — [`MultisigVoterNotAllowed()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisigvoternotallowed-ism1)
* Selector is not in the plugin allowlist — [`MultisigMethodNotAllowed()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisigmethodnotallowed-ism1)
* Execution of the approved action fails — [`MultisigExecutionFailed()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisigexecutionfailed-ism1)

**Overrides:** None

**Function Calls:**

* [getPluginMultisigStorage()](#getpluginmultisigstorage-balp1) — BeneficiaryAaveV3SupplyPlugin, internal
* [getMultisigAllowedMethods()](#getmultisigallowedmethods-balp1) — BeneficiaryAaveV3SupplyPlugin, internal
* [LibSafeMinimalBeneficiaryMultisig.\_propose(...)](#_propose-lsmb1) — LibSafeMinimalBeneficiaryMultisig, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(b) by beneficiary count

**Example:** Beneficiary voter proposes a `baavesSupply` action after distribution starts.

***

### baavesConfirm (BALP1)

**Contract/Library:** BeneficiaryAaveV3SupplyPlugin

**Description:** Confirms an existing plugin proposal and executes it once quorum is reached.

**Detailed Description:** Validates the caller as an allowed voter, records their confirmation, recomputes the confirmation count, and executes the underlying Aave/StataToken action when the multisig threshold is met.

**Parameters:**

* \_proposalId (uint256): Proposal index to confirm

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external payable nonReentrant onlyDistributionReady

**Access Control:**

* Caller must be an authorized beneficiary voter

**Side Effects:**

* Updates per-proposal confirmation bookkeeping
* May execute the underlying action
* Credits held ETH when execution leaves surplus native value behind

**Emits:**

* [ConfirmSafeMinimalMultisigProposal](https://docs.cryptolegacy.app/documentation/events-reference#confirmsafeminimalmultisigproposal-ism1) — `ConfirmSafeMinimalMultisigProposal(uint256 proposalId, bytes32 voter, uint128 reqConfirmations, uint256 confirms)`
* [ExecuteSafeMinimalMultisigProposal](https://docs.cryptolegacy.app/documentation/events-reference#executesafeminimalmultisigproposal-ism1) — `ExecuteSafeMinimalMultisigProposal(uint256 proposalId, bytes32 voter, bool executed, bytes returnData)` (on execution)
* [AddHeldEth](https://docs.cryptolegacy.app/documentation/events-reference#addheldeth-ism1) — `AddHeldEth(bytes32 voter, uint256 value)` (when ETH is retained)

**Reverts if:**

* Distribution not yet ready — [`TooEarly()`](https://docs.cryptolegacy.app/documentation/errors-reference#tooearly-icl1)
* Reentrant call — "ReentrancyGuard: reentrant call"
* Caller is not an allowed voter — [`MultisigVoterNotAllowed()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisigvoternotallowed-ism1)
* Proposal is not pending — [`MultisigProposalNotPending()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisigproposalnotpending-ism1)
* Execution of the approved action fails — [`MultisigExecutionFailed()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisigexecutionfailed-ism1)

**Overrides:** None

**Function Calls:**

* [getPluginMultisigStorage()](#getpluginmultisigstorage-balp1) — BeneficiaryAaveV3SupplyPlugin, internal
* [LibSafeMinimalBeneficiaryMultisig.\_confirm(...)](#_confirm-lsmb1) — LibSafeMinimalBeneficiaryMultisig, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(b) by beneficiary count

**Example:** Second beneficiary confirms a pending `baavesWithdraw` proposal so it can execute.

***

### baavesCancel (BALP1)

**Contract/Library:** BeneficiaryAaveV3SupplyPlugin

**Description:** Removes the caller's confirmation from a pending plugin proposal.

**Detailed Description:** Ensures the proposal is still pending, clears the caller's confirmation, recomputes the remaining confirmations, and cancels the proposal if no confirmations remain.

**Parameters:**

* \_proposalId (uint256): Proposal index to unconfirm

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external nonpayable nonReentrant onlyDistributionReady

**Access Control:**

* Caller must be an authorized beneficiary voter who previously confirmed

**Side Effects:**

* Updates proposal confirmation bookkeeping and may mark the proposal as canceled

**Emits:**

* [CancelSafeMinimalMultisigProposal](https://docs.cryptolegacy.app/documentation/events-reference#cancelsafeminimalmultisigproposal-ism1) — `CancelSafeMinimalMultisigProposal(uint256 proposalId, bytes32 voter, uint128 reqConfirmations, ISafeMinimalMultisig.ProposalStatus status)`

**Reverts if:**

* Distribution not yet ready — [`TooEarly()`](https://docs.cryptolegacy.app/documentation/errors-reference#tooearly-icl1)
* Reentrant call — "ReentrancyGuard: reentrant call"
* Caller is not an allowed voter — [`MultisigVoterNotAllowed()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisigvoternotallowed-ism1)
* Proposal is not pending — [`MultisigProposalNotPending()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisigproposalnotpending-ism1)
* Caller had not confirmed — [`MultisigNotConfirmed()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisignotconfirmed-ism1)

**Overrides:** None

**Function Calls:**

* [getPluginMultisigStorage()](#getpluginmultisigstorage-balp1) — BeneficiaryAaveV3SupplyPlugin, internal
* [LibSafeMinimalBeneficiaryMultisig.\_cancel(...)](#_cancel-lsmb1) — LibSafeMinimalBeneficiaryMultisig, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(b) by beneficiary count

**Example:** Beneficiary retracts a proposal to deposit into a StataToken vault.

***

### baavesGetInitializationStatus (BALP1)

**Contract/Library:** BeneficiaryAaveV3SupplyPlugin

**Description:** Reports whether the plugin's multisig configuration has been initialized.

**Detailed Description:** Delegates to `LibSafeMinimalBeneficiaryMultisig._initializationStatus(...)` to determine whether the confirmation threshold is already configured for the current beneficiary set.

**Parameters:** None

**Returns:**

* status (ISafeMinimalMultisig.InitializationStatus): Current multisig initialization state

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [getPluginMultisigStorage()](#getpluginmultisigstorage-balp1) — BeneficiaryAaveV3SupplyPlugin, internal
* [LibSafeMinimalBeneficiaryMultisig.\_initializationStatus(...)](#_initializationstatus-lsmb1) — LibSafeMinimalBeneficiaryMultisig, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** UI checks whether beneficiaries have configured the Aave plugin multisig.

***

### baavesGetVotersAndConfirmations (BALP1)

**Contract/Library:** BeneficiaryAaveV3SupplyPlugin

**Description:** Returns the beneficiary voter list and current confirmation threshold.

**Detailed Description:** Delegates to `LibSafeMinimalBeneficiaryMultisig._getVotersAndConfirmations(...)` to expose the plugin's current multisig configuration.

**Parameters:** None

**Returns:**

* voters (bytes32\[], memory): Current beneficiary voter hashes
* requiredConfirmations (uint128): Confirmation threshold used for proposal execution

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [getPluginMultisigStorage()](#getpluginmultisigstorage-balp1) — BeneficiaryAaveV3SupplyPlugin, internal
* [LibSafeMinimalBeneficiaryMultisig.\_getVotersAndConfirmations(...)](#_getvotersandconfirmations-lsmb1) — LibSafeMinimalBeneficiaryMultisig, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(b) by beneficiary count

**Example:** Monitoring UI reads the current voter set and required confirmations for the plugin.

***

### baavesGetProposalWithStatus (BALP1)

**Contract/Library:** BeneficiaryAaveV3SupplyPlugin

**Description:** Returns a single multisig proposal together with its derived execution status.

**Detailed Description:** Loads both CryptoLegacy storage and plugin multisig storage, then delegates to `LibSafeMinimalBeneficiaryMultisig._getProposalWithStatus(...)` so clients can inspect one proposal plus its effective status and voter metadata.

**Parameters:**

* \_proposalId (uint256): Proposal index to inspect

**Returns:**

* voters (bytes32\[], memory): Current voter list used to interpret the proposal
* requiredConfirmations (uint128): Confirmation threshold for the proposal
* proposalWithStatus (ISafeMinimalMultisig.ProposalWithStatus, memory): Proposal payload plus derived status

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:**

* `_proposalId` is out of range — `panic(0x32)`

**Overrides:** None

**Function Calls:**

* [LibCryptoLegacy.getCryptoLegacyStorage()](#getcryptolegacystorage-lcl1) — LibCryptoLegacy, internal
* [getPluginMultisigStorage()](#getpluginmultisigstorage-balp1) — BeneficiaryAaveV3SupplyPlugin, internal
* [LibSafeMinimalBeneficiaryMultisig.\_getProposalWithStatus(...)](#_getproposalwithstatus-lsmb1) — LibSafeMinimalBeneficiaryMultisig, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(b) by beneficiary count

**Example:** Front-end opens one pending Aave plugin proposal with its confirmation status.

***

### baavesGetProposalListWithStatuses (BALP1)

**Contract/Library:** BeneficiaryAaveV3SupplyPlugin

**Description:** Returns the full plugin proposal list with derived statuses.

**Detailed Description:** Delegates to `LibSafeMinimalBeneficiaryMultisig._getProposalListWithStatuses(...)` so clients can inspect every recorded proposal together with the current voter configuration.

**Parameters:** None

**Returns:**

* voters (bytes32\[], memory): Current voter list
* requiredConfirmations (uint128): Current confirmation threshold
* proposalsWithStatuses (ISafeMinimalMultisig.ProposalWithStatus\[], memory): Proposal list with derived statuses

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [LibCryptoLegacy.getCryptoLegacyStorage()](#getcryptolegacystorage-lcl1) — LibCryptoLegacy, internal
* [getPluginMultisigStorage()](#getpluginmultisigstorage-balp1) — BeneficiaryAaveV3SupplyPlugin, internal
* [LibSafeMinimalBeneficiaryMultisig.\_getProposalListWithStatuses(...)](#_getproposallistwithstatuses-lsmb1) — LibSafeMinimalBeneficiaryMultisig, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(p + b) by proposal count and beneficiary count

**Example:** Dashboard renders the full history of Aave plugin proposals with live statuses.

***

### baavesSupply (BALP1)

**Contract/Library:** BeneficiaryAaveV3SupplyPlugin

**Description:** Supplies a reserve asset into Aave V3 and migrates beneficiary claims into the corresponding aToken.

**Detailed Description:** Restricted to the beneficiary multisig executor after distribution starts. The function validates the input amount, resolves the reserve's aToken, snapshots both token balances, clears and reapplies the Pool allowance, executes `IAaveV3Pool.supply(...)`, migrates claims from the reserve asset into the aToken via `LibOneStepClaimMigration.migrate(...)`, and emits `AaveSupply`.

**Parameters:**

* asset (address): Reserve asset to supply into Aave
* amount (uint256): Asset amount to supply
* referralCode (uint16): Requested referral code; `0` falls back to [`DEFAULT_REFERRAL_CODE (BALP-D5)`](https://docs.cryptolegacy.app/documentation/data-structures-reference#default_referral_code-balp1-d5)

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external nonpayable onlyDistributionReady

**Access Control:**

* Must be invoked by the beneficiary multisig executor after distribution starts

**Side Effects:**

* Updates ERC-20 approvals for the input asset
* Supplies the asset into Aave and increases the plugin's aToken balance
* Migrates beneficiary claims from `asset` into the resolved aToken

**Emits:**

* [AaveSupply](https://docs.cryptolegacy.app/documentation/events-reference#aavesupply-balp1) — `AaveSupply(address indexed asset, address indexed aToken, uint256 amount)`

**Reverts if:**

* Distribution not yet ready — [`TooEarly()`](https://docs.cryptolegacy.app/documentation/errors-reference#tooearly-icl1)
* Caller is not the multisig executor — [`MultisigOnlyExecutor()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisigonlyexecutor-ism1)
* `amount == 0` — [`ZeroAmount()`](https://docs.cryptolegacy.app/documentation/errors-reference#zeroamount-balp1)
* PoolDataProvider returns no aToken for `asset` — [`ATokenNotFound()`](https://docs.cryptolegacy.app/documentation/errors-reference#atokennotfound-balp1)
* ERC-20 approval helper fails — [`ApprovalFailed()`](https://docs.cryptolegacy.app/documentation/errors-reference#approvalfailed-lclu1)
* Aave pool call reverts — may revert per Aave implementation

**Overrides:** None

**Function Calls:**

* [LibSafeMinimalBeneficiaryMultisig.\_checkIsMultisigExecutor()](#_checkismultisigexecutor-lsmb1) — LibSafeMinimalBeneficiaryMultisig, internal
* [LibCryptoLegacy.getCryptoLegacyStorage()](#getcryptolegacystorage-lcl1) — LibCryptoLegacy, internal
* [IERC20(asset).balanceOf(address)](#balanceof-iweth1) — IERC20, external (staticcall)
* [IERC20(aToken).balanceOf(address)](#balanceof-iweth1) — IERC20, external (staticcall)
* [LibCLUtils.approveToken(address,address,uint256)](#approvetoken-lclu1) — LibCLUtils, internal
* [IAaveV3Pool.supply(address,uint256,address,uint16)](#supply-iav3p1) — IAaveV3Pool, external
* [\_getAToken(address)](#_getatoken-balp1) — BeneficiaryAaveV3SupplyPlugin, internal
* [LibOneStepClaimMigration.migrate(ICryptoLegacy.CryptoLegacyStorage,address,address,uint256,uint256,uint256,uint256)](#migrate-loscm1) — LibOneStepClaimMigration, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1) plus external Aave and ERC-20 calls

**Example:** Beneficiaries approve a proposal that supplies idle USDC into Aave and tracks claims against the resulting aUSDC.

***

### baavesWithdraw (BALP1)

**Contract/Library:** BeneficiaryAaveV3SupplyPlugin

**Description:** Withdraws a reserve asset from Aave V3 and migrates beneficiary claims from the aToken back into the reserve asset.

**Detailed Description:** After the multisig executor check and zero-amount guard, the function resolves the reserve's aToken, snapshots aToken and asset balances, executes `IAaveV3Pool.withdraw(...)`, migrates claims from the aToken back into the underlying asset, and emits `AaveWithdraw`.

**Parameters:**

* asset (address): Reserve asset to withdraw
* amount (uint256): Asset amount to withdraw

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external nonpayable onlyDistributionReady

**Access Control:**

* Must be invoked by the beneficiary multisig executor after distribution starts

**Side Effects:**

* Burns the plugin's aToken balance in the Aave pool
* Increases the plugin's underlying asset balance
* Migrates beneficiary claims from the aToken back into `asset`

**Emits:**

* [AaveWithdraw](https://docs.cryptolegacy.app/documentation/events-reference#aavewithdraw-balp1) — `AaveWithdraw(address indexed asset, address indexed aToken, uint256 amount)`

**Reverts if:**

* Distribution not yet ready — [`TooEarly()`](https://docs.cryptolegacy.app/documentation/errors-reference#tooearly-icl1)
* Caller is not the multisig executor — [`MultisigOnlyExecutor()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisigonlyexecutor-ism1)
* `amount == 0` — [`ZeroAmount()`](https://docs.cryptolegacy.app/documentation/errors-reference#zeroamount-balp1)
* PoolDataProvider returns no aToken for `asset` — [`ATokenNotFound()`](https://docs.cryptolegacy.app/documentation/errors-reference#atokennotfound-balp1)
* Aave pool call reverts — may revert per Aave implementation

**Overrides:** None

**Function Calls:**

* [LibSafeMinimalBeneficiaryMultisig.\_checkIsMultisigExecutor()](#_checkismultisigexecutor-lsmb1) — LibSafeMinimalBeneficiaryMultisig, internal
* [LibCryptoLegacy.getCryptoLegacyStorage()](#getcryptolegacystorage-lcl1) — LibCryptoLegacy, internal
* [IERC20(aToken).balanceOf(address)](#balanceof-iweth1) — IERC20, external (staticcall)
* [IERC20(asset).balanceOf(address)](#balanceof-iweth1) — IERC20, external (staticcall)
* [IAaveV3Pool.withdraw(address,uint256,address)](#withdraw-iav3p1) — IAaveV3Pool, external
* [\_getAToken(address)](#_getatoken-balp1) — BeneficiaryAaveV3SupplyPlugin, internal
* [LibOneStepClaimMigration.migrate(ICryptoLegacy.CryptoLegacyStorage,address,address,uint256,uint256,uint256,uint256)](#migrate-loscm1) — LibOneStepClaimMigration, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1) plus external Aave and ERC-20 calls

**Example:** Beneficiaries approve a proposal that withdraws a portion of aUSDC back into USDC.

***

### baavesWrapATokenToStataToken (BALP1)

**Contract/Library:** BeneficiaryAaveV3SupplyPlugin

**Description:** Wraps rebasing aTokens into non-rebasing StataToken shares.

**Detailed Description:** Resolves the reserve's aToken and matching StataToken, optionally expands `type(uint256).max` to the full aToken balance, applies the required allowance reset pattern, deposits aTokens into the StataToken vault, migrates claims from the aToken into the StataToken shares, and emits `WrapATokenToStataToken`.

**Parameters:**

* asset (address): Reserve asset whose aToken should be wrapped
* aTokenAmount (uint256): aToken amount to wrap; `type(uint256).max` means "entire balance"

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external nonpayable onlyDistributionReady

**Access Control:**

* Must be invoked by the beneficiary multisig executor after distribution starts

**Side Effects:**

* Updates aToken allowance for the StataToken wrapper
* Converts the plugin's aToken holdings into StataToken shares
* Migrates beneficiary claims from the aToken into the StataToken

**Emits:**

* [WrapATokenToStataToken](https://docs.cryptolegacy.app/documentation/events-reference#wrapatokentostatatoken-balp1) — `WrapATokenToStataToken(address indexed aToken, address indexed stataToken, uint256 aTokenAmount, uint256 stataTokenReceived)`

**Reverts if:**

* Distribution not yet ready — [`TooEarly()`](https://docs.cryptolegacy.app/documentation/errors-reference#tooearly-icl1)
* Caller is not the multisig executor — [`MultisigOnlyExecutor()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisigonlyexecutor-ism1)
* Effective wrap amount is zero — [`ZeroAmount()`](https://docs.cryptolegacy.app/documentation/errors-reference#zeroamount-balp1)
* PoolDataProvider returns no aToken for `asset` — [`ATokenNotFound()`](https://docs.cryptolegacy.app/documentation/errors-reference#atokennotfound-balp1)
* StataTokenFactory returns no wrapper for `asset` — [`StataTokenNotFound()`](https://docs.cryptolegacy.app/documentation/errors-reference#statatokennotfound-balp1)
* ERC-20 approval helper fails — [`ApprovalFailed()`](https://docs.cryptolegacy.app/documentation/errors-reference#approvalfailed-lclu1)
* StataToken call reverts — may revert per vault implementation

**Overrides:** None

**Function Calls:**

* [LibSafeMinimalBeneficiaryMultisig.\_checkIsMultisigExecutor()](#_checkismultisigexecutor-lsmb1) — LibSafeMinimalBeneficiaryMultisig, internal
* [LibCryptoLegacy.getCryptoLegacyStorage()](#getcryptolegacystorage-lcl1) — LibCryptoLegacy, internal
* [\_getAToken(address)](#_getatoken-balp1) — BeneficiaryAaveV3SupplyPlugin, internal
* [\_getStataToken(address)](#_getstatatoken-balp1) — BeneficiaryAaveV3SupplyPlugin, internal
* [IERC20(aToken).balanceOf(address)](#balanceof-iweth1) — IERC20, external (staticcall)
* [IERC20(stataToken).balanceOf(address)](#balanceof-iweth1) — IERC20, external (staticcall)
* [LibCLUtils.approveToken(address,address,uint256)](#approvetoken-lclu1) — LibCLUtils, internal
* [IStataToken.depositATokens(uint256,address)](#depositatokens-ista1) — IStataToken, external
* [LibOneStepClaimMigration.migrate(ICryptoLegacy.CryptoLegacyStorage,address,address,uint256,uint256,uint256,uint256)](#migrate-loscm1) — LibOneStepClaimMigration, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1) plus ERC-20 and vault calls

**Example:** Beneficiaries convert rebasing aUSDC into a non-rebasing StataToken position before a downstream strategy uses it.

***

### baavesUnwrapStataTokenToAToken (BALP1)

**Contract/Library:** BeneficiaryAaveV3SupplyPlugin

**Description:** Redeems StataToken shares back into rebasing aTokens.

**Detailed Description:** Resolves the reserve's aToken and StataToken, snapshots balances, redeems the requested share amount via `redeemATokens(...)`, migrates claims from the StataToken back into the aToken, and emits `UnwrapStataTokenToAToken`.

**Parameters:**

* asset (address): Reserve asset whose StataToken should be redeemed
* stataTokenShares (uint256): Share amount to unwrap

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external nonpayable onlyDistributionReady

**Access Control:**

* Must be invoked by the beneficiary multisig executor after distribution starts

**Side Effects:**

* Burns StataToken shares held by the plugin
* Increases the plugin's aToken balance
* Migrates beneficiary claims from the StataToken into the aToken

**Emits:**

* [UnwrapStataTokenToAToken](https://docs.cryptolegacy.app/documentation/events-reference#unwrapstatatokentoatoken-balp1) — `UnwrapStataTokenToAToken(address indexed stataToken, address indexed aToken, uint256 stataTokenShares, uint256 aTokenReceived)`

**Reverts if:**

* Distribution not yet ready — [`TooEarly()`](https://docs.cryptolegacy.app/documentation/errors-reference#tooearly-icl1)
* Caller is not the multisig executor — [`MultisigOnlyExecutor()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisigonlyexecutor-ism1)
* `stataTokenShares == 0` — [`ZeroAmount()`](https://docs.cryptolegacy.app/documentation/errors-reference#zeroamount-balp1)
* PoolDataProvider returns no aToken for `asset` — [`ATokenNotFound()`](https://docs.cryptolegacy.app/documentation/errors-reference#atokennotfound-balp1)
* StataTokenFactory returns no wrapper for `asset` — [`StataTokenNotFound()`](https://docs.cryptolegacy.app/documentation/errors-reference#statatokennotfound-balp1)
* StataToken call reverts — may revert per vault implementation

**Overrides:** None

**Function Calls:**

* [LibSafeMinimalBeneficiaryMultisig.\_checkIsMultisigExecutor()](#_checkismultisigexecutor-lsmb1) — LibSafeMinimalBeneficiaryMultisig, internal
* [LibCryptoLegacy.getCryptoLegacyStorage()](#getcryptolegacystorage-lcl1) — LibCryptoLegacy, internal
* [\_getAToken(address)](#_getatoken-balp1) — BeneficiaryAaveV3SupplyPlugin, internal
* [\_getStataToken(address)](#_getstatatoken-balp1) — BeneficiaryAaveV3SupplyPlugin, internal
* [IERC20(stataToken).balanceOf(address)](#balanceof-iweth1) — IERC20, external (staticcall)
* [IERC20(aToken).balanceOf(address)](#balanceof-iweth1) — IERC20, external (staticcall)
* [IStataToken.redeemATokens(uint256,address,address)](#redeematokens-ista1) — IStataToken, external
* [LibOneStepClaimMigration.migrate(ICryptoLegacy.CryptoLegacyStorage,address,address,uint256,uint256,uint256,uint256)](#migrate-loscm1) — LibOneStepClaimMigration, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1) plus ERC-20 and vault calls

**Example:** Beneficiaries redeem StataToken shares back into aTokens before withdrawing from Aave.

***

### baavesDepositToStataToken (BALP1)

**Contract/Library:** BeneficiaryAaveV3SupplyPlugin

**Description:** Deposits a reserve asset directly into its StataToken wrapper in one step.

**Detailed Description:** Resolves the StataToken wrapper for `asset`, snapshots balances, clears and reapplies the allowance, deposits the reserve asset directly into the wrapper, migrates claims from the reserve asset into the wrapper shares, and emits `DepositToStataToken`.

**Parameters:**

* asset (address): Reserve asset to deposit
* amount (uint256): Asset amount to deposit

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external nonpayable onlyDistributionReady

**Access Control:**

* Must be invoked by the beneficiary multisig executor after distribution starts

**Side Effects:**

* Updates ERC-20 allowance for the StataToken wrapper
* Converts the reserve asset directly into StataToken shares
* Migrates beneficiary claims from `asset` into the wrapper shares

**Emits:**

* [DepositToStataToken](https://docs.cryptolegacy.app/documentation/events-reference#deposittostatatoken-balp1) — `DepositToStataToken(address indexed asset, address indexed stataToken, uint256 amount, uint256 stataTokenReceived)`

**Reverts if:**

* Distribution not yet ready — [`TooEarly()`](https://docs.cryptolegacy.app/documentation/errors-reference#tooearly-icl1)
* Caller is not the multisig executor — [`MultisigOnlyExecutor()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisigonlyexecutor-ism1)
* `amount == 0` — [`ZeroAmount()`](https://docs.cryptolegacy.app/documentation/errors-reference#zeroamount-balp1)
* StataTokenFactory returns no wrapper for `asset` — [`StataTokenNotFound()`](https://docs.cryptolegacy.app/documentation/errors-reference#statatokennotfound-balp1)
* ERC-20 approval helper fails — [`ApprovalFailed()`](https://docs.cryptolegacy.app/documentation/errors-reference#approvalfailed-lclu1)
* Vault deposit reverts — may revert per StataToken implementation

**Overrides:** None

**Function Calls:**

* [LibSafeMinimalBeneficiaryMultisig.\_checkIsMultisigExecutor()](#_checkismultisigexecutor-lsmb1) — LibSafeMinimalBeneficiaryMultisig, internal
* [LibCryptoLegacy.getCryptoLegacyStorage()](#getcryptolegacystorage-lcl1) — LibCryptoLegacy, internal
* [\_getStataToken(address)](#_getstatatoken-balp1) — BeneficiaryAaveV3SupplyPlugin, internal
* [IERC20(asset).balanceOf(address)](#balanceof-iweth1) — IERC20, external (staticcall)
* [IERC20(stataToken).balanceOf(address)](#balanceof-iweth1) — IERC20, external (staticcall)
* [LibCLUtils.approveToken(address,address,uint256)](#approvetoken-lclu1) — LibCLUtils, internal
* [IStataToken.deposit(uint256,address)](#deposit-ista1) — IStataToken, external
* [LibOneStepClaimMigration.migrate(ICryptoLegacy.CryptoLegacyStorage,address,address,uint256,uint256,uint256,uint256)](#migrate-loscm1) — LibOneStepClaimMigration, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1) plus ERC-20 and vault calls

**Example:** Beneficiaries deposit idle USDC directly into a StataToken wrapper instead of first minting aTokens.

***

### baavesRedeemFromStataToken (BALP1)

**Contract/Library:** BeneficiaryAaveV3SupplyPlugin

**Description:** Redeems StataToken shares directly into the reserve asset in one step.

**Detailed Description:** Resolves the StataToken wrapper for `asset`, snapshots share and reserve balances, redeems the requested share amount, migrates claims from the wrapper shares back into the reserve asset, and emits `RedeemFromStataToken`.

**Parameters:**

* asset (address): Reserve asset to receive
* stataTokenShares (uint256): Share amount to redeem

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external nonpayable onlyDistributionReady

**Access Control:**

* Must be invoked by the beneficiary multisig executor after distribution starts

**Side Effects:**

* Burns StataToken shares held by the plugin
* Increases the plugin's reserve-asset balance
* Migrates beneficiary claims from the wrapper shares back into the reserve asset

**Emits:**

* [RedeemFromStataToken](https://docs.cryptolegacy.app/documentation/events-reference#redeemfromstatatoken-balp1) — `RedeemFromStataToken(address indexed stataToken, address indexed asset, uint256 stataTokenShares, uint256 assetReceived)`

**Reverts if:**

* Distribution not yet ready — [`TooEarly()`](https://docs.cryptolegacy.app/documentation/errors-reference#tooearly-icl1)
* Caller is not the multisig executor — [`MultisigOnlyExecutor()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisigonlyexecutor-ism1)
* `stataTokenShares == 0` — [`ZeroAmount()`](https://docs.cryptolegacy.app/documentation/errors-reference#zeroamount-balp1)
* StataTokenFactory returns no wrapper for `asset` — [`StataTokenNotFound()`](https://docs.cryptolegacy.app/documentation/errors-reference#statatokennotfound-balp1)
* Vault redemption reverts — may revert per StataToken implementation

**Overrides:** None

**Function Calls:**

* [LibSafeMinimalBeneficiaryMultisig.\_checkIsMultisigExecutor()](#_checkismultisigexecutor-lsmb1) — LibSafeMinimalBeneficiaryMultisig, internal
* [LibCryptoLegacy.getCryptoLegacyStorage()](#getcryptolegacystorage-lcl1) — LibCryptoLegacy, internal
* [\_getStataToken(address)](#_getstatatoken-balp1) — BeneficiaryAaveV3SupplyPlugin, internal
* [IERC20(stataToken).balanceOf(address)](#balanceof-iweth1) — IERC20, external (staticcall)
* [IERC20(asset).balanceOf(address)](#balanceof-iweth1) — IERC20, external (staticcall)
* [IStataToken.redeem(uint256,address,address)](#redeem-ista1) — IStataToken, external
* [LibOneStepClaimMigration.migrate(ICryptoLegacy.CryptoLegacyStorage,address,address,uint256,uint256,uint256,uint256)](#migrate-loscm1) — LibOneStepClaimMigration, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1) plus ERC-20 and vault calls

**Example:** Beneficiaries redeem a StataToken position back into the underlying reserve asset.

***

### \_getAToken (BALP1)

**Contract/Library:** BeneficiaryAaveV3SupplyPlugin

**Description:** Resolves the aToken address for a given reserve asset.

**Detailed Description:** Queries the configured PoolDataProvider for reserve token addresses and returns the aToken component, reverting when the provider reports `address(0)`.

**Parameters:**

* asset (address): Reserve asset whose aToken should be resolved

**Returns:**

* aToken (address): aToken address for the reserve asset

**Modifiers / Visibility / Mutability:**

* private view

**Access Control:**

* Internal helper used only by this plugin

**Side Effects:** None

**Emits:** None

**Reverts if:**

* PoolDataProvider returns `address(0)` for the reserve — [`ATokenNotFound()`](https://docs.cryptolegacy.app/documentation/errors-reference#atokennotfound-balp1)
* PoolDataProvider call reverts — may revert per Aave implementation

**Overrides:** None

**Function Calls:**

* [IAaveV3PoolDataProvider.getReserveTokensAddresses(address)](#getreservetokensaddresses-iav3pdp1) — IAaveV3PoolDataProvider, external (staticcall)

**Called by:**

* [baavesSupply(address,uint256,uint16)](#baavessupply-balp1) — BeneficiaryAaveV3SupplyPlugin
* [baavesWithdraw(address,uint256)](#baaveswithdraw-balp1) — BeneficiaryAaveV3SupplyPlugin
* [baavesWrapATokenToStataToken(address,uint256)](#baaveswrapatokentostatatoken-balp1) — BeneficiaryAaveV3SupplyPlugin
* [baavesUnwrapStataTokenToAToken(address,uint256)](#baavesunwrapstatatokentoatoken-balp1) — BeneficiaryAaveV3SupplyPlugin

**Gas / Complexity note:** O(1) plus one external view call

**Example:** Not applicable

***

### \_getStataToken (BALP1)

**Contract/Library:** BeneficiaryAaveV3SupplyPlugin

**Description:** Resolves the StataToken wrapper address for a given reserve asset.

**Detailed Description:** Queries the configured StataTokenFactory and returns the wrapper address, reverting when the factory reports `address(0)` for the requested reserve.

**Parameters:**

* asset (address): Reserve asset whose wrapper should be resolved

**Returns:**

* stataToken (address): StataToken wrapper address for the reserve asset

**Modifiers / Visibility / Mutability:**

* private view

**Access Control:**

* Internal helper used only by this plugin

**Side Effects:** None

**Emits:** None

**Reverts if:**

* Factory returns `address(0)` for the reserve — [`StataTokenNotFound()`](https://docs.cryptolegacy.app/documentation/errors-reference#statatokennotfound-balp1)
* Factory call reverts — may revert per factory implementation

**Overrides:** None

**Function Calls:**

* [IStataTokenFactory.getStataToken(address)](#getstatatoken-istf1) — IStataTokenFactory, external (staticcall)

**Called by:**

* [baavesWrapATokenToStataToken(address,uint256)](#baaveswrapatokentostatatoken-balp1) — BeneficiaryAaveV3SupplyPlugin
* [baavesUnwrapStataTokenToAToken(address,uint256)](#baavesunwrapstatatokentoatoken-balp1) — BeneficiaryAaveV3SupplyPlugin
* [baavesDepositToStataToken(address,uint256)](#baavesdeposittostatatoken-balp1) — BeneficiaryAaveV3SupplyPlugin
* [baavesRedeemFromStataToken(address,uint256)](#baavesredeemfromstatatoken-balp1) — BeneficiaryAaveV3SupplyPlugin

**Gas / Complexity note:** O(1) plus one external view call

**Example:** Not applicable

***

## BeneficiaryLidoStakingPlugin (BLSP1)

### constructor (BLSP1)

**Contract/Library:** BeneficiaryLidoStakingPlugin

**Description:** Stores the helper contract used to unwrap WETH into native ETH for the Lido flows.

**Detailed Description:** Initializes the plugin with the external [`WETH_UNWRAP (BLSP-D9)`](https://docs.cryptolegacy.app/documentation/data-structures-reference#weth_unwrap-blsp1-d9) helper that converts WETH into ETH before staking into Lido or wrapping into wstETH. All other protocol endpoints used by the plugin remain hard-coded constants.

**Parameters:**

* wethUnwrap (address): Helper contract that pulls WETH, unwraps it, and returns ETH to this plugin

**Returns:** None

**Modifiers / Visibility / Mutability:**

* constructor nonpayable

**Access Control:**

* Unrestricted at deployment time

**Side Effects:**

* Sets [`WETH_UNWRAP (BLSP-D9)`](https://docs.cryptolegacy.app/documentation/data-structures-reference#weth_unwrap-blsp1-d9) once as immutable configuration

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:** None (deployment only)

**Gas / Complexity note:** O(1)

**Example:** `new BeneficiaryLidoStakingPlugin(wethUnwrap);`

***

### getSigs (BLSP1)

**Contract/Library:** BeneficiaryLidoStakingPlugin

**Description:** Returns the selectors exposed by the Lido beneficiary plugin.

**Detailed Description:** Builds the 19-selector array used by the diamond to register the multisig-management getters, Lido request/claim helpers, and the staking / wrapping execution entry points.

**Parameters:** None

**Returns:**

* sigs (bytes4\[], memory): Selector array covering the plugin's public surface

**Modifiers / Visibility / Mutability:**

* external pure

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:** None (entry point)

**Gas / Complexity note:** O(1) — fixed-length selector assembly

**Example:** Facet-registration tooling reads `getSigs()` before wiring the plugin into the diamond.

***

### getSetupSigs (BLSP1)

**Contract/Library:** BeneficiaryLidoStakingPlugin

**Description:** Returns the setup-time selectors required by the Lido beneficiary plugin.

**Detailed Description:** Returns an empty array, confirming that the plugin does not require any dedicated setup selectors during installation.

**Parameters:** None

**Returns:**

* sigs (bytes4\[], memory): Always an empty selector array

**Modifiers / Visibility / Mutability:**

* external pure

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Install flow checks `getSetupSigs()` and skips extra setup calls because the array is empty.

***

### getMultisigAllowedMethods (BLSP1)

**Contract/Library:** BeneficiaryLidoStakingPlugin

**Description:** Lists selectors that beneficiary multisig proposals are allowed to execute.

**Detailed Description:** Returns the eight Lido-facing execution selectors that the beneficiary multisig may schedule: stake / wrap flows, withdrawal requests, migration abandonment, and the unsafe-claim escape hatch.

**Parameters:** None

**Returns:**

* sigs (bytes4\[], memory): Allowed multisig method selectors

**Modifiers / Visibility / Mutability:**

* public pure

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:**

* [blsPropose(bytes4,bytes)](#blspropose-blsp1) — BeneficiaryLidoStakingPlugin

**Gas / Complexity note:** O(1)

**Example:** `blsPropose` checks this list before accepting a new Lido proposal.

***

### getPluginName (BLSP1)

**Contract/Library:** BeneficiaryLidoStakingPlugin

**Description:** Returns the unique plugin name string.

**Detailed Description:** Supplies the stable identifier `"beneficiary_lido_staking"` for registry displays, tooling, and plugin metadata views.

**Parameters:** None

**Returns:**

* name (string, memory): Static plugin name `"beneficiary_lido_staking"`

**Modifiers / Visibility / Mutability:**

* public pure

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Front-end uses `getPluginName()` to label the installed facet.

***

### getPluginVer (BLSP1)

**Contract/Library:** BeneficiaryLidoStakingPlugin

**Description:** Returns the semantic version for the Lido beneficiary plugin.

**Detailed Description:** Exposes the hard-coded version `1` so deployment and upgrade tooling can compare the installed facet against the expected release.

**Parameters:** None

**Returns:**

* version (uint16): Static plugin version `1`

**Modifiers / Visibility / Mutability:**

* external pure

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Upgrade tooling checks `getPluginVer()` before replacing the Lido facet.

***

### modifier onlyDistributionReady (BLSP1)

**Contract/Library:** BeneficiaryLidoStakingPlugin

**Description:** Restricts execution to phases where beneficiary distribution is already active.

**Detailed Description:** Loads CryptoLegacy storage and forwards it to `LibCryptoLegacy._checkDistributionReady(...)`, requiring the distribution-start timestamp to be set and already reached before the wrapped function proceeds.

**Parameters:** None

**Returns:** None

**Modifiers / Visibility / Mutability:**

* modifier nonpayable

**Access Control:**

* Distribution must already be active

**Side Effects:** None

**Emits:** None

**Reverts if:**

* Distribution not yet ready — [`TooEarly()`](https://docs.cryptolegacy.app/documentation/errors-reference#tooearly-icl1)

**Overrides:** None

**Function Calls:**

* [LibCryptoLegacy.getCryptoLegacyStorage()](#getcryptolegacystorage-lcl1) — LibCryptoLegacy, internal
* [LibCryptoLegacy.\_checkDistributionReady(ICryptoLegacy.CryptoLegacyStorage)](#_checkdistributionready-lcl1) — LibCryptoLegacy, internal

**Called by:**

* [blsPropose(bytes4,bytes)](#blspropose-blsp1) — BeneficiaryLidoStakingPlugin
* [blsConfirm(uint256)](#blsconfirm-blsp1) — BeneficiaryLidoStakingPlugin
* [blsCancel(uint256)](#blscancel-blsp1) — BeneficiaryLidoStakingPlugin
* [blsLidoStakeWethToStEth(uint256,address)](#blslidostakewethtosteth-blsp1) — BeneficiaryLidoStakingPlugin
* [blsLidoWrapWethToWstEth(uint256)](#blslidowrapwethtowsteth-blsp1) — BeneficiaryLidoStakingPlugin
* [blsLidoWrapStEthToWstEth(uint256)](#blslidowrapstethtowsteth-blsp1) — BeneficiaryLidoStakingPlugin
* [blsLidoUnwrapWstEthToStEth(uint256)](#blslidounwrapwstethtosteth-blsp1) — BeneficiaryLidoStakingPlugin

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### getPluginMultisigStorage (BLSP1)

**Contract/Library:** BeneficiaryLidoStakingPlugin

**Description:** Retrieves the plugin-specific multisig storage slot.

**Detailed Description:** Uses inline assembly to reinterpret [`PLUGIN_MULTISIG_POSITION (BLSP-D1)`](https://docs.cryptolegacy.app/documentation/data-structures-reference#plugin_multisig_position-blsp1-d1) as an `ISafeMinimalMultisig.Storage` reference shared by the plugin's multisig helpers and views.

**Parameters:** None

**Returns:**

* storageStruct (ISafeMinimalMultisig.Storage, storage): Multisig storage layout for this plugin

**Modifiers / Visibility / Mutability:**

* internal pure

**Access Control:**

* Internal helper used only by this plugin

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:**

* [blsSetMultisigConfig(uint128)](#blssetmultisigconfig-blsp1) — BeneficiaryLidoStakingPlugin
* [blsPropose(bytes4,bytes)](#blspropose-blsp1) — BeneficiaryLidoStakingPlugin
* [blsConfirm(uint256)](#blsconfirm-blsp1) — BeneficiaryLidoStakingPlugin
* [blsCancel(uint256)](#blscancel-blsp1) — BeneficiaryLidoStakingPlugin
* [blsGetInitializationStatus()](#blsgetinitializationstatus-blsp1) — BeneficiaryLidoStakingPlugin
* [blsGetVotersAndConfirmations()](#blsgetvotersandconfirmations-blsp1) — BeneficiaryLidoStakingPlugin
* [blsGetProposalWithStatus(uint256)](#blsgetproposalwithstatus-blsp1) — BeneficiaryLidoStakingPlugin
* [blsGetProposalListWithStatuses()](#blsgetproposallistwithstatuses-blsp1) — BeneficiaryLidoStakingPlugin

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### getPendingMigrationStorage (BLSP1)

**Contract/Library:** BeneficiaryLidoStakingPlugin

**Description:** Retrieves the plugin-local storage slot that holds the active two-step migration state.

**Detailed Description:** Uses [`PLUGIN_PENDING_MIGRATION_POSITION (BLSP-D2)`](https://docs.cryptolegacy.app/documentation/data-structures-reference#plugin_pending_migration_position-blsp1-d2) to expose the [`PendingMigrationStorage (LTSCM-S3)`](https://docs.cryptolegacy.app/documentation/data-structures-reference#pendingmigrationstorage-ltscm1-s3) layout reused by the Lido request / claim flow.

**Parameters:** None

**Returns:**

* storageStruct (LibTwoStepClaimMigration.PendingMigrationStorage, storage): Pending-migration storage layout for this plugin

**Modifiers / Visibility / Mutability:**

* internal pure

**Access Control:**

* Internal helper used only by this plugin

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:**

* [blsLidoGetPendingMigration()](#blslidogetpendingmigration-blsp1) — BeneficiaryLidoStakingPlugin
* [blsLidoRequestStEthWithdrawal(uint256\[\])](#blslidorequeststethwithdrawal-blsp1) — BeneficiaryLidoStakingPlugin
* [blsLidoRequestWstEthWithdrawal(uint256\[\])](#blslidorequestwstethwithdrawal-blsp1) — BeneficiaryLidoStakingPlugin
* [blsLidoClaimWithdrawals(uint256\[\])](#blslidoclaimwithdrawals-blsp1) — BeneficiaryLidoStakingPlugin
* [blsLidoUnsafeClaimWithdrawals(uint256\[\],uint256\[\])](#blslidounsafeclaimwithdrawals-blsp1) — BeneficiaryLidoStakingPlugin
* [blsLidoAbandonMigration()](#blslidoabandonmigration-blsp1) — BeneficiaryLidoStakingPlugin

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### getLidoWithdrawalStorage (BLSP1)

**Contract/Library:** BeneficiaryLidoStakingPlugin

**Description:** Retrieves the plugin-local storage slot that caches pending Lido withdrawal request IDs.

**Detailed Description:** Uses [`PLUGIN_LIDO_WITHDRAWAL_POSITION (BLSP-D3)`](https://docs.cryptolegacy.app/documentation/data-structures-reference#plugin_lido_withdrawal_position-blsp1-d3) to expose the [`LidoWithdrawalStorage (BLSP-S1)`](https://docs.cryptolegacy.app/documentation/data-structures-reference#lidowithdrawalstorage-blsp1-s1) struct that stores queued request identifiers between request and claim steps.

**Parameters:** None

**Returns:**

* storageStruct (LidoWithdrawalStorage, storage): Lido withdrawal request cache for this plugin

**Modifiers / Visibility / Mutability:**

* internal pure

**Access Control:**

* Internal helper used only by this plugin

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:**

* [blsLidoGetPendingRequestIds()](#blslidogetpendingrequestids-blsp1) — BeneficiaryLidoStakingPlugin
* [blsLidoClaimWithdrawals(uint256\[\])](#blslidoclaimwithdrawals-blsp1) — BeneficiaryLidoStakingPlugin
* [blsLidoAbandonMigration()](#blslidoabandonmigration-blsp1) — BeneficiaryLidoStakingPlugin
* [\_storeLidoRequestIds(uint256\[\])](#_storelidorequestids-blsp1) — BeneficiaryLidoStakingPlugin

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### getBeneficiarySwitchGuardStorage (BLSP1)

**Contract/Library:** BeneficiaryLidoStakingPlugin

**Description:** Retrieves the plugin-local guard storage that freezes beneficiary switching while migration is pending.

**Detailed Description:** Uses [`PLUGIN_BENEFICIARY_SWITCH_GUARD_POSITION (BLSP-D4)`](https://docs.cryptolegacy.app/documentation/data-structures-reference#plugin_beneficiary_switch_guard_position-blsp1-d4) to expose [`BeneficiarySwitchGuardStorage (BLSP-S2)`](https://docs.cryptolegacy.app/documentation/data-structures-reference#beneficiaryswitchguardstorage-blsp1-s2), which snapshots and restores switch timelocks.

**Parameters:** None

**Returns:**

* storageStruct (BeneficiarySwitchGuardStorage, storage): Switch-guard storage layout for this plugin

**Modifiers / Visibility / Mutability:**

* internal pure

**Access Control:**

* Internal helper used only by this plugin

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:**

* [\_activateBeneficiarySwitchGuard(ICryptoLegacy.CryptoLegacyStorage)](#_activatebeneficiaryswitchguard-blsp1) — BeneficiaryLidoStakingPlugin
* [\_releaseBeneficiarySwitchGuard(ICryptoLegacy.CryptoLegacyStorage)](#_releasebeneficiaryswitchguard-blsp1) — BeneficiaryLidoStakingPlugin

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### blsSetMultisigConfig (BLSP1)

**Contract/Library:** BeneficiaryLidoStakingPlugin

**Description:** Updates the beneficiary multisig confirmation threshold for the Lido plugin.

**Detailed Description:** If called by the contract itself, the function rechecks distribution readiness; otherwise it enforces owner authority. It then loads the current beneficiary set and forwards the new threshold to `LibSafeMinimalBeneficiaryMultisig._setConfirmations(...)`.

**Parameters:**

* \_requiredConfirmations (uint128): Desired confirmation threshold

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external nonpayable

**Access Control:**

* Owner when called externally; `address(this)` may call it once distribution is ready

**Side Effects:**

* Updates `requiredConfirmations` inside plugin multisig storage

**Emits:**

* [SetConfirmations](https://docs.cryptolegacy.app/documentation/events-reference#setconfirmations-ism1) — `SetConfirmations(uint128 requiredConfirmations)`

**Reverts if:**

* Distribution already started on the owner path — [`DistributionStarted()`](https://docs.cryptolegacy.app/documentation/errors-reference#distributionstarted-icl1)
* Initial fee unpaid on the owner path — [`InitialFeeNotPaid()`](https://docs.cryptolegacy.app/documentation/errors-reference#initialfeenotpaid-icl1)
* Caller is not owner on the owner path — [`NotTheOwner()`](https://docs.cryptolegacy.app/documentation/errors-reference#nottheowner-icl1)
* Distribution not yet ready on the self-call path — [`TooEarly()`](https://docs.cryptolegacy.app/documentation/errors-reference#tooearly-icl1)
* Invalid threshold for the current beneficiary set — [`MultisigIncorrectRequiredConfirmations()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisigincorrectrequiredconfirmations-ism1)

**Overrides:** None

**Function Calls:**

* [LibCryptoLegacy.getCryptoLegacyStorage()](#getcryptolegacystorage-lcl1) — LibCryptoLegacy, internal
* [LibCryptoLegacy.\_checkDistributionReady(ICryptoLegacy.CryptoLegacyStorage)](#_checkdistributionready-lcl1) — LibCryptoLegacy, internal
* [LibCryptoLegacy.\_checkOwner()](#_checkowner-lcl1) — LibCryptoLegacy, internal
* [getPluginMultisigStorage()](#getpluginmultisigstorage-blsp1) — BeneficiaryLidoStakingPlugin, internal
* [LibSafeMinimalBeneficiaryMultisig.\_setConfirmations(...)](#_setconfirmations-lsmb1) — LibSafeMinimalBeneficiaryMultisig, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(b) by number of beneficiaries

**Example:** Owner raises the number of beneficiary confirmations required for Lido actions.

***

### blsPropose (BLSP1)

**Contract/Library:** BeneficiaryLidoStakingPlugin

**Description:** Creates a multisig proposal for an allowed Lido beneficiary action.

**Detailed Description:** Requires distribution to be active, validates the caller as an allowed beneficiary voter, checks the requested selector against the plugin allowlist, and records a proposal that may execute immediately if only one confirmation is required.

**Parameters:**

* \_selector (bytes4): Target function selector
* \_params (bytes, memory): ABI-encoded arguments for the target call

**Returns:**

* proposalId (uint256): Newly created proposal index

**Modifiers / Visibility / Mutability:**

* external nonpayable nonReentrant onlyDistributionReady

**Access Control:**

* Caller must be an authorized beneficiary voter

**Side Effects:**

* Appends a proposal to plugin multisig storage
* Records the proposer's confirmation and may execute immediately

**Emits:**

* [CreateSafeMinimalMultisigProposal](https://docs.cryptolegacy.app/documentation/events-reference#createsafeminimalmultisigproposal-ism1) — `CreateSafeMinimalMultisigProposal(uint256 proposalId, bytes32 voter, uint128 reqConfirmations)`
* [ExecuteSafeMinimalMultisigProposal](https://docs.cryptolegacy.app/documentation/events-reference#executesafeminimalmultisigproposal-ism1) — `ExecuteSafeMinimalMultisigProposal(uint256 proposalId, bytes32 voter, bool executed, bytes returnData)` (when quorum is reached immediately)

**Reverts if:**

* Distribution not yet ready — [`TooEarly()`](https://docs.cryptolegacy.app/documentation/errors-reference#tooearly-icl1)
* Reentrant call — "ReentrancyGuard: reentrant call"
* Caller is not an allowed voter — [`MultisigVoterNotAllowed()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisigvoternotallowed-ism1)
* Selector is not in the plugin allowlist — [`MultisigMethodNotAllowed()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisigmethodnotallowed-ism1)
* Execution of the approved action fails — [`MultisigExecutionFailed()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisigexecutionfailed-ism1)

**Overrides:** None

**Function Calls:**

* [getPluginMultisigStorage()](#getpluginmultisigstorage-blsp1) — BeneficiaryLidoStakingPlugin, internal
* [getMultisigAllowedMethods()](#getmultisigallowedmethods-blsp1) — BeneficiaryLidoStakingPlugin, internal
* [LibSafeMinimalBeneficiaryMultisig.\_propose(...)](#_propose-lsmb1) — LibSafeMinimalBeneficiaryMultisig, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(b) by beneficiary count

**Example:** Beneficiary voter proposes a Lido withdrawal request after distribution starts.

***

### blsConfirm (BLSP1)

**Contract/Library:** BeneficiaryLidoStakingPlugin

**Description:** Confirms an existing Lido plugin proposal and executes it once quorum is reached.

**Detailed Description:** Validates the caller as an allowed voter, records their confirmation, recomputes the confirmation count, and executes the underlying action when the multisig threshold is met.

**Parameters:**

* \_proposalId (uint256): Proposal index to confirm

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external nonpayable nonReentrant onlyDistributionReady

**Access Control:**

* Caller must be an authorized beneficiary voter

**Side Effects:**

* Updates per-proposal confirmation state
* May execute the underlying Lido action

**Emits:**

* [ConfirmSafeMinimalMultisigProposal](https://docs.cryptolegacy.app/documentation/events-reference#confirmsafeminimalmultisigproposal-ism1) — `ConfirmSafeMinimalMultisigProposal(uint256 proposalId, bytes32 voter, uint128 reqConfirmations, uint256 confirms)`
* [ExecuteSafeMinimalMultisigProposal](https://docs.cryptolegacy.app/documentation/events-reference#executesafeminimalmultisigproposal-ism1) — `ExecuteSafeMinimalMultisigProposal(uint256 proposalId, bytes32 voter, bool executed, bytes returnData)` (on execution)

**Reverts if:**

* Distribution not yet ready — [`TooEarly()`](https://docs.cryptolegacy.app/documentation/errors-reference#tooearly-icl1)
* Reentrant call — "ReentrancyGuard: reentrant call"
* Caller is not an allowed voter — [`MultisigVoterNotAllowed()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisigvoternotallowed-ism1)
* `_proposalId` out of range — `panic(0x32)`
* Proposal not pending — [`MultisigProposalNotPending()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisigproposalnotpending-ism1)
* Execution of the approved action fails — [`MultisigExecutionFailed()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisigexecutionfailed-ism1)

**Overrides:** None

**Function Calls:**

* [getPluginMultisigStorage()](#getpluginmultisigstorage-blsp1) — BeneficiaryLidoStakingPlugin, internal
* [LibSafeMinimalBeneficiaryMultisig.\_confirm(...)](#_confirm-lsmb1) — LibSafeMinimalBeneficiaryMultisig, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(b) by beneficiary count

**Example:** Second beneficiary confirms a pending Lido withdrawal proposal.

***

### blsCancel (BLSP1)

**Contract/Library:** BeneficiaryLidoStakingPlugin

**Description:** Removes the caller's confirmation from a pending Lido multisig proposal.

**Detailed Description:** Ensures distribution is active, validates the caller against the voter set, clears their confirmation flag, recomputes the confirmation count, and cancels the proposal if no confirmations remain.

**Parameters:**

* \_proposalId (uint256): Proposal index to un-confirm

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external nonpayable nonReentrant onlyDistributionReady

**Access Control:**

* Caller must be an authorized voter who previously confirmed

**Side Effects:**

* Updates confirmation bookkeeping; may set proposal status to `CANCELED`

**Emits:**

* [CancelSafeMinimalMultisigProposal](https://docs.cryptolegacy.app/documentation/events-reference#cancelsafeminimalmultisigproposal-ism1) — `CancelSafeMinimalMultisigProposal(uint256 proposalId, bytes32 voter, uint128 reqConfirmations, ISafeMinimalMultisig.ProposalStatus status)`

**Reverts if:**

* Distribution not yet ready — [`TooEarly()`](https://docs.cryptolegacy.app/documentation/errors-reference#tooearly-icl1)
* Reentrant call — "ReentrancyGuard: reentrant call"
* Caller is not an authorized voter — [`MultisigVoterNotAllowed()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisigvoternotallowed-ism1)
* `_proposalId` out of range — `panic(0x32)`
* Proposal not pending — [`MultisigProposalNotPending()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisigproposalnotpending-ism1)
* Caller had not confirmed — [`MultisigNotConfirmed()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisignotconfirmed-ism1)

**Overrides:** None

**Function Calls:**

* [getPluginMultisigStorage()](#getpluginmultisigstorage-blsp1) — BeneficiaryLidoStakingPlugin, internal
* [LibSafeMinimalBeneficiaryMultisig.\_cancel(...)](#_cancel-lsmb1) — LibSafeMinimalBeneficiaryMultisig, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(b) by beneficiary count

**Example:** Beneficiary retracts support for a pending staking proposal.

***

### blsGetInitializationStatus (BLSP1)

**Contract/Library:** BeneficiaryLidoStakingPlugin

**Description:** Reports whether the plugin multisig configuration has been initialized.

**Detailed Description:** Delegates to `LibSafeMinimalBeneficiaryMultisig._initializationStatus(...)` to determine if required confirmations are already set or if initialization is still pending.

**Parameters:** None

**Returns:**

* status (ISafeMinimalMultisig.InitializationStatus): Current initialization state

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [getPluginMultisigStorage()](#getpluginmultisigstorage-blsp1) — BeneficiaryLidoStakingPlugin, internal
* [LibSafeMinimalBeneficiaryMultisig.\_initializationStatus(...)](#_initializationstatus-lsmb1) — LibSafeMinimalBeneficiaryMultisig, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** UI checks if the Lido plugin multisig still needs confirmation setup.

***

### blsGetVotersAndConfirmations (BLSP1)

**Contract/Library:** BeneficiaryLidoStakingPlugin

**Description:** Returns the current multisig voter list and confirmation threshold for the Lido plugin.

**Detailed Description:** Fetches the beneficiary set, computes or returns the stored confirmation requirement, and exposes both pieces of data for UI and review flows.

**Parameters:** None

**Returns:**

* voters (bytes32\[], memory): Beneficiary voter identifiers
* requiredConfirmations (uint128): Confirmations required to execute proposals

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [getPluginMultisigStorage()](#getpluginmultisigstorage-blsp1) — BeneficiaryLidoStakingPlugin, internal
* [LibSafeMinimalBeneficiaryMultisig.\_getVotersAndConfirmations(...)](#_getvotersandconfirmations-lsmb1) — LibSafeMinimalBeneficiaryMultisig, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(b) by beneficiary count

**Example:** UI surfaces current multisig configuration for the Lido facet.

***

### blsGetProposalWithStatus (BLSP1)

**Contract/Library:** BeneficiaryLidoStakingPlugin

**Description:** Fetches a single proposal and its per-voter confirmation flags.

**Detailed Description:** Retrieves the beneficiary voter list, loads the indexed proposal, builds the confirmation bitmap, and returns the derived metadata together with the confirmation threshold.

**Parameters:**

* \_proposalId (uint256): Proposal index to inspect

**Returns:**

* voters (bytes32\[], memory): Eligible voter identifiers
* requiredConfirmations (uint128): Confirmation threshold
* proposalWithStatus (ISafeMinimalMultisig.ProposalWithStatus, memory): Proposal and confirmation flags

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:**

* `_proposalId` out of range — `panic(0x32)`

**Overrides:** None

**Function Calls:**

* [LibCryptoLegacy.getCryptoLegacyStorage()](#getcryptolegacystorage-lcl1) — LibCryptoLegacy, internal
* [getPluginMultisigStorage()](#getpluginmultisigstorage-blsp1) — BeneficiaryLidoStakingPlugin, internal
* [LibSafeMinimalBeneficiaryMultisig.\_getProposalWithStatus(...)](#_getproposalwithstatus-lsmb1) — LibSafeMinimalBeneficiaryMultisig, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(b) by beneficiary count

**Example:** Operator inspects a queued Lido proposal before confirming it.

***

### blsGetProposalListWithStatuses (BLSP1)

**Contract/Library:** BeneficiaryLidoStakingPlugin

**Description:** Returns all plugin proposals with confirmation metadata.

**Detailed Description:** Collects the voter list, computes the confirmation requirement, and builds an array of proposal snapshots for every entry stored in the plugin multisig.

**Parameters:** None

**Returns:**

* voters (bytes32\[], memory): Eligible voter identifiers
* requiredConfirmations (uint128): Confirmation threshold
* proposalsWithStatuses (ISafeMinimalMultisig.ProposalWithStatus\[], memory): Proposals plus confirmation flags

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [LibCryptoLegacy.getCryptoLegacyStorage()](#getcryptolegacystorage-lcl1) — LibCryptoLegacy, internal
* [getPluginMultisigStorage()](#getpluginmultisigstorage-blsp1) — BeneficiaryLidoStakingPlugin, internal
* [LibSafeMinimalBeneficiaryMultisig.\_getProposalListWithStatuses(...)](#_getproposallistwithstatuses-lsmb1) — LibSafeMinimalBeneficiaryMultisig, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(b + p·b) where b = beneficiary count, p = proposal count

**Example:** UI lists every queued or executed Lido proposal with confirmation state.

***

### blsLidoGetPendingRequestIds (BLSP1)

**Contract/Library:** BeneficiaryLidoStakingPlugin

**Description:** Returns the currently cached Lido withdrawal request IDs used by the fair-claim path.

**Detailed Description:** Reads [`LidoWithdrawalStorage (BLSP-S1)`](https://docs.cryptolegacy.app/documentation/data-structures-reference#lidowithdrawalstorage-blsp1-s1) and returns the pending request IDs that were stored when the plugin submitted withdrawal requests.

**Parameters:** None

**Returns:**

* requestIds (uint256\[], memory): Pending Lido withdrawal request identifiers

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [getLidoWithdrawalStorage()](#getlidowithdrawalstorage-blsp1) — BeneficiaryLidoStakingPlugin, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(n) by pending request count

**Example:** Operator checks which Lido request IDs are still waiting to be claimed.

***

### blsLidoGetPendingMigration (BLSP1)

**Contract/Library:** BeneficiaryLidoStakingPlugin

**Description:** Returns the details of the currently pending two-step migration.

**Detailed Description:** Reads the active [`PendingMigrationStorage (LTSCM-S3)`](https://docs.cryptolegacy.app/documentation/data-structures-reference#pendingmigrationstorage-ltscm1-s3) record and surfaces whether a migration is active together with the source token, destination token, amount, and pre-withdrawal snapshot.

**Parameters:** None

**Returns:**

* active (bool): True when a migration is pending
* tokenOut (address): Source token address
* tokenIn (address): Destination token address
* amountOut (uint256): Source-token amount removed when the migration started
* outBalanceBefore (uint256): Source-token balance snapshot captured before the request

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [getPendingMigrationStorage()](#getpendingmigrationstorage-blsp1) — BeneficiaryLidoStakingPlugin, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** UI checks whether a Lido withdrawal request still has an unresolved migration.

***

### blsLidoStakeWethToStEth (BLSP1)

**Contract/Library:** BeneficiaryLidoStakingPlugin

**Description:** Unwraps WETH and stakes the resulting ETH into Lido, minting stETH.

**Detailed Description:** Restricted to the beneficiary multisig executor after distribution starts. The function unwraps WETH through [`WethUnwrap`](#unwrap_weth-wu1), verifies the ETH delta matches the requested amount, resolves the effective referral, submits the ETH to [`ILido.submit(address)`](#submit-ild1), refreshes WETH and stETH distribution balances, and emits [`StakeWethToStEth`](https://docs.cryptolegacy.app/documentation/events-reference#stakewethtosteth-blsp1).

**Parameters:**

* wethAmount (uint256): Amount of WETH to unwrap and stake
* referral (address): Optional Lido referral; zero address falls back to [`LIDO_REFERRAL (BLSP-D10)`](https://docs.cryptolegacy.app/documentation/data-structures-reference#lido_referral-blsp1-d10)

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external nonpayable onlyDistributionReady

**Access Control:**

* Restricted to the beneficiary multisig executor after distribution starts

**Side Effects:**

* Approves [`WETH_UNWRAP (BLSP-D9)`](https://docs.cryptolegacy.app/documentation/data-structures-reference#weth_unwrap-blsp1-d9) to pull WETH
* Converts WETH into ETH and stakes the ETH into Lido
* Updates `cls.tokenDistribution[WETH].lastBalance` and `cls.tokenDistribution[stETH].lastBalance`

**Emits:**

* [StakeWethToStEth](https://docs.cryptolegacy.app/documentation/events-reference#stakewethtosteth-blsp1) — `StakeWethToStEth(uint256 wethAmount, uint256 sharesMinted)`

**Reverts if:**

* Distribution not yet ready — [`TooEarly()`](https://docs.cryptolegacy.app/documentation/errors-reference#tooearly-icl1)
* Caller is not the multisig executor — [`MultisigOnlyExecutor()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisigonlyexecutor-ism1)
* `wethAmount == 0` — [`ZeroWethAmount()`](https://docs.cryptolegacy.app/documentation/errors-reference#zerowethamount-blsp1)
* Unwrapped ETH delta differs from `wethAmount` — [`WethUnwrapAmountMismatch()`](https://docs.cryptolegacy.app/documentation/errors-reference#wethunwrapamountmismatch-blsp1)
* [`WethUnwrap.unwrap_weth(uint256,bytes)`](#unwrap_weth-wu1) fails — bubbled
* [`ILido.submit(address)`](#submit-ild1) fails — bubbled from Lido

**Overrides:** None

**Function Calls:**

* [LibSafeMinimalBeneficiaryMultisig.\_checkIsMultisigExecutor()](#_checkismultisigexecutor-lsmb1) — LibSafeMinimalBeneficiaryMultisig, internal
* [LibCryptoLegacy.getCryptoLegacyStorage()](#getcryptolegacystorage-lcl1) — LibCryptoLegacy, internal
* [LibCryptoLegacy.\_checkDistributionReady(ICryptoLegacy.CryptoLegacyStorage)](#_checkdistributionready-lcl1) — LibCryptoLegacy, internal
* `IERC20(WETH).approve(address,uint256)` — IERC20, external
* [WethUnwrap.unwrap\_weth(uint256,bytes)](#unwrap_weth-wu1) — WethUnwrap, external
* [ILido.submit(address)](#submit-ild1) — ILido, external
* `IERC20(WETH).balanceOf(address)` — IERC20, external (staticcall)
* `IERC20(stETH).balanceOf(address)` — IERC20, external (staticcall)

**Called by:** None (entry point)

**Gas / Complexity note:** O(1) plus the external unwrap and Lido staking costs

**Example:** Beneficiaries approve a multisig proposal to convert idle WETH into rebasing stETH.

***

### blsLidoWrapWethToWstEth (BLSP1)

**Contract/Library:** BeneficiaryLidoStakingPlugin

**Description:** Unwraps WETH and wraps the resulting ETH directly into wstETH.

**Detailed Description:** Restricted to the beneficiary multisig executor after distribution starts. The function unwraps WETH through [`WethUnwrap`](#unwrap_weth-wu1), verifies the ETH delta, forwards the ETH to [`wstETH (BLSP-D7)`](https://docs.cryptolegacy.app/documentation/data-structures-reference#wsteth-blsp1-d7) via payable fallback, updates WETH / wstETH distribution balances, and emits [`WrapWethToWstEth`](https://docs.cryptolegacy.app/documentation/events-reference#wrapwethtowsteth-blsp1).

**Parameters:**

* wethAmount (uint256): Amount of WETH to unwrap and wrap into wstETH

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external nonpayable onlyDistributionReady

**Access Control:**

* Restricted to the beneficiary multisig executor after distribution starts

**Side Effects:**

* Approves [`WETH_UNWRAP (BLSP-D9)`](https://docs.cryptolegacy.app/documentation/data-structures-reference#weth_unwrap-blsp1-d9) to pull WETH
* Converts WETH into ETH and forwards the ETH into the wstETH wrapper
* Updates `cls.tokenDistribution[WETH].lastBalance` and `cls.tokenDistribution[wstETH].lastBalance`

**Emits:**

* [WrapWethToWstEth](https://docs.cryptolegacy.app/documentation/events-reference#wrapwethtowsteth-blsp1) — `WrapWethToWstEth(uint256 wethAmount, uint256 wstEthMinted)`

**Reverts if:**

* Distribution not yet ready — [`TooEarly()`](https://docs.cryptolegacy.app/documentation/errors-reference#tooearly-icl1)
* Caller is not the multisig executor — [`MultisigOnlyExecutor()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisigonlyexecutor-ism1)
* `wethAmount == 0` — [`ZeroWethAmount()`](https://docs.cryptolegacy.app/documentation/errors-reference#zerowethamount-blsp1)
* Unwrapped ETH delta differs from `wethAmount` — [`WethUnwrapAmountMismatch()`](https://docs.cryptolegacy.app/documentation/errors-reference#wethunwrapamountmismatch-blsp1)
* ETH forwarding to the wstETH contract fails — [`WstEthWrapFailed()`](https://docs.cryptolegacy.app/documentation/errors-reference#wstethwrapfailed-blsp1)

**Overrides:** None

**Function Calls:**

* [LibSafeMinimalBeneficiaryMultisig.\_checkIsMultisigExecutor()](#_checkismultisigexecutor-lsmb1) — LibSafeMinimalBeneficiaryMultisig, internal
* [LibCryptoLegacy.getCryptoLegacyStorage()](#getcryptolegacystorage-lcl1) — LibCryptoLegacy, internal
* [LibCryptoLegacy.\_checkDistributionReady(ICryptoLegacy.CryptoLegacyStorage)](#_checkdistributionready-lcl1) — LibCryptoLegacy, internal
* `IERC20(WETH).approve(address,uint256)` — IERC20, external
* [WethUnwrap.unwrap\_weth(uint256,bytes)](#unwrap_weth-wu1) — WethUnwrap, external
* `payable(wstETH).call(bytes)` — address, external
* `IERC20(WETH).balanceOf(address)` — IERC20, external (staticcall)
* `IERC20(wstETH).balanceOf(address)` — IERC20, external (staticcall)

**Called by:** None (entry point)

**Gas / Complexity note:** O(1) plus unwrap and wrapping costs

**Example:** Beneficiaries convert WETH into non-rebasing wstETH through the multisig flow.

***

### blsLidoRequestStEthWithdrawal (BLSP1)

**Contract/Library:** BeneficiaryLidoStakingPlugin

**Description:** Requests stETH withdrawals from the Lido withdrawal queue and starts a pending migration to WETH.

**Detailed Description:** Restricted to the beneficiary multisig executor after distribution starts. The function validates a non-empty amount list, approves the queue for the full stETH balance, submits the withdrawal request, records the pending request IDs, starts a [`LibTwoStepClaimMigration`](#start-ltscm1) from stETH to WETH, activates the beneficiary-switch guard, and emits [`RequestStEthWithdrawal`](https://docs.cryptolegacy.app/documentation/events-reference#requeststethwithdrawal-blsp1).

**Parameters:**

* stEthAmounts (uint256\[], calldata): stETH amounts to queue for withdrawal

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external nonpayable

**Access Control:**

* Restricted to the beneficiary multisig executor after distribution starts

**Side Effects:**

* Approves [`LIDO_WITHDRAWAL_QUEUE (BLSP-D8)`](https://docs.cryptolegacy.app/documentation/data-structures-reference#lido_withdrawal_queue-blsp1-d8) to pull stETH
* Stores pending request IDs in [`LidoWithdrawalStorage (BLSP-S1)`](https://docs.cryptolegacy.app/documentation/data-structures-reference#lidowithdrawalstorage-blsp1-s1)
* Starts a two-step migration from stETH to WETH and freezes beneficiary switching

**Emits:**

* [RequestStEthWithdrawal](https://docs.cryptolegacy.app/documentation/events-reference#requeststethwithdrawal-blsp1) — `RequestStEthWithdrawal(uint256[] requestIds, uint256[] stEthAmounts)`

**Reverts if:**

* Distribution not yet ready — [`TooEarly()`](https://docs.cryptolegacy.app/documentation/errors-reference#tooearly-icl1)
* Caller is not the multisig executor — [`MultisigOnlyExecutor()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisigonlyexecutor-ism1)
* `stEthAmounts.length == 0` — [`EmptyWithdrawalAmounts()`](https://docs.cryptolegacy.app/documentation/errors-reference#emptywithdrawalamounts-blsp1)
* Migration already active and switch guard cannot be re-armed — [`BeneficiarySwitchGuardAlreadyActive()`](https://docs.cryptolegacy.app/documentation/errors-reference#beneficiaryswitchguardalreadyactive-blsp1)
* [`ILidoWithdrawalQueue.requestWithdrawals(uint256[],address)`](#requestwithdrawals-ilwq1) fails — bubbled
* [`LibTwoStepClaimMigration.start(...)`](#start-ltscm1) fails — bubbled

**Overrides:** None

**Function Calls:**

* [LibSafeMinimalBeneficiaryMultisig.\_checkIsMultisigExecutor()](#_checkismultisigexecutor-lsmb1) — LibSafeMinimalBeneficiaryMultisig, internal
* [LibCryptoLegacy.getCryptoLegacyStorage()](#getcryptolegacystorage-lcl1) — LibCryptoLegacy, internal
* [LibCryptoLegacy.\_checkDistributionReady(ICryptoLegacy.CryptoLegacyStorage)](#_checkdistributionready-lcl1) — LibCryptoLegacy, internal
* `IERC20(stETH).balanceOf(address)` — IERC20, external (staticcall)
* `IERC20(stETH).approve(address,uint256)` — IERC20, external
* [ILidoWithdrawalQueue.requestWithdrawals(uint256\[\],address)](#requestwithdrawals-ilwq1) — ILidoWithdrawalQueue, external
* [getPendingMigrationStorage()](#getpendingmigrationstorage-blsp1) — BeneficiaryLidoStakingPlugin, internal
* [LibTwoStepClaimMigration.start(ICryptoLegacy.CryptoLegacyStorage,LibTwoStepClaimMigration.PendingMigrationStorage,address,address,uint256,uint256)](#start-ltscm1) — LibTwoStepClaimMigration, internal
* [\_activateBeneficiarySwitchGuard(ICryptoLegacy.CryptoLegacyStorage)](#_activatebeneficiaryswitchguard-blsp1) — BeneficiaryLidoStakingPlugin, internal
* [\_storeLidoRequestIds(uint256\[\])](#_storelidorequestids-blsp1) — BeneficiaryLidoStakingPlugin, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(n) by `stEthAmounts.length` plus migration snapshot cost by beneficiary count

**Example:** Beneficiaries queue a set of stETH withdrawals that will later settle into WETH.

***

### blsLidoRequestWstEthWithdrawal (BLSP1)

**Contract/Library:** BeneficiaryLidoStakingPlugin

**Description:** Requests wstETH withdrawals from the Lido withdrawal queue and starts a pending migration to WETH.

**Detailed Description:** Restricted to the beneficiary multisig executor after distribution starts. The function validates a non-empty amount list, approves the queue for the full wstETH balance, submits the withdrawal request, records the pending request IDs, starts a two-step migration from wstETH to WETH, activates the beneficiary-switch guard, and emits [`RequestWstEthWithdrawal`](https://docs.cryptolegacy.app/documentation/events-reference#requestwstethwithdrawal-blsp1).

**Parameters:**

* wstEthAmounts (uint256\[], calldata): wstETH amounts to queue for withdrawal

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external nonpayable

**Access Control:**

* Restricted to the beneficiary multisig executor after distribution starts

**Side Effects:**

* Approves [`LIDO_WITHDRAWAL_QUEUE (BLSP-D8)`](https://docs.cryptolegacy.app/documentation/data-structures-reference#lido_withdrawal_queue-blsp1-d8) to pull wstETH
* Stores pending request IDs in [`LidoWithdrawalStorage (BLSP-S1)`](https://docs.cryptolegacy.app/documentation/data-structures-reference#lidowithdrawalstorage-blsp1-s1)
* Starts a two-step migration from wstETH to WETH and freezes beneficiary switching

**Emits:**

* [RequestWstEthWithdrawal](https://docs.cryptolegacy.app/documentation/events-reference#requestwstethwithdrawal-blsp1) — `RequestWstEthWithdrawal(uint256[] requestIds, uint256[] wstEthAmounts)`

**Reverts if:**

* Distribution not yet ready — [`TooEarly()`](https://docs.cryptolegacy.app/documentation/errors-reference#tooearly-icl1)
* Caller is not the multisig executor — [`MultisigOnlyExecutor()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisigonlyexecutor-ism1)
* `wstEthAmounts.length == 0` — [`EmptyWithdrawalAmounts()`](https://docs.cryptolegacy.app/documentation/errors-reference#emptywithdrawalamounts-blsp1)
* Migration already active and switch guard cannot be re-armed — [`BeneficiarySwitchGuardAlreadyActive()`](https://docs.cryptolegacy.app/documentation/errors-reference#beneficiaryswitchguardalreadyactive-blsp1)
* [`ILidoWithdrawalQueue.requestWithdrawalsWstETH(uint256[],address)`](#requestwithdrawalswsteth-ilwq1) fails — bubbled

**Overrides:** None

**Function Calls:**

* [LibSafeMinimalBeneficiaryMultisig.\_checkIsMultisigExecutor()](#_checkismultisigexecutor-lsmb1) — LibSafeMinimalBeneficiaryMultisig, internal
* [LibCryptoLegacy.getCryptoLegacyStorage()](#getcryptolegacystorage-lcl1) — LibCryptoLegacy, internal
* [LibCryptoLegacy.\_checkDistributionReady(ICryptoLegacy.CryptoLegacyStorage)](#_checkdistributionready-lcl1) — LibCryptoLegacy, internal
* `IERC20(wstETH).balanceOf(address)` — IERC20, external (staticcall)
* `IERC20(wstETH).approve(address,uint256)` — IERC20, external
* [ILidoWithdrawalQueue.requestWithdrawalsWstETH(uint256\[\],address)](#requestwithdrawalswsteth-ilwq1) — ILidoWithdrawalQueue, external
* [getPendingMigrationStorage()](#getpendingmigrationstorage-blsp1) — BeneficiaryLidoStakingPlugin, internal
* [LibTwoStepClaimMigration.start(ICryptoLegacy.CryptoLegacyStorage,LibTwoStepClaimMigration.PendingMigrationStorage,address,address,uint256,uint256)](#start-ltscm1) — LibTwoStepClaimMigration, internal
* [\_activateBeneficiarySwitchGuard(ICryptoLegacy.CryptoLegacyStorage)](#_activatebeneficiaryswitchguard-blsp1) — BeneficiaryLidoStakingPlugin, internal
* [\_storeLidoRequestIds(uint256\[\])](#_storelidorequestids-blsp1) — BeneficiaryLidoStakingPlugin, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(n) by `wstEthAmounts.length` plus migration snapshot cost by beneficiary count

**Example:** Beneficiaries queue a set of wstETH withdrawals that will later settle into WETH.

***

### blsLidoClaimWithdrawals (BLSP1)

**Contract/Library:** BeneficiaryLidoStakingPlugin

**Description:** Claims finalized Lido withdrawals, wraps the received ETH into WETH, and completes the pending migration.

**Detailed Description:** Restricted to beneficiary-facing calls once distribution is active. The function reads the stored request IDs, claims the finalized Lido withdrawals, wraps any returned ETH into [`WETH (BLSP-D5)`](https://docs.cryptolegacy.app/documentation/data-structures-reference#weth-blsp1-d5), completes the pending two-step migration, releases the beneficiary-switch guard, clears the cached request IDs, and emits [`ClaimWithdrawals`](https://docs.cryptolegacy.app/documentation/events-reference#claimwithdrawals-blsp1).

**Parameters:**

* hints (uint256\[], calldata): Lido queue hints for the pending request IDs

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external nonpayable nonReentrant

**Access Control:**

* Restricted to beneficiaries after distribution starts

**Side Effects:**

* Claims queued Lido withdrawals into ETH
* Wraps claimed ETH into WETH
* Completes the pending migration and restores beneficiary-switch timelocks
* Clears cached request IDs from [`LidoWithdrawalStorage (BLSP-S1)`](https://docs.cryptolegacy.app/documentation/data-structures-reference#lidowithdrawalstorage-blsp1-s1)

**Emits:**

* [ClaimWithdrawals](https://docs.cryptolegacy.app/documentation/events-reference#claimwithdrawals-blsp1) — `ClaimWithdrawals(uint256[] requestIds, uint256 ethClaimedAmount)`

**Reverts if:**

* Distribution is not ready for beneficiary actions — [`TooEarly()`](https://docs.cryptolegacy.app/documentation/errors-reference#tooearly-icl1)
* Reentrant call — "ReentrancyGuard: reentrant call"
* No pending request IDs are stored — [`LidoRequestIdsEmpty()`](https://docs.cryptolegacy.app/documentation/errors-reference#lidorequestidsempty-blsp1)
* [`ILidoWithdrawalQueue.claimWithdrawals(uint256[],uint256[])`](#claimwithdrawals-ilwq1) fails — bubbled
* [`LibTwoStepClaimMigration.complete(...)`](#complete-ltscm1) fails — bubbled

**Overrides:** None

**Function Calls:**

* [LibCryptoLegacy.getCryptoLegacyStorage()](#getcryptolegacystorage-lcl1) — LibCryptoLegacy, internal
* [LibCryptoLegacy.\_checkDistributionReadyForBeneficiary(ICryptoLegacy.CryptoLegacyStorage)](#_checkdistributionreadyforbeneficiary-lcl1) — LibCryptoLegacy, internal
* [getLidoWithdrawalStorage()](#getlidowithdrawalstorage-blsp1) — BeneficiaryLidoStakingPlugin, internal
* [ILidoWithdrawalQueue.claimWithdrawals(uint256\[\],uint256\[\])](#claimwithdrawals-ilwq1) — ILidoWithdrawalQueue, external
* [IWETH.deposit()](#deposit-iweth1) — IWETH, external
* [getPendingMigrationStorage()](#getpendingmigrationstorage-blsp1) — BeneficiaryLidoStakingPlugin, internal
* [LibTwoStepClaimMigration.getPendingTokens(LibTwoStepClaimMigration.PendingMigrationStorage)](#getpendingtokens-ltscm1) — LibTwoStepClaimMigration, internal
* [LibTwoStepClaimMigration.complete(ICryptoLegacy.CryptoLegacyStorage,LibTwoStepClaimMigration.PendingMigrationStorage,uint256,uint256,uint256)](#complete-ltscm1) — LibTwoStepClaimMigration, internal
* [\_releaseBeneficiarySwitchGuard(ICryptoLegacy.CryptoLegacyStorage)](#_releasebeneficiaryswitchguard-blsp1) — BeneficiaryLidoStakingPlugin, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(n) by pending request count plus migration completion cost by beneficiary count

**Example:** Beneficiary completes a mature Lido withdrawal cycle and restores fair WETH claim accounting.

***

### blsLidoUnsafeClaimWithdrawals (BLSP1)

**Contract/Library:** BeneficiaryLidoStakingPlugin

**Description:** Claims finalized Lido withdrawals without completing claim-migration reconciliation.

**Detailed Description:** Emergency-only path for delayed claims after a fair migration has already been abandoned. Restricted to the beneficiary multisig executor after distribution starts, the function claims the specified request IDs, wraps any returned ETH into WETH, refreshes the WETH distribution balance, optionally records a transfer block number when the prior balance was zero, and emits [`UnsafeClaimWithdrawals`](https://docs.cryptolegacy.app/documentation/events-reference#unsafeclaimwithdrawals-blsp1).

**Parameters:**

* requestIds (uint256\[], calldata): Withdrawal request IDs to claim
* hints (uint256\[], calldata): Lido queue hints for each request ID

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external nonpayable nonReentrant

**Access Control:**

* Restricted to the beneficiary multisig executor after distribution starts

**Side Effects:**

* Claims specified Lido withdrawals into ETH
* Wraps claimed ETH into WETH and refreshes distribution state
* Appends a transfer block number when WETH was previously zero

**Emits:**

* [UnsafeClaimWithdrawals](https://docs.cryptolegacy.app/documentation/events-reference#unsafeclaimwithdrawals-blsp1) — `UnsafeClaimWithdrawals(uint256[] requestIds, uint256 ethClaimedAmount)`

**Reverts if:**

* Distribution not yet ready — [`TooEarly()`](https://docs.cryptolegacy.app/documentation/errors-reference#tooearly-icl1)
* Caller is not the multisig executor — [`MultisigOnlyExecutor()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisigonlyexecutor-ism1)
* Reentrant call — "ReentrancyGuard: reentrant call"
* `requestIds.length == 0` — [`LidoRequestIdsEmpty()`](https://docs.cryptolegacy.app/documentation/errors-reference#lidorequestidsempty-blsp1)
* A fair migration is still active — [`PendingMigrationActive()`](https://docs.cryptolegacy.app/documentation/errors-reference#pendingmigrationactive-blsp1)
* [`ILidoWithdrawalQueue.claimWithdrawals(uint256[],uint256[])`](#claimwithdrawals-ilwq1) fails — bubbled

**Overrides:** None

**Function Calls:**

* [LibSafeMinimalBeneficiaryMultisig.\_checkIsMultisigExecutor()](#_checkismultisigexecutor-lsmb1) — LibSafeMinimalBeneficiaryMultisig, internal
* [LibCryptoLegacy.getCryptoLegacyStorage()](#getcryptolegacystorage-lcl1) — LibCryptoLegacy, internal
* [LibCryptoLegacy.\_checkDistributionReady(ICryptoLegacy.CryptoLegacyStorage)](#_checkdistributionready-lcl1) — LibCryptoLegacy, internal
* [LibTwoStepClaimMigration.isActive(LibTwoStepClaimMigration.PendingMigrationStorage)](#isactive-ltscm1) — LibTwoStepClaimMigration, internal
* [getPendingMigrationStorage()](#getpendingmigrationstorage-blsp1) — BeneficiaryLidoStakingPlugin, internal
* `IERC20(WETH).balanceOf(address)` — IERC20, external (staticcall)
* [ILidoWithdrawalQueue.claimWithdrawals(uint256\[\],uint256\[\])](#claimwithdrawals-ilwq1) — ILidoWithdrawalQueue, external
* [LibCryptoLegacy.\_tokenPrepareToDistribute(ICryptoLegacy.CryptoLegacyStorage,address)](#_tokenpreparetodistribute-lcl1) — LibCryptoLegacy, internal
* [IWETH.deposit()](#deposit-iweth1) — IWETH, external
* `ArbSys(address(100)).arbBlockNumber()` — ArbSys, external (staticcall)

**Called by:** None (entry point)

**Gas / Complexity note:** O(n) by claimed request count

**Example:** Beneficiaries use the emergency path to recover matured withdrawals after abandoning the fair migration.

***

### blsLidoAbandonMigration (BLSP1)

**Contract/Library:** BeneficiaryLidoStakingPlugin

**Description:** Abandons the active Lido two-step migration and restores claim state.

**Detailed Description:** Restricted to the beneficiary multisig executor after distribution starts. The function restores cached claim state through [`LibTwoStepClaimMigration.abandon(...)`](#abandon-ltscm1), either zeroes or refreshes the outgoing token's distribution accounting depending on the remaining balance, clears cached request IDs, releases the beneficiary-switch guard, and emits [`AbandonMigration`](https://docs.cryptolegacy.app/documentation/events-reference#abandonmigration-blsp1).

**Parameters:** None

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external nonpayable

**Access Control:**

* Restricted to the beneficiary multisig executor after distribution starts

**Side Effects:**

* Restores cached claim state and clears pending migration data
* Updates outgoing-token distribution accounting after abandonment
* Clears cached Lido request IDs and restores beneficiary-switch timelocks

**Emits:**

* [AbandonMigration](https://docs.cryptolegacy.app/documentation/events-reference#abandonmigration-blsp1) — `AbandonMigration(address indexed tokenOut, address indexed tokenIn, uint256 tokenOutBalance)`

**Reverts if:**

* Distribution not yet ready — [`TooEarly()`](https://docs.cryptolegacy.app/documentation/errors-reference#tooearly-icl1)
* Caller is not the multisig executor — [`MultisigOnlyExecutor()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisigonlyexecutor-ism1)
* No migration is active — [`NoPendingMigration()`](https://docs.cryptolegacy.app/documentation/errors-reference#nopendingmigration-ltscm1)

**Overrides:** None

**Function Calls:**

* [LibSafeMinimalBeneficiaryMultisig.\_checkIsMultisigExecutor()](#_checkismultisigexecutor-lsmb1) — LibSafeMinimalBeneficiaryMultisig, internal
* [LibCryptoLegacy.getCryptoLegacyStorage()](#getcryptolegacystorage-lcl1) — LibCryptoLegacy, internal
* [LibCryptoLegacy.\_checkDistributionReady(ICryptoLegacy.CryptoLegacyStorage)](#_checkdistributionready-lcl1) — LibCryptoLegacy, internal
* [LibTwoStepClaimMigration.abandon(ICryptoLegacy.CryptoLegacyStorage,LibTwoStepClaimMigration.PendingMigrationStorage)](#abandon-ltscm1) — LibTwoStepClaimMigration, internal
* [getPendingMigrationStorage()](#getpendingmigrationstorage-blsp1) — BeneficiaryLidoStakingPlugin, internal
* [\_setTokenBeneficiaryClaimsToZero(ICryptoLegacy.CryptoLegacyStorage,address)](#_settokenbeneficiaryclaimstozero-blsp1) — BeneficiaryLidoStakingPlugin, internal
* [LibCryptoLegacy.\_tokenPrepareToDistribute(ICryptoLegacy.CryptoLegacyStorage,address)](#_tokenpreparetodistribute-lcl1) — LibCryptoLegacy, internal
* [getLidoWithdrawalStorage()](#getlidowithdrawalstorage-blsp1) — BeneficiaryLidoStakingPlugin, internal
* [\_releaseBeneficiarySwitchGuard(ICryptoLegacy.CryptoLegacyStorage)](#_releasebeneficiaryswitchguard-blsp1) — BeneficiaryLidoStakingPlugin, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(b) by beneficiary count

**Example:** Beneficiaries abandon an unresolved Lido migration when fair completion is no longer possible.

***

### blsLidoWrapStEthToWstEth (BLSP1)

**Contract/Library:** BeneficiaryLidoStakingPlugin

**Description:** Wraps rebasing stETH into non-rebasing wstETH and migrates claim accounting in one step.

**Detailed Description:** Restricted to the beneficiary multisig executor after distribution starts. The function validates a non-zero amount, checks the stETH balance, approves the wrapper, calls [`IWstETH.wrap(uint256)`](#wrap-iwsteth1), and migrates claim accounting from stETH to wstETH through [`LibOneStepClaimMigration.migrate(...)`](#migrate-loscm1).

**Parameters:**

* stEthAmount (uint256): Amount of stETH to wrap

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external nonpayable onlyDistributionReady

**Access Control:**

* Restricted to the beneficiary multisig executor after distribution starts

**Side Effects:**

* Approves the wstETH wrapper to pull stETH
* Converts stETH into wstETH and updates cross-token claim accounting

**Emits:** None

**Reverts if:**

* Distribution not yet ready — [`TooEarly()`](https://docs.cryptolegacy.app/documentation/errors-reference#tooearly-icl1)
* Caller is not the multisig executor — [`MultisigOnlyExecutor()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisigonlyexecutor-ism1)
* `stEthAmount == 0` — [`ZeroStEthAmount()`](https://docs.cryptolegacy.app/documentation/errors-reference#zerostethamount-blsp1)
* `stEthAmount > stETH balance` — [`InsufficientStEth()`](https://docs.cryptolegacy.app/documentation/errors-reference#insufficientsteth-blsp1)
* [`IWstETH.wrap(uint256)`](#wrap-iwsteth1) fails — bubbled
* [`LibOneStepClaimMigration.migrate(...)`](#migrate-loscm1) fails — bubbled

**Overrides:** None

**Function Calls:**

* [LibSafeMinimalBeneficiaryMultisig.\_checkIsMultisigExecutor()](#_checkismultisigexecutor-lsmb1) — LibSafeMinimalBeneficiaryMultisig, internal
* [LibCryptoLegacy.getCryptoLegacyStorage()](#getcryptolegacystorage-lcl1) — LibCryptoLegacy, internal
* [LibCryptoLegacy.\_checkDistributionReady(ICryptoLegacy.CryptoLegacyStorage)](#_checkdistributionready-lcl1) — LibCryptoLegacy, internal
* `IERC20(stETH).balanceOf(address)` — IERC20, external (staticcall)
* `IERC20(wstETH).balanceOf(address)` — IERC20, external (staticcall)
* `IERC20(stETH).approve(address,uint256)` — IERC20, external
* [IWstETH.wrap(uint256)](#wrap-iwsteth1) — IWstETH, external
* [LibOneStepClaimMigration.migrate(ICryptoLegacy.CryptoLegacyStorage,address,address,uint256,uint256,uint256,uint256)](#migrate-loscm1) — LibOneStepClaimMigration, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(b) by beneficiary count plus wrapper call cost

**Example:** Beneficiaries convert rebasing stETH holdings into non-rebasing wstETH.

***

### blsLidoUnwrapWstEthToStEth (BLSP1)

**Contract/Library:** BeneficiaryLidoStakingPlugin

**Description:** Unwraps wstETH into stETH and migrates claim accounting in one step.

**Detailed Description:** Restricted to the beneficiary multisig executor after distribution starts. The function validates a non-zero amount, checks the wstETH balance, calls [`IWstETH.unwrap(uint256)`](#unwrap-iwsteth1), and migrates claim accounting from wstETH back into stETH through [`LibOneStepClaimMigration.migrate(...)`](#migrate-loscm1).

**Parameters:**

* wstEthAmount (uint256): Amount of wstETH to unwrap

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external nonpayable onlyDistributionReady

**Access Control:**

* Restricted to the beneficiary multisig executor after distribution starts

**Side Effects:**

* Converts wstETH into stETH and updates cross-token claim accounting

**Emits:** None

**Reverts if:**

* Distribution not yet ready — [`TooEarly()`](https://docs.cryptolegacy.app/documentation/errors-reference#tooearly-icl1)
* Caller is not the multisig executor — [`MultisigOnlyExecutor()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisigonlyexecutor-ism1)
* `wstEthAmount == 0` — [`ZeroWstEthAmount()`](https://docs.cryptolegacy.app/documentation/errors-reference#zerowstethamount-blsp1)
* `wstEthAmount > wstETH balance` — [`InsufficientWstEth()`](https://docs.cryptolegacy.app/documentation/errors-reference#insufficientwsteth-blsp1)
* [`IWstETH.unwrap(uint256)`](#unwrap-iwsteth1) fails — bubbled
* [`LibOneStepClaimMigration.migrate(...)`](#migrate-loscm1) fails — bubbled

**Overrides:** None

**Function Calls:**

* [LibSafeMinimalBeneficiaryMultisig.\_checkIsMultisigExecutor()](#_checkismultisigexecutor-lsmb1) — LibSafeMinimalBeneficiaryMultisig, internal
* [LibCryptoLegacy.getCryptoLegacyStorage()](#getcryptolegacystorage-lcl1) — LibCryptoLegacy, internal
* [LibCryptoLegacy.\_checkDistributionReady(ICryptoLegacy.CryptoLegacyStorage)](#_checkdistributionready-lcl1) — LibCryptoLegacy, internal
* `IERC20(wstETH).balanceOf(address)` — IERC20, external (staticcall)
* `IERC20(stETH).balanceOf(address)` — IERC20, external (staticcall)
* [IWstETH.unwrap(uint256)](#unwrap-iwsteth1) — IWstETH, external
* [LibOneStepClaimMigration.migrate(ICryptoLegacy.CryptoLegacyStorage,address,address,uint256,uint256,uint256,uint256)](#migrate-loscm1) — LibOneStepClaimMigration, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(b) by beneficiary count plus unwrap cost

**Example:** Beneficiaries convert wstETH back into rebasing stETH before requesting withdrawals.

***

### \_storeLidoRequestIds (BLSP1)

**Contract/Library:** BeneficiaryLidoStakingPlugin

**Description:** Replaces the cached pending-request list with the request IDs returned by Lido.

**Detailed Description:** Clears the existing cached request list and copies the provided request IDs into [`LidoWithdrawalStorage (BLSP-S1)`](https://docs.cryptolegacy.app/documentation/data-structures-reference#lidowithdrawalstorage-blsp1-s1).

**Parameters:**

* requestIds (uint256\[], memory): Lido withdrawal request IDs returned by the queue

**Returns:** None

**Modifiers / Visibility / Mutability:**

* private nonpayable

**Access Control:**

* Internal helper only

**Side Effects:**

* Rewrites the cached `pendingRequestIds` array

**Emits:** None

**Reverts if:**

* `requestIds.length == 0` — [`LidoRequestIdsEmpty()`](https://docs.cryptolegacy.app/documentation/errors-reference#lidorequestidsempty-blsp1)

**Overrides:** None

**Function Calls:**

* [getLidoWithdrawalStorage()](#getlidowithdrawalstorage-blsp1) — BeneficiaryLidoStakingPlugin, internal

**Called by:**

* [blsLidoRequestStEthWithdrawal(uint256\[\])](#blslidorequeststethwithdrawal-blsp1) — BeneficiaryLidoStakingPlugin
* [blsLidoRequestWstEthWithdrawal(uint256\[\])](#blslidorequestwstethwithdrawal-blsp1) — BeneficiaryLidoStakingPlugin

**Gas / Complexity note:** O(n) by `requestIds.length`

**Example:** Not applicable

***

### \_activateBeneficiarySwitchGuard (BLSP1)

**Contract/Library:** BeneficiaryLidoStakingPlugin

**Description:** Freezes beneficiary switching while a delayed migration is pending.

**Detailed Description:** Snapshots each beneficiary's original-hash switch timelock, stores it in [`BeneficiarySwitchGuardStorage (BLSP-S2)`](https://docs.cryptolegacy.app/documentation/data-structures-reference#beneficiaryswitchguardstorage-blsp1-s2), and then sets the live timelock to `type(uint64).max` to block switching until the migration is resolved.

**Parameters:**

* cls (ICryptoLegacy.CryptoLegacyStorage, storage): Core CryptoLegacy storage reference

**Returns:** None

**Modifiers / Visibility / Mutability:**

* private nonpayable

**Access Control:**

* Internal helper only

**Side Effects:**

* Marks the switch guard active
* Snapshots beneficiary original hashes and prior timelocks
* Sets each beneficiary switch timelock to `type(uint64).max`

**Emits:** None

**Reverts if:**

* Guard is already active — [`BeneficiarySwitchGuardAlreadyActive()`](https://docs.cryptolegacy.app/documentation/errors-reference#beneficiaryswitchguardalreadyactive-blsp1)

**Overrides:** None

**Function Calls:**

* [getBeneficiarySwitchGuardStorage()](#getbeneficiaryswitchguardstorage-blsp1) — BeneficiaryLidoStakingPlugin, internal

**Called by:**

* [blsLidoRequestStEthWithdrawal(uint256\[\])](#blslidorequeststethwithdrawal-blsp1) — BeneficiaryLidoStakingPlugin
* [blsLidoRequestWstEthWithdrawal(uint256\[\])](#blslidorequestwstethwithdrawal-blsp1) — BeneficiaryLidoStakingPlugin

**Gas / Complexity note:** O(b) by beneficiary count

**Example:** Not applicable

***

### \_releaseBeneficiarySwitchGuard (BLSP1)

**Contract/Library:** BeneficiaryLidoStakingPlugin

**Description:** Restores beneficiary-switch timelocks and clears the migration guard snapshot.

**Detailed Description:** If the guard is active, restores each previously snapshotted timelock, deletes the stored mapping entries and original-hash list, and resets the active flag.

**Parameters:**

* cls (ICryptoLegacy.CryptoLegacyStorage, storage): Core CryptoLegacy storage reference

**Returns:** None

**Modifiers / Visibility / Mutability:**

* private nonpayable

**Access Control:**

* Internal helper only

**Side Effects:**

* Restores beneficiary switch timelocks
* Clears the guard snapshot and deactivates the guard

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [getBeneficiarySwitchGuardStorage()](#getbeneficiaryswitchguardstorage-blsp1) — BeneficiaryLidoStakingPlugin, internal

**Called by:**

* [blsLidoClaimWithdrawals(uint256\[\])](#blslidoclaimwithdrawals-blsp1) — BeneficiaryLidoStakingPlugin
* [blsLidoAbandonMigration()](#blslidoabandonmigration-blsp1) — BeneficiaryLidoStakingPlugin

**Gas / Complexity note:** O(b) by beneficiary count

**Example:** Not applicable

***

### \_setTokenBeneficiaryClaimsToZero (BLSP1)

**Contract/Library:** BeneficiaryLidoStakingPlugin

**Description:** Clears every beneficiary's claimed balance for a given token.

**Detailed Description:** Iterates through the beneficiary set and calls [`LibCryptoLegacy._setBeneficiaryClaimed(...)`](#_setbeneficiaryclaimed-lcl1) with zero for each beneficiary-token pair. The helper is used when abandoning a migration and the outgoing token balance has gone fully to zero.

**Parameters:**

* cls (ICryptoLegacy.CryptoLegacyStorage, storage): Core CryptoLegacy storage reference
* token (address): Token whose per-beneficiary claimed balances should be reset

**Returns:** None

**Modifiers / Visibility / Mutability:**

* private nonpayable

**Access Control:**

* Internal helper only

**Side Effects:**

* Resets all beneficiary claimed balances for `token` to zero

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [LibCryptoLegacy.\_setBeneficiaryClaimed(ICryptoLegacy.CryptoLegacyStorage,bytes32,address,uint256)](#_setbeneficiaryclaimed-lcl1) — LibCryptoLegacy, internal

**Called by:**

* [blsLidoAbandonMigration()](#blslidoabandonmigration-blsp1) — BeneficiaryLidoStakingPlugin

**Gas / Complexity note:** O(b) by beneficiary count

**Example:** Not applicable

***

## BeneficiaryPluginAddRights (BPAR1)

### getSigs (BPAR1)

**Contract/Library:** BeneficiaryPluginAddRights

**Description:** Lists the external function selectors exposed by this plugin.

**Detailed Description:** Returns the ordered selector array for `barGetInitializationStatus`, `barSetMultisigConfig`, `barPropose`, `barCancel`, `barConfirm`, `barAddPluginList`, `barGetVotersAndConfirmations`, `barGetProposalWithStatus`, `barGetProposalListWithStatuses`, `barWithdrawHeldEth`, and `barGetHeldEth`.

**Parameters:** None

**Returns:**

* sigs (bytes4\[], memory): Selector list described above

**Modifiers / Visibility / Mutability:**

* external pure

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:** None (entry point)

**Gas / Complexity note:** O(1) — constant-length array assembly

**Example:** Registry queries selectors when wiring the plugin into the diamond.

***

### getSetupSigs (BPAR1)

**Contract/Library:** BeneficiaryPluginAddRights

**Description:** Reports setup-time selectors required by the plugin.

**Detailed Description:** Returns an empty array, indicating no additional setup calls are needed when installing this facet.

**Parameters:** None

**Returns:**

* sigs (bytes4\[], memory): Always an empty array

**Modifiers / Visibility / Mutability:**

* external pure

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Used by the build manager while installing the facet.

***

### getMultisigAllowedMethods (BPAR1)

**Contract/Library:** BeneficiaryPluginAddRights

**Description:** Lists selectors that multisig proposals are permitted to execute.

**Detailed Description:** Returns the two whitelisted selectors (`barAddPluginList` and `barSetMultisigConfig`) that beneficiaries may schedule through the multisig flow.

**Parameters:** None

**Returns:**

* sigs (bytes4\[], memory): Allowed multisig method selectors

**Modifiers / Visibility / Mutability:**

* public pure

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:**

* [barPropose(bytes4,bytes)](#barpropose-bpar1) — BeneficiaryPluginAddRights

**Gas / Complexity note:** O(1)

**Example:** Used to validate proposal targets during `barPropose`.

***

### getPluginName (BPAR1)

**Contract/Library:** BeneficiaryPluginAddRights

**Description:** Returns the human-readable plugin identifier.

**Detailed Description:** Hard-codes the plugin name to `"beneficiary_plugin_add_rights"` for registry and UI display.

**Parameters:** None

**Returns:**

* name (string, memory): Literal plugin identifier

**Modifiers / Visibility / Mutability:**

* public pure

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Registry reads this to label the facet.

***

### getPluginVer (BPAR1)

**Contract/Library:** BeneficiaryPluginAddRights

**Description:** Reports the semantic version number for the plugin.

**Detailed Description:** Returns the constant version `1` encoded as `uint16`.

**Parameters:** None

**Returns:**

* version (uint16): Version identifier (currently 1)

**Modifiers / Visibility / Mutability:**

* external pure

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Used by plugin registries when displaying version metadata.

***

### modifier onlyOwner (BPAR1)

**Contract/Library:** BeneficiaryPluginAddRights

**Description:** Ensures distribution has not started, the initial fee is paid, and the caller is the owner.

**Detailed Description:** Invokes `LibCryptoLegacy._checkOwner()`, which first verifies distribution has not begun, ensures `lastFeePaidAt` is set (initial fee settled), and finally checks `msg.sender` against the diamond owner.

**Parameters:** None

**Returns:** None

**Modifiers / Visibility / Mutability:**

* modifier nonpayable

**Access Control:**

* Owner-only (enforced via library check)

**Side Effects:** None

**Emits:** None

**Reverts if:**

* Distribution already started — [`DistributionStarted()`](https://docs.cryptolegacy.app/documentation/errors-reference#distributionstarted-icl1)
* Initial fee unpaid — [`InitialFeeNotPaid()`](https://docs.cryptolegacy.app/documentation/errors-reference#initialfeenotpaid-icl1)
* Caller is not the owner — [`NotTheOwner()`](https://docs.cryptolegacy.app/documentation/errors-reference#nottheowner-icl1)

**Overrides:** None

**Function Calls:**

* [LibCryptoLegacy.\_checkOwner()](#_checkowner-lcl1) — LibCryptoLegacy, internal

**Called by:** None

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### modifier onlyDistributionReady (BPAR1)

**Contract/Library:** BeneficiaryPluginAddRights

**Description:** Restricts execution to phases where distribution has already started.

**Detailed Description:** Calls `LibCryptoLegacy._checkDistributionReady(...)`, which requires the distribution start timestamp to be set and in the past.

**Parameters:** None

**Returns:** None

**Modifiers / Visibility / Mutability:**

* modifier nonpayable

**Access Control:**

* Distribution must be active

**Side Effects:** None

**Emits:** None

**Reverts if:**

* Distribution not yet ready — [`TooEarly()`](https://docs.cryptolegacy.app/documentation/errors-reference#tooearly-icl1)

**Overrides:** None

**Function Calls:**

* [LibCryptoLegacy.getCryptoLegacyStorage()](#getcryptolegacystorage-lcl1) — LibCryptoLegacy, internal
* [LibCryptoLegacy.\_checkDistributionReady(ICryptoLegacy.CryptoLegacyStorage)](#_checkdistributionready-lcl1) — LibCryptoLegacy, internal

**Called by:**

* [barPropose(bytes4,bytes)](#barpropose-bpar1) — BeneficiaryPluginAddRights
* [barConfirm(uint256)](#barconfirm-bpar1) — BeneficiaryPluginAddRights
* [barCancel(uint256)](#barcancel-bpar1) — BeneficiaryPluginAddRights
* [barAddPluginList(address\[\])](#baraddpluginlist-bpar1) — BeneficiaryPluginAddRights

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### getPluginMultisigStorage (BPAR1)

**Contract/Library:** BeneficiaryPluginAddRights

**Description:** Retrieves the plugin-specific multisig storage slot.

**Detailed Description:** Uses inline assembly to map the constant slot [`PLUGIN_MULTISIG_POSITION`](https://docs.cryptolegacy.app/documentation/data-structures-reference#plugin_multisig_position-lrp1-d1) to an [`ISafeMinimalMultisig.Storage`](https://docs.cryptolegacy.app/documentation/data-structures-reference#storage-ism1-s1) reference, enabling shared access across helper routines.

**Parameters:** None

**Returns:**

* storageStruct (ISafeMinimalMultisig.Storage, storage): Multisig storage layout for this plugin

**Modifiers / Visibility / Mutability:**

* internal pure

**Access Control:**

* Internal helper used exclusively by this plugin

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:**

* [barSetMultisigConfig(uint128)](#barsetmultisigconfig-bpar1) — BeneficiaryPluginAddRights
* [barPropose(bytes4,bytes)](#barpropose-bpar1) — BeneficiaryPluginAddRights
* [barConfirm(uint256)](#barconfirm-bpar1) — BeneficiaryPluginAddRights
* [barCancel(uint256)](#barcancel-bpar1) — BeneficiaryPluginAddRights
* [barWithdrawHeldEth(address)](#barwithdrawheldeth-bpar1) — BeneficiaryPluginAddRights
* [barGetHeldEth(bytes32)](#bargetheldeth-bpar1) — BeneficiaryPluginAddRights
* [barGetInitializationStatus()](#bargetinitializationstatus-bpar1) — BeneficiaryPluginAddRights
* [barGetVotersAndConfirmations()](#bargetvotersandconfirmations-bpar1) — BeneficiaryPluginAddRights
* [barGetProposalWithStatus(uint256)](#bargetproposalwithstatus-bpar1) — BeneficiaryPluginAddRights
* [barGetProposalListWithStatuses()](#bargetproposallistwithstatuses-bpar1) — BeneficiaryPluginAddRights

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### barSetMultisigConfig (BPAR1)

**Contract/Library:** BeneficiaryPluginAddRights

**Description:** Updates multisig confirmation thresholds for beneficiary actions.

**Detailed Description:** If invoked via self-call, re-verifies distribution readiness; otherwise enforces the owner preconditions via `LibCryptoLegacy._checkOwner()`. Pulls the current beneficiary voter list and forwards the new requirement to LibSafeMinimalBeneficiaryMultisig.\_setConfirmations(#\_setconfirmations-lsmb1).

**Parameters:**

* \_requiredConfirmations (uint128): Desired confirmation threshold

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external nonpayable

**Access Control:**

* Owner when called externally; contract itself may call once distribution is ready

**Side Effects:**

* Updates `requiredConfirmations` within plugin multisig storage

**Emits:**

* [SetConfirmations](https://docs.cryptolegacy.app/documentation/events-reference#setconfirmations-ism1) — `SetConfirmations(uint128 requiredConfirmations)`

**Reverts if:**

* Distribution already started (owner path) — [`DistributionStarted()`](https://docs.cryptolegacy.app/documentation/errors-reference#distributionstarted-icl1)
* Initial fee unpaid (owner path) — [`InitialFeeNotPaid()`](https://docs.cryptolegacy.app/documentation/errors-reference#initialfeenotpaid-icl1)
* Caller not owner (owner path) — [`NotTheOwner()`](https://docs.cryptolegacy.app/documentation/errors-reference#nottheowner-icl1)
* Distribution not yet ready (self-call path) — [`TooEarly()`](https://docs.cryptolegacy.app/documentation/errors-reference#tooearly-icl1)
* Invalid threshold for voter count — [`MultisigIncorrectRequiredConfirmations()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisigincorrectrequiredconfirmations-ism1)

**Overrides:** None

**Function Calls:**

* [LibCryptoLegacy.getCryptoLegacyStorage()](#getcryptolegacystorage-lcl1) — LibCryptoLegacy, internal
* [LibCryptoLegacy.\_checkDistributionReady(ICryptoLegacy.CryptoLegacyStorage)](#_checkdistributionready-lcl1) — LibCryptoLegacy, internal
* [LibCryptoLegacy.\_checkOwner()](#_checkowner-lcl1) — LibCryptoLegacy, internal
* [LibCryptoLegacy.getCryptoLegacyStorage()](#getcryptolegacystorage-lcl1) — LibCryptoLegacy, internal
* [getPluginMultisigStorage()](#getpluginmultisigstorage-bpar1) — BeneficiaryPluginAddRights, internal
* [LibSafeMinimalBeneficiaryMultisig.\_setConfirmations(...)](#_setconfirmations-lsmb1) — LibSafeMinimalBeneficiaryMultisig, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(b) by number of beneficiaries

**Example:** Owner schedules a self-call to raise confirmations after adding more beneficiaries.

***

### barPropose (BPAR1)

**Contract/Library:** BeneficiaryPluginAddRights

**Description:** Creates a multisig proposal for an allowed beneficiary action.

**Detailed Description:** Requires distribution to be active, then verifies the caller is an authorized beneficiary voter and that the selector is allowed. Records the proposal, auto-confirms for the proposer, executes immediately if only one confirmation is required, and tracks any ETH returned to the contract as held ETH for the voter.

**Parameters:**

* \_selector (bytes4): Target function selector
* \_params (bytes, memory): ABI-encoded parameters for the target call

**Returns:**

* proposalId (uint256): Index of the newly created proposal

**Modifiers / Visibility / Mutability:**

* external payable nonReentrant onlyDistributionReady

**Access Control:**

* Caller must be an authorized voter

**Side Effects:**

* Appends to the multisig `proposals` array
* Marks the proposer as confirmed and may execute the proposal immediately
* Credits leftover ETH to `heldEth` for the proposer

**Emits:**

* [SetConfirmations](https://docs.cryptolegacy.app/documentation/events-reference#setconfirmations-ism1) — `SetConfirmations(uint128 requiredConfirmations)` (when multisig initialises during the call)
* [CreateSafeMinimalMultisigProposal](https://docs.cryptolegacy.app/documentation/events-reference#createsafeminimalmultisigproposal-ism1) — `CreateSafeMinimalMultisigProposal(uint256 proposalId, bytes32 voter, uint128 reqConfirmations)`
* [ExecuteSafeMinimalMultisigProposal](https://docs.cryptolegacy.app/documentation/events-reference#executesafeminimalmultisigproposal-ism1) — `ExecuteSafeMinimalMultisigProposal(uint256 proposalId, bytes32 voter, bool executed, bytes returnData)` (when quorum reached instantly)
* [AddHeldEth](https://docs.cryptolegacy.app/documentation/events-reference#addheldeth-ism1) — `AddHeldEth(bytes32 voter, uint256 value)` (when surplus ETH is retained)

**Reverts if:**

* Distribution not ready — [`TooEarly()`](https://docs.cryptolegacy.app/documentation/errors-reference#tooearly-icl1)
* Reentrant call — "ReentrancyGuard: reentrant call"
* Caller not an authorized voter — [`MultisigVoterNotAllowed()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisigvoternotallowed-ism1)
* Selector not in allowlist — [`MultisigMethodNotAllowed()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisigmethodnotallowed-ism1)
* Invalid confirmation threshold during initialization — [`MultisigIncorrectRequiredConfirmations()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisigincorrectrequiredconfirmations-ism1)
* Execution of the proposal’s action fails — [`MultisigExecutionFailed()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisigexecutionfailed-ism1)

**Overrides:** None

**Function Calls:**

* [getPluginMultisigStorage()](#getpluginmultisigstorage-bpar1) — BeneficiaryPluginAddRights, internal
* [getMultisigAllowedMethods()](#getmultisigallowedmethods-bpar1) — BeneficiaryPluginAddRights, internal
* [LibSafeMinimalBeneficiaryMultisig.\_propose(...)](#_propose-lsmb1) — LibSafeMinimalBeneficiaryMultisig, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(b) by beneficiary count (voter scanning and held-ETH accounting)

**Example:** Beneficiary voter proposes to add a new plugin list once distribution is underway.

***

### barConfirm (BPAR1)

**Contract/Library:** BeneficiaryPluginAddRights

**Description:** Confirms an existing multisig proposal and executes it once quorum is reached.

**Detailed Description:** Distribution readiness gating ensures the challenge period has elapsed; the function verifies the caller is an allowed voter and the proposal remains pending, records the confirmation, recomputes the confirmation count, executes once the threshold is met, and updates held ETH balances for any excess funds.

**Parameters:**

* \_proposalId (uint256): Proposal index to confirm

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external payable nonReentrant onlyDistributionReady

**Access Control:**

* Caller must be an authorized voter

**Side Effects:**

* Updates per-proposal confirmation state
* May execute the underlying action
* Credits surplus ETH to `heldEth`

**Emits:**

* [SetConfirmations](https://docs.cryptolegacy.app/documentation/events-reference#setconfirmations-ism1) — `SetConfirmations(uint128 requiredConfirmations)` (when multisig initialises during the call)
* [ConfirmSafeMinimalMultisigProposal](https://docs.cryptolegacy.app/documentation/events-reference#confirmsafeminimalmultisigproposal-ism1) — `ConfirmSafeMinimalMultisigProposal(uint256 proposalId, bytes32 voter, uint128 reqConfirmations, uint256 confirms)`
* [ExecuteSafeMinimalMultisigProposal](https://docs.cryptolegacy.app/documentation/events-reference#executesafeminimalmultisigproposal-ism1) — `ExecuteSafeMinimalMultisigProposal(uint256 proposalId, bytes32 voter, bool executed, bytes returnData)` (on execution)
* [AddHeldEth](https://docs.cryptolegacy.app/documentation/events-reference#addheldeth-ism1) — `AddHeldEth(bytes32 voter, uint256 value)` (when ETH is retained)

**Reverts if:**

* Distribution not ready — [`TooEarly()`](https://docs.cryptolegacy.app/documentation/errors-reference#tooearly-icl1)
* Reentrant call — "ReentrancyGuard: reentrant call"
* Invalid confirmation threshold during initialization — [`MultisigIncorrectRequiredConfirmations()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisigincorrectrequiredconfirmations-ism1)
* Caller not an authorized voter — [`MultisigVoterNotAllowed()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisigvoternotallowed-ism1)
* `_proposalId` out of range — `panic(0x32)`
* Proposal not pending — [`MultisigProposalNotPending()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisigproposalnotpending-ism1)
* Execution of the proposal’s action fails — [`MultisigExecutionFailed()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisigexecutionfailed-ism1)

**Overrides:** None

**Function Calls:**

* [getPluginMultisigStorage()](#getpluginmultisigstorage-bpar1) — BeneficiaryPluginAddRights, internal
* [LibSafeMinimalBeneficiaryMultisig.\_confirm(...)](#_confirm-lsmb1) — LibSafeMinimalBeneficiaryMultisig, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(b) by beneficiary count

**Example:** Beneficiary voter confirms a proposal to add a new plugin list.

***

### barCancel (BPAR1)

**Contract/Library:** BeneficiaryPluginAddRights

**Description:** Removes the caller’s confirmation from a pending multisig proposal.

**Detailed Description:** Ensures distribution is active, validates the caller against the voter set, clears their confirmation flag, recomputes the confirmation count, and cancels the proposal if no confirmations remain.

**Parameters:**

* \_proposalId (uint256): Proposal index to un-confirm

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external nonpayable nonReentrant onlyDistributionReady

**Access Control:**

* Caller must be an authorized voter who previously confirmed

**Side Effects:**

* Updates confirmation bookkeeping; may set proposal status to `CANCELED`

**Emits:**

* [CancelSafeMinimalMultisigProposal](https://docs.cryptolegacy.app/documentation/events-reference#cancelsafeminimalmultisigproposal-ism1) — `CancelSafeMinimalMultisigProposal(uint256 proposalId, bytes32 voter, uint128 reqConfirmations, ISafeMinimalMultisig.ProposalStatus status)`

**Reverts if:**

* Distribution not ready — [`TooEarly()`](https://docs.cryptolegacy.app/documentation/errors-reference#tooearly-icl1)
* Reentrant call — "ReentrancyGuard: reentrant call"
* Caller not an authorized voter — [`MultisigVoterNotAllowed()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisigvoternotallowed-ism1)
* `_proposalId` out of range — `panic(0x32)`
* Proposal not pending — [`MultisigProposalNotPending()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisigproposalnotpending-ism1)
* Caller had not confirmed — [`MultisigNotConfirmed()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisignotconfirmed-ism1)

**Overrides:** None

**Function Calls:**

* [getPluginMultisigStorage()](#getpluginmultisigstorage-bpar1) — BeneficiaryPluginAddRights, internal
* [LibSafeMinimalBeneficiaryMultisig.\_cancel(...)](#_cancel-lsmb1) — LibSafeMinimalBeneficiaryMultisig, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(b) by beneficiary count

**Example:** Beneficiary retracts their confirmation after circumstances change.

***

### barAddPluginList (BPAR1)

**Contract/Library:** BeneficiaryPluginAddRights

**Description:** Executes the approved plugin-addition proposal.

**Detailed Description:** Restricted to multisig execution (contract self-call) after distribution is active. Verifies the caller is the multisig executor, revalidates distribution readiness, checks each plugin against the build manager registry, and installs their setup selectors into the diamond.

**Parameters:**

* \_plugins (address\[], memory): Plugin facet addresses to add

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external nonpayable onlyDistributionReady

**Access Control:**

* Must be invoked by the multisig executor (`address(this)`)

**Side Effects:**

* Updates diamond storage to register new facet selectors (may append new facet addresses)

**Emits:**

* [AddFunctions](https://docs.cryptolegacy.app/documentation/events-reference#addfunctions-icl1) — `AddFunctions(address _facetAddress, bytes4[] _functionSelectors, uint16 selectorPosition)`

**Reverts if:**

* Not invoked by multisig executor — [`MultisigOnlyExecutor()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisigonlyexecutor-ism1)
* Distribution not ready — [`TooEarly()`](https://docs.cryptolegacy.app/documentation/errors-reference#tooearly-icl1)
* Plugin not registered with build manager — [`PluginNotRegistered()`](https://docs.cryptolegacy.app/documentation/errors-reference#pluginnotregistered-icl1)
* Facet address missing code — "NO\_CODE"
* Selector already registered — [`CantAddFunctionThatAlreadyExists()`](https://docs.cryptolegacy.app/documentation/errors-reference#cantaddfunctionthatalreadyexists-icl1)
* Facet address zero — [`FacetCantBeZero()`](https://docs.cryptolegacy.app/documentation/errors-reference#facetcantbezero-icl1)

**Overrides:** None

**Function Calls:**

* [LibSafeMinimalBeneficiaryMultisig.\_checkIsMultisigExecutor()](#_checkismultisigexecutor-lsmb1) — LibSafeMinimalBeneficiaryMultisig, internal
* [LibCryptoLegacy.getCryptoLegacyStorage()](#getcryptolegacystorage-lcl1) — LibCryptoLegacy, internal
* [LibCryptoLegacy.\_checkDistributionReady(ICryptoLegacy.CryptoLegacyStorage)](#_checkdistributionready-lcl1) — LibCryptoLegacy, internal
* [\_addPluginList(ICryptoLegacy.CryptoLegacyStorage,address\[\])](#_addpluginlist-lclp1) — LibCryptoLegacyPlugins, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(p·s) where p = number of plugins, s = selectors per plugin

**Example:** Executed via multisig to install a new claims plugin approved by beneficiaries.

***

### barWithdrawHeldEth (BPAR1)

**Contract/Library:** BeneficiaryPluginAddRights

**Description:** Allows a voter to withdraw ETH accrued during proposal execution.

**Detailed Description:** Loads multisig storage, authenticates the caller against the beneficiary voter list, retrieves the caller’s credited balance, zeroes it out, and transfers the ETH to the requested recipient.

**Parameters:**

* \_recipient (address): Destination for the withdrawn ETH

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external nonpayable nonReentrant

**Access Control:**

* Caller must be an authorized voter with a positive held balance

**Side Effects:**

* Updates `heldEth` mapping and transfers native funds

**Emits:**

* [WithdrawHeldEth](https://docs.cryptolegacy.app/documentation/events-reference#withdrawheldeth-ism1) — `WithdrawHeldEth(bytes32 voter, uint256 value)`

**Reverts if:**

* Reentrant call — "ReentrancyGuard: reentrant call"
* Caller not an authorized voter — [`MultisigVoterNotAllowed()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisigvoternotallowed-ism1)
* No ETH available — [`MultisigNothingToWithdraw()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisignothingtowithdraw-ism1)
* Transfer fails — [`TransferFeeFailed(bytes response)`](https://docs.cryptolegacy.app/documentation/errors-reference#transferfeefailed-ism1)

**Overrides:** None

**Function Calls:**

* [LibCryptoLegacy.getCryptoLegacyStorage()](#getcryptolegacystorage-lcl1) — LibCryptoLegacy, internal
* [getPluginMultisigStorage()](#getpluginmultisigstorage-bpar1) — BeneficiaryPluginAddRights, internal
* [\_withdrawHeldEth(ISafeMinimalMultisig.Storage,bytes32,bytes32\[\],address)](#_withdrawheldeth-lsmb1) — LibSafeMinimalBeneficiaryMultisig, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(b) by beneficiary count (voter lookup)

**Example:** Beneficiary withdraws leftover ETH reimbursed from a proposal execution.

***

### barGetHeldEth (BPAR1)

**Contract/Library:** BeneficiaryPluginAddRights

**Description:** Returns the held ETH balance for a beneficiary voter.

**Detailed Description:** Reads the multisig `heldEth` mapping keyed by the provided voter hash.

**Parameters:**

* \_hash (bytes32): Voter identifier hash

**Returns:**

* heldEthBalance (uint256): Withdrawable ETH for the voter

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [getPluginMultisigStorage()](#getpluginmultisigstorage-bpar1) — BeneficiaryPluginAddRights, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Front-end displays pending withdrawal balances per beneficiary voter.

***

### barGetInitializationStatus (BPAR1)

**Contract/Library:** BeneficiaryPluginAddRights

**Description:** Reports whether the multisig configuration has been initialized.

**Detailed Description:** Delegates to LibSafeMinimalBeneficiaryMultisig.\_initializationStatus(#\_initializationstatus-lsmb1) to determine if required confirmations are set or if initialization is unnecessary.

**Parameters:** None

**Returns:**

* status (ISafeMinimalMultisig.InitializationStatus): Current initialization state

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [getPluginMultisigStorage()](#getpluginmultisigstorage-bpar1) — BeneficiaryPluginAddRights, internal
* [LibSafeMinimalBeneficiaryMultisig.\_initializationStatus(...)](#_initializationstatus-lsmb1) — LibSafeMinimalBeneficiaryMultisig, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Used to display whether beneficiaries have completed multisig setup.

***

### barGetVotersAndConfirmations (BPAR1)

**Contract/Library:** BeneficiaryPluginAddRights

**Description:** Returns the current multisig voter list and confirmation threshold.

**Detailed Description:** Fetches the beneficiary set, computes (or defaults) the required confirmations, and returns both pieces of data.

**Parameters:** None

**Returns:**

* voters (bytes32\[], memory): Beneficiary voter identifiers
* requiredConfirmations (uint128): Confirmations required to execute proposals

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [getPluginMultisigStorage()](#getpluginmultisigstorage-bpar1) — BeneficiaryPluginAddRights, internal
* [LibSafeMinimalBeneficiaryMultisig.\_getVotersAndConfirmations(...)](#_getvotersandconfirmations-lsmb1) — LibSafeMinimalBeneficiaryMultisig, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(b) by beneficiary count

**Example:** UI surfaces current multisig configuration to owners and beneficiaries.

***

### barGetProposalWithStatus (BPAR1)

**Contract/Library:** BeneficiaryPluginAddRights

**Description:** Fetches a single proposal and its per-voter confirmation flags.

**Detailed Description:** Retrieves the beneficiary voter list, loads the indexed proposal, builds the confirmation bitmap, and returns the derived metadata along with the confirmation threshold.

**Parameters:**

* \_proposalId (uint256): Proposal index to inspect

**Returns:**

* voters (bytes32\[], memory): Eligible voter identifiers
* requiredConfirmations (uint128): Confirmation threshold
* proposalWithStatus (ISafeMinimalMultisig.ProposalWithStatus, memory): Proposal and confirmation flags

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:**

* `_proposalId` out of range — `panic(0x32)`

**Overrides:** None

**Function Calls:**

* [LibCryptoLegacy.getCryptoLegacyStorage()](#getcryptolegacystorage-lcl1) — LibCryptoLegacy, internal
* [getPluginMultisigStorage()](#getpluginmultisigstorage-bpar1) — BeneficiaryPluginAddRights, internal
* [\_getProposalWithStatus(ISafeMinimalMultisig.Storage,bytes32\[\],uint256)](#_getproposalwithstatus-lsmb1) — LibSafeMinimalBeneficiaryMultisig, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(b) by beneficiary count

**Example:** Inspect a proposal before confirming or canceling it.

***

### barGetProposalListWithStatuses (BPAR1)

**Contract/Library:** BeneficiaryPluginAddRights

**Description:** Returns all multisig proposals with confirmation metadata.

**Detailed Description:** Collects the voter list, computes the confirmation requirement, and builds an array of [`ProposalWithStatus`](https://docs.cryptolegacy.app/documentation/data-structures-reference#proposalwithstatus-ism1-s3) entries for each stored proposal.

**Parameters:** None

**Returns:**

* voters (bytes32\[], memory): Eligible voter identifiers
* requiredConfirmations (uint128): Confirmation threshold
* proposalsWithStatuses (ISafeMinimalMultisig.ProposalWithStatus\[], memory): Proposals plus confirmation flags

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [LibCryptoLegacy.getCryptoLegacyStorage()](#getcryptolegacystorage-lcl1) — LibCryptoLegacy, internal
* [getPluginMultisigStorage()](#getpluginmultisigstorage-bpar1) — BeneficiaryPluginAddRights, internal
* [LibSafeMinimalBeneficiaryMultisig.\_getProposalListWithStatuses(...)](#_getproposallistwithstatuses-lsmb1) — LibSafeMinimalBeneficiaryMultisig, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(b + p·b) where b = beneficiary count, p = proposal count

**Example:** List all pending proposals and current confirmations in the UI.

***

## BeneficiaryUniswapV4SwapPlugin (BU4SP1)

### constructor (BU4SP1)

**Contract/Library:** BeneficiaryUniswapV4SwapPlugin

**Description:** Stores the Universal Router and Permit2 addresses used by the plugin.

**Detailed Description:** Initializes the plugin with the Universal Router and Permit2 endpoints that power both the single-hop and multi-hop swap flows.

**Parameters:**

* \_universalRouter (address): Universal Router entry point used to execute V4 swaps
* \_permit2 (address): Permit2 contract used to authorize the router to spend input tokens

**Returns:** None

**Modifiers / Visibility / Mutability:**

* constructor nonpayable

**Access Control:**

* Unrestricted at deployment time

**Side Effects:**

* Sets [`UNIVERSAL_ROUTER (BU4SP-D7)`](https://docs.cryptolegacy.app/documentation/data-structures-reference#universal_router-bu4sp1-d7) and [`PERMIT2 (BU4SP-D8)`](https://docs.cryptolegacy.app/documentation/data-structures-reference#permit2-bu4sp1-d8) once as immutable configuration

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:** None (deployment only)

**Gas / Complexity note:** O(1)

**Example:** `new BeneficiaryUniswapV4SwapPlugin(router, permit2);`

***

### getSigs (BU4SP1)

**Contract/Library:** BeneficiaryUniswapV4SwapPlugin

**Description:** Returns the selectors exposed by the Uniswap V4 beneficiary plugin.

**Detailed Description:** Builds the 10-selector array used by the diamond to register the plugin's multisig-management getters and the two swap execution entry points.

**Parameters:** None

**Returns:**

* sigs (bytes4\[], memory): Selector list covering the plugin's public surface

**Modifiers / Visibility / Mutability:**

* external pure

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:** None (entry point)

**Gas / Complexity note:** O(1) — fixed-length selector assembly

**Example:** Plugin registry reads `getSigs()` before wiring the facet into the diamond.

***

### getSetupSigs (BU4SP1)

**Contract/Library:** BeneficiaryUniswapV4SwapPlugin

**Description:** Returns setup-time selectors required by the Uniswap V4 beneficiary plugin.

**Detailed Description:** Returns an empty array, confirming that the plugin does not require any special setup selectors during installation.

**Parameters:** None

**Returns:**

* sigs (bytes4\[], memory): Always an empty selector array

**Modifiers / Visibility / Mutability:**

* external pure

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Installer checks `getSetupSigs()` and skips extra setup calls because the array is empty.

***

### getMultisigAllowedMethods (BU4SP1)

**Contract/Library:** BeneficiaryUniswapV4SwapPlugin

**Description:** Lists selectors that beneficiary multisig proposals are allowed to execute.

**Detailed Description:** Returns the two allowed execution selectors for the plugin: the single-hop exact-input swap and the multi-hop exact-input swap.

**Parameters:** None

**Returns:**

* sigs (bytes4\[], memory): Allowed multisig method selectors

**Modifiers / Visibility / Mutability:**

* public pure

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:**

* [bunisPropose(bytes4,bytes)](#bunispropose-bu4sp1) — BeneficiaryUniswapV4SwapPlugin

**Gas / Complexity note:** O(1)

**Example:** `bunisPropose` checks this list before accepting a new swap proposal.

***

### getPluginName (BU4SP1)

**Contract/Library:** BeneficiaryUniswapV4SwapPlugin

**Description:** Returns the unique plugin name string.

**Detailed Description:** Supplies the stable identifier `"beneficiary_uniswap_v4_swap"` for registry displays and plugin metadata views.

**Parameters:** None

**Returns:**

* name (string, memory): Static plugin name `"beneficiary_uniswap_v4_swap"`

**Modifiers / Visibility / Mutability:**

* public pure

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Front-end uses `getPluginName()` to display the installed swap facet.

***

### getPluginVer (BU4SP1)

**Contract/Library:** BeneficiaryUniswapV4SwapPlugin

**Description:** Returns the semantic version for the Uniswap V4 beneficiary plugin.

**Detailed Description:** Exposes the hard-coded version `1` so deployment and upgrade tooling can compare the installed facet against the expected release.

**Parameters:** None

**Returns:**

* version (uint16): Static plugin version `1`

**Modifiers / Visibility / Mutability:**

* external pure

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Upgrade tooling checks `getPluginVer()` before replacing the swap facet.

***

### modifier onlyDistributionReady (BU4SP1)

**Contract/Library:** BeneficiaryUniswapV4SwapPlugin

**Description:** Restricts execution to phases where beneficiary distribution is already active.

**Detailed Description:** Loads CryptoLegacy storage and forwards it to `LibCryptoLegacy._checkDistributionReady(...)`, requiring the distribution-start timestamp to be set and already reached before the wrapped function proceeds.

**Parameters:** None

**Returns:** None

**Modifiers / Visibility / Mutability:**

* modifier nonpayable

**Access Control:**

* Distribution must already be active

**Side Effects:** None

**Emits:** None

**Reverts if:**

* Distribution not yet ready — [`TooEarly()`](https://docs.cryptolegacy.app/documentation/errors-reference#tooearly-icl1)

**Overrides:** None

**Function Calls:**

* [LibCryptoLegacy.getCryptoLegacyStorage()](#getcryptolegacystorage-lcl1) — LibCryptoLegacy, internal
* [LibCryptoLegacy.\_checkDistributionReady(ICryptoLegacy.CryptoLegacyStorage)](#_checkdistributionready-lcl1) — LibCryptoLegacy, internal

**Called by:**

* [bunisPropose(bytes4,bytes)](#bunispropose-bu4sp1) — BeneficiaryUniswapV4SwapPlugin
* [bunisConfirm(uint256)](#bunisconfirm-bu4sp1) — BeneficiaryUniswapV4SwapPlugin
* [bunisCancel(uint256)](#buniscancel-bu4sp1) — BeneficiaryUniswapV4SwapPlugin
* [bunisSwapExactInputSingle(BeneficiaryUniswapV4SwapPlugin.PoolKey,bool,uint128,uint128,bytes)](#bunisswapexactinputsingle-bu4sp1) — BeneficiaryUniswapV4SwapPlugin
* [bunisSwapExactInput(address,BeneficiaryUniswapV4SwapPlugin.PathKey\[\],uint128,uint128)](#bunisswapexactinput-bu4sp1) — BeneficiaryUniswapV4SwapPlugin

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### getPluginMultisigStorage (BU4SP1)

**Contract/Library:** BeneficiaryUniswapV4SwapPlugin

**Description:** Retrieves the plugin-specific multisig storage slot.

**Detailed Description:** Uses inline assembly to reinterpret [`PLUGIN_MULTISIG_POSITION (BU4SP-D1)`](https://docs.cryptolegacy.app/documentation/data-structures-reference#plugin_multisig_position-bu4sp1-d1) as an `ISafeMinimalMultisig.Storage` reference shared by the plugin's multisig helpers and views.

**Parameters:** None

**Returns:**

* storageStruct (ISafeMinimalMultisig.Storage, storage): Multisig storage layout for this plugin

**Modifiers / Visibility / Mutability:**

* internal pure

**Access Control:**

* Internal helper used only by this plugin

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:**

* [bunisSetMultisigConfig(uint128)](#bunissetmultisigconfig-bu4sp1) — BeneficiaryUniswapV4SwapPlugin
* [bunisPropose(bytes4,bytes)](#bunispropose-bu4sp1) — BeneficiaryUniswapV4SwapPlugin
* [bunisConfirm(uint256)](#bunisconfirm-bu4sp1) — BeneficiaryUniswapV4SwapPlugin
* [bunisCancel(uint256)](#buniscancel-bu4sp1) — BeneficiaryUniswapV4SwapPlugin
* [bunisGetInitializationStatus()](#bunisgetinitializationstatus-bu4sp1) — BeneficiaryUniswapV4SwapPlugin
* [bunisGetVotersAndConfirmations()](#bunisgetvotersandconfirmations-bu4sp1) — BeneficiaryUniswapV4SwapPlugin
* [bunisGetProposalWithStatus(uint256)](#bunisgetproposalwithstatus-bu4sp1) — BeneficiaryUniswapV4SwapPlugin
* [bunisGetProposalListWithStatuses()](#bunisgetproposallistwithstatuses-bu4sp1) — BeneficiaryUniswapV4SwapPlugin

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### bunisSetMultisigConfig (BU4SP1)

**Contract/Library:** BeneficiaryUniswapV4SwapPlugin

**Description:** Updates the beneficiary multisig confirmation threshold for the swap plugin.

**Detailed Description:** If called by the contract itself, the function rechecks distribution readiness; otherwise it enforces owner authority. It then loads the current beneficiary set and forwards the new threshold to `LibSafeMinimalBeneficiaryMultisig._setConfirmations(...)`.

**Parameters:**

* \_requiredConfirmations (uint128): Desired confirmation threshold

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external nonpayable

**Access Control:**

* Owner when called externally; `address(this)` may call it once distribution is ready

**Side Effects:**

* Updates `requiredConfirmations` inside plugin multisig storage

**Emits:**

* [SetConfirmations](https://docs.cryptolegacy.app/documentation/events-reference#setconfirmations-ism1) — `SetConfirmations(uint128 requiredConfirmations)`

**Reverts if:**

* Distribution already started on the owner path — [`DistributionStarted()`](https://docs.cryptolegacy.app/documentation/errors-reference#distributionstarted-icl1)
* Initial fee unpaid on the owner path — [`InitialFeeNotPaid()`](https://docs.cryptolegacy.app/documentation/errors-reference#initialfeenotpaid-icl1)
* Caller is not owner on the owner path — [`NotTheOwner()`](https://docs.cryptolegacy.app/documentation/errors-reference#nottheowner-icl1)
* Distribution not yet ready on the self-call path — [`TooEarly()`](https://docs.cryptolegacy.app/documentation/errors-reference#tooearly-icl1)
* Invalid threshold for the current beneficiary set — [`MultisigIncorrectRequiredConfirmations()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisigincorrectrequiredconfirmations-ism1)

**Overrides:** None

**Function Calls:**

* [LibCryptoLegacy.getCryptoLegacyStorage()](#getcryptolegacystorage-lcl1) — LibCryptoLegacy, internal
* [LibCryptoLegacy.\_checkDistributionReady(ICryptoLegacy.CryptoLegacyStorage)](#_checkdistributionready-lcl1) — LibCryptoLegacy, internal
* [LibCryptoLegacy.\_checkOwner()](#_checkowner-lcl1) — LibCryptoLegacy, internal
* [getPluginMultisigStorage()](#getpluginmultisigstorage-bu4sp1) — BeneficiaryUniswapV4SwapPlugin, internal
* [LibSafeMinimalBeneficiaryMultisig.\_setConfirmations(...)](#_setconfirmations-lsmb1) — LibSafeMinimalBeneficiaryMultisig, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(b) by number of beneficiaries

**Example:** Owner raises the number of beneficiary confirmations required for swap proposals.

***

### bunisPropose (BU4SP1)

**Contract/Library:** BeneficiaryUniswapV4SwapPlugin

**Description:** Creates a multisig proposal for an allowed Uniswap V4 beneficiary action.

**Detailed Description:** Requires distribution to be active, validates the caller as an allowed beneficiary voter, checks the requested selector against the plugin allowlist, and records a proposal that may execute immediately if only one confirmation is required.

**Parameters:**

* \_selector (bytes4): Target function selector
* \_params (bytes, memory): ABI-encoded arguments for the target call

**Returns:**

* proposalId (uint256): Newly created proposal index

**Modifiers / Visibility / Mutability:**

* external payable nonReentrant onlyDistributionReady

**Access Control:**

* Caller must be an authorized beneficiary voter

**Side Effects:**

* Appends a proposal to plugin multisig storage
* Records the proposer's confirmation and may execute immediately
* Credits held ETH when execution leaves surplus native value behind

**Emits:**

* [CreateSafeMinimalMultisigProposal](https://docs.cryptolegacy.app/documentation/events-reference#createsafeminimalmultisigproposal-ism1) — `CreateSafeMinimalMultisigProposal(uint256 proposalId, bytes32 voter, uint128 reqConfirmations)`
* [ExecuteSafeMinimalMultisigProposal](https://docs.cryptolegacy.app/documentation/events-reference#executesafeminimalmultisigproposal-ism1) — `ExecuteSafeMinimalMultisigProposal(uint256 proposalId, bytes32 voter, bool executed, bytes returnData)` (when quorum is reached immediately)
* [AddHeldEth](https://docs.cryptolegacy.app/documentation/events-reference#addheldeth-ism1) — `AddHeldEth(bytes32 voter, uint256 value)` (when ETH is retained)

**Reverts if:**

* Distribution not yet ready — [`TooEarly()`](https://docs.cryptolegacy.app/documentation/errors-reference#tooearly-icl1)
* Reentrant call — "ReentrancyGuard: reentrant call"
* Caller is not an allowed voter — [`MultisigVoterNotAllowed()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisigvoternotallowed-ism1)
* Selector is not in the plugin allowlist — [`MultisigMethodNotAllowed()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisigmethodnotallowed-ism1)
* Execution of the approved action fails — [`MultisigExecutionFailed()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisigexecutionfailed-ism1)

**Overrides:** None

**Function Calls:**

* [getPluginMultisigStorage()](#getpluginmultisigstorage-bu4sp1) — BeneficiaryUniswapV4SwapPlugin, internal
* [getMultisigAllowedMethods()](#getmultisigallowedmethods-bu4sp1) — BeneficiaryUniswapV4SwapPlugin, internal
* [LibSafeMinimalBeneficiaryMultisig.\_propose(...)](#_propose-lsmb1) — LibSafeMinimalBeneficiaryMultisig, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(b) by beneficiary count

**Example:** Beneficiary voter proposes a `bunisSwapExactInputSingle` action after distribution starts.

***

### bunisConfirm (BU4SP1)

**Contract/Library:** BeneficiaryUniswapV4SwapPlugin

**Description:** Confirms an existing plugin proposal and executes it once quorum is reached.

**Detailed Description:** Validates the caller as an allowed voter, records their confirmation, recomputes the confirmation count, and executes the underlying swap action when the multisig threshold is met.

**Parameters:**

* \_proposalId (uint256): Proposal index to confirm

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external payable nonReentrant onlyDistributionReady

**Access Control:**

* Caller must be an authorized beneficiary voter

**Side Effects:**

* Updates per-proposal confirmation bookkeeping
* May execute the underlying action
* Credits held ETH when execution leaves surplus native value behind

**Emits:**

* [ConfirmSafeMinimalMultisigProposal](https://docs.cryptolegacy.app/documentation/events-reference#confirmsafeminimalmultisigproposal-ism1) — `ConfirmSafeMinimalMultisigProposal(uint256 proposalId, bytes32 voter, uint128 reqConfirmations, uint256 confirms)`
* [ExecuteSafeMinimalMultisigProposal](https://docs.cryptolegacy.app/documentation/events-reference#executesafeminimalmultisigproposal-ism1) — `ExecuteSafeMinimalMultisigProposal(uint256 proposalId, bytes32 voter, bool executed, bytes returnData)` (on execution)
* [AddHeldEth](https://docs.cryptolegacy.app/documentation/events-reference#addheldeth-ism1) — `AddHeldEth(bytes32 voter, uint256 value)` (when ETH is retained)

**Reverts if:**

* Distribution not yet ready — [`TooEarly()`](https://docs.cryptolegacy.app/documentation/errors-reference#tooearly-icl1)
* Reentrant call — "ReentrancyGuard: reentrant call"
* Caller is not an allowed voter — [`MultisigVoterNotAllowed()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisigvoternotallowed-ism1)
* Proposal is not pending — [`MultisigProposalNotPending()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisigproposalnotpending-ism1)
* Execution of the approved action fails — [`MultisigExecutionFailed()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisigexecutionfailed-ism1)

**Overrides:** None

**Function Calls:**

* [getPluginMultisigStorage()](#getpluginmultisigstorage-bu4sp1) — BeneficiaryUniswapV4SwapPlugin, internal
* [LibSafeMinimalBeneficiaryMultisig.\_confirm(...)](#_confirm-lsmb1) — LibSafeMinimalBeneficiaryMultisig, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(b) by beneficiary count

**Example:** Second beneficiary confirms a pending swap proposal so it can execute.

***

### bunisCancel (BU4SP1)

**Contract/Library:** BeneficiaryUniswapV4SwapPlugin

**Description:** Removes the caller's confirmation from a pending plugin proposal.

**Detailed Description:** Ensures the proposal is still pending, clears the caller's confirmation, recomputes the remaining confirmations, and cancels the proposal if no confirmations remain.

**Parameters:**

* \_proposalId (uint256): Proposal index to unconfirm

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external nonpayable nonReentrant onlyDistributionReady

**Access Control:**

* Caller must be an authorized beneficiary voter who previously confirmed

**Side Effects:**

* Updates proposal confirmation bookkeeping and may mark the proposal as canceled

**Emits:**

* [CancelSafeMinimalMultisigProposal](https://docs.cryptolegacy.app/documentation/events-reference#cancelsafeminimalmultisigproposal-ism1) — `CancelSafeMinimalMultisigProposal(uint256 proposalId, bytes32 voter, uint128 reqConfirmations, ISafeMinimalMultisig.ProposalStatus status)`

**Reverts if:**

* Distribution not yet ready — [`TooEarly()`](https://docs.cryptolegacy.app/documentation/errors-reference#tooearly-icl1)
* Reentrant call — "ReentrancyGuard: reentrant call"
* Caller is not an allowed voter — [`MultisigVoterNotAllowed()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisigvoternotallowed-ism1)
* Proposal is not pending — [`MultisigProposalNotPending()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisigproposalnotpending-ism1)
* Caller had not confirmed — [`MultisigNotConfirmed()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisignotconfirmed-ism1)

**Overrides:** None

**Function Calls:**

* [getPluginMultisigStorage()](#getpluginmultisigstorage-bu4sp1) — BeneficiaryUniswapV4SwapPlugin, internal
* [LibSafeMinimalBeneficiaryMultisig.\_cancel(...)](#_cancel-lsmb1) — LibSafeMinimalBeneficiaryMultisig, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(b) by beneficiary count

**Example:** Beneficiary retracts a proposal to execute a swap route.

***

### bunisGetInitializationStatus (BU4SP1)

**Contract/Library:** BeneficiaryUniswapV4SwapPlugin

**Description:** Reports whether the plugin's multisig configuration has been initialized.

**Detailed Description:** Delegates to `LibSafeMinimalBeneficiaryMultisig._initializationStatus(...)` to determine whether the confirmation threshold is already configured for the current beneficiary set.

**Parameters:** None

**Returns:**

* status (ISafeMinimalMultisig.InitializationStatus): Current multisig initialization state

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [getPluginMultisigStorage()](#getpluginmultisigstorage-bu4sp1) — BeneficiaryUniswapV4SwapPlugin, internal
* [LibSafeMinimalBeneficiaryMultisig.\_initializationStatus(...)](#_initializationstatus-lsmb1) — LibSafeMinimalBeneficiaryMultisig, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** UI checks whether beneficiaries have configured the Uniswap plugin multisig.

***

### bunisGetVotersAndConfirmations (BU4SP1)

**Contract/Library:** BeneficiaryUniswapV4SwapPlugin

**Description:** Returns the beneficiary voter list and current confirmation threshold.

**Detailed Description:** Delegates to `LibSafeMinimalBeneficiaryMultisig._getVotersAndConfirmations(...)` to expose the plugin's current multisig configuration.

**Parameters:** None

**Returns:**

* voters (bytes32\[], memory): Current beneficiary voter hashes
* requiredConfirmations (uint128): Confirmation threshold used for proposal execution

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [getPluginMultisigStorage()](#getpluginmultisigstorage-bu4sp1) — BeneficiaryUniswapV4SwapPlugin, internal
* [LibSafeMinimalBeneficiaryMultisig.\_getVotersAndConfirmations(...)](#_getvotersandconfirmations-lsmb1) — LibSafeMinimalBeneficiaryMultisig, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(b) by beneficiary count

**Example:** Monitoring UI reads the current voter set and required confirmations for the plugin.

***

### bunisGetProposalWithStatus (BU4SP1)

**Contract/Library:** BeneficiaryUniswapV4SwapPlugin

**Description:** Returns a single multisig proposal together with its derived execution status.

**Detailed Description:** Loads both CryptoLegacy storage and plugin multisig storage, then delegates to `LibSafeMinimalBeneficiaryMultisig._getProposalWithStatus(...)` so clients can inspect one proposal plus its effective status and voter metadata.

**Parameters:**

* \_proposalId (uint256): Proposal index to inspect

**Returns:**

* voters (bytes32\[], memory): Current voter list used to interpret the proposal
* requiredConfirmations (uint128): Confirmation threshold for the proposal
* proposalWithStatus (ISafeMinimalMultisig.ProposalWithStatus, memory): Proposal payload plus derived status

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:**

* `_proposalId` is out of range — `panic(0x32)`

**Overrides:** None

**Function Calls:**

* [LibCryptoLegacy.getCryptoLegacyStorage()](#getcryptolegacystorage-lcl1) — LibCryptoLegacy, internal
* [getPluginMultisigStorage()](#getpluginmultisigstorage-bu4sp1) — BeneficiaryUniswapV4SwapPlugin, internal
* [LibSafeMinimalBeneficiaryMultisig.\_getProposalWithStatus(...)](#_getproposalwithstatus-lsmb1) — LibSafeMinimalBeneficiaryMultisig, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(b) by beneficiary count

**Example:** Front-end opens one pending swap proposal with its confirmation status.

***

### bunisGetProposalListWithStatuses (BU4SP1)

**Contract/Library:** BeneficiaryUniswapV4SwapPlugin

**Description:** Returns the full plugin proposal list with derived statuses.

**Detailed Description:** Delegates to `LibSafeMinimalBeneficiaryMultisig._getProposalListWithStatuses(...)` so clients can inspect every recorded proposal together with the current voter configuration.

**Parameters:** None

**Returns:**

* voters (bytes32\[], memory): Current voter list
* requiredConfirmations (uint128): Current confirmation threshold
* proposalsWithStatuses (ISafeMinimalMultisig.ProposalWithStatus\[], memory): Proposal list with derived statuses

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [LibCryptoLegacy.getCryptoLegacyStorage()](#getcryptolegacystorage-lcl1) — LibCryptoLegacy, internal
* [getPluginMultisigStorage()](#getpluginmultisigstorage-bu4sp1) — BeneficiaryUniswapV4SwapPlugin, internal
* [LibSafeMinimalBeneficiaryMultisig.\_getProposalListWithStatuses(...)](#_getproposallistwithstatuses-lsmb1) — LibSafeMinimalBeneficiaryMultisig, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(p + b) by proposal count and beneficiary count

**Example:** Dashboard renders the full history of Uniswap plugin proposals with live statuses.

***

### bunisSwapExactInputSingle (BU4SP1)

**Contract/Library:** BeneficiaryUniswapV4SwapPlugin

**Description:** Executes a single-hop exact-input Uniswap V4 swap and migrates claims into the output token.

**Detailed Description:** Restricted to the beneficiary multisig executor after distribution starts. The function validates the input amount, resolves `tokenIn` and `tokenOut` from the provided pool key and direction flag, snapshots balances, resets ERC-20 allowance through `LibCLUtils`, grants Permit2 approval to the Universal Router, executes the encoded router call, migrates beneficiary claims into the output token, and emits `UniswapV4SwapExactInputSingle`.

**Parameters:**

* key (BeneficiaryUniswapV4SwapPlugin.PoolKey, calldata): Single-hop pool definition
* zeroForOne (bool): Swap direction flag
* amountIn (uint128): Exact input amount
* amountOutMinimum (uint128): Minimum acceptable output amount
* hookData (bytes, calldata): Hook payload forwarded to the router

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external nonpayable onlyDistributionReady

**Access Control:**

* Must be invoked by the beneficiary multisig executor after distribution starts

**Side Effects:**

* Updates ERC-20 and Permit2 approvals for the input token
* Executes a Universal Router swap
* Migrates beneficiary claims from `tokenIn` into `tokenOut`

**Emits:**

* [UniswapV4SwapExactInputSingle](https://docs.cryptolegacy.app/documentation/events-reference#uniswapv4swapexactinputsingle-bu4sp1) — `UniswapV4SwapExactInputSingle(address indexed tokenIn, address indexed tokenOut, uint256 amountIn, uint256 amountOut)`

**Reverts if:**

* Distribution not yet ready — [`TooEarly()`](https://docs.cryptolegacy.app/documentation/errors-reference#tooearly-icl1)
* Caller is not the multisig executor — [`MultisigOnlyExecutor()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisigonlyexecutor-ism1)
* `amountIn == 0` — [`ZeroAmount()`](https://docs.cryptolegacy.app/documentation/errors-reference#zeroamount-bu4sp1)
* ERC-20 approval helper fails — [`ApprovalFailed()`](https://docs.cryptolegacy.app/documentation/errors-reference#approvalfailed-lclu1)
* Permit2 or Universal Router call reverts — may revert per external implementation

**Overrides:** None

**Function Calls:**

* [LibSafeMinimalBeneficiaryMultisig.\_checkIsMultisigExecutor()](#_checkismultisigexecutor-lsmb1) — LibSafeMinimalBeneficiaryMultisig, internal
* [LibCryptoLegacy.getCryptoLegacyStorage()](#getcryptolegacystorage-lcl1) — LibCryptoLegacy, internal
* `IERC20(tokenIn).balanceOf(address)` — IERC20, external (staticcall)
* `IERC20(tokenOut).balanceOf(address)` — IERC20, external (staticcall)
* [LibCLUtils.approveToken(address,address,uint256)](#approvetoken-lclu1) — LibCLUtils, internal
* [IPermit2.approve(address,address,uint160,uint48)](#approve-ipm21) — IPermit2, external
* [\_executeExactInputSingleRouter(BeneficiaryUniswapV4SwapPlugin.PoolKey,bool,uint128,uint128,bytes,address,address)](#_executeexactinputsinglerouter-bu4sp1) — BeneficiaryUniswapV4SwapPlugin, internal
* [LibOneStepClaimMigration.migrate(ICryptoLegacy.CryptoLegacyStorage,address,address,uint256,uint256,uint256,uint256)](#migrate-loscm1) — LibOneStepClaimMigration, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1) plus ERC-20, Permit2, and router calls

**Example:** Beneficiaries swap WETH into USDC through one V4 pool while keeping beneficiary accounting aligned to the received token.

***

### bunisSwapExactInput (BU4SP1)

**Contract/Library:** BeneficiaryUniswapV4SwapPlugin

**Description:** Executes a multi-hop exact-input Uniswap V4 swap and migrates claims into the final output token.

**Detailed Description:** Restricted to the beneficiary multisig executor after distribution starts. The function validates both the input amount and route length, snapshots balances for the sold token and final output token, resets ERC-20 allowance through `LibCLUtils`, grants Permit2 approval to the Universal Router, executes the encoded router call, migrates claims into the final route output, and emits `UniswapV4SwapExactInput`.

**Parameters:**

* currencyIn (address): Input token for the route
* path (BeneficiaryUniswapV4SwapPlugin.PathKey\[], calldata): Multi-hop route definition
* amountIn (uint128): Exact input amount
* amountOutMinimum (uint128): Minimum acceptable final output amount

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external nonpayable onlyDistributionReady

**Access Control:**

* Must be invoked by the beneficiary multisig executor after distribution starts

**Side Effects:**

* Updates ERC-20 and Permit2 approvals for the input token
* Executes a Universal Router swap
* Migrates beneficiary claims from `currencyIn` into the route's final token

**Emits:**

* [UniswapV4SwapExactInput](https://docs.cryptolegacy.app/documentation/events-reference#uniswapv4swapexactinput-bu4sp1) — `UniswapV4SwapExactInput(address indexed tokenIn, address indexed tokenOut, uint256 amountIn, uint256 amountOut)`

**Reverts if:**

* Distribution not yet ready — [`TooEarly()`](https://docs.cryptolegacy.app/documentation/errors-reference#tooearly-icl1)
* Caller is not the multisig executor — [`MultisigOnlyExecutor()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisigonlyexecutor-ism1)
* `amountIn == 0` — [`ZeroAmount()`](https://docs.cryptolegacy.app/documentation/errors-reference#zeroamount-bu4sp1)
* `path.length == 0` — [`EmptyPath()`](https://docs.cryptolegacy.app/documentation/errors-reference#emptypath-bu4sp1)
* ERC-20 approval helper fails — [`ApprovalFailed()`](https://docs.cryptolegacy.app/documentation/errors-reference#approvalfailed-lclu1)
* Permit2 or Universal Router call reverts — may revert per external implementation

**Overrides:** None

**Function Calls:**

* [LibSafeMinimalBeneficiaryMultisig.\_checkIsMultisigExecutor()](#_checkismultisigexecutor-lsmb1) — LibSafeMinimalBeneficiaryMultisig, internal
* [LibCryptoLegacy.getCryptoLegacyStorage()](#getcryptolegacystorage-lcl1) — LibCryptoLegacy, internal
* `IERC20(currencyIn).balanceOf(address)` — IERC20, external (staticcall)
* `IERC20(tokenOut).balanceOf(address)` — IERC20, external (staticcall)
* [LibCLUtils.approveToken(address,address,uint256)](#approvetoken-lclu1) — LibCLUtils, internal
* [IPermit2.approve(address,address,uint160,uint48)](#approve-ipm21) — IPermit2, external
* [\_executeExactInputRouter(address,BeneficiaryUniswapV4SwapPlugin.PathKey\[\],uint128,uint128,address)](#_executeexactinputrouter-bu4sp1) — BeneficiaryUniswapV4SwapPlugin, internal
* [LibOneStepClaimMigration.migrate(ICryptoLegacy.CryptoLegacyStorage,address,address,uint256,uint256,uint256,uint256)](#migrate-loscm1) — LibOneStepClaimMigration, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(h) by route hop count plus external router calls

**Example:** Beneficiaries swap WETH through multiple V4 pools into USDC while keeping accounting aligned to the final route output.

***

### \_executeExactInputSingleRouter (BU4SP1)

**Contract/Library:** BeneficiaryUniswapV4SwapPlugin

**Description:** Encodes and submits the single-hop exact-input swap command sequence to the Universal Router.

**Detailed Description:** Builds the V4 action byte arrays, wraps the provided pool data into `ExactInputSingleParams`, ABI-encodes the router input payload, and executes the Universal Router call with the current timestamp as the deadline.

**Parameters:**

* key (BeneficiaryUniswapV4SwapPlugin.PoolKey, calldata): Single-hop pool definition
* zeroForOne (bool): Swap direction flag
* amountIn (uint128): Exact input amount
* amountOutMinimum (uint128): Minimum acceptable output amount
* hookData (bytes, calldata): Hook payload forwarded to the router
* tokenIn (address): Input token address used in the settlement action
* tokenOut (address): Output token address used in the take-all action

**Returns:** None

**Modifiers / Visibility / Mutability:**

* private nonpayable

**Access Control:**

* Internal helper used only by this plugin

**Side Effects:**

* Allocates encoded command payloads and forwards them to the Universal Router

**Emits:** None

**Reverts if:**

* Universal Router call reverts — may revert per external implementation

**Overrides:** None

**Function Calls:**

* [IUniversalRouter.execute(bytes,bytes\[\],uint256)](#execute-iur1) — IUniversalRouter, external

**Called by:**

* [bunisSwapExactInputSingle(BeneficiaryUniswapV4SwapPlugin.PoolKey,bool,uint128,uint128,bytes)](#bunisswapexactinputsingle-bu4sp1) — BeneficiaryUniswapV4SwapPlugin

**Gas / Complexity note:** O(1) plus one external router call

**Example:** Not applicable

***

### \_executeExactInputRouter (BU4SP1)

**Contract/Library:** BeneficiaryUniswapV4SwapPlugin

**Description:** Encodes and submits the multi-hop exact-input swap command sequence to the Universal Router.

**Detailed Description:** Builds the V4 action byte arrays, wraps the provided route into `ExactInputParams`, initializes an empty `maxHopSlippage` array, ABI-encodes the router input payload, and executes the Universal Router call with the current timestamp as the deadline.

**Parameters:**

* currencyIn (address): Input token for the route
* path (BeneficiaryUniswapV4SwapPlugin.PathKey\[], calldata): Multi-hop route definition
* amountIn (uint128): Exact input amount
* amountOutMinimum (uint128): Minimum acceptable final output amount
* tokenOut (address): Final output token address used in the take-all action

**Returns:** None

**Modifiers / Visibility / Mutability:**

* private nonpayable

**Access Control:**

* Internal helper used only by this plugin

**Side Effects:**

* Allocates encoded command payloads and forwards them to the Universal Router

**Emits:** None

**Reverts if:**

* Universal Router call reverts — may revert per external implementation

**Overrides:** None

**Function Calls:**

* [IUniversalRouter.execute(bytes,bytes\[\],uint256)](#execute-iur1) — IUniversalRouter, external

**Called by:**

* [bunisSwapExactInput(address,BeneficiaryUniswapV4SwapPlugin.PathKey\[\],uint128,uint128)](#bunisswapexactinput-bu4sp1) — BeneficiaryUniswapV4SwapPlugin

**Gas / Complexity note:** O(h) by route hop count plus one external router call

**Example:** Not applicable

***

## CryptoLegacyBasePlugin (CLBP1)

### getSigs (CLBP1)

**Contract/Library:** CryptoLegacyBasePlugin

**Description:** Lists the primary external selectors exposed by the base plugin.

**Detailed Description:** Returns a fixed array containing selectors for operational entry points such as pausing, fee payments, beneficiary management, messaging, challenge handling, and telemetry helpers.

**Parameters:** None

**Returns:**

* sigs (bytes4\[], memory): Ordered selector list used when wiring the facet

**Modifiers / Visibility / Mutability:**

* external pure

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Facet loader fetches selectors prior to diamond cut.

***

### getSetupSigs (CLBP1)

**Contract/Library:** CryptoLegacyBasePlugin

**Description:** Lists view selectors needed during plugin setup.

**Detailed Description:** Returns a length-5 array containing informational selectors (`getCryptoLegacyVer`, `owner`, `buildManager`, `isPaused`, `isLifetimeActive`) used by deployment tooling.

**Parameters:** None

**Returns:**

* sigs (bytes4\[], memory): Setup selector list

**Modifiers / Visibility / Mutability:**

* external pure

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Deployment script queries these selectors before installing the facet.

***

### getPluginName (CLBP1)

**Contract/Library:** CryptoLegacyBasePlugin

**Description:** Returns the canonical plugin name.

**Detailed Description:** Hard-coded to `"base"` so registries and dashboards can label the facet consistently.

**Parameters:** None

**Returns:**

* `name (string, memory): Literal plugin identifier`

**Modifiers / Visibility / Mutability:**

* public pure

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Plugin registry displays the base facet name.

***

### getPluginVer (CLBP1)

**Contract/Library:** CryptoLegacyBasePlugin

**Description:** Returns the plugin’s semantic version.

**Detailed Description:** Encodes the current plugin version (`1`) as `uint16`.

**Parameters:** None

**Returns:**

* `version (uint16): Plugin version identifier`

**Modifiers / Visibility / Mutability:**

* external pure

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** UI surfaces the plugin version alongside other metadata.

***

### getCryptoLegacyVer (CLBP1)

**Contract/Library:** CryptoLegacyBasePlugin

**Description:** Returns the base CryptoLegacy protocol version.

**Detailed Description:** Static value (`1`) signifying compatibility with the current on-chain schema.

**Parameters:** None

**Returns:**

* `version (uint16): Protocol version supported by this facet`

**Modifiers / Visibility / Mutability:**

* external pure

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Build manager checks for version compatibility before upgrades.

***

### constructor (CLBP1)

**Contract/Library:** CryptoLegacyBasePlugin

**Description:** Empty constructor for upgradeable deployment pattern.

**Detailed Description:** Leaves state uninitialized so that `initializeByBuildManager` can be invoked via proxy.

**Parameters:** None

**Returns:** None

**Modifiers / Visibility / Mutability:**

* constructor nonpayable

**Access Control:**

* Unrestricted (deployment only)

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Deployer constructs implementation once; proxy handles initialization.

***

### initializeByBuildManager (CLBP1)

**Contract/Library:** CryptoLegacyBasePlugin

**Description:** Initializes core storage via the authorized build manager.

**Detailed Description:** Allowed only once and only when `msg.sender` equals `buildManager`. Configures beneficiaries via [`_setBeneficiaries`](#_setbeneficiaries-clbp1), stores update fees/intervals, challenge timeout, and inviter ref code. If the initial fee is zero, marks it as paid; otherwise pauses execution until the fee is settled. Registers the owner in the `BeneficiaryRegistry` and primes reentrancy guard state.

**Parameters:**

* \_updateFee (uint256): Recurring update fee size
* \_initialFeeToPay (uint256): Initial fee required; `0` marks it paid immediately
* \_beneficiaryHashes (bytes32\[], memory): Beneficiary identifiers to seed
* \_beneficiaryConfig ([BeneficiaryConfig](https://docs.cryptolegacy.app/documentation/data-structures-reference#beneficiaryconfig-icl1-s1)\[], memory): Matching configs for each beneficiary
* \_refCode (bytes8): Referral code associated with this legacy
* \_updateInterval (uint64): Seconds between required updates
* \_challengeTimeout (uint64): Delay between challenge and distribution start

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external nonpayable initializer

**Access Control:**

* Caller must equal `buildManager`

**Side Effects:**

* Seeds beneficiary sets and configs
* Updates fee schedule and timing parameters
* Optionally pauses the contract until the initial fee is paid
* Registers the owner in `BeneficiaryRegistry`
* Initializes reentrancy guard state

**Emits:**

* [SetBeneficiary](https://docs.cryptolegacy.app/documentation/events-reference#setbeneficiary-clbp1) — `SetBeneficiary(bytes32 indexed beneficiary, uint64 indexed vestingPeriod, uint64 shareBps, uint64 claimDelay)` (per beneficiary)
* [PauseSet](https://docs.cryptolegacy.app/documentation/events-reference#pauseset-icl1) — `PauseSet(bool indexed isPaused)`
* [AddCryptoLegacyForBeneficiary](https://docs.cryptolegacy.app/documentation/events-reference#addcryptolegacyforbeneficiary-ibr1) — `AddCryptoLegacyForBeneficiary(bytes32 indexed beneficiary, address indexed cryptoLegacy)`
* [AddCryptoLegacyForOwner](https://docs.cryptolegacy.app/documentation/events-reference#addcryptolegacyforowner-ibr1) — `AddCryptoLegacyForOwner(bytes32 indexed owner, address indexed cryptoLegacy)`
* [BeneficiaryRegistryNotDefined](https://docs.cryptolegacy.app/documentation/events-reference#beneficiaryregistrynotdefined-icl1) — `BeneficiaryRegistryNotDefined()`
* [SetCryptoLegacyOwnerCatch](https://docs.cryptolegacy.app/documentation/events-reference#setcryptolegacyownercatch-icl1) — `SetCryptoLegacyOwnerCatch(bytes reason)`
* [SetCryptoLegacyBeneficiaryCatch](https://docs.cryptolegacy.app/documentation/events-reference#setcryptolegacybeneficiarycatch-icl1) — `SetCryptoLegacyBeneficiaryCatch(bytes reason)`

**Reverts if:**

* Caller not build manager — [`NotBuildManager()`](https://docs.cryptolegacy.app/documentation/errors-reference#notbuildmanager-icl1)
* Beneficiary arrays length mismatch — [`LengthMismatch()`](https://docs.cryptolegacy.app/documentation/errors-reference#lengthmismatch-icl1)
* Duplicate original beneficiary hash detected — [`OriginalHashDuplicate()`](https://docs.cryptolegacy.app/documentation/errors-reference#originalhashduplicate-icl1)
* Beneficiary shares do not sum to 10,000 — [`ShareSumDoesntMatchBase()`](https://docs.cryptolegacy.app/documentation/errors-reference#sharesumdoesntmatchbase-icl1)
* Pausing not permitted (challenge already started) — [`ChallengePeriodStarted()`](https://docs.cryptolegacy.app/documentation/errors-reference#challengeperiodstarted-icl1)
* Re-initialization attempt — "Initializable: contract is already initialized"

**Overrides:** None

**Function Calls:**

* [LibCryptoLegacy.getCryptoLegacyStorage()](#getcryptolegacystorage-lcl1) — LibCryptoLegacy, internal
* [\_setBeneficiaries(bytes32\[\],BeneficiaryConfig\[\])](#_setbeneficiaries-clbp1) — CryptoLegacyBasePlugin, internal
* [LibCryptoLegacy.\_setPause(ICryptoLegacy.CryptoLegacyStorage,bool)](#_setpause-lcl1) — LibCryptoLegacy, internal
* [owner()](#owner-clbp1) — CryptoLegacyBasePlugin, internal
* [LibCryptoLegacy.\_addressToHash(address)](#_addresstohash-lcl1) — LibCryptoLegacy, internal
* [LibCryptoLegacy.\_setCryptoLegacyToBeneficiaryRegistry(ICryptoLegacy.CryptoLegacyStorage,bytes32,IBeneficiaryRegistry.EntityType,bool)](#_setcryptolegacytobeneficiaryregistry-lcl1) — LibCryptoLegacy, internal
* `__ReentrancyGuard_init()` — OpenZeppelin, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(n) by number of seeded beneficiaries

**Example:** Build manager finalizes deployment and seeds beneficiaries immediately after creating the proxy.

***

### owner (CLBP1)

**Contract/Library:** CryptoLegacyBasePlugin

**Description:** Returns the current contract owner.

**Detailed Description:** Delegates to the diamond storage helper `LibDiamond.contractOwner()` for compatibility with EIP-2535 ownership semantics.

**Parameters:** None

**Returns:**

* ownerAddress (address): Current owner address

**Modifiers / Visibility / Mutability:**

* public view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [LibDiamond.contractOwner()](#contractowner-ld1) — LibDiamond, internal

**Called by:**

* [initializeByBuildManager(uint256,uint256,bytes32\[\],BeneficiaryConfig\[\],bytes8,uint64,uint64)](#initializebybuildmanager-clbp1) — CryptoLegacyBasePlugin
* [payInitialFee()](#payinitialfee-clbp1) — CryptoLegacyBasePlugin
* [update()](#update-clbp1) — CryptoLegacyBasePlugin
* [beneficiaryClaim()](#beneficiaryclaim-clbp1) — CryptoLegacyBasePlugin
* [isLifetimeActive()](#islifetimeactive-clbp1) — CryptoLegacyBasePlugin

**Gas / Complexity note:** O(1)

**Example:** Front-end displays current control address.

***

### isPaused (CLBP1)

**Contract/Library:** CryptoLegacyBasePlugin

**Description:** Returns whether the contract is currently paused.

**Detailed Description:** Reads `isPaused` from storage via `LibCryptoLegacy._getPause`.

**Parameters:** None

**Returns:**

* paused (bool): `true` if paused

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [LibCryptoLegacy.getCryptoLegacyStorage()](#getcryptolegacystorage-lcl1) — LibCryptoLegacy, internal
* [LibCryptoLegacy.\_getPause(ICryptoLegacy.CryptoLegacyStorage)](#_getpause-lcl1) — LibCryptoLegacy, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Monitoring service checks pause status.

***

### buildManager (CLBP1)

**Contract/Library:** CryptoLegacyBasePlugin

**Description:** Returns the associated build manager contract.

**Detailed Description:** Reads `buildManager` from CryptoLegacy storage.

**Parameters:** None

**Returns:**

* manager (ICryptoLegacyBuildManager): Build manager interface

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [LibCryptoLegacy.getCryptoLegacyStorage()](#getcryptolegacystorage-lcl1) — LibCryptoLegacy, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Integration queries the managing contract address.

***

### transferOwnership (CLBP1)

**Contract/Library:** CryptoLegacyBasePlugin

**Description:** Begins the two-step ownership transfer process.

**Detailed Description:** Callable only by the current owner; the modifier guards against in-progress distributions, ensures the initial fee has been paid, and verifies sender ownership before delegating to `_transferOwnership`. Stores the pending owner and emits `OwnershipTransferStarted`; the new owner must later call `acceptOwnership`.

**Parameters:**

* newOwner (address): Proposed new owner address

**Returns:** None

**Modifiers / Visibility / Mutability:**

* public virtual nonpayable onlyOwner

**Access Control:**

* Current owner only

**Side Effects:**

* Updates `pendingOwner` in storage

**Emits:**

* [OwnershipTransferStarted](https://docs.cryptolegacy.app/documentation/events-reference#ownershiptransferstarted-iclo1) — `OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner)`

**Reverts if:**

* Distribution already started — [`DistributionStarted()`](https://docs.cryptolegacy.app/documentation/errors-reference#distributionstarted-icl1)
* Initial fee unpaid — [`InitialFeeNotPaid()`](https://docs.cryptolegacy.app/documentation/errors-reference#initialfeenotpaid-icl1)
* Caller not owner — [`NotTheOwner()`](https://docs.cryptolegacy.app/documentation/errors-reference#nottheowner-icl1)
* `newOwner` is zero address — [`ZeroAddress()`](https://docs.cryptolegacy.app/documentation/errors-reference#zeroaddress-icl1)

**Overrides:** None

**Function Calls:**

* [LibCryptoLegacy.getCryptoLegacyStorage()](#getcryptolegacystorage-lcl1) — LibCryptoLegacy, internal
* [\_transferOwnership(ICryptoLegacy.CryptoLegacyStorage,address)](#_transferownership-clo1) — CryptoLegacyOwnable, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Owner nominates a new executor to assume control.

***

### payInitialFee (CLBP1)

**Contract/Library:** CryptoLegacyBasePlugin

**Description:** Pays the one-time initial fee and unpauses the contract.

**Detailed Description:** Ensures the fee was not paid before, validates array lengths, unpauses the contract, and stamps `lastFeePaidAt/lastUpdateAt`. If a lifetime NFT is active the function checks that no ETH was sent and emits `FeePaidByLifetime`. Otherwise it attempts to route payment through the build manager (`payInitialFee`), falling back to direct transfer after verifying the fee amount. On success resets `initialFeeToPay` to zero.

**Parameters:**

* \_lockToChainIds (uint256\[], memory): Chain IDs for cross-chain fee locking
* \_crossChainFees (uint256\[], memory): Per-chain fees aligned with `_lockToChainIds`

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external payable nonReentrant

**Access Control:**

* Unrestricted

**Side Effects:**

* Clears pause flag
* Updates fee timestamps and `initialFeeToPay`
* Transfers ETH to build manager and optionally refund sender

**Emits:**

* [PauseSet](https://docs.cryptolegacy.app/documentation/events-reference#pauseset-icl1) — `PauseSet(bool indexed isPaused)`
* [FeePaidByLifetime](https://docs.cryptolegacy.app/documentation/events-reference#feepaidbylifetime-icl1) — `FeePaidByLifetime(bytes8 indexed refCode, bool indexed initial, address factory, uint64 lastFeePaidAt)`
* [FeePaidByDefault](https://docs.cryptolegacy.app/documentation/events-reference#feepaidbydefault-icl1) — `FeePaidByDefault(bytes8 indexed refCode, bool indexed initial, uint256 value, uint256 returnedValue, address factory, uint64 lastFeePaidAt)`
* [FeePaidByTransfer](https://docs.cryptolegacy.app/documentation/events-reference#feepaidbytransfer-icl1) — `FeePaidByTransfer(bytes8 indexed refCode, bool indexed initial, uint256 value, address factory, uint64 lastFeePaidAt)`
* [IsLifetimeNftLockedAndUpdateCatch](https://docs.cryptolegacy.app/documentation/events-reference#islifetimenftlockedandupdatecatch-icl1) — `IsLifetimeNftLockedAndUpdateCatch(bytes reason)` when build manager check reverts

**Reverts if:**

* Initial fee already paid — [`InitialFeeAlreadyPaid()`](https://docs.cryptolegacy.app/documentation/errors-reference#initialfeealreadypaid-icl1)
* `_lockToChainIds` and `_crossChainFees` lengths differ — [`ArrayLengthMismatch()`](https://docs.cryptolegacy.app/documentation/errors-reference#arraylengthmismatch-icl1)
* Challenge already started when unpausing — [`ChallengePeriodStarted()`](https://docs.cryptolegacy.app/documentation/errors-reference#challengeperiodstarted-icl1)
* Build manager call reports unregistered legacy — [`NotRegisteredCryptoLegacy()`](https://docs.cryptolegacy.app/documentation/errors-reference#notregisteredcryptolegacy-iclbm1)
* Build manager call reports wrong owner — [`NotOwnerOfCryptoLegacy()`](https://docs.cryptolegacy.app/documentation/errors-reference#notownerofcryptolegacy-iclbm1)
* Lifetime NFT path received ETH — [`NoValueAllowed()`](https://docs.cryptolegacy.app/documentation/errors-reference#novalueallowed-icl1)
* ETH transfer fails — [`TransferFeeFailed(bytes)`](https://docs.cryptolegacy.app/documentation/errors-reference#transferfeefailed-icl1)
* Provided fee invalid — [`IncorrectFee(uint256)`](https://docs.cryptolegacy.app/documentation/errors-reference#incorrectfee-icl1)

**Overrides:** None

**Function Calls:**

* [LibCryptoLegacy.getCryptoLegacyStorage()](#getcryptolegacystorage-lcl1) — LibCryptoLegacy, internal
* [LibCryptoLegacy.\_setPause(ICryptoLegacy.CryptoLegacyStorage,bool)](#_setpause-lcl1) — LibCryptoLegacy, internal
* [owner()](#owner-clbp1) — CryptoLegacyBasePlugin, internal
* [LibCryptoLegacy.\_isLifetimeActiveAndUpdate(ICryptoLegacy.CryptoLegacyStorage,address)](#_islifetimeactiveandupdate-lcl1) — LibCryptoLegacy, internal
* [LibCryptoLegacy.\_checkNoFee()](#_checknofee-lcl1) — LibCryptoLegacy, internal
* `cls.buildManager.payInitialFee(bytes8,address,uint256[],uint256[])` — ICryptoLegacyBuildManager *(at `cls.buildManager`)*, external
* [LibCryptoLegacy.\_transferFee(ICryptoLegacy.CryptoLegacyStorage,address,uint256)](#_transferfee-lcl1) — LibCryptoLegacy, internal
* [LibCryptoLegacy.\_checkFee(uint256)](#_checkfee-lcl1) — LibCryptoLegacy, internal
* [LibCryptoLegacy.\_transferFee(ICryptoLegacy.CryptoLegacyStorage,address,uint256)](#_transferfee-lcl1) — LibCryptoLegacy, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1); external build-manager logic dominates cost

**Example:** Owner pays the onboarding fee after beneficiaries approve the deployment.

***

### setBeneficiaries (CLBP1)

**Contract/Library:** CryptoLegacyBasePlugin

**Description:** Updates beneficiary list and configs under owner control.

**Detailed Description:** Owner-only wrapper around [`_setBeneficiaries`](#_setbeneficiaries-clbp1) to adjust allocations and delays.

**Parameters:**

* \_beneficiaryHashes (bytes32\[], memory): Beneficiary identifiers to update
* \_beneficiaryConfig ([BeneficiaryConfig](https://docs.cryptolegacy.app/documentation/data-structures-reference#beneficiaryconfig-icl1-s1)\[], memory): Matching configuration structs

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external nonpayable onlyOwner

**Access Control:**

* Owner only

**Side Effects:**

* Updates `beneficiaries` set and `beneficiaryConfig` mappings via [\_setBeneficiaries](#_setbeneficiaries-clbp1)
* Refreshes `originalBeneficiaryHash` entries and external registry links

**Emits:**

* [SetBeneficiary](https://docs.cryptolegacy.app/documentation/events-reference#setbeneficiary-clbp1) — `SetBeneficiary(bytes32 indexed beneficiary, uint64 indexed vestingPeriod, uint64 shareBps, uint64 claimDelay)` (per entry)
* [AddCryptoLegacyForBeneficiary](https://docs.cryptolegacy.app/documentation/events-reference#addcryptolegacyforbeneficiary-ibr1) — `AddCryptoLegacyForBeneficiary(bytes32 indexed beneficiary, address indexed cryptoLegacy)` when adding
* [RemoveCryptoLegacyForBeneficiary](https://docs.cryptolegacy.app/documentation/events-reference#removecryptolegacyforbeneficiary-ibr1) — `RemoveCryptoLegacyForBeneficiary(bytes32 indexed beneficiary, address indexed cryptoLegacy)` when removing
* [BeneficiaryRegistryNotDefined](https://docs.cryptolegacy.app/documentation/events-reference#beneficiaryregistrynotdefined-icl1) — `BeneficiaryRegistryNotDefined()` when registry address is missing
* [SetCryptoLegacyBeneficiaryCatch](https://docs.cryptolegacy.app/documentation/events-reference#setcryptolegacybeneficiarycatch-icl1) — `SetCryptoLegacyBeneficiaryCatch(bytes reason)` when registry update fails

**Reverts if:**

* Distribution already started — [`DistributionStarted()`](https://docs.cryptolegacy.app/documentation/errors-reference#distributionstarted-icl1)
* Initial fee unpaid — [`InitialFeeNotPaid()`](https://docs.cryptolegacy.app/documentation/errors-reference#initialfeenotpaid-icl1)
* Caller not owner — [`NotTheOwner()`](https://docs.cryptolegacy.app/documentation/errors-reference#nottheowner-icl1)
* Input array lengths differ — [`LengthMismatch()`](https://docs.cryptolegacy.app/documentation/errors-reference#lengthmismatch-icl1)
* Duplicate original beneficiary hash detected — [`OriginalHashDuplicate()`](https://docs.cryptolegacy.app/documentation/errors-reference#originalhashduplicate-icl1)
* Beneficiary shares do not total 10,000 — [`ShareSumDoesntMatchBase()`](https://docs.cryptolegacy.app/documentation/errors-reference#sharesumdoesntmatchbase-icl1)

**Overrides:** None

**Function Calls:**

* [\_setBeneficiaries(bytes32\[\],BeneficiaryConfig\[\])](#_setbeneficiaries-clbp1) — CryptoLegacyBasePlugin, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(n + n²) — delegates to [\_setBeneficiaries](#_setbeneficiaries-clbp1) with nested share validations

**Example:** Owner updates beneficiary shares after family changes.

***

### \_setBeneficiaries (CLBP1)

**Contract/Library:** CryptoLegacyBasePlugin

**Description:** Internal routine to add, update, or remove beneficiary records.

**Detailed Description:** Validates input length, iterates through each beneficiary hash, and either removes it (if share is zero) or inserts/updates configuration. Maintains `originalBeneficiaryHash`, emits `SetBeneficiary`, and synchronizes the external `BeneficiaryRegistry`. Ensures total shares equal [`SHARE_BASE`](https://docs.cryptolegacy.app/documentation/data-structures-reference#share_base-lcl1-d1) and that original hashes remain unique.

**Parameters:**

* \_beneficiaryHashes (bytes32\[], memory): Beneficiary identifiers
* \_beneficiaryConfig ([BeneficiaryConfig](https://docs.cryptolegacy.app/documentation/data-structures-reference#beneficiaryconfig-icl1-s1)\[], memory): Configuration structs with share, vesting, delay

**Returns:** None

**Modifiers / Visibility / Mutability:**

* internal nonpayable

**Access Control:**

* Unrestricted (internal)

**Side Effects:**

* Updates beneficiary sets, configs, and original hash mapping
* Updates external registry links

**Emits:**

* [SetBeneficiary](https://docs.cryptolegacy.app/documentation/events-reference#setbeneficiary-clbp1) — `SetBeneficiary(bytes32 indexed beneficiary, uint64 indexed vestingPeriod, uint64 shareBps, uint64 claimDelay)` (per entry)
* [AddCryptoLegacyForBeneficiary](https://docs.cryptolegacy.app/documentation/events-reference#addcryptolegacyforbeneficiary-ibr1) — `AddCryptoLegacyForBeneficiary(bytes32 indexed beneficiary, address indexed cryptoLegacy)` when adding
* [RemoveCryptoLegacyForBeneficiary](https://docs.cryptolegacy.app/documentation/events-reference#removecryptolegacyforbeneficiary-ibr1) — `RemoveCryptoLegacyForBeneficiary(bytes32 indexed beneficiary, address indexed cryptoLegacy)` when removing
* [BeneficiaryRegistryNotDefined](https://docs.cryptolegacy.app/documentation/events-reference#beneficiaryregistrynotdefined-icl1) — `BeneficiaryRegistryNotDefined()` when registry address is missing
* [SetCryptoLegacyBeneficiaryCatch](https://docs.cryptolegacy.app/documentation/events-reference#setcryptolegacybeneficiarycatch-icl1) — `SetCryptoLegacyBeneficiaryCatch(bytes reason)` when registry update fails

**Reverts if:**

* Arrays lengths mismatch — [`LengthMismatch()`](https://docs.cryptolegacy.app/documentation/errors-reference#lengthmismatch-icl1)
* Duplicate origin hash detected — [`OriginalHashDuplicate()`](https://docs.cryptolegacy.app/documentation/errors-reference#originalhashduplicate-icl1)
* Share sum != 10,000 — [`ShareSumDoesntMatchBase()`](https://docs.cryptolegacy.app/documentation/errors-reference#sharesumdoesntmatchbase-icl1)

**Overrides:** None

**Function Calls:**

* [LibCryptoLegacy.getCryptoLegacyStorage()](#getcryptolegacystorage-lcl1) — LibCryptoLegacy, internal
* [LibCryptoLegacy.\_setCryptoLegacyToBeneficiaryRegistry(ICryptoLegacy.CryptoLegacyStorage,bytes32,IBeneficiaryRegistry.EntityType,bool)](#_setcryptolegacytobeneficiaryregistry-lcl1) — LibCryptoLegacy, internal
* `EnumerableSet.Bytes32Set` helpers (`contains`, `add`, `remove`, `values`) — OpenZeppelin EnumerableSet, internal

**Called by:**

* [initializeByBuildManager(uint256,uint256,bytes32\[\],BeneficiaryConfig\[\],bytes8,uint64,uint64)](#initializebybuildmanager-clbp1) — CryptoLegacyBasePlugin
* [setBeneficiaries](#setbeneficiaries-clbp1) — CryptoLegacyBasePlugin

**Gas / Complexity note:** O(n + n²) — due to share sum computation and duplicate checks

**Example:** Not applicable

***

### update (CLBP1)

**Contract/Library:** CryptoLegacyBasePlugin

**Description:** Periodic upkeep that charges update fees and resets the distribution timer.

**Detailed Description:** Owner pays any required update fee (optionally cross-chain) via `LibCryptoLegacy._takeFee`, which handles lifetime NFT shortcuts, build manager interactions, or direct transfers. After fee processing the function stamps `lastUpdateAt`, clears `distributionStartAt`, and emits `Update`.

**Parameters:**

* \_lockToChainIds (uint256\[], memory): Chain IDs for fee locking
* \_crossChainFees (uint256\[], memory): Matching fee amounts

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external payable onlyOwner nonReentrant

**Access Control:**

* Owner only

**Side Effects:**

* May transfer ETH to the build manager and refund any returned surplus to the caller
* Updates `lastUpdateAt` and clears `distributionStartAt`

**Emits:**

* [Update](https://docs.cryptolegacy.app/documentation/events-reference#update-icl1) — `Update(uint256 updateFee, bytes32 indexed byPlugin)`
* [GetUpdateFeeCatch](https://docs.cryptolegacy.app/documentation/events-reference#getupdatefeecatch-icl1) — `GetUpdateFeeCatch(bytes reason)` when build manager fee query fails
* [FeePaidByLifetime](https://docs.cryptolegacy.app/documentation/events-reference#feepaidbylifetime-icl1) — `FeePaidByLifetime(bytes8 indexed refCode, bool indexed initial, address factory, uint64 lastFeePaidAt)` when lifetime NFT covers payment
* [FeePaidByDefault](https://docs.cryptolegacy.app/documentation/events-reference#feepaidbydefault-icl1) — `FeePaidByDefault(bytes8 indexed refCode, bool indexed initial, uint256 value, uint256 returnedValue, address factory, uint64 lastFeePaidAt)` when build manager processes the fee
* [PayFeeCatch](https://docs.cryptolegacy.app/documentation/events-reference#payfeecatch-icl1) — `PayFeeCatch(bytes reason)` when falling back from a failed build-manager call
* [FeePaidByTransfer](https://docs.cryptolegacy.app/documentation/events-reference#feepaidbytransfer-icl1) — `FeePaidByTransfer(bytes8 indexed refCode, bool indexed initial, uint256 value, address factory, uint64 lastFeePaidAt)` on direct ETH transfer path
* [SkipSendFeeByTransfer](https://docs.cryptolegacy.app/documentation/events-reference#skipsendfeebytransfer-icl1) — `SkipSendFeeByTransfer(address buildManager, uint256 value)` when no transfer happens due to zero value

**Reverts if:**

* Distribution already started — [`DistributionStarted()`](https://docs.cryptolegacy.app/documentation/errors-reference#distributionstarted-icl1)
* Initial fee unpaid — [`InitialFeeNotPaid()`](https://docs.cryptolegacy.app/documentation/errors-reference#initialfeenotpaid-icl1)
* Caller not owner — [`NotTheOwner()`](https://docs.cryptolegacy.app/documentation/errors-reference#nottheowner-icl1)
* Array lengths mismatch — [`ArrayLengthMismatch()`](https://docs.cryptolegacy.app/documentation/errors-reference#arraylengthmismatch-icl1)
* Build manager call reports unregistered legacy — [`NotRegisteredCryptoLegacy()`](https://docs.cryptolegacy.app/documentation/errors-reference#notregisteredcryptolegacy-iclbm1)
* Build manager call reports wrong owner — [`NotOwnerOfCryptoLegacy()`](https://docs.cryptolegacy.app/documentation/errors-reference#notownerofcryptolegacy-iclbm1)
* Lifetime NFT fee path but ETH sent — [`NoValueAllowed()`](https://docs.cryptolegacy.app/documentation/errors-reference#novalueallowed-icl1)
* Fee array exceeds supported length — [`TooLongArray(uint256)`](https://docs.cryptolegacy.app/documentation/errors-reference#toolongarray-icl1)
* Provided fee invalid — [`IncorrectFee(uint256)`](https://docs.cryptolegacy.app/documentation/errors-reference#incorrectfee-icl1)
* ETH transfer fails — [`TransferFeeFailed(bytes)`](https://docs.cryptolegacy.app/documentation/errors-reference#transferfeefailed-icl1)

**Overrides:** None

**Function Calls:**

* [LibCryptoLegacy.getCryptoLegacyStorage()](#getcryptolegacystorage-lcl1) — LibCryptoLegacy, internal
* [owner()](#owner-clbp1) — CryptoLegacyBasePlugin, internal
* [\_takeFee(ICryptoLegacy.CryptoLegacyStorage,address,address,uint256,uint256\[\],uint256\[\])](#_takefee-lcl1) — LibCryptoLegacy, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1); dominant work happens inside build-manager integrations

**Example:** Owner performs scheduled upkeep to keep legacy active.

***

### setGasLimitMultiplier (CLBP1)

**Contract/Library:** CryptoLegacyBasePlugin

**Description:** Adjusts the gas multiplier used for fee-related calls.

**Detailed Description:** Owner-only setter that validates the new multiplier against [`MAX_GAS_MULTIPLIER`](https://docs.cryptolegacy.app/documentation/data-structures-reference#max_gas_multiplier-lcl1-d5), stores it, and emits `SetGasLimitMultiplier`.

**Parameters:**

* \_gasLimitMultiplier (uint8): New multiplier value

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external payable onlyOwner nonReentrant

**Access Control:**

* Owner only

**Side Effects:**

* Updates `gasLimitMultiplier` in storage

**Emits:**

* [SetGasLimitMultiplier](https://docs.cryptolegacy.app/documentation/events-reference#setgaslimitmultiplier-icl1) — `SetGasLimitMultiplier(uint256 gasLimitMultiplier)`

**Reverts if:**

* Distribution already started — [`DistributionStarted()`](https://docs.cryptolegacy.app/documentation/errors-reference#distributionstarted-icl1)
* Initial fee unpaid — [`InitialFeeNotPaid()`](https://docs.cryptolegacy.app/documentation/errors-reference#initialfeenotpaid-icl1)
* Caller not owner — [`NotTheOwner()`](https://docs.cryptolegacy.app/documentation/errors-reference#nottheowner-icl1)
* `_gasLimitMultiplier` exceeds limit — [`TooBigMultiplier(uint8)`](https://docs.cryptolegacy.app/documentation/errors-reference#toobigmultiplier-icl1)

**Overrides:** None

**Function Calls:**

* [LibCryptoLegacy.getCryptoLegacyStorage()](#getcryptolegacystorage-lcl1) — LibCryptoLegacy, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Owner increases the multiplier to accommodate higher gas chains.

***

### initiateChallenge (CLBP1)

**Contract/Library:** CryptoLegacyBasePlugin

**Description:** Starts the challenge window when upkeep is overdue.

**Detailed Description:** Ensures the contract is not paused, `distributionStartAt` is unset, and the current block time exceeds `lastUpdateAt + updateInterval`. Confirms the caller is a registered beneficiary, sets `distributionStartAt` to now plus `challengeTimeout`, and emits `ChallengeInitiate`.

**Parameters:** None

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external nonpayable

**Access Control:**

* Beneficiary-only (checked on-chain)

**Side Effects:**

* Sets `distributionStartAt`

**Emits:**

* [ChallengeInitiate](https://docs.cryptolegacy.app/documentation/events-reference#challengeinitiate-clbp1) — `ChallengeInitiate(bytes32 indexed beneficiary)`

**Reverts if:**

* Contract paused — [`Pause()`](https://docs.cryptolegacy.app/documentation/errors-reference#pause-icl1)
* Distribution already scheduled — [`DistributionStartAlreadySet()`](https://docs.cryptolegacy.app/documentation/errors-reference#distributionstartalreadyset-icl1)
* Update interval not elapsed — [`TooEarly()`](https://docs.cryptolegacy.app/documentation/errors-reference#tooearly-icl1)
* Caller not a beneficiary — [`NotTheBeneficiary()`](https://docs.cryptolegacy.app/documentation/errors-reference#notthebeneficiary-icl1)

**Overrides:** None

**Function Calls:**

* [LibCryptoLegacy.getCryptoLegacyStorage()](#getcryptolegacystorage-lcl1) — LibCryptoLegacy, internal
* [LibCryptoLegacy.\_checkPause(ICryptoLegacy.CryptoLegacyStorage)](#_checkpause-lcl1) — LibCryptoLegacy, internal
* [LibCryptoLegacy.\_checkAddressIsBeneficiary(ICryptoLegacy.CryptoLegacyStorage,address)](#_checkaddressisbeneficiary-lcl1) — LibCryptoLegacy, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Beneficiary initiates distribution after owner inactivity.

***

### transferTreasuryTokensToLegacy (CLBP1)

**Contract/Library:** CryptoLegacyBasePlugin

**Description:** Pulls treasury tokens from holders into the legacy contract for distribution.

**Detailed Description:** Requires contract not paused and distribution ready for the calling beneficiary. Iterates holders and tokens, transferring available allowances into the legacy contract through `safeTransferFrom`, updates token distribution state, pushes the block number marker, and emits `TransferTreasuryTokensToLegacy`.

**Parameters:**

* \_holders (address\[], memory): Addresses holding treasury tokens
* \_tokens (address\[], memory): ERC20 token addresses to sweep

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external nonpayable nonReentrant

**Access Control:**

* Beneficiary-only (requires distribution ready)

**Side Effects:**

* Transfers ERC20 balances into the contract
* Updates token distribution metadata
* Records transfer block number

**Emits:**

* [TransferTreasuryTokensToLegacy](https://docs.cryptolegacy.app/documentation/events-reference#transfertreasurytokenstolegacy-icl1) — `TransferTreasuryTokensToLegacy(address[] holders, address[] tokens)`

**Reverts if:**

* Contract paused — [`Pause()`](https://docs.cryptolegacy.app/documentation/errors-reference#pause-icl1)
* Distribution not ready — [`TooEarly()`](https://docs.cryptolegacy.app/documentation/errors-reference#tooearly-icl1)
* Caller not a beneficiary — [`NotTheBeneficiary()`](https://docs.cryptolegacy.app/documentation/errors-reference#notthebeneficiary-icl1)
* LibCryptoLegacy.\_transferTreasuryTokensToLegacy(...)(#\_transfertreasurytokenstolegacy-lcl1) — may revert per token implementation

**Overrides:** None

**Function Calls:**

* [LibCryptoLegacy.getCryptoLegacyStorage()](#getcryptolegacystorage-lcl1) — LibCryptoLegacy, internal
* [LibCryptoLegacy.\_checkPause(ICryptoLegacy.CryptoLegacyStorage)](#_checkpause-lcl1) — LibCryptoLegacy, internal
* [LibCryptoLegacy.\_checkDistributionReadyForBeneficiary(ICryptoLegacy.CryptoLegacyStorage)](#_checkdistributionreadyforbeneficiary-lcl1) — LibCryptoLegacy, internal
* [\_transferTreasuryTokensToLegacy(ICryptoLegacy.CryptoLegacyStorage,address\[\],address\[\])](#_transfertreasurytokenstolegacy-lcl1) — LibCryptoLegacy, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(t·h) for tokens × holders

**Example:** Beneficiaries move pooled assets into the legacy contract before claiming.

***

### \_claimTokenWithVesting (CLBP1)

**Contract/Library:** CryptoLegacyBasePlugin

**Description:** Internal helper to distribute vested ERC20 tokens.

**Detailed Description:** Fetches beneficiary config/vesting structs, computes claimable amounts via `LibCryptoLegacy._getVestedAndClaimedAmount`, transfers tokens with `safeTransfer`, updates distribution balance, and emits `BeneficiaryClaim` (and `BeneficiaryClaimAmountDecrease` when applicable).

**Parameters:**

* cls ([CryptoLegacyStorage](https://docs.cryptolegacy.app/documentation/data-structures-reference#cryptolegacystorage-icl1-s4), storage): Global storage pointer
* td ([TokenDistribution](https://docs.cryptolegacy.app/documentation/data-structures-reference#tokendistribution-icl1-s3), storage): Token distribution slot
* \_beneficiary (bytes32): Beneficiary hash
* \_token (address): ERC20 token being claimed
* \_startDate (uint64): Vesting start timestamp
* \_endDate (uint64): Vesting end timestamp

**Returns:**

* amountToClaim (uint256): Tokens transferred to the beneficiary

**Modifiers / Visibility / Mutability:**

* internal nonpayable

**Access Control:**

* Unrestricted (internal)

**Side Effects:**

* Updates vesting claim totals and token distribution balance
* Transfers ERC20 tokens to caller

**Emits:**

* [BeneficiaryClaimAmountDecrease](https://docs.cryptolegacy.app/documentation/events-reference#beneficiaryclaimamountdecrease-icl1) — `BeneficiaryClaimAmountDecrease(address indexed token, bytes32 indexed beneficiary, uint256 prevAmount, uint256 newAmount)` (when rebase reduces claim)
* [BeneficiaryClaim](https://docs.cryptolegacy.app/documentation/events-reference#beneficiaryclaim-icl1) — `BeneficiaryClaim(address indexed token, uint256 amount, bytes32 indexed beneficiary)`

**Reverts if:**

* Beneficiary missing — [`BeneficiaryNotExist()`](https://docs.cryptolegacy.app/documentation/errors-reference#beneficiarynotexist-icl1)
* `IERC20.safeTransfer(...)` — may revert per token implementation

**Overrides:** None

**Function Calls:**

* [LibCryptoLegacy.\_getBeneficiaryConfigAndVesting(ICryptoLegacy.CryptoLegacyStorage,bytes32)](#_getbeneficiaryconfigandvesting-lcl1) — LibCryptoLegacy, internal
* [LibCryptoLegacy.\_getVestedAndClaimedAmount(ICryptoLegacy.TokenDistribution,ICryptoLegacy.BeneficiaryConfig,ICryptoLegacy.BeneficiaryVesting,address,uint64,uint64)](#_getvestedandclaimedamount-lcl1) — LibCryptoLegacy, internal
* `IERC20(_token).safeTransfer(address,uint256)` — IERC20, external
* `IERC20(_token).balanceOf(address)` — IERC20, external (staticcall)

**Called by:**

* [beneficiaryClaim](#beneficiaryclaim-clbp1) — CryptoLegacyBasePlugin

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### beneficiaryClaim (CLBP1)

**Contract/Library:** CryptoLegacyBasePlugin

**Description:** Enables a beneficiary to claim vested ERC20 tokens.

**Detailed Description:** Validates pause state and that the claim function is enabled, processes any fee through `_takeFee`, verifies distribution readiness, enforces vesting start date, then iterates through tokens preparing distributions and calling `_claimTokenWithVesting`. Supports optional referral sharing.

**Parameters:**

* \_tokens (address\[], memory): Tokens to claim
* \_ref (address): Optional referral address
* \_refShare (uint256): Referral share in basis points (denominator 10,000)

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external payable nonReentrant

**Access Control:**

* Caller must be a registered beneficiary

**Side Effects:**

* Updates `lastFeePaidAt` and may refresh `updateFee` via `_takeFee`
* Transfers ETH to the build manager and optional referral during fee processing
* Adjusts token distribution totals (`amountToDistribute`, `lastBalance`) via `_tokenPrepareToDistribute`
* Increments `beneficiaryVesting.tokenAmountClaimed` for each processed token
* Transfers ERC20 tokens to caller

**Emits:**

* [FeePaidByLifetime](https://docs.cryptolegacy.app/documentation/events-reference#feepaidbylifetime-icl1) — `FeePaidByLifetime(bytes8 indexed refCode, bool indexed initial, address factory, uint64 lastFeePaidAt)` (via `_takeFee`)
* [GetUpdateFeeCatch](https://docs.cryptolegacy.app/documentation/events-reference#getupdatefeecatch-icl1) — `GetUpdateFeeCatch(bytes reason)` (via `_takeFee`)
* [FeePaidByDefault](https://docs.cryptolegacy.app/documentation/events-reference#feepaidbydefault-icl1) — `FeePaidByDefault(bytes8 indexed refCode, bool indexed initial, uint256 value, uint256 returnedValue, address factory, uint64 lastFeePaidAt)` (via `_takeFee`)
* [PayFeeCatch](https://docs.cryptolegacy.app/documentation/events-reference#payfeecatch-icl1) — `PayFeeCatch(bytes reason)` (via `_takeFee`)
* [SkipSendFeeByTransfer](https://docs.cryptolegacy.app/documentation/events-reference#skipsendfeebytransfer-icl1) — `SkipSendFeeByTransfer(address buildManager, uint256 value)` (via `_sendFeeByTransfer`)
* [FeeSentToRefByTransfer](https://docs.cryptolegacy.app/documentation/events-reference#feesenttorefbytransfer-icl1) — `FeeSentToRefByTransfer(bytes8 indexed refCode, uint256 value, address ref)` (via `_sendFeeByTransfer`)
* [FeePaidByTransfer](https://docs.cryptolegacy.app/documentation/events-reference#feepaidbytransfer-icl1) — `FeePaidByTransfer(bytes8 indexed refCode, bool indexed initial, uint256 value, address factory, uint64 lastFeePaidAt)` (via `_takeFee`)
* [BeneficiaryClaimAmountDecrease](https://docs.cryptolegacy.app/documentation/events-reference#beneficiaryclaimamountdecrease-icl1) — `BeneficiaryClaimAmountDecrease(address indexed token, bytes32 indexed beneficiary, uint256 prevAmount, uint256 newAmount)` (when applicable)
* [BeneficiaryClaim](https://docs.cryptolegacy.app/documentation/events-reference#beneficiaryclaim-icl1) — `BeneficiaryClaim(address indexed token, uint256 amount, bytes32 indexed beneficiary)`

**Reverts if:**

* Contract paused — [`Pause()`](https://docs.cryptolegacy.app/documentation/errors-reference#pause-icl1)
* Claim function disabled — [`DisabledFunc()`](https://docs.cryptolegacy.app/documentation/errors-reference#disabledfunc-icl1)
* Fee amount below or above expected — [`IncorrectFee(uint256)`](https://docs.cryptolegacy.app/documentation/errors-reference#incorrectfee-icl1)
* Referral share exceeds base — [`IncorrectRefShare()`](https://docs.cryptolegacy.app/documentation/errors-reference#incorrectrefshare-icl1)
* Lifetime fee path supplied value — [`NoValueAllowed()`](https://docs.cryptolegacy.app/documentation/errors-reference#novalueallowed-icl1)
* Fee transfer call fails — [`TransferFeeFailed(bytes)`](https://docs.cryptolegacy.app/documentation/errors-reference#transferfeefailed-icl1)
* Caller not beneficiary — [`NotTheBeneficiary()`](https://docs.cryptolegacy.app/documentation/errors-reference#notthebeneficiary-icl1)
* Distribution not ready — [`TooEarly()`](https://docs.cryptolegacy.app/documentation/errors-reference#tooearly-icl1)
* Before vesting start — [`TooEarly()`](https://docs.cryptolegacy.app/documentation/errors-reference#tooearly-icl1)
* `LibCryptoLegacy._takeFee(...)` — may revert with [`NotRegisteredCryptoLegacy()`](https://docs.cryptolegacy.app/documentation/errors-reference#notregisteredcryptolegacy-iclbm1) (bubbled)
* `LibCryptoLegacy._takeFee(...)` — may revert with [`NotOwnerOfCryptoLegacy()`](https://docs.cryptolegacy.app/documentation/errors-reference#notownerofcryptolegacy-iclbm1) (bubbled)
* `IERC20.safeTransfer(...)` — may revert per token implementation

**Overrides:** None

**Function Calls:**

* [LibCryptoLegacy.getCryptoLegacyStorage()](#getcryptolegacystorage-lcl1) — LibCryptoLegacy, internal
* [LibCryptoLegacy.\_checkPause(ICryptoLegacy.CryptoLegacyStorage)](#_checkpause-lcl1) — LibCryptoLegacy, internal
* [LibCryptoLegacy.\_checkDisabledFunc(ICryptoLegacy.CryptoLegacyStorage,uint8)](#_checkdisabledfunc-lcl1) — LibCryptoLegacy, internal
* [owner()](#owner-clbp1) — CryptoLegacyBasePlugin, internal
* [\_takeFee(ICryptoLegacy.CryptoLegacyStorage,address,address,uint256,uint256\[\],uint256\[\])](#_takefee-lcl1) — LibCryptoLegacy, internal
* [LibCryptoLegacy.\_checkDistributionReadyForBeneficiary(ICryptoLegacy.CryptoLegacyStorage)](#_checkdistributionreadyforbeneficiary-lcl1) — LibCryptoLegacy, internal
* [LibCryptoLegacy.\_getStartAndEndDate(ICryptoLegacy.CryptoLegacyStorage,ICryptoLegacy.BeneficiaryConfig)](#_getstartandenddate-lcl1) — LibCryptoLegacy, internal
* [LibCryptoLegacy.\_tokenPrepareToDistribute(ICryptoLegacy.CryptoLegacyStorage,address)](#_tokenpreparetodistribute-lcl1) — LibCryptoLegacy, internal
* [\_claimTokenWithVesting(ICryptoLegacy.CryptoLegacyStorage,TokenDistribution,bytes32,address,uint64,uint64)](#_claimtokenwithvesting-clbp1) — CryptoLegacyBasePlugin, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(t·b) where t = `_tokens.length`, b = beneficiaries (for rebase adjustments)

**Example:** Beneficiary calls once distribution window opens to collect accrued tokens.

***

### beneficiarySwitch (CLBP1)

**Contract/Library:** CryptoLegacyBasePlugin

**Description:** Allows a beneficiary to switch their identifier hash.

**Detailed Description:** Confirms the caller is a beneficiary, enforces the switch timelock on the original beneficiary hash, verifies the replacement hash is unused, updates beneficiary sets/configs, refreshes registry mappings, resets the timelock, and emits `SwitchBeneficiary`.

**Parameters:**

* \_newBeneficiary (bytes32): Replacement beneficiary hash

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external nonpayable

**Access Control:**

* Caller must be the existing beneficiary

**Side Effects:**

* Replaces beneficiary entries and updates registry

**Emits:**

* [SwitchBeneficiary](https://docs.cryptolegacy.app/documentation/events-reference#switchbeneficiary-clbp1) — `SwitchBeneficiary(bytes32 indexed oldBeneficiary, bytes32 indexed newBeneficiary)`

**Reverts if:**

* Caller not beneficiary — [`NotTheBeneficiary()`](https://docs.cryptolegacy.app/documentation/errors-reference#notthebeneficiary-icl1)
* Switch timelock active — [`BeneficiarySwitchTimelock()`](https://docs.cryptolegacy.app/documentation/errors-reference#beneficiaryswitchtimelock-icl1)
* New hash already present — [`AlreadySet()`](https://docs.cryptolegacy.app/documentation/errors-reference#alreadyset-icl1)

**Overrides:** None

**Function Calls:**

* [LibCryptoLegacy.getCryptoLegacyStorage()](#getcryptolegacystorage-lcl1) — LibCryptoLegacy, internal
* [LibCryptoLegacy.\_checkAddressIsBeneficiary(ICryptoLegacy.CryptoLegacyStorage,address)](#_checkaddressisbeneficiary-lcl1) — LibCryptoLegacy, internal
* `EnumerableSet.Bytes32Set.contains(bytes32)` — EnumerableSet, internal
* `EnumerableSet.Bytes32Set.remove(bytes32)` — EnumerableSet, internal
* `EnumerableSet.Bytes32Set.add(bytes32)` — EnumerableSet, internal
* [LibCryptoLegacy.\_setCryptoLegacyToBeneficiaryRegistry(ICryptoLegacy.CryptoLegacyStorage,bytes32,IBeneficiaryRegistry.EntityType,bool)](#_setcryptolegacytobeneficiaryregistry-lcl1) — LibCryptoLegacy, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1) (constant-time set updates)

**Example:** Beneficiary refreshes their identifier after legal name change.

***

### sendMessagesToBeneficiary (CLBP1)

**Contract/Library:** CryptoLegacyBasePlugin

**Description:** Owner broadcast of off-chain messages to beneficiaries.

**Detailed Description:** Owner-only function that emits paired message events for each beneficiary hash and records the corresponding block number (Arbitrum L2 aware).

**Parameters:**

* \_beneficiaryList (bytes32\[], memory): Beneficiary hashes
* \_messageHashList (bytes32\[], memory): Message hashes aligned with beneficiaries
* \_messageList (bytes\[], memory): Raw message bytes
* \_messageCheckList (bytes\[], memory): Complementary check payloads
* \_messageType (uint256): Application-specific type identifier

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external nonpayable onlyOwner

**Access Control:**

* Owner only

**Side Effects:**

* Appends block numbers to `beneficiaryMessagesGotByBlockNumber`

**Emits:**

* [BeneficiaryMessage](https://docs.cryptolegacy.app/documentation/events-reference#beneficiarymessage-clbp1) — `BeneficiaryMessage(bytes32 indexed toBeneficiary, bytes32 messageHash, bytes message, uint256 indexed messageType)`
* [BeneficiaryMessageCheck](https://docs.cryptolegacy.app/documentation/events-reference#beneficiarymessagecheck-clbp1) — `BeneficiaryMessageCheck(bytes32 indexed toBeneficiary, bytes32 messageHash, bytes message, uint256 indexed messageType)`

**Reverts if:**

* Distribution already started — [`DistributionStarted()`](https://docs.cryptolegacy.app/documentation/errors-reference#distributionstarted-icl1)
* Initial fee unpaid — [`InitialFeeNotPaid()`](https://docs.cryptolegacy.app/documentation/errors-reference#initialfeenotpaid-icl1)
* `_beneficiaryList`, `_messageHashList`, `_messageList`, `_messageCheckList` length mismatch — `Panic(0x32)`
* Caller not owner — [`NotTheOwner()`](https://docs.cryptolegacy.app/documentation/errors-reference#nottheowner-icl1)

**Overrides:** None

**Function Calls:**

* [LibCryptoLegacy.getCryptoLegacyStorage()](#getcryptolegacystorage-lcl1) — LibCryptoLegacy, internal
* `ArbSys(address(100)).arbBlockNumber()` — ArbSys, external (staticcall)

**Called by:** None (entry point)

**Gas / Complexity note:** O(n) by `_beneficiaryList.length`

**Example:** Owner sends encrypted distribution instructions to beneficiaries.

***

### isLifetimeActive (CLBP1)

**Contract/Library:** CryptoLegacyBasePlugin

**Description:** Checks if the owner’s lifetime NFT is locked.

**Detailed Description:** Queries the build manager for the lifetime NFT lock status associated with `owner()`.

**Parameters:** None

**Returns:**

* isNftLocked (bool): `true` if the NFT is active/locked

**Modifiers / Visibility / Mutability:**

* public view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [LibCryptoLegacy.getCryptoLegacyStorage()](#getcryptolegacystorage-lcl1) — LibCryptoLegacy, internal
* [owner()](#owner-clbp1) — CryptoLegacyBasePlugin, internal
* `cls.buildManager.isLifetimeNftLocked(address)` — ICryptoLegacyBuildManager, external (staticcall)

**Called by:**

* [isLifetimeActive(address)](#islifetimeactive-clexl1) — CryptoLegacyExternalLens

**Gas / Complexity note:** O(1) (single external view call)

**Example:** Beneficiaries check if lifetime fee exemption applies.

***

### getGasBySelector (CLBP1)

**Contract/Library:** CryptoLegacyBasePlugin

**Description:** Returns the stored gas hint for a selector.

**Detailed Description:** Delegates to `LibCryptoLegacy._gasBySelector` to fetch the gas value (after applying multiplier) for instrumentation or UI display.

**Parameters:**

* \_selector (bytes4): Function selector to query

**Returns:**

* gasLimit (uint): Stored gas value

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [LibCryptoLegacy.getCryptoLegacyStorage()](#getcryptolegacystorage-lcl1) — LibCryptoLegacy, internal
* [LibCryptoLegacy.\_gasBySelector(ICryptoLegacy.CryptoLegacyStorage,bytes4)](#_gasbyselector-lcl1) — LibCryptoLegacy, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Front-end displays per-function gas estimates.

***

## LegacyRecoveryPlugin (LRP1)

### getSigs (LRP1)

**Contract/Library:** LegacyRecoveryPlugin

**Description:** Lists the public selectors exposed by the recovery plugin facet.

**Detailed Description:** Returns the ordered selector array for multisig configuration, proposal management, treasury token recovery, guardian reset, held-ETH accounting, and view helpers.

**Parameters:** None

**Returns:**

* sigs (bytes4\[], memory): Selector list described above

**Modifiers / Visibility / Mutability:**

* external pure

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Facet loader fetches selectors before wiring the plugin.

***

### getSetupSigs (LRP1)

**Contract/Library:** LegacyRecoveryPlugin

**Description:** Reports selectors required during plugin setup.

**Detailed Description:** Returns an empty array, indicating no setup-only calls are necessary.

**Parameters:** None

**Returns:**

* sigs (bytes4\[], memory): Always empty

**Modifiers / Visibility / Mutability:**

* external pure

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Installer confirms no setup steps are needed.

***

### getMultisigAllowedMethods (LRP1)

**Contract/Library:** LegacyRecoveryPlugin

**Description:** Enumerates selectors that recovery multisig proposals may execute.

**Detailed Description:** Returns the three operation selectors permitted for multisig execution: transferring treasury tokens to the legacy contract, withdrawing tokens from the legacy contract, and resetting guardian voting.

**Parameters:** None

**Returns:**

* sigs (bytes4\[], memory): Allowed multisig selectors

**Modifiers / Visibility / Mutability:**

* public pure

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:**

* [lrPropose(bytes4,bytes,bytes32)](#lrpropose-lrp1) — LegacyRecoveryPlugin

**Gas / Complexity note:** O(1)

**Example:** Used to validate recovery proposals before enqueuing them.

***

### getPluginName (LRP1)

**Contract/Library:** LegacyRecoveryPlugin

**Description:** Returns the canonical plugin identifier.

**Detailed Description:** Hard-coded to `"legacy_recover"` for registry display.

**Parameters:** None

**Returns:**

* `name (string, memory): Plugin name literal`

**Modifiers / Visibility / Mutability:**

* public pure

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Plugin registry lists the facet name.

***

### getPluginVer (LRP1)

**Contract/Library:** LegacyRecoveryPlugin

**Description:** Reports the plugin version.

**Detailed Description:** Returns the constant semantic version `1` encoded as `uint16`.

**Parameters:** None

**Returns:**

* `version (uint16): Version identifier`

**Modifiers / Visibility / Mutability:**

* external pure

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Dashboard shows the plugin version next to the name.

***

### modifier onlyOwner (LRP1)

**Contract/Library:** LegacyRecoveryPlugin

**Description:** Restricts recovery admin flows to the diamond owner before distribution starts.

**Detailed Description:** Delegates to `LibCryptoLegacy._checkOwner()` so that any guarded function first ensures distribution has not begun, the initial fee has been paid, and `msg.sender` equals the diamond owner.

**Parameters:** None

**Returns:** None

**Modifiers / Visibility / Mutability:**

* modifier nonpayable

**Access Control:**

* Owner only (enforced via library check)

**Side Effects:** None

**Emits:** None

**Reverts if:**

* Distribution already started — [`ICryptoLegacy.DistributionStarted()`](https://docs.cryptolegacy.app/documentation/errors-reference#distributionstarted-icl1)
* Initial fee unpaid — [`ICryptoLegacy.InitialFeeNotPaid()`](https://docs.cryptolegacy.app/documentation/errors-reference#initialfeenotpaid-icl1)
* Caller is not the owner — [`ICryptoLegacy.NotTheOwner()`](https://docs.cryptolegacy.app/documentation/errors-reference#nottheowner-icl1)

**Overrides:** None

**Function Calls:**

* [LibCryptoLegacy.\_checkOwner()](#_checkowner-lcl1) — LibCryptoLegacy, internal

**Called by:**

* [lrSetMultisigConfig(bytes32\[\],uint8)](#lrsetmultisigconfig-lrp1) — LegacyRecoveryPlugin

**Gas / Complexity note:** O(1)

**Example:** Owner updates recovery multisig parameters before beneficiaries can trigger distribution.

***

### getPluginMultisigStorage (LRP1)

**Contract/Library:** LegacyRecoveryPlugin

**Description:** Retrieves plugin-specific multisig storage.

**Detailed Description:** Uses inline assembly to bind the constant storage slot [`PLUGIN_MULTISIG_POSITION`](https://docs.cryptolegacy.app/documentation/data-structures-reference#plugin_multisig_position-lrp1-d1) to the multisig storage struct.

**Parameters:** None

**Returns:**

* storageStruct ([ISafeMinimalMultisig.Storage](https://docs.cryptolegacy.app/documentation/data-structures-reference#storage-ism1-s1), storage): Multisig storage for recovery plugin

**Modifiers / Visibility / Mutability:**

* internal pure

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:**

* [lrSetMultisigConfig(bytes32\[\],uint8)](#lrsetmultisigconfig-lrp1) — LegacyRecoveryPlugin
* [lrPropose(bytes4,bytes,bytes32)](#lrpropose-lrp1) — LegacyRecoveryPlugin
* [lrConfirm(uint256,bytes32)](#lrconfirm-lrp1) — LegacyRecoveryPlugin
* [lrCancel(uint256,bytes32)](#lrcancel-lrp1) — LegacyRecoveryPlugin
* [lrWithdrawHeldEth(bytes32,address)](#lrwithdrawheldeth-lrp1) — LegacyRecoveryPlugin
* [lrGetHeldEth(bytes32)](#lrgetheldeth-lrp1) — LegacyRecoveryPlugin
* [lrGetInitializationStatus()](#lrgetinitializationstatus-lrp1) — LegacyRecoveryPlugin
* [lrGetProposalWithStatus(uint256)](#lrgetproposalwithstatus-lrp1) — LegacyRecoveryPlugin
* [lrGetProposalListWithStatuses()](#lrgetproposallistwithstatuses-lrp1) — LegacyRecoveryPlugin

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### lrSetMultisigConfig (LRP1)

**Contract/Library:** LegacyRecoveryPlugin

**Description:** Owner-only configuration of recovery multisig voters and threshold.

**Detailed Description:** Caches existing voter list, updates the Beneficiary Registry’s recovery entries via LibCryptoLegacy.\_setCryptoLegacyListToBeneficiaryRegistry(#\_setcryptolegacylisttobeneficiaryregistry-lcl1), and calls `LibSafeMinimalMultisig._setVotersAndConfirmations` to persist the new configuration.

**Parameters:**

* \_voters (bytes32\[], memory): Recovery voter identifiers
* \_requiredConfirmations (uint8): Confirmation threshold

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external nonpayable onlyOwner

**Access Control:**

* Owner only (distribution must not have started and initial fee must be paid)

**Side Effects:**

* Updates multisig voter list and threshold
* Refreshes recovery entries in `BeneficiaryRegistry`

**Emits:**

* [BeneficiaryRegistryNotDefined](https://docs.cryptolegacy.app/documentation/events-reference#beneficiaryregistrynotdefined-icl1) — `BeneficiaryRegistryNotDefined()`
* [SetCryptoLegacyRecoveryAddressesCatch](https://docs.cryptolegacy.app/documentation/events-reference#setcryptolegacyrecoveryaddressescatch-icl1) — `SetCryptoLegacyRecoveryAddressesCatch(bytes reason)`
* [BeneficiaryRegistryCatch](https://docs.cryptolegacy.app/documentation/events-reference#beneficiaryregistrycatch-icl1) — `BeneficiaryRegistryCatch(bytes reason)`
* [SetVotersAndConfirmations](https://docs.cryptolegacy.app/documentation/events-reference#setvotersandconfirmations-ism1) — `SetVotersAndConfirmations(bytes32[] voters, uint128 requiredConfirmations)`

**Reverts if:**

* Distribution already started — [`DistributionStarted()`](https://docs.cryptolegacy.app/documentation/errors-reference#distributionstarted-icl1)
* Initial fee unpaid — [`InitialFeeNotPaid()`](https://docs.cryptolegacy.app/documentation/errors-reference#initialfeenotpaid-icl1)
* Caller not owner — [`NotTheOwner()`](https://docs.cryptolegacy.app/documentation/errors-reference#nottheowner-icl1)
* `_requiredConfirmations` invalid for the voter count — [`MultisigIncorrectRequiredConfirmations()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisigincorrectrequiredconfirmations-ism1)

**Overrides:** None

**Function Calls:**

* [getPluginMultisigStorage()](#getpluginmultisigstorage-lrp1) — LegacyRecoveryPlugin, internal
* [LibCryptoLegacy.getCryptoLegacyStorage()](#getcryptolegacystorage-lcl1) — LibCryptoLegacy, internal
* [LibCryptoLegacy.\_setCryptoLegacyListToBeneficiaryRegistry(...)](#_setcryptolegacylisttobeneficiaryregistry-lcl1) — LibCryptoLegacy, internal
* [LibSafeMinimalMultisig.\_setVotersAndConfirmations(...)](#_setvotersandconfirmations-lsm1) — LibSafeMinimalMultisig, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(n) by number of voters

**Example:** Owner reconfigures recovery voters after updating beneficiary contacts.

***

### lrPropose (LRP1)

**Contract/Library:** LegacyRecoveryPlugin

**Description:** Submits a new recovery multisig proposal.

**Detailed Description:** Validates caller authorization (optionally salted), confirms the selector is allowlisted, records the proposal, auto-confirms the proposer, executes immediately when quorum is 1, and credits any surplus ETH to the proposer’s held balance.

**Parameters:**

* \_selector (bytes4): Target selector
* \_params (bytes, memory): ABI-encoded parameters for the target call
* \_salt (bytes32): Optional salt mixed into voter hashing

**Returns:**

* proposalId (uint256): Index of the newly created proposal

**Modifiers / Visibility / Mutability:**

* external payable

**Access Control:**

* Caller must be an authorized voter

**Side Effects:**

* Appends to `proposals` and records confirmations
* May execute proposal immediately
* May credit `heldEth` for the caller

**Emits:**

* [CreateSafeMinimalMultisigProposal](https://docs.cryptolegacy.app/documentation/events-reference#createsafeminimalmultisigproposal-ism1) — `CreateSafeMinimalMultisigProposal(uint256 proposalId, bytes32 voter, uint128 reqConfirmations)`
* [ExecuteSafeMinimalMultisigProposal](https://docs.cryptolegacy.app/documentation/events-reference#executesafeminimalmultisigproposal-ism1) — `ExecuteSafeMinimalMultisigProposal(uint256 proposalId, bytes32 voter, bool executed, bytes returnData)` (emitted if quorum == 1 triggers execution)
* [AddHeldEth](https://docs.cryptolegacy.app/documentation/events-reference#addheldeth-ism1) — `AddHeldEth(bytes32 voter, uint256 value)` (when surplus ETH accrues)

**Reverts if:**

* Caller not an allowed voter — [`MultisigVoterNotAllowed()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisigvoternotallowed-ism1)
* Selector not allowlisted — [`MultisigMethodNotAllowed()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisigmethodnotallowed-ism1)
* Immediate execution fails — [`MultisigExecutionFailed()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisigexecutionfailed-ism1)

**Overrides:** None

**Function Calls:**

* [getPluginMultisigStorage()](#getpluginmultisigstorage-lrp1) — LegacyRecoveryPlugin, internal
* [getMultisigAllowedMethods()](#getmultisigallowedmethods-lrp1) — LegacyRecoveryPlugin, internal
* [LibSafeMinimalMultisig.\_propose(...)](#_propose-lsm1) — LibSafeMinimalMultisig, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(n) by voter count

**Example:** Recovery voters propose transferring treasury tokens to the legacy contract.

***

### lrConfirm (LRP1)

**Contract/Library:** LegacyRecoveryPlugin

**Description:** Confirms a recovery proposal and executes it when quorum is met.

**Detailed Description:** Verifies voter authorization, records confirmation, updates confirmation counts, executes the proposal once confirmations reach the threshold, and credits any surplus ETH to the confirming voter.

**Parameters:**

* \_proposalId (uint256): Proposal index
* \_salt (bytes32): Optional salt for voter hashing

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external payable

**Access Control:**

* Caller must be an authorized voter

**Side Effects:**

* Updates confirmation bookkeeping
* May execute the proposal and credit held ETH

**Emits:**

* [ConfirmSafeMinimalMultisigProposal](https://docs.cryptolegacy.app/documentation/events-reference#confirmsafeminimalmultisigproposal-ism1) — `ConfirmSafeMinimalMultisigProposal(uint256 proposalId, bytes32 voter, uint128 reqConfirmations, uint256 confirms)`
* [ExecuteSafeMinimalMultisigProposal](https://docs.cryptolegacy.app/documentation/events-reference#executesafeminimalmultisigproposal-ism1) — `ExecuteSafeMinimalMultisigProposal(uint256 proposalId, bytes32 voter, bool executed, bytes returnData)` (emitted on execution)
* [AddHeldEth](https://docs.cryptolegacy.app/documentation/events-reference#addheldeth-ism1) — `AddHeldEth(bytes32 voter, uint256 value)` (when surplus ETH accrues)

**Reverts if:**

* Caller not authorized — [`MultisigVoterNotAllowed()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisigvoternotallowed-ism1)
* Proposal not pending — [`MultisigProposalNotPending()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisigproposalnotpending-ism1)
* Execution fails — [`MultisigExecutionFailed()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisigexecutionfailed-ism1)
* `_proposalId` out of range for `proposals` — `panic(uint256(0x32))`

**Overrides:** None

**Function Calls:**

* [getPluginMultisigStorage()](#getpluginmultisigstorage-lrp1) — LegacyRecoveryPlugin, internal
* [LibSafeMinimalMultisig.\_confirm(...)](#_confirm-lsm1) — LibSafeMinimalMultisig, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(n) by voter count

**Example:** Second guardian confirms the proposal to move treasury assets back into the legacy contract.

***

### lrCancel (LRP1)

**Contract/Library:** LegacyRecoveryPlugin

**Description:** Removes the caller’s confirmation from a pending recovery proposal.

**Detailed Description:** Ensures the voter is authorized, verifies the proposal is pending and previously confirmed by the caller, removes the confirmation, updates counts, and cancels the proposal if zero confirmations remain.

**Parameters:**

* \_proposalId (uint256): Proposal index
* \_salt (bytes32): Optional salt for voter hashing

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external nonpayable

**Access Control:**

* Caller must be an authorized voter who previously confirmed

**Side Effects:**

* Updates proposal confirmations

**Emits:**

* [CancelSafeMinimalMultisigProposal](https://docs.cryptolegacy.app/documentation/events-reference#cancelsafeminimalmultisigproposal-ism1) — `CancelSafeMinimalMultisigProposal(uint256 proposalId, bytes32 voter, uint128 reqConfirmations, ISafeMinimalMultisig.ProposalStatus status)`

**Reverts if:**

* Caller not authorized — [`MultisigVoterNotAllowed()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisigvoternotallowed-ism1)
* Proposal not pending — [`MultisigProposalNotPending()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisigproposalnotpending-ism1)
* Caller had not confirmed — [`MultisigNotConfirmed()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisignotconfirmed-ism1)
* `_proposalId` is out of bounds for `proposals` array — `panic(uint256(0x32))`

**Overrides:** None

**Function Calls:**

* [getPluginMultisigStorage()](#getpluginmultisigstorage-lrp1) — LegacyRecoveryPlugin, internal
* [LibSafeMinimalMultisig.\_cancel(...)](#_cancel-lsm1) — LibSafeMinimalMultisig, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(n) by voter count

**Example:** Voter rescinds approval after the issue is resolved off-chain.

***

### lrTransferTreasuryTokensToLegacy (LRP1)

**Contract/Library:** LegacyRecoveryPlugin

**Description:** Multisig-executor action to pull treasury ERC20 tokens into the legacy contract.

**Detailed Description:** Requires execution via multisig (`address(this)`). After authorization, delegates to LibCryptoLegacy.\_transferTreasuryTokensToLegacy(#\_transfertreasurytokenstolegacy-lcl1), which iterates holders/tokens, performs `safeTransferFrom`, updates distribution, and records the block number.

**Parameters:**

* \_holders (address\[], memory): Addresses currently holding treasury tokens
* \_tokens (address\[], memory): Token addresses to collect

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external nonpayable nonReentrant

**Access Control:**

* Must be invoked by multisig executor

**Side Effects:**

* Transfers ERC20 balances into the legacy contract
* Updates distribution metadata

**Emits:**

* [TransferTreasuryTokensToLegacy](https://docs.cryptolegacy.app/documentation/events-reference#transfertreasurytokenstolegacy-icl1) — `TransferTreasuryTokensToLegacy(address[] holders, address[] tokens)`

**Reverts if:**

* Caller not multisig executor — [`MultisigOnlyExecutor()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisigonlyexecutor-ism1)
* `IERC20(_tokensi).safeTransferFrom(...)` — may revert per token implementation

**Overrides:** None

**Function Calls:**

* [LibSafeMinimalMultisig.\_checkIsMultisigExecutor()](#_checkismultisigexecutor-lsm1) — LibSafeMinimalMultisig, internal
* [LibCryptoLegacy.getCryptoLegacyStorage()](#getcryptolegacystorage-lcl1) — LibCryptoLegacy, internal
* [\_transferTreasuryTokensToLegacy(ICryptoLegacy.CryptoLegacyStorage,address\[\],address\[\])](#_transfertreasurytokenstolegacy-lcl1) — LibCryptoLegacy, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(t·h) for tokens × holders

**Example:** Recovery proposal sweeps assets back into the legacy contract before claim processing.

***

### lrWithdrawTokensFromLegacy (LRP1)

**Contract/Library:** LegacyRecoveryPlugin

**Description:** Multisig-executor withdrawal of tokens from the legacy contract to designated recipients.

**Detailed Description:** Ensures execution context is multisig, then delegates to LibCryptoLegacy.\_transferTokensFromLegacy(#\_transfertokensfromlegacy-lcl1), which transfers ERC20 tokens directly to specified recipients and records the block number.

**Parameters:**

* \_transfers ([ICryptoLegacy.TokenTransferTo](https://docs.cryptolegacy.app/documentation/data-structures-reference#tokentransferto-icl1-s5)\[], memory): Array of token transfer instructions

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external nonpayable nonReentrant

**Access Control:**

* Multisig executor only

**Side Effects:**

* Transfers ERC20 tokens out of the contract
* Records transfer metadata

**Emits:**

* [TransferTokensFromLegacy](https://docs.cryptolegacy.app/documentation/events-reference#transfertokensfromlegacy-icl1) — `TransferTokensFromLegacy(ICryptoLegacy.TokenTransferTo[] transfers)`

**Reverts if:**

* Caller not multisig executor — [`MultisigOnlyExecutor()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisigonlyexecutor-ism1)
* `IERC20(_transfersi.token).safeTransfer(...)` — may revert per token implementation

**Overrides:** None

**Function Calls:**

* [LibSafeMinimalMultisig.\_checkIsMultisigExecutor()](#_checkismultisigexecutor-lsm1) — LibSafeMinimalMultisig, internal
* [LibCryptoLegacy.getCryptoLegacyStorage()](#getcryptolegacystorage-lcl1) — LibCryptoLegacy, internal
* [\_transferTokensFromLegacy(ICryptoLegacy.CryptoLegacyStorage,ICryptoLegacy.TokenTransferTo\[\])](#_transfertokensfromlegacy-lcl1) — LibCryptoLegacy, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(n) by `_transfers.length`

**Example:** Recovery proposal sends held tokens back to original owners.

***

### lrResetGuardianVoting (LRP1)

**Contract/Library:** LegacyRecoveryPlugin

**Description:** Multisig-executor action to reset guardian voting state and distribution start timestamp.

**Detailed Description:** Checks multisig executor context, verifies distribution not yet started, invokes `LibTrustedGuardiansPlugin._resetGuardianVoting` which clears guardian votes, resets `distributionStartAt`, optionally processes fees via `_takeFee`, and emits `ResetGuardiansVoting`.

**Parameters:** None

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external payable nonReentrant

**Access Control:**

* Multisig executor only

**Side Effects:**

* Clears guardian vote list in `LibTrustedGuardiansPlugin` storage
* Sets `ICryptoLegacy.[CryptoLegacyStorage](https://docs.cryptolegacy.app/documentation/data-structures-reference#cryptolegacystorage-icl1-s4).distributionStartAt` to `0`
* Updates `cls.lastFeePaidAt`/`cls.updateFee` and transfers ETH when `_takeFee` succeeds

**Emits:**

* [ResetGuardiansVoting](https://docs.cryptolegacy.app/documentation/events-reference#resetguardiansvoting-itgp1) — `ResetGuardiansVoting()`
* [FeePaidByLifetime](https://docs.cryptolegacy.app/documentation/events-reference#feepaidbylifetime-icl1) — `FeePaidByLifetime(bytes8 indexed refCode, bool indexed initial, address factory, uint64 lastFeePaidAt)`
* [FeePaidByDefault](https://docs.cryptolegacy.app/documentation/events-reference#feepaidbydefault-icl1) — `FeePaidByDefault(bytes8 indexed refCode, bool indexed initial, uint256 value, uint256 returnedValue, address factory, uint64 lastFeePaidAt)`
* [SkipSendFeeByTransfer](https://docs.cryptolegacy.app/documentation/events-reference#skipsendfeebytransfer-icl1) — `SkipSendFeeByTransfer(address buildManagerAddress, uint256 value)`
* [FeePaidByTransfer](https://docs.cryptolegacy.app/documentation/events-reference#feepaidbytransfer-icl1) — `FeePaidByTransfer(bytes8 indexed refCode, bool indexed initial, uint256 value, address factory, uint64 lastFeePaidAt)`
* [GetUpdateFeeCatch](https://docs.cryptolegacy.app/documentation/events-reference#getupdatefeecatch-icl1) — `GetUpdateFeeCatch(bytes reason)`
* [PayFeeCatch](https://docs.cryptolegacy.app/documentation/events-reference#payfeecatch-icl1) — `PayFeeCatch(bytes reason)`
* [IsLifetimeNftLockedAndUpdateCatch](https://docs.cryptolegacy.app/documentation/events-reference#islifetimenftlockedandupdatecatch-icl1) — `IsLifetimeNftLockedAndUpdateCatch(bytes reason)`

**Reverts if:**

* Caller not multisig executor — [`MultisigOnlyExecutor()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisigonlyexecutor-ism1)
* Distribution already started — [`DistributionStarted()`](https://docs.cryptolegacy.app/documentation/errors-reference#distributionstarted-icl1)
* Lifetime NFT active but fee supplied — [`NoValueAllowed()`](https://docs.cryptolegacy.app/documentation/errors-reference#novalueallowed-icl1)
* Provided fee amount outside tolerated range — [`IncorrectFee(uint256)`](https://docs.cryptolegacy.app/documentation/errors-reference#incorrectfee-icl1)
* ETH transfer to build manager or referral fails — [`TransferFeeFailed(bytes)`](https://docs.cryptolegacy.app/documentation/errors-reference#transferfeefailed-ism1)
* Build manager call reports unregistered legacy — [`ICryptoLegacyBuildManager.NotRegisteredCryptoLegacy()`](https://docs.cryptolegacy.app/documentation/errors-reference#notregisteredcryptolegacy-iclbm1)
* Build manager call reports caller not owner — [`ICryptoLegacyBuildManager.NotOwnerOfCryptoLegacy()`](https://docs.cryptolegacy.app/documentation/errors-reference#notownerofcryptolegacy-iclbm1)

**Overrides:** None

**Function Calls:**

* [LibSafeMinimalMultisig.\_checkIsMultisigExecutor()](#_checkismultisigexecutor-lsm1) — LibSafeMinimalMultisig, internal
* [LibCryptoLegacy.getCryptoLegacyStorage()](#getcryptolegacystorage-lcl1) — LibCryptoLegacy, internal
* [LibCryptoLegacy.\_checkDistributionStart(ICryptoLegacy.CryptoLegacyStorage)](#_checkdistributionstart-lcl1) — LibCryptoLegacy, internal
* [LibTrustedGuardiansPlugin.\_resetGuardianVoting(ICryptoLegacy.CryptoLegacyStorage)](#_resetguardianvoting-ltgp1) — LibTrustedGuardiansPlugin, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Recovery multisig restarts guardian voting after aborting a recovery attempt.

***

### lrWithdrawHeldEth (LRP1)

**Contract/Library:** LegacyRecoveryPlugin

**Description:** Allows a voter to withdraw ETH accumulated during proposal execution.

**Detailed Description:** Authenticates the caller via hashed voter identity (optionally salted), retrieves their `heldEth` balance, resets it, and transfers ETH to the requested recipient.

**Parameters:**

* \_salt (bytes32): Optional salt for voter hashing
* \_recipient (address): Destination address for withdrawn ETH

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external nonpayable nonReentrant

**Access Control:**

* Caller must be an authorized voter with a positive balance

**Side Effects:**

* Updates `heldEth` mapping
* Transfers ETH to `_recipient`

**Emits:**

* [WithdrawHeldEth](https://docs.cryptolegacy.app/documentation/events-reference#withdrawheldeth-ism1) — `WithdrawHeldEth(bytes32 voter, uint256 value)`

**Reverts if:**

* Caller not authorized — [`MultisigVoterNotAllowed()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisigvoternotallowed-ism1)
* No ETH available — [`MultisigNothingToWithdraw()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisignothingtowithdraw-ism1)
* ETH transfer fails — [`TransferFeeFailed(bytes)`](https://docs.cryptolegacy.app/documentation/errors-reference#transferfeefailed-ism1)

**Overrides:** None

**Function Calls:**

* [getPluginMultisigStorage()](#getpluginmultisigstorage-lrp1) — LegacyRecoveryPlugin, internal
* [\_withdrawHeldEth(ISafeMinimalMultisig.Storage,bytes32,bytes32\[\],address)](#_withdrawheldeth-lsm1) — LibSafeMinimalMultisig, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(n) by voter count

**Example:** Multisig voter retrieves reimbursed ETH after proposal execution.

***

### lrGetHeldEth (LRP1)

**Contract/Library:** LegacyRecoveryPlugin

**Description:** Returns the held ETH balance for a given voter hash.

**Detailed Description:** Reads the `heldEth` mapping in multisig storage for the supplied voter identifier.

**Parameters:**

* \_hash (bytes32): Voter identifier hash

**Returns:**

* heldEthBalance (uint256): Withdrawable ETH for that voter

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [getPluginMultisigStorage()](#getpluginmultisigstorage-lrp1) — LegacyRecoveryPlugin, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Frontend shows pending ETH reimbursements per voter.

***

### lrGetInitializationStatus (LRP1)

**Contract/Library:** LegacyRecoveryPlugin

**Description:** Indicates whether the recovery multisig has been initialized.

**Detailed Description:** Delegates to `LibSafeMinimalMultisig._initializationStatus` to check if required confirmations are non-zero.

**Parameters:** None

**Returns:**

* status ([ISafeMinimalMultisig.InitializationStatus](https://docs.cryptolegacy.app/documentation/data-structures-reference#initializationstatus-ism1-e2)): Current initialization state

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [getPluginMultisigStorage()](#getpluginmultisigstorage-lrp1) — LegacyRecoveryPlugin, internal
* [LibSafeMinimalMultisig.\_initializationStatus(ISafeMinimalMultisig.Storage)](#_initializationstatus-lsm1) — LibSafeMinimalMultisig, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** UI shows whether recovery multisig setup is complete.

***

### lrGetProposalWithStatus (LRP1)

**Contract/Library:** LegacyRecoveryPlugin

**Description:** Retrieves a specific proposal and its confirmation status.

**Detailed Description:** Returns the stored voter list, confirmation threshold, and [`ProposalWithStatus`](https://docs.cryptolegacy.app/documentation/data-structures-reference#proposalwithstatus-ism1-s3) struct produced by `LibSafeMinimalMultisig._getProposalWithStatus`. Dereferencing `_proposalId` relies on Solidity bounds checks, so an invalid index triggers `panic(0x32)`.

**Parameters:**

* \_proposalId (uint256): Proposal index

**Returns:**

* voters (bytes32\[], memory): Current voter list stored for the plugin
* requiredConfirmations (uint128): Multisig confirmation threshold
* proposalWithStatus ([ISafeMinimalMultisig.ProposalWithStatus](https://docs.cryptolegacy.app/documentation/data-structures-reference#proposalwithstatus-ism1-s3), memory): Proposal payload with per-voter confirmations

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:**

* `_proposalId` out of range — `panic(uint256(0x32))`

**Overrides:** None

**Function Calls:**

* [getPluginMultisigStorage()](#getpluginmultisigstorage-lrp1) — LegacyRecoveryPlugin, internal
* [\_getProposalWithStatus(ISafeMinimalMultisig.Storage,bytes32\[\],uint256)](#_getproposalwithstatus-lsm1) — LibSafeMinimalMultisig, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(n) by voter count

**Example:** Operator inspects confirmations before deciding to approve.

***

### lrGetProposalListWithStatuses (LRP1)

**Contract/Library:** LegacyRecoveryPlugin

**Description:** Returns all recovery proposals with confirmation metadata.

**Detailed Description:** Delegates to `LibSafeMinimalMultisig._getProposalListWithStatusesAndStorageVoters`, which builds an array of [`ProposalWithStatus`](https://docs.cryptolegacy.app/documentation/data-structures-reference#proposalwithstatus-ism1-s3) for every stored proposal, along with voters and the confirmation threshold.

**Parameters:** None

**Returns:**

* voters (bytes32\[], memory): Stored voter identifiers
* requiredConfirmations (uint128): Required number of confirmations
* proposalsWithStatuses ([ISafeMinimalMultisig.ProposalWithStatus](https://docs.cryptolegacy.app/documentation/data-structures-reference#proposalwithstatus-ism1-s3)\[], memory): Full proposal list paired with confirmation statuses

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [getPluginMultisigStorage()](#getpluginmultisigstorage-lrp1) — LegacyRecoveryPlugin, internal
* [LibSafeMinimalMultisig.\_getProposalListWithStatusesAndStorageVoters(ISafeMinimalMultisig.Storage)](#_getproposallistwithstatusesandstoragevoters-lsm1) — LibSafeMinimalMultisig, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(p·n) where p = number of proposals, n = voter count

**Example:** UI displays every recovery proposal with current confirmations.

***

## LensPlugin (LP1)

### getSigs (LP1)

**Contract/Library:** LensPlugin

**Description:** Enumerates every externally exposed selector for the Lens plugin.

**Detailed Description:** Builds a 20-element bytes4 array and fills it with the selectors for time/fee getters, beneficiary views, distribution helpers, and plugin metadata readers so the diamond router can register the facet.

**Parameters:** None

**Returns:**

* sigs (bytes4\[], memory): Ordered selector list covering the LensPlugin read-only API

**Modifiers / Visibility / Mutability:**

* public pure

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:** None (entry point)

**Gas / Complexity note:** O(1) — fixed-length selector array allocation

**Example:** Plugin registry enumerates selectors when wiring this facet into the diamond.

***

### getSetupSigs (LP1)

**Contract/Library:** LensPlugin

**Description:** Reports setup-time selectors required by the Lens plugin.

**Detailed Description:** Returns an empty array, signalling that the plugin needs no deferred initialization calls during installation.

**Parameters:** None

**Returns:**

* sigs (bytes4\[], memory): Empty selector list indicating no setup functions

**Modifiers / Visibility / Mutability:**

* external pure

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Deployment script confirms no setup hooks are necessary for the lens facet.

***

### getPluginName (LP1)

**Contract/Library:** LensPlugin

**Description:** Reveals the human-readable name of the plugin.

**Detailed Description:** Returns the literal string `"lens"`, used by registries and dashboards to label this facet.

**Parameters:** None

**Returns:**

* name (string, memory): Constant plugin name "lens"

**Modifiers / Visibility / Mutability:**

* external pure

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** UI components read the plugin name to label analytics panels.

***

### getPluginVer (LP1)

**Contract/Library:** LensPlugin

**Description:** Returns the semantic version of the Lens plugin.

**Detailed Description:** Provides the hard-coded version `1`, enabling compatibility checks across plugin upgrades.

**Parameters:** None

**Returns:**

* version (uint16): Constant version identifier 1

**Modifiers / Visibility / Mutability:**

* external pure

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Monitoring tooling fetches the version to ensure the expected facet is installed.

***

### updateInterval (LP1)

**Contract/Library:** LensPlugin

**Description:** Reads the configured update interval for the CryptoLegacy instance.

**Detailed Description:** Obtains the shared storage via `LibCryptoLegacy` and returns `cls.updateInterval`, representing seconds between mandatory updates.

**Parameters:** None

**Returns:**

* interval (uint64): Current update interval in seconds

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [LibCryptoLegacy.getCryptoLegacyStorage()](#getcryptolegacystorage-lcl1) — LibCryptoLegacy, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Dashboard displays the cadence required for keepers to call `update()`.

***

### challengeTimeout (LP1)

**Contract/Library:** LensPlugin

**Description:** Exposes the challenge timeout value.

**Detailed Description:** Loads CryptoLegacy storage and returns `cls.challengeTimeout`, indicating how long challenges remain open.

**Parameters:** None

**Returns:**

* timeout (uint64): Challenge window duration in seconds

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [LibCryptoLegacy.getCryptoLegacyStorage()](#getcryptolegacystorage-lcl1) — LibCryptoLegacy, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Explorer shows the active challenge timeout for a CryptoLegacy instance.

***

### distributionStartAt (LP1)

**Contract/Library:** LensPlugin

**Description:** Returns when beneficiary distribution began.

**Detailed Description:** Reads `cls.distributionStartAt` from CryptoLegacy storage, reflecting the timestamp that unlocked beneficiary claims.

**Parameters:** None

**Returns:**

* startTimestamp (uint64): Distribution start timestamp

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [LibCryptoLegacy.getCryptoLegacyStorage()](#getcryptolegacystorage-lcl1) — LibCryptoLegacy, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Beneficiary portal shows when vesting started for an estate.

***

### lastFeePaidAt (LP1)

**Contract/Library:** LensPlugin

**Description:** Reports the block timestamp of the last paid maintenance fee.

**Detailed Description:** Fetches `cls.lastFeePaidAt` from CryptoLegacy storage to surface the latest successful fee payment time.

**Parameters:** None

**Returns:**

* lastPaidAt (uint64): Timestamp of the latest fee payment

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [LibCryptoLegacy.getCryptoLegacyStorage()](#getcryptolegacystorage-lcl1) — LibCryptoLegacy, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Operations dashboard monitors when recurring fees were last settled.

***

### lastUpdateAt (LP1)

**Contract/Library:** LensPlugin

**Description:** Exposes the timestamp of the most recent `update()` call.

**Detailed Description:** Reads `cls.lastUpdateAt` from storage, allowing observers to track how recently the CryptoLegacy plan was refreshed.

**Parameters:** None

**Returns:**

* lastUpdated (uint64): Unix timestamp of the last update

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [LibCryptoLegacy.getCryptoLegacyStorage()](#getcryptolegacystorage-lcl1) — LibCryptoLegacy, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Observers verify that periodic updates are occurring on schedule.

***

### initialFeeToPay (LP1)

**Contract/Library:** LensPlugin

**Description:** Provides the initial fee amount required when activating a CryptoLegacy instance.

**Detailed Description:** Returns `cls.initialFeeToPay` from storage, reflecting the upfront payment tracked by CryptoLegacy.

**Parameters:** None

**Returns:**

* initialFee (uint128): Initial fee in wei owed to the build manager

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [LibCryptoLegacy.getCryptoLegacyStorage()](#getcryptolegacystorage-lcl1) — LibCryptoLegacy, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Front-end displays the upfront fee alongside the subscription terms.

***

### updateFee (LP1)

**Contract/Library:** LensPlugin

**Description:** Returns the recurring fee charged per update interval.

**Detailed Description:** Reads `cls.updateFee` so external dashboards can show the on-chain recurring cost.

**Parameters:** None

**Returns:**

* fee (uint128): Recurring update fee in wei

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [LibCryptoLegacy.getCryptoLegacyStorage()](#getcryptolegacystorage-lcl1) — LibCryptoLegacy, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Billing widgets show the live recurring fee owed to maintain the CryptoLegacy instance.

***

### invitedByRefCode (LP1)

**Contract/Library:** LensPlugin

**Description:** Exposes the referral code associated with the CryptoLegacy instance.

**Detailed Description:** Returns `cls.invitedByRefCode`, allowing analytics to correlate CryptoLegacy instances with referral programs.

**Parameters:** None

**Returns:**

* refCode (bytes8): Referral code recorded at creation

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [LibCryptoLegacy.getCryptoLegacyStorage()](#getcryptolegacystorage-lcl1) — LibCryptoLegacy, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Marketing dashboards attribute CryptoLegacy usage to the originating referral code.

***

### getBeneficiaryClaimed (LP1)

**Contract/Library:** LensPlugin

**Description:** Returns how much of a given token a beneficiary has already claimed.

**Detailed Description:** Loads CryptoLegacy storage and reads `cls.beneficiaryVesting_beneficiary.tokenAmountClaimed_token`, providing the cumulative withdrawals recorded for that beneficiary hash.

**Parameters:**

* \_beneficiary (bytes32): Beneficiary hash to inspect
* \_token (address): ERC20 token being distributed

**Returns:**

* claimedAmount (uint256): Total amount already claimed by the beneficiary

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [LibCryptoLegacy.getCryptoLegacyStorage()](#getcryptolegacystorage-lcl1) — LibCryptoLegacy, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Beneficiary dashboard displays previously withdrawn token amounts per asset.

***

### getOriginalBeneficiaryHash (LP1)

**Contract/Library:** LensPlugin

**Description:** Reveals the original beneficiary hash mapped to a derived hash.

**Detailed Description:** Fetches `cls.originalBeneficiaryHash_beneficiary` to expose the canonical identifier used for vesting bookkeeping.

**Parameters:**

* \_beneficiary (bytes32): Derived beneficiary hash to resolve

**Returns:**

* originalHash (bytes32): Original beneficiary hash stored in the contract

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [LibCryptoLegacy.getCryptoLegacyStorage()](#getcryptolegacystorage-lcl1) — LibCryptoLegacy, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Indexer reconciles beneficiary aliases against their original identifiers.

***

### getBeneficiaryConfig (LP1)

**Contract/Library:** LensPlugin

**Description:** Retrieves the vesting configuration for a beneficiary hash.

**Detailed Description:** Returns `cls.beneficiaryConfig_beneficiary`, exposing claim delay, vesting period, and share basis points even if distribution is pending.

**Parameters:**

* \_beneficiary (bytes32): Beneficiary hash being queried

**Returns:**

* config (ICryptoLegacy.BeneficiaryConfig, memory): Struct with delay, vesting period, and shareBps

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [LibCryptoLegacy.getCryptoLegacyStorage()](#getcryptolegacystorage-lcl1) — LibCryptoLegacy, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** UI reveals each beneficiary’s vesting configuration alongside contact details.

***

### getBeneficiaries (LP1)

**Contract/Library:** LensPlugin

**Description:** Lists all beneficiaries, their original hashes, and configurations.

**Detailed Description:** Delegates to `_getBeneficiaries` to enumerate the `EnumerableSet` of beneficiary hashes, collecting the mapped original hashes and configuration structs.

**Parameters:** None

**Returns:**

* hashes (bytes32\[], memory): Current beneficiary hashes
* originalHashes (bytes32\[], memory): Corresponding original beneficiary hashes
* configs (ICryptoLegacy.BeneficiaryConfig\[], memory): Config entries aligned with each hash

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [LibCryptoLegacy.getCryptoLegacyStorage()](#getcryptolegacystorage-lcl1) — LibCryptoLegacy, internal
* [\_getBeneficiaries(ICryptoLegacy.CryptoLegacyStorage)](#_getbeneficiaries-lp1) — LensPlugin, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(b) by number of beneficiaries

**Example:** Explorer fetches the full beneficiary roster with claim parameters.

***

### \_getBeneficiaries (LP1)

**Contract/Library:** LensPlugin

**Description:** Internal helper that assembles beneficiary hashes, originals, and configs.

**Detailed Description:** Copies the `cls.beneficiaries` set into memory arrays, then for each entry reads `beneficiaryConfig` and `originalBeneficiaryHash` to build aligned arrays returned to callers.

**Parameters:**

* cls (ICryptoLegacy.CryptoLegacyStorage, storage): CryptoLegacy storage pointer

**Returns:**

* hashes (bytes32\[], memory): Beneficiary hashes from storage
* originalHashes (bytes32\[], memory): Original hashes paired with each beneficiary
* configs (ICryptoLegacy.BeneficiaryConfig\[], memory): Configuration structs per beneficiary

**Modifiers / Visibility / Mutability:**

* internal view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:**

* [getBeneficiaries](#getbeneficiaries-lp1) — LensPlugin
* [getCryptoLegacyListData](#getcryptolegacylistdata-lp1) — LensPlugin

**Gas / Complexity note:** O(b) by beneficiary count

**Example:** Not applicable

***

### getTransferBlockNumbers (LP1)

**Contract/Library:** LensPlugin

**Description:** Returns the block numbers recorded for asset movements involving the CryptoLegacy contract.

**Detailed Description:** Reads `cls.transfersGotByBlockNumber`, which `_transferTreasuryTokensToLegacy` and `_transferTokensFromLegacy` append to after inbound or outbound transfers touching the CryptoLegacy contract.

**Parameters:** None

**Returns:**

* blockNumbers (uint64\[], memory): Recorded block numbers for CryptoLegacy transfers

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [LibCryptoLegacy.getCryptoLegacyStorage()](#getcryptolegacystorage-lcl1) — LibCryptoLegacy, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(t) by number of stored transfer checkpoints

**Example:** Compliance service reconciles deposits into and payouts from the CryptoLegacy contract using the recorded block numbers.

***

### getTokensDistribution (LP1)

**Contract/Library:** LensPlugin

**Description:** Summarises distribution totals for a token list.

**Detailed Description:** Delegates to `_getTokensDistribution` to compute per-token distribution amounts, last balances, and aggregate claimed totals for each supplied token address.

**Parameters:**

* \_tokens (address\[], memory): Tokens to evaluate

**Returns:**

* list (ICryptoLegacyLens.LensTokenDistribution\[], memory): Distribution snapshot per token

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [\_getTokensDistribution(address\[\])](#_gettokensdistribution-lp1) — LensPlugin, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(t·b) via the internal helper (t = `_tokens.length`, b = beneficiaries)

**Example:** Portfolio view requests token distribution stats for the tracked asset list.

***

### \_getTokensDistribution (LP1)

**Contract/Library:** LensPlugin

**Description:** Internal aggregator that builds per-token distribution data.

**Detailed Description:** Fetches CryptoLegacy storage, then for each token reads its [`TokenDistribution`](https://docs.cryptolegacy.app/documentation/data-structures-reference#tokendistribution-icl1-s3) struct, calls `LibCryptoLegacy._getTotalClaimed` to sum claimed amounts across beneficiaries, and packs the values into [`LensTokenDistribution`](https://docs.cryptolegacy.app/documentation/data-structures-reference#lenstokendistribution-icll1-s4) entries.

**Parameters:**

* \_tokens (address\[], memory): Token addresses to process

**Returns:**

* list (ICryptoLegacyLens.LensTokenDistribution\[], memory): Amount to distribute, last balance, and total claimed per token

**Modifiers / Visibility / Mutability:**

* internal view

**Access Control:**

* Unrestricted (internal)

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [LibCryptoLegacy.getCryptoLegacyStorage()](#getcryptolegacystorage-lcl1) — LibCryptoLegacy, internal
* [LibCryptoLegacy.\_getTotalClaimed(...)](#_gettotalclaimed-lcl1) — LibCryptoLegacy, internal

**Called by:**

* [getTokensDistribution](#gettokensdistribution-lp1) — LensPlugin
* [getCryptoLegacyListData](#getcryptolegacylistdata-lp1) — LensPlugin

**Gas / Complexity note:** O(t·b) where t = `_tokens.length` and b = beneficiary count

**Example:** Not applicable

***

### getCryptoLegacyBaseData (LP1)

**Contract/Library:** LensPlugin

**Description:** Returns a snapshot of the core CryptoLegacy configuration.

**Detailed Description:** Reads storage via `LibCryptoLegacy` and assembles [`CryptoLegacyBaseData`](https://docs.cryptolegacy.app/documentation/data-structures-reference#cryptolegacybasedata-icll1-s3) containing fee amounts, timing parameters, distribution start, referral code, default function flags, and the build manager address.

**Parameters:** None

**Returns:**

* data ([CryptoLegacyBaseData](https://docs.cryptolegacy.app/documentation/data-structures-reference#cryptolegacybasedata-icll1-s3), memory): Aggregate base configuration fields

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [LibCryptoLegacy.getCryptoLegacyStorage()](#getcryptolegacystorage-lcl1) — LibCryptoLegacy, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Analytics backend gathers base contract metadata for indexing.

***

### getCryptoLegacyListData (LP1)

**Contract/Library:** LensPlugin

**Description:** Provides a comprehensive snapshot including beneficiaries, plugins, and token distributions.

**Detailed Description:** Retrieves storage, invokes `_getBeneficiaries` for beneficiary listings, returns the recorded transfer block numbers, appends plugin metadata via `_getPluginInfoList`, and enriches the result with `_getTokensDistribution` for the supplied token list.

**Parameters:**

* \_tokens (address\[], memory): Tokens to include in the distribution summary

**Returns:**

* data ([CryptoLegacyListData](https://docs.cryptolegacy.app/documentation/data-structures-reference#cryptolegacylistdata-icll1-s5), memory): Consolidated snapshot combining beneficiaries, transfers, plugin info, and token distributions

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:**

* `ICryptoLegacyPlugin(facet).getPluginName()` — may revert per plugin implementation (bubbled via `_getPluginInfoList`)
* `ICryptoLegacyPlugin(facet).getPluginVer()` — may revert per plugin implementation (bubbled via `_getPluginInfoList`)
* `cls.buildManager.pluginsRegistry().getPluginDescriptionBlockNumbers(facet)` — may revert per registry implementation (bubbled via `_getPluginInfoList`)

**Overrides:** None

**Function Calls:**

* [LibCryptoLegacy.getCryptoLegacyStorage()](#getcryptolegacystorage-lcl1) — LibCryptoLegacy, internal
* [\_getBeneficiaries(ICryptoLegacy.CryptoLegacyStorage)](#_getbeneficiaries-lp1) — LensPlugin, internal
* [\_getPluginInfoList(ICryptoLegacy.CryptoLegacyStorage)](#_getplugininfolist-lp1) — LensPlugin, internal
* [\_getTokensDistribution(address\[\])](#_gettokensdistribution-lp1) — LensPlugin, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(b + p + t·b) where b = beneficiaries, p = plugins, t = `_tokens.length`

**Example:** Explorer composes a single RPC call to display the full CryptoLegacy state snapshot.

***

### getMessagesBlockNumbersByRecipient (LP1)

**Contract/Library:** LensPlugin

**Description:** Lists when messages were received for a beneficiary.

**Detailed Description:** Loads `cls.beneficiaryMessagesGotByBlockNumber_recipient` so observers can inspect communication activity tied to the beneficiary hash.

**Parameters:**

* \_recipient (bytes32): Beneficiary hash whose message history is requested

**Returns:**

* blockNumbers (uint64\[], memory): Block numbers where messages were logged

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [LibCryptoLegacy.getCryptoLegacyStorage()](#getcryptolegacystorage-lcl1) — LibCryptoLegacy, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(m) by number of stored message checkpoints

**Example:** Notifications service shows when beneficiaries received status messages.

***

### getVestedAndClaimedData (LP1)

**Contract/Library:** LensPlugin

**Description:** Calculates vested, claimable, and claimed token amounts for a beneficiary.

**Detailed Description:** Acquires storage, then for each token loads the beneficiary config and vesting structs, derives vesting windows via `_getStartAndEndDate`, and delegates to `_getVestedAndClaimedAmount` to compute totals, vested balances, and currently claimable amounts (clamped by contract balance). Returns the per-token data alongside the common start/end timestamps.

**Parameters:**

* \_beneficiary (bytes32): Beneficiary hash being evaluated
* \_tokens (address\[], memory): Token list to analyse

**Returns:**

* result ([BeneficiaryTokenData](https://docs.cryptolegacy.app/documentation/data-structures-reference#beneficiarytokendata-icll1-s1)\[], memory): Claimable, claimed, and total allocation per token
* startDate (uint64): Vesting start timestamp derived from beneficiary config
* endDate (uint64): Vesting end timestamp derived from beneficiary config

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:**

* `_beneficiary` not registered — [`ICryptoLegacy.BeneficiaryNotExist()`](https://docs.cryptolegacy.app/documentation/errors-reference#beneficiarynotexist-icl1)
* `IERC20(_tokensi).balanceOf(address(this))` — may revert per token implementation (bubbled via `LibCryptoLegacy._getVestedAndClaimedAmount`)

**Overrides:** None

**Function Calls:**

* [LibCryptoLegacy.getCryptoLegacyStorage()](#getcryptolegacystorage-lcl1) — LibCryptoLegacy, internal
* [LibCryptoLegacy.\_getBeneficiaryConfigAndVesting(...)](#_getbeneficiaryconfigandvesting-lcl1) — LibCryptoLegacy, internal
* [LibCryptoLegacy.\_getStartAndEndDate(...)](#_getstartandenddate-lcl1) — LibCryptoLegacy, internal
* [LibCryptoLegacy.\_getVestedAndClaimedAmount(...)](#_getvestedandclaimedamount-lcl1) — LibCryptoLegacy, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(t) by `_tokens.length` (vested math per token)

**Example:** Beneficiary dashboard shows claimable vs. claimed balances for selected assets.

***

### \_getPluginInfoList (LP1)

**Contract/Library:** LensPlugin

**Description:** Internal helper that compiles plugin metadata for all installed facets.

**Detailed Description:** Pulls the diamond storage to enumerate facet addresses, then for each invokes `_getPluginMetadata` to capture name, version, and description history, assembling an array of [`PluginInfo`](https://docs.cryptolegacy.app/documentation/data-structures-reference#plugininfo-ipr1-s1) structs.

**Parameters:**

* cls (ICryptoLegacy.CryptoLegacyStorage, storage): CryptoLegacy storage pointer

**Returns:**

* plugins ([PluginInfo](https://docs.cryptolegacy.app/documentation/data-structures-reference#plugininfo-ipr1-s1)\[], memory): Plugin metadata entries ordered by facet address list

**Modifiers / Visibility / Mutability:**

* internal view

**Access Control:**

* Unrestricted (internal)

**Side Effects:** None

**Emits:** None

**Reverts if:**

* `ICryptoLegacyPlugin(facet).getPluginName()` — may revert per plugin implementation (bubbled)
* `ICryptoLegacyPlugin(facet).getPluginVer()` — may revert per plugin implementation (bubbled)
* `cls.buildManager.pluginsRegistry().getPluginDescriptionBlockNumbers(facet)` — may revert per registry implementation (bubbled)

**Overrides:** None

**Function Calls:**

* [LibDiamond.diamondStorage()](#diamondstorage-ld1) — LibDiamond, internal
* [\_getPluginMetadata(address)](#_getpluginmetadata-lp1) — LensPlugin, internal

**Called by:**

* [getCryptoLegacyListData](#getcryptolegacylistdata-lp1) — LensPlugin
* [getPluginInfoList](#getplugininfolist-lp1) — LensPlugin

**Gas / Complexity note:** O(p) by number of facets/plugins installed

**Example:** Not applicable

***

### \_getPluginMetadata (LP1)

**Contract/Library:** LensPlugin

**Description:** Fetches metadata for a specific plugin address.

**Detailed Description:** Queries the plugin contract for its name and version via `ICryptoLegacyPlugin`, then calls into the build manager’s plugins registry to retrieve description block numbers, returning the tuple to callers.

**Parameters:**

* cls (ICryptoLegacy.CryptoLegacyStorage, storage): CryptoLegacy storage pointer
* \_plugin (address): Plugin contract to inspect

**Returns:**

* name (string, memory): Plugin name reported by the plugin contract
* version (uint16): Plugin version reported by the plugin contract
* descriptionBlockNumbers (uint64\[], memory): Description update checkpoints registered for the plugin

**Modifiers / Visibility / Mutability:**

* internal view

**Access Control:**

* Unrestricted (internal)

**Side Effects:** None

**Emits:** None

**Reverts if:**

* `ICryptoLegacyPlugin(_plugin).getPluginName()` — may revert per plugin implementation (bubbled)
* `ICryptoLegacyPlugin(_plugin).getPluginVer()` — may revert per plugin implementation (bubbled)
* `cls.buildManager.pluginsRegistry().getPluginDescriptionBlockNumbers(_plugin)` — may revert per registry implementation (bubbled)

**Overrides:** None

**Function Calls:**

* `ICryptoLegacyPlugin.getPluginName()` — `ICryptoLegacyPlugin` *(at `_plugin`)*, external (staticcall)
* `ICryptoLegacyPlugin.getPluginVer()` — `ICryptoLegacyPlugin` *(at `_plugin`)*, external (staticcall)
* [`pluginsRegistry()`](https://docs.cryptolegacy.app/documentation/data-structures-reference#pluginsregistry-clbm1-d2) — `ICryptoLegacyBuildManager` *(at `cls.buildManager`)*, external (staticcall)
* `IPluginsRegistry.getPluginDescriptionBlockNumbers(address)` — `IPluginsRegistry`, external (staticcall)

**Called by:**

* [\_getPluginInfoList](#_getplugininfolist-lp1) — LensPlugin
* [getPluginMetadata](#getpluginmetadata-lp1) — LensPlugin

**Gas / Complexity note:** O(1) plus three external (staticcall) lookups

**Example:** Not applicable

***

### getPluginInfoList (LP1)

**Contract/Library:** LensPlugin

**Description:** Exposes metadata for all plugins attached to the CryptoLegacy instance.

**Detailed Description:** Calls `_getPluginInfoList` with current storage to gather plugin addresses, names, versions, and description history into an array.

**Parameters:** None

**Returns:**

* plugins ([PluginInfo](https://docs.cryptolegacy.app/documentation/data-structures-reference#plugininfo-ipr1-s1)\[], memory): Plugin metadata records for the active facets

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:**

* `ICryptoLegacyPlugin(facet).getPluginName()` — may revert per plugin implementation (bubbled via `_getPluginInfoList`)
* `ICryptoLegacyPlugin(facet).getPluginVer()` — may revert per plugin implementation (bubbled via `_getPluginInfoList`)
* `cls.buildManager.pluginsRegistry().getPluginDescriptionBlockNumbers(facet)` — may revert per registry implementation (bubbled via `_getPluginInfoList`)

**Overrides:** None

**Function Calls:**

* [LibCryptoLegacy.getCryptoLegacyStorage()](#getcryptolegacystorage-lcl1) — LibCryptoLegacy, internal
* [\_getPluginInfoList(ICryptoLegacy.CryptoLegacyStorage)](#_getplugininfolist-lp1) — LensPlugin, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(p) by number of installed plugins, including external (staticcall) metadata reads

**Example:** Analytics endpoint lists all active plugins with versioning info.

***

### getPluginMetadata (LP1)

**Contract/Library:** LensPlugin

**Description:** Returns metadata for a specific plugin address through the lens facet.

**Detailed Description:** Acquires storage via `LibCryptoLegacy` and forwards to `_getPluginMetadata`, exposing the individual plugin’s name, version, and description history.

**Parameters:**

* \_plugin (address): Plugin contract to query

**Returns:**

* name (string, memory): Plugin name sourced from the plugin contract
* version (uint16): Plugin version returned by the plugin contract
* descriptionBlockNumbers (uint64\[], memory): Description history recorded in the plugins registry

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:**

* `ICryptoLegacyPlugin(_plugin).getPluginName()` — may revert per plugin implementation (bubbled via `_getPluginMetadata`)
* `ICryptoLegacyPlugin(_plugin).getPluginVer()` — may revert per plugin implementation (bubbled via `_getPluginMetadata`)
* `cls.buildManager.pluginsRegistry().getPluginDescriptionBlockNumbers(_plugin)` — may revert per registry implementation (bubbled via `_getPluginMetadata`)

**Overrides:** None

**Function Calls:**

* [LibCryptoLegacy.getCryptoLegacyStorage()](#getcryptolegacystorage-lcl1) — LibCryptoLegacy, internal
* [\_getPluginMetadata(address)](#_getpluginmetadata-lp1) — LensPlugin, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1) plus three external (staticcall) metadata lookups

**Example:** Analytics or UI components fetch plugin metadata for display.

***

## NftLegacyPlugin (NLP1)

### getSigs (NLP1)

**Contract/Library:** NftLegacyPlugin

**Description:** Lists the externally callable selectors for the NFT inheritance facet.

**Detailed Description:** Allocates a fixed array of three selectors corresponding to `setNftBeneficiary`, `transferNftTokensToLegacy`, and `beneficiaryClaimNft`, enabling registry tooling to register this facet with the diamond router.

**Parameters:** None

**Returns:**

* sigs (bytes4\[], memory): Selector array exposing the NFT management entry points

**Modifiers / Visibility / Mutability:**

* external pure

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:** None (entry point)

**Gas / Complexity note:** O(1) — constant-length selector assembly

**Example:** Plugin registry queries selectors before adding the facet to a CryptoLegacy diamond.

***

### getSetupSigs (NLP1)

**Contract/Library:** NftLegacyPlugin

**Description:** Reports any setup-time selectors required by the NFT plugin.

**Detailed Description:** Returns an empty array, signalling that no post-deployment setup calls are necessary when installing this facet.

**Parameters:** None

**Returns:**

* sigs (bytes4\[], memory): Empty array indicating no setup hooks

**Modifiers / Visibility / Mutability:**

* external pure

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Deployment script verifies that no setup selectors need to be scheduled.

***

### getPluginName (NLP1)

**Contract/Library:** NftLegacyPlugin

**Description:** Returns the human-readable identifier for the NFT plugin.

**Detailed Description:** Provides the static string `"nft_legacy"`, allowing dashboards and registries to label this facet consistently.

**Parameters:** None

**Returns:**

* name (string, memory): Constant plugin name "nft\_legacy"

**Modifiers / Visibility / Mutability:**

* external pure

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Front-end labels the facet as “NFT Legacy” using this constant.

***

### getPluginVer (NLP1)

**Contract/Library:** NftLegacyPlugin

**Description:** Provides the semantic version of the NFT plugin.

**Detailed Description:** Returns the encoded version `1`, enabling compatibility checks for plugin upgrades.

**Parameters:** None

**Returns:**

* version (uint16): Constant version identifier 1

**Modifiers / Visibility / Mutability:**

* external pure

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Monitoring tooling checks the facet version to detect upgrades.

***

### getPluginStorage (NLP1)

**Contract/Library:** NftLegacyPlugin

**Description:** Returns the plugin’s dedicated storage slot.

**Detailed Description:** Uses the fixed [`PLUGIN_POSITION`](https://docs.cryptolegacy.app/documentation/data-structures-reference#plugin_position-urp1-d1) hash and inline assembly to map the struct pointer to persistent storage, giving callers access to the plugin’s NFT beneficiary mappings.

**Parameters:** None

**Returns:**

* storageStruct (PluginStorage, storage): Storage pointer holding NFT beneficiary configuration

**Modifiers / Visibility / Mutability:**

* internal pure

**Access Control:**

* Unrestricted (internal)

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:**

* [setNftBeneficiary](#setnftbeneficiary-nlp1) — NftLegacyPlugin
* [transferNftTokensToLegacy](#transfernfttokenstolegacy-nlp1) — NftLegacyPlugin
* [beneficiaryClaimNft](#beneficiaryclaimnft-nlp1) — NftLegacyPlugin

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### modifier onlyOwner (NLP1)

**Contract/Library:** NftLegacyPlugin

**Description:** Restricts access to the CryptoLegacy owner before distribution starts.

**Detailed Description:** Invokes `LibCryptoLegacy._checkOwner()` to ensure distribution has not begun, the initial fee is paid, and `msg.sender` matches the diamond owner before allowing the wrapped function to execute.

**Parameters:** None

**Returns:** None

**Modifiers / Visibility / Mutability:**

* modifier nonpayable

**Access Control:**

* Enforced by the modifier itself

**Side Effects:** None

**Emits:** None

**Reverts if:**

* Distribution already started — [`DistributionStarted()`](https://docs.cryptolegacy.app/documentation/errors-reference#distributionstarted-icl1)
* Initial fee unpaid — [`InitialFeeNotPaid()`](https://docs.cryptolegacy.app/documentation/errors-reference#initialfeenotpaid-icl1)
* Caller is not the owner — [`NotTheOwner()`](https://docs.cryptolegacy.app/documentation/errors-reference#nottheowner-icl1)

**Overrides:** None

**Function Calls:**

* [LibCryptoLegacy.\_checkOwner()](#_checkowner-lcl1) — LibCryptoLegacy, internal

**Called by:**

* [setNftBeneficiary](#setnftbeneficiary-nlp1) — NftLegacyPlugin

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### setNftBeneficiary (NLP1)

**Contract/Library:** NftLegacyPlugin

**Description:** Assigns a beneficiary hash and claim delay to multiple NFTs.

**Detailed Description:** Obtains plugin storage, then iterates over `_tokenIds`, storing the provided beneficiary hash and delay for each `(contract, tokenId)` pair before emitting `SetNftBeneficiary`. Requires ownership via the modifier.

**Parameters:**

* \_beneficiary (bytes32): Beneficiary hash to assign
* \_nftContract (address): ERC721 contract holding the tokens
* \_tokenIds (uint256\[], memory): Token identifiers receiving the assignment
* \_delay (uint32): Seconds beneficiaries must wait after distribution starts

**Returns:** None

**Modifiers / Visibility / Mutability:**

* public nonpayable onlyOwner

**Access Control:**

* Owner only (enforced by `onlyOwner`)

**Side Effects:**

* Updates `nftBeneficiary_nftContract_tokenId` for each token

**Emits:**

* [SetNftBeneficiary](https://docs.cryptolegacy.app/documentation/events-reference#setnftbeneficiary-nlp1) — `SetNftBeneficiary(address indexed nftContract, uint256 indexed tokenId, bytes32 indexed beneficiaryHash)`

**Reverts if:**

* Distribution already started — [`DistributionStarted()`](https://docs.cryptolegacy.app/documentation/errors-reference#distributionstarted-icl1)
* Initial fee unpaid — [`InitialFeeNotPaid()`](https://docs.cryptolegacy.app/documentation/errors-reference#initialfeenotpaid-icl1)
* Caller is not the owner — [`NotTheOwner()`](https://docs.cryptolegacy.app/documentation/errors-reference#nottheowner-icl1)

**Overrides:** None

**Function Calls:**

* [getPluginStorage()](#getpluginstorage-nlp1) — NftLegacyPlugin, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(n) by `_tokenIds.length`

**Example:** Owner assigns multiple NFTs to a beneficiary with a 30-day claim delay.

***

### transferNftTokensToLegacy (NLP1)

**Contract/Library:** NftLegacyPlugin

**Description:** Pulls configured NFTs into the CryptoLegacy contract once distribution is ready.

**Detailed Description:** Fetches shared storage, ensures distribution has started, and derives the caller’s beneficiary hash. Iterates through `_tokenIds`, confirming each has an assigned beneficiary, tracking whether the caller is that beneficiary, and transfers the NFT into the CryptoLegacy contract. After the loop, verifies non-beneficiary callers hold a non-zero share before completing.

**Parameters:**

* \_nftContract (address): ERC721 contract holding the NFTs
* \_tokenIds (uint256\[], memory): Token identifiers to move into the CryptoLegacy contract

**Returns:** None

**Modifiers / Visibility / Mutability:**

* public nonpayable nonReentrant

**Access Control:**

* Unrestricted; caller must either be the configured beneficiary or hold a non-zero beneficiary share

**Side Effects:**

* Transfers each NFT from its current owner to the CryptoLegacy contract

**Emits:**

* [TransferNftToCryptoLegacy](https://docs.cryptolegacy.app/documentation/events-reference#transfernfttocryptolegacy-nlp1) — `TransferNftToCryptoLegacy(address indexed nftContract, uint256 indexed tokenId)`

**Reverts if:**

* Distribution not ready — [`TooEarly()`](https://docs.cryptolegacy.app/documentation/errors-reference#tooearly-icl1)
* NFT beneficiary not set — [`BeneficiaryNotSet()`](https://docs.cryptolegacy.app/documentation/errors-reference#beneficiarynotset-icl1)
* Caller lacks beneficiary entitlement — [`NotTheBeneficiary()`](https://docs.cryptolegacy.app/documentation/errors-reference#notthebeneficiary-icl1)
* `IERC721(_nftContract).ownerOf(_tokenIdsi)` — may revert per token implementation (bubbled)
* `IERC721(_nftContract).transferFrom(tokenOwner, address(this), _tokenIdsi)` — may revert per token implementation (bubbled)

**Overrides:** None

**Function Calls:**

* [LibCryptoLegacy.getCryptoLegacyStorage()](#getcryptolegacystorage-lcl1) — LibCryptoLegacy, internal
* [LibCryptoLegacy.\_checkDistributionReady(...)](#_checkdistributionready-lcl1) — LibCryptoLegacy, internal
* [LibCryptoLegacy.\_addressToHash(address)](#_addresstohash-lcl1) — LibCryptoLegacy, internal
* [getPluginStorage()](#getpluginstorage-nlp1) — NftLegacyPlugin, internal
* `IERC721.ownerOf(uint256)` — `IERC721` *(at `_nftContract`)*, external (staticcall)
* `IERC721.transferFrom(address,address,uint256)` — `IERC721` *(at `_nftContract`)*, external

**Called by:** None (entry point)

**Gas / Complexity note:** O(n) by `_tokenIds.length`

**Example:** Guardian deposits a batch of estate NFTs into the CryptoLegacy contract once heirs are eligible.

***

### beneficiaryClaimNft (NLP1)

**Contract/Library:** NftLegacyPlugin

**Description:** Lets the designated beneficiary withdraw NFTs after the claim delay.

**Detailed Description:** Ensures token list is non-empty, confirms distribution readiness, and derives the caller’s beneficiary hash. For each NFT, it validates beneficiary ownership, enforces the configured delay relative to `distributionStartAt`, then transfers the NFT from the CryptoLegacy contract to the caller while emitting `BeneficiaryClaimNft`.

**Parameters:**

* \_nftContract (address): ERC721 contract holding the NFTs
* \_tokenIds (uint256\[], memory): Token identifiers the beneficiary is claiming

**Returns:** None

**Modifiers / Visibility / Mutability:**

* public nonpayable nonReentrant

**Access Control:**

* Restricted to the beneficiary whose hash matches the stored assignment

**Side Effects:**

* Transfers each NFT from the CryptoLegacy contract to the caller

**Emits:**

* [BeneficiaryClaimNft](https://docs.cryptolegacy.app/documentation/events-reference#beneficiaryclaimnft-nlp1) — `BeneficiaryClaimNft(address indexed nftContract, uint256 indexed tokenId, bytes32 indexed beneficiaryHash, address beneficiaryAddress)`

**Reverts if:**

* `_tokenIds.length == 0` — [`ZeroTokens()`](https://docs.cryptolegacy.app/documentation/errors-reference#zerotokens-icl1)
* Distribution not ready — [`TooEarly()`](https://docs.cryptolegacy.app/documentation/errors-reference#tooearly-icl1)
* Caller not the configured beneficiary — [`NotTheBeneficiary()`](https://docs.cryptolegacy.app/documentation/errors-reference#notthebeneficiary-icl1)
* Claim delay not elapsed — [`DistributionDelay()`](https://docs.cryptolegacy.app/documentation/errors-reference#distributiondelay-icl1)
* `IERC721(_nftContract).ownerOf(_tokenIdsi)` — may revert per token implementation (bubbled)
* `IERC721(_nftContract).transferFrom(tokenOwner, msg.sender, _tokenIdsi)` — may revert per token implementation (bubbled)

**Overrides:** None

**Function Calls:**

* [LibCryptoLegacy.getCryptoLegacyStorage()](#getcryptolegacystorage-lcl1) — LibCryptoLegacy, internal
* [LibCryptoLegacy.\_checkDistributionReady(...)](#_checkdistributionready-lcl1) — LibCryptoLegacy, internal
* [LibCryptoLegacy.\_addressToHash(address)](#_addresstohash-lcl1) — LibCryptoLegacy, internal
* [getPluginStorage()](#getpluginstorage-nlp1) — NftLegacyPlugin, internal
* `IERC721.ownerOf(uint256)` — `IERC721` *(at `_nftContract`)*, external (staticcall)
* `IERC721.transferFrom(address,address,uint256)` — `IERC721` *(at `_nftContract`)*, external

**Called by:** None (entry point)

**Gas / Complexity note:** O(n) by `_tokenIds.length`

**Example:** After the delay expires, the beneficiary redeems each assigned NFT to a beneficiary-controlled address.

***

## ReceiveEthPlugin (REP1)

### constructor (REP1)

**Contract/Library:** ReceiveEthPlugin

**Description:** Stores the WETH contract address used when wrapping received ETH.

**Detailed Description:** Initializes the plugin with the canonical WETH token that will receive wrapped balances when `wrapEthToWeth` is executed after ETH has accumulated on the CryptoLegacy diamond.

**Parameters:**

* \_weth (address): WETH contract used for wrap operations

**Returns:** None

**Modifiers / Visibility / Mutability:**

* constructor nonpayable

**Access Control:**

* Unrestricted at deployment time

**Side Effects:**

* Sets [`WETH (REP-D1)`](https://docs.cryptolegacy.app/documentation/data-structures-reference#weth-rep1-d1) once as an immutable plugin configuration value

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:** None (deployment only)

**Gas / Complexity note:** O(1)

**Example:** `new ReceiveEthPlugin(weth);`

***

### getSigs (REP1)

**Contract/Library:** ReceiveEthPlugin

**Description:** Returns the selectors exposed by the receive-ETH plugin.

**Detailed Description:** Builds the selector list used by the diamond to register this facet, including both the zero selector for empty-calldata ETH transfers and the explicit `wrapEthToWeth` entry point.

**Parameters:** None

**Returns:**

* sigs (bytes4\[], memory): Selector array containing `bytes4(0)` and `wrapEthToWeth`

**Modifiers / Visibility / Mutability:**

* external pure

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Facet-registration tooling reads `getSigs()` before wiring the plugin into the diamond.

***

### getSetupSigs (REP1)

**Contract/Library:** ReceiveEthPlugin

**Description:** Returns setup-time selectors required for the receive-ETH plugin.

**Detailed Description:** Exposes the zero selector as the only setup selector so the diamond can route empty-calldata ETH transfers into this facet immediately after installation.

**Parameters:** None

**Returns:**

* sigs (bytes4\[], memory): Selector array containing only `bytes4(0)`

**Modifiers / Visibility / Mutability:**

* external pure

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Installer checks `getSetupSigs()` to confirm the facet expects empty-calldata routing during setup.

***

### getPluginName (REP1)

**Contract/Library:** ReceiveEthPlugin

**Description:** Returns the unique plugin name string.

**Detailed Description:** Supplies the stable identifier `"receive-eth"` so governance, tooling, and frontends can label the facet consistently across deployments.

**Parameters:** None

**Returns:**

* name (string, memory): Static plugin name `"receive-eth"`

**Modifiers / Visibility / Mutability:**

* external pure

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Frontend reads `getPluginName()` to show the plugin's label in the installed-facets list.

***

### getPluginVer (REP1)

**Contract/Library:** ReceiveEthPlugin

**Description:** Returns the semantic version for the receive-ETH plugin.

**Detailed Description:** Exposes the hard-coded version `1`, allowing deployment tooling to compare the installed facet against the expected plugin release.

**Parameters:** None

**Returns:**

* version (uint16): Static plugin version `1`

**Modifiers / Visibility / Mutability:**

* external pure

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Upgrade tooling checks `getPluginVer()` before replacing an older facet.

***

### wrapEthToWeth (REP1)

**Contract/Library:** ReceiveEthPlugin

**Description:** Wraps all ETH currently held by the CryptoLegacy diamond into WETH.

**Detailed Description:** Loads CryptoLegacy storage, verifies distribution readiness for the beneficiary-facing flow, rejects zero-balance wraps, prepares WETH distribution state, deposits the full ETH balance into WETH, refreshes `lastBalance`, emits `WrapEthToWeth`, and records the transfer block number (using Arbitrum's `ArbSys` on chain `42161`).

**Parameters:** None

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external nonpayable

**Access Control:**

* Restricted: callable only when beneficiary distribution is ready

**Side Effects:**

* Reads the contract ETH balance and wraps it into WETH
* Prepares and updates WETH distribution accounting in CryptoLegacy storage
* Appends a new transfer block number to `cls.transfersGotByBlockNumber`

**Emits:**

* [WrapEthToWeth](https://docs.cryptolegacy.app/documentation/events-reference#wrapethtoweth-rep1) — `WrapEthToWeth(uint256 amount)`

**Reverts if:**

* Distribution is not ready for beneficiary actions — bubbled from `LibCryptoLegacy._checkDistributionReadyForBeneficiary(...)`
* The contract holds no ETH — [`NoEthToWrap()`](https://docs.cryptolegacy.app/documentation/errors-reference#noethtowrap-rep1)
* [IWETH.deposit()](#deposit-iweth1) fails — bubbled from the WETH implementation
* [IERC20.balanceOf(address)](/documentation/functions-reference) on `WETH` fails — bubbled from the token implementation

**Overrides:** None

**Function Calls:**

* [LibCryptoLegacy.getCryptoLegacyStorage()](#getcryptolegacystorage-lcl1) — LibCryptoLegacy, internal
* [LibCryptoLegacy.\_checkDistributionReadyForBeneficiary(ICryptoLegacy.CryptoLegacyStorage)](#_checkdistributionreadyforbeneficiary-lcl1) — LibCryptoLegacy, internal
* [LibCryptoLegacy.\_tokenPrepareToDistribute(ICryptoLegacy.CryptoLegacyStorage,address)](#_tokenpreparetodistribute-lcl1) — LibCryptoLegacy, internal
* [IWETH.deposit()](#deposit-iweth1) — IWETH, external
* `IERC20(WETH).balanceOf(address)` — IERC20, external
* `ArbSys(address(100)).arbBlockNumber()` — ArbSys, external (staticcall)

**Called by:** None (entry point)

**Gas / Complexity note:** O(1) on mainnet; O(1) plus one Arbitrum system call on chain 42161

**Example:** After a beneficiary sends ETH to the diamond with empty calldata, `wrapEthToWeth()` converts that balance into distributable WETH.

***

### receive (REP1)

**Contract/Library:** ReceiveEthPlugin

**Description:** Accepts plain ETH transfers routed into the facet by the diamond.

**Detailed Description:** Provides the payable receive hook that lets the CryptoLegacy diamond accept empty-calldata ETH transfers through this facet before the balance is later wrapped via `wrapEthToWeth`.

**Parameters:** None

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external payable

**Access Control:**

* Unrestricted

**Side Effects:**

* Increases the ETH balance held by the diamond/facet context

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:** None (ETH receive hook)

**Gas / Complexity note:** O(1)

**Example:** Triggered implicitly when a beneficiary sends ETH to the diamond with empty calldata after the plugin has registered selector `0x00000000`.

***

## TrustedGuardiansPlugin (TGP1)

### getSigs (TGP1)

**Contract/Library:** TrustedGuardiansPlugin

**Description:** Enumerates every externally exposed selector for guardian management.

**Detailed Description:** Allocates a 9-element selector array covering guardian setup, voting, treasury transfers, and data getters so the diamond router can wire this facet.

**Parameters:** None

**Returns:**

* sigs (bytes4\[], memory): Selector list for all TrustedGuardiansPlugin entry points

**Modifiers / Visibility / Mutability:**

* external pure

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:** None (entry point)

**Gas / Complexity note:** O(1) — fixed-length selector assembly

**Example:** Plugins registry queries selectors before registering the guardians facet.

***

### getSetupSigs (TGP1)

**Contract/Library:** TrustedGuardiansPlugin

**Description:** Reports setup-time selectors that the facet expects during installation.

**Detailed Description:** Returns a single-element array containing `isGuardiansInitialized`, signalling setup processes that should run via static calls.

**Parameters:** None

**Returns:**

* sigs (bytes4\[], memory): Array containing the selector for \`isGuardiansInitialized\`

**Modifiers / Visibility / Mutability:**

* external pure

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Deployment script schedules a static call to confirm guardians were set up.

***

### getPluginName (TGP1)

**Contract/Library:** TrustedGuardiansPlugin

**Description:** Returns the facet’s human-readable identifier.

**Detailed Description:** Supplies the static name `"trusted_guardians"`, letting dashboards label this plugin consistently.

**Parameters:** None

**Returns:**

* name (string, memory): Constant plugin name "trusted\_guardians"

**Modifiers / Visibility / Mutability:**

* external pure

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Frontend displays the plugin name in guardian configuration panels.

***

### getPluginVer (TGP1)

**Contract/Library:** TrustedGuardiansPlugin

**Description:** Exposes the semantic version of the guardians facet.

**Detailed Description:** Returns the encoded version `1`, allowing upgrade tooling to detect mismatches.

**Parameters:** None

**Returns:**

* version (uint16): Constant version identifier 1

**Modifiers / Visibility / Mutability:**

* external pure

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Monitoring alerts if the deployed guardians facet version differs from expectations.

***

### modifier onlyOwner (TGP1)

**Contract/Library:** TrustedGuardiansPlugin

**Description:** Restricts execution to the CryptoLegacy owner prior to distribution start.

**Detailed Description:** Delegates to `LibCryptoLegacy._checkOwner()` to ensure distribution has not begun, the initial fee is settled, and the caller is the diamond owner before letting the wrapped function run.

**Parameters:** None

**Returns:** None

**Modifiers / Visibility / Mutability:**

* modifier nonpayable

**Access Control:**

* Enforced by the modifier itself

**Side Effects:** None

**Emits:** None

**Reverts if:**

* Distribution already started — [`ICryptoLegacy.DistributionStarted()`](https://docs.cryptolegacy.app/documentation/errors-reference#distributionstarted-icl1)
* Initial fee unpaid — [`ICryptoLegacy.InitialFeeNotPaid()`](https://docs.cryptolegacy.app/documentation/errors-reference#initialfeenotpaid-icl1)
* Caller is not the owner — [`ICryptoLegacy.NotTheOwner()`](https://docs.cryptolegacy.app/documentation/errors-reference#nottheowner-icl1)

**Overrides:** None

**Function Calls:**

* [LibCryptoLegacy.\_checkOwner()](#_checkowner-lcl1) — LibCryptoLegacy, internal

**Called by:**

* [initializeGuardians](#initializeguardians-tgp1) — TrustedGuardiansPlugin
* [setGuardians](#setguardians-tgp1) — TrustedGuardiansPlugin
* [setGuardiansConfig](#setguardiansconfig-tgp1) — TrustedGuardiansPlugin
* [resetGuardianVoting](#resetguardianvoting-tgp1) — TrustedGuardiansPlugin

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### \_isGuardianVoted (TGP1)

**Contract/Library:** TrustedGuardiansPlugin

**Description:** Checks whether a guardian hash already appears in the vote ledger.

**Detailed Description:** Iterates through `guardiansVoted`; when the explicit guardians set is empty it drops hashes no longer present in beneficiaries before returning true once it encounters the caller’s hash.

**Parameters:**

* cls (ICryptoLegacy.CryptoLegacyStorage, storage): Core CryptoLegacy storage
* \_pluginStorage (ITrustedGuardiansPlugin.PluginStorage, storage): Guardians plugin storage
* \_hash (bytes32): Guardian hash derived from the caller

**Returns:**

* isVoted (bool): True if the guardian has an existing vote recorded

**Modifiers / Visibility / Mutability:**

* internal nonpayable

**Access Control:**

* Unrestricted (internal)

**Side Effects:**

* Removes stale guardian hashes from `guardiansVoted` when the explicit guardian set is empty and the beneficiary fallback no longer recognises the voter

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [\_checkGuardianAndRemoveInvalid(ICryptoLegacy.CryptoLegacyStorage,ITrustedGuardiansPlugin.PluginStorage,bool,uint256)](#_checkguardianandremoveinvalid-tgp1) — TrustedGuardiansPlugin, internal

**Called by:**

* [\_checkGuardianNotVoted()](#_checkguardiannotvoted-tgp1) — TrustedGuardiansPlugin
* [checkGuardiansVotedAndGetGuardiansData](#checkguardiansvotedandgetguardiansdata-tgp1) — TrustedGuardiansPlugin

**Gas / Complexity note:** O(v) by current `guardiansVoted.length`

**Example:** Not applicable

***

### \_checkGuardianAndRemoveInvalid (TGP1)

**Contract/Library:** TrustedGuardiansPlugin

**Description:** Validates a stored guardian vote and prunes it if the guardian is no longer recognised.

**Detailed Description:** Loads the vote at `_index`; if guardians are being inferred from beneficiaries and the voter is no longer a beneficiary, the entry is swapped with the array tail and popped. Returns the inspected guardian hash alongside whether it was removed.

**Parameters:**

* cls (ICryptoLegacy.CryptoLegacyStorage, storage): Core storage used to check beneficiary membership
* \_pluginStorage (ITrustedGuardiansPlugin.PluginStorage, storage): Guardians plugin storage
* \_isInitialized (bool): True when an explicit guardian set exists
* \_index (uint256): Position within `guardiansVoted` to inspect

**Returns:**

* guardianToCheck (bytes32): Guardian hash from the vote entry
* isRemoved (bool): True if the entry was deleted during the check

**Modifiers / Visibility / Mutability:**

* internal nonpayable

**Access Control:**

* Unrestricted (internal)

**Side Effects:**

* Mutates `guardiansVoted` when removing obsolete entries

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:**

* [\_isGuardianVoted(ICryptoLegacy.CryptoLegacyStorage,ITrustedGuardiansPlugin.PluginStorage,bytes32)](#_isguardianvoted-tgp1) — TrustedGuardiansPlugin

**Gas / Complexity note:** O(1) per invocation (swap-and-pop)

**Example:** Not applicable

***

### \_checkGuardian (TGP1)

**Contract/Library:** TrustedGuardiansPlugin

**Description:** Ensures the caller is a registered guardian and the contract has paid its initial fee.

**Detailed Description:** Retrieves core and plugin storage, hashes `msg.sender`, confirms the hash exists within the guardian set (explicit or beneficiary fallback), and verifies that `lastFeePaidAt` is non-zero. Returns the storage references and hash for downstream calls.

**Parameters:** None

**Returns:**

* cls (ICryptoLegacy.CryptoLegacyStorage, storage): Core CryptoLegacy storage pointer
* pluginStorage (ITrustedGuardiansPlugin.PluginStorage, storage): Guardians plugin storage pointer
* hash (bytes32): Guardian identifier for the caller

**Modifiers / Visibility / Mutability:**

* internal view

**Access Control:**

* Unrestricted (internal)

**Side Effects:** None

**Emits:** None

**Reverts if:**

* Caller hash not listed as guardian — [`NotGuardian()`](https://docs.cryptolegacy.app/documentation/errors-reference#notguardian-itgp1)
* Initial fee unpaid — [`ICryptoLegacy.InitialFeeNotPaid()`](https://docs.cryptolegacy.app/documentation/errors-reference#initialfeenotpaid-icl1)

**Overrides:** None

**Function Calls:**

* [LibCryptoLegacy.getCryptoLegacyStorage()](#getcryptolegacystorage-lcl1) — LibCryptoLegacy, internal
* [LibTrustedGuardiansPlugin.getPluginStorage()](#getpluginstorage-ltgp1) — LibTrustedGuardiansPlugin, internal
* [LibCryptoLegacy.\_addressToHash(address)](#_addresstohash-lcl1) — LibCryptoLegacy, internal
* [\_getGuardians(ICryptoLegacy.CryptoLegacyStorage,ITrustedGuardiansPlugin.PluginStorage)](#_getguardians-tgp1) — TrustedGuardiansPlugin, internal

**Called by:**

* [\_checkGuardianNotVoted()](#_checkguardiannotvoted-tgp1) — TrustedGuardiansPlugin
* [guardiansTransferTreasuryTokensToLegacy](#guardianstransfertreasurytokenstolegacy-tgp1) — TrustedGuardiansPlugin
* [checkGuardiansVotedAndGetGuardiansData](#checkguardiansvotedandgetguardiansdata-tgp1) — TrustedGuardiansPlugin

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### \_checkGuardianNotVoted (TGP1)

**Contract/Library:** TrustedGuardiansPlugin

**Description:** Validates that the caller is an authorised guardian who has not yet voted.

**Detailed Description:** Invokes `_checkGuardian` to gather storage references and the caller hash, then consults `_isGuardianVoted`. If the guardian already has an active vote, the call reverts.

**Parameters:** None

**Returns:**

* cls (ICryptoLegacy.CryptoLegacyStorage, storage): Core storage pointer
* pluginStorage (ITrustedGuardiansPlugin.PluginStorage, storage): Guardians plugin storage pointer
* hash (bytes32): Guardian hash of the caller

**Modifiers / Visibility / Mutability:**

* internal nonpayable

**Access Control:**

* Unrestricted (internal)

**Side Effects:**

* Relies on [\_isGuardianVoted](#_isguardianvoted-tgp1) which may prune stale votes

**Emits:** None

**Reverts if:**

* Caller hash not listed as guardian — [`NotGuardian()`](https://docs.cryptolegacy.app/documentation/errors-reference#notguardian-itgp1)
* Initial fee unpaid — [`ICryptoLegacy.InitialFeeNotPaid()`](https://docs.cryptolegacy.app/documentation/errors-reference#initialfeenotpaid-icl1)
* Guardian already has an active vote — [`GuardianAlreadyVoted()`](https://docs.cryptolegacy.app/documentation/errors-reference#guardianalreadyvoted-itgp1)

**Overrides:** None

**Function Calls:**

* [\_checkGuardian()](#_checkguardian-tgp1) — TrustedGuardiansPlugin, internal
* [\_isGuardianVoted(ICryptoLegacy.CryptoLegacyStorage,ITrustedGuardiansPlugin.PluginStorage,bytes32)](#_isguardianvoted-tgp1) — TrustedGuardiansPlugin, internal

**Called by:**

* [guardiansVoteForDistribution](#guardiansvotefordistribution-tgp1) — TrustedGuardiansPlugin

**Gas / Complexity note:** O(v) due to the underlying vote scan

**Example:** Not applicable

***

### \_getGuardians (TGP1)

**Contract/Library:** TrustedGuardiansPlugin

**Description:** Resolves the active guardian set, falling back to beneficiaries when no explicit list exists.

**Detailed Description:** Returns the plugin’s guardian `EnumerableSet` unless it is empty, in which case it surfaces the core beneficiaries set as the implicit guardian pool.

**Parameters:**

* \_cls (ICryptoLegacy.CryptoLegacyStorage, storage): Core CryptoLegacy storage
* \_pluginStorage (ITrustedGuardiansPlugin.PluginStorage, storage): Guardians plugin storage

**Returns:**

* guardians (EnumerableSet.Bytes32Set, storage): Storage reference to the active guardian set

**Modifiers / Visibility / Mutability:**

* internal view

**Access Control:**

* Unrestricted (internal)

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:**

* [\_getGuardiansThreshold(ICryptoLegacy.CryptoLegacyStorage,ITrustedGuardiansPlugin.PluginStorage)](#_getguardiansthreshold-tgp1) — TrustedGuardiansPlugin
* [\_afterGuardiansSet(ICryptoLegacy.CryptoLegacyStorage,ITrustedGuardiansPlugin.PluginStorage)](#_afterguardiansset-tgp1) — TrustedGuardiansPlugin
* [getGuardiansData](#getguardiansdata-tgp1) — TrustedGuardiansPlugin
* [checkGuardiansVotedAndGetGuardiansData](#checkguardiansvotedandgetguardiansdata-tgp1) — TrustedGuardiansPlugin
* [\_checkGuardian()](#_checkguardian-tgp1) — TrustedGuardiansPlugin

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### \_getGuardiansThreshold (TGP1)

**Contract/Library:** TrustedGuardiansPlugin

**Description:** Computes the effective vote threshold for guardians.

**Detailed Description:** Derives the guardian set length and, if no custom threshold is stored, calculates the default quorum through `LibSafeMinimalMultisig._calcDefaultConfirmations`. Caps stored threshold at the guardian count.

**Parameters:**

* \_cls (ICryptoLegacy.CryptoLegacyStorage, storage): Core storage used to fetch beneficiaries when required
* \_pluginStorage (ITrustedGuardiansPlugin.PluginStorage, storage): Guardians plugin storage

**Returns:**

* guardiansThreshold (uint128): Required confirmations for a guardian-triggered distribution

**Modifiers / Visibility / Mutability:**

* internal view

**Access Control:**

* Unrestricted (internal)

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [\_getGuardians(ICryptoLegacy.CryptoLegacyStorage,ITrustedGuardiansPlugin.PluginStorage)](#_getguardians-tgp1) — TrustedGuardiansPlugin, internal
* [LibSafeMinimalMultisig.\_calcDefaultConfirmations(uint128)](#_calcdefaultconfirmations-lsm1) — LibSafeMinimalMultisig, internal

**Called by:**

* [guardiansVoteForDistribution](#guardiansvotefordistribution-tgp1) — TrustedGuardiansPlugin
* [getGuardiansData](#getguardiansdata-tgp1) — TrustedGuardiansPlugin
* [checkGuardiansVotedAndGetGuardiansData](#checkguardiansvotedandgetguardiansdata-tgp1) — TrustedGuardiansPlugin

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### \_getGuardiansChallengeTimeout (TGP1)

**Contract/Library:** TrustedGuardiansPlugin

**Description:** Retrieves the challenge timeout applied once guardians reach quorum.

**Detailed Description:** Returns the stored timeout if a custom threshold exists; otherwise falls back to the [`DEFAULT_GUARDIANS_CHALLENGE_TIMEOUT`](https://docs.cryptolegacy.app/documentation/data-structures-reference#default_guardians_challenge_timeout-tgp1-d1) constant (30 days).

**Parameters:**

* \_pluginStorage (ITrustedGuardiansPlugin.PluginStorage, storage): Guardians plugin storage

**Returns:**

* guardiansChallengeTimeout (uint64): Timeout in seconds appended before distribution activation

**Modifiers / Visibility / Mutability:**

* internal view

**Access Control:**

* Unrestricted (internal)

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:**

* [guardiansVoteForDistribution](#guardiansvotefordistribution-tgp1) — TrustedGuardiansPlugin
* [getGuardiansData](#getguardiansdata-tgp1) — TrustedGuardiansPlugin
* [checkGuardiansVotedAndGetGuardiansData](#checkguardiansvotedandgetguardiansdata-tgp1) — TrustedGuardiansPlugin

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### initializeGuardians (TGP1)

**Contract/Library:** TrustedGuardiansPlugin

**Description:** Configures the guardian roster, threshold, and challenge timeout in a single owner call.

**Detailed Description:** Loads plugin and core storage, applies the supplied guardian changes via `_setGuardians`, writes the threshold and timeout through `_setGuardiansConfig`, and finally validates threshold bounds and clears existing votes by calling `_afterGuardiansSet`.

**Parameters:**

* \_guardians (GuardianToChange\[], memory): Guardians to add or remove
* \_guardiansThreshold (uint128): Required confirmations; zero derives a default
* \_guardiansChallengeTimeout (uint64): Timeout (seconds) added once quorum is reached

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external nonpayable onlyOwner nonReentrant

**Access Control:**

* Owner only

**Side Effects:**

* Updates the guardian set and registry entries
* Stores a new threshold and challenge timeout
* Resets `guardiansVoted`

**Emits:**

* [BeneficiaryRegistryNotDefined](https://docs.cryptolegacy.app/documentation/events-reference#beneficiaryregistrynotdefined-icl1) — `BeneficiaryRegistryNotDefined()` (conditional when registry address not set)
* [SetCryptoLegacyGuardianCatch](https://docs.cryptolegacy.app/documentation/events-reference#setcryptolegacyguardiancatch-icl1) — `SetCryptoLegacyGuardianCatch(bytes reason)` (conditional when registry update reverts)
* [SetGuardian](https://docs.cryptolegacy.app/documentation/events-reference#setguardian-itgp1) — `SetGuardian(bytes32 indexed guardian, bool indexed _isAdd)` (per guardian change)
* [SetGuardiansConfig](https://docs.cryptolegacy.app/documentation/events-reference#setguardiansconfig-itgp1) — `SetGuardiansConfig(uint128 guardiansThreshold, uint64 guardiansChallengeTimeout)`
* [ClearGuardiansVoted](https://docs.cryptolegacy.app/documentation/events-reference#clearguardiansvoted-itgp1) — `ClearGuardiansVoted()`

**Reverts if:**

* Distribution already started — [`ICryptoLegacy.DistributionStarted()`](https://docs.cryptolegacy.app/documentation/errors-reference#distributionstarted-icl1)
* Initial fee unpaid — [`ICryptoLegacy.InitialFeeNotPaid()`](https://docs.cryptolegacy.app/documentation/errors-reference#initialfeenotpaid-icl1)
* Caller is not the owner — [`ICryptoLegacy.NotTheOwner()`](https://docs.cryptolegacy.app/documentation/errors-reference#nottheowner-icl1)
* Guardian hash is zero — [`ZeroGuardian()`](https://docs.cryptolegacy.app/documentation/errors-reference#zeroguardian-itgp1)
* Challenge timeout exceeds the cap — [`MaxGuardiansTimeout(uint64)`](https://docs.cryptolegacy.app/documentation/errors-reference#maxguardianstimeout-itgp1)
* Challenge timeout is zero — [`GuardiansTimeoutCantBeZero()`](https://docs.cryptolegacy.app/documentation/errors-reference#guardianstimeoutcantbezero-itgp1)
* Threshold exceeds guardian count — [`ThresholdTooBig()`](https://docs.cryptolegacy.app/documentation/errors-reference#thresholdtoobig-itgp1)
* Reentrant call detected — "ReentrancyGuard: reentrant call"

**Overrides:** None

**Function Calls:**

* [LibTrustedGuardiansPlugin.getPluginStorage()](#getpluginstorage-ltgp1) — LibTrustedGuardiansPlugin, internal
* [LibCryptoLegacy.getCryptoLegacyStorage()](#getcryptolegacystorage-lcl1) — LibCryptoLegacy, internal
* [\_setGuardians(ICryptoLegacy.CryptoLegacyStorage,ITrustedGuardiansPlugin.PluginStorage,GuardianToChange\[\])](#_setguardians-tgp1) — TrustedGuardiansPlugin, internal
* [\_setGuardians(ICryptoLegacy.CryptoLegacyStorage,ITrustedGuardiansPlugin.PluginStorage,GuardianToChange\[\])](#_setguardiansconfig-tgp1) — TrustedGuardiansPlugin, internal
* [\_afterGuardiansSet(ICryptoLegacy.CryptoLegacyStorage,ITrustedGuardiansPlugin.PluginStorage)](#_afterguardiansset-tgp1) — TrustedGuardiansPlugin, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(g) by `_guardians.length`

**Example:** Owner bootstraps a dedicated guardian council with a custom quorum and timeout.

***

### setGuardians (TGP1)

**Contract/Library:** TrustedGuardiansPlugin

**Description:** Updates the guardian membership without touching threshold configuration.

**Detailed Description:** Fetches plugin and core storage, iterates `_guardians` to add or remove entries via `_setGuardians`, then validates the stored threshold and clears existing votes by calling `_afterGuardiansSet`.

**Parameters:**

* \_guardians (GuardianToChange\[], memory): Guardians to add (isAdd=true) or remove (false)

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external nonpayable onlyOwner nonReentrant

**Access Control:**

* Owner only

**Side Effects:**

* Updates the guardians set and beneficiary registry
* Clears `guardiansVoted`

**Emits:**

* [BeneficiaryRegistryNotDefined](https://docs.cryptolegacy.app/documentation/events-reference#beneficiaryregistrynotdefined-icl1) — `BeneficiaryRegistryNotDefined()` (conditional when registry address not set)
* [SetCryptoLegacyGuardianCatch](https://docs.cryptolegacy.app/documentation/events-reference#setcryptolegacyguardiancatch-icl1) — `SetCryptoLegacyGuardianCatch(bytes reason)` (conditional when registry update reverts)
* [SetGuardian](https://docs.cryptolegacy.app/documentation/events-reference#setguardian-itgp1) — `SetGuardian(bytes32 indexed guardian, bool indexed _isAdd)`
* [ClearGuardiansVoted](https://docs.cryptolegacy.app/documentation/events-reference#clearguardiansvoted-itgp1) — `ClearGuardiansVoted()`

**Reverts if:**

* Distribution already started — [`ICryptoLegacy.DistributionStarted()`](https://docs.cryptolegacy.app/documentation/errors-reference#distributionstarted-icl1)
* Initial fee unpaid — [`ICryptoLegacy.InitialFeeNotPaid()`](https://docs.cryptolegacy.app/documentation/errors-reference#initialfeenotpaid-icl1)
* Caller is not the owner — [`ICryptoLegacy.NotTheOwner()`](https://docs.cryptolegacy.app/documentation/errors-reference#nottheowner-icl1)
* Guardian hash is zero — [`ZeroGuardian()`](https://docs.cryptolegacy.app/documentation/errors-reference#zeroguardian-itgp1)
* Threshold exceeds updated guardian count — [`ThresholdTooBig()`](https://docs.cryptolegacy.app/documentation/errors-reference#thresholdtoobig-itgp1)
* Reentrant call detected — "ReentrancyGuard: reentrant call"

**Overrides:** None

**Function Calls:**

* [LibTrustedGuardiansPlugin.getPluginStorage()](#getpluginstorage-ltgp1) — LibTrustedGuardiansPlugin, internal
* [LibCryptoLegacy.getCryptoLegacyStorage()](#getcryptolegacystorage-lcl1) — LibCryptoLegacy, internal
* [\_setGuardians(ICryptoLegacy.CryptoLegacyStorage,ITrustedGuardiansPlugin.PluginStorage,GuardianToChange\[\])](#_setguardians-tgp1) — TrustedGuardiansPlugin, internal
* [\_afterGuardiansSet(ICryptoLegacy.CryptoLegacyStorage,ITrustedGuardiansPlugin.PluginStorage)](#_afterguardiansset-tgp1) — TrustedGuardiansPlugin, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(g) by `_guardians.length`

**Example:** Owner rotates a guardian hash after a multisig participant change.

***

### \_setGuardians (TGP1)

**Contract/Library:** TrustedGuardiansPlugin

**Description:** Internal helper that mutates the guardian set and beneficiary registry.

**Detailed Description:** Iterates over `_guardians`, ensuring each hash is non-zero, then inserts or removes it from the plugin’s `guardians` set while notifying the `BeneficiaryRegistry` via LibCryptoLegacy.\_setCryptoLegacyToBeneficiaryRegistry(#\_setcryptolegacytobeneficiaryregistry-lcl1). Emits `SetGuardian` for each change.

**Parameters:**

* cls (ICryptoLegacy.CryptoLegacyStorage, storage): Core storage used for registry updates
* \_pluginStorage (ITrustedGuardiansPlugin.PluginStorage, storage): Guardians plugin storage
* \_guardians (GuardianToChange\[], memory): Guardian operations to apply

**Returns:** None

**Modifiers / Visibility / Mutability:**

* internal nonpayable

**Access Control:**

* Unrestricted (internal)

**Side Effects:**

* Adds or removes guardians from the plugin set
* Synchronises guardian status with the BeneficiaryRegistry

**Emits:**

* [BeneficiaryRegistryNotDefined](https://docs.cryptolegacy.app/documentation/events-reference#beneficiaryregistrynotdefined-icl1) — `BeneficiaryRegistryNotDefined()` (conditional when registry address not set)
* [SetCryptoLegacyGuardianCatch](https://docs.cryptolegacy.app/documentation/events-reference#setcryptolegacyguardiancatch-icl1) — `SetCryptoLegacyGuardianCatch(bytes reason)` (conditional when registry update reverts)
* [SetGuardian](https://docs.cryptolegacy.app/documentation/events-reference#setguardian-itgp1) — `SetGuardian(bytes32 indexed guardian, bool indexed _isAdd)`

**Reverts if:**

* Guardian hash is zero — [`ZeroGuardian()`](https://docs.cryptolegacy.app/documentation/errors-reference#zeroguardian-itgp1)

**Overrides:** None

**Function Calls:**

* [LibCryptoLegacy.\_setCryptoLegacyToBeneficiaryRegistry(...)](#_setcryptolegacytobeneficiaryregistry-lcl1) — LibCryptoLegacy, internal

**Called by:**

* [initializeGuardians](#initializeguardians-tgp1) — TrustedGuardiansPlugin
* [setGuardians](#setguardians-tgp1) — TrustedGuardiansPlugin

**Gas / Complexity note:** O(g) by `_guardians.length`

**Example:** Not applicable

***

### setGuardiansConfig (TGP1)

**Contract/Library:** TrustedGuardiansPlugin

**Description:** Updates guardian quorum configuration while preserving the existing guardian list.

**Detailed Description:** Retrieves plugin storage, applies the new threshold and challenge timeout via `_setGuardiansConfig`, and then clears vote state with `_afterGuardiansSet` using the latest configuration.

**Parameters:**

* \_guardiansThreshold (uint128): Required confirmations; zero applies the default
* \_guardiansChallengeTimeout (uint64): Timeout (seconds) applied once quorum is met

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external nonpayable onlyOwner nonReentrant

**Access Control:**

* Owner only

**Side Effects:**

* Stores new quorum settings
* Resets guardian voting progress

**Emits:**

* [SetGuardiansConfig](https://docs.cryptolegacy.app/documentation/events-reference#setguardiansconfig-itgp1) — `SetGuardiansConfig(uint128 guardiansThreshold, uint64 guardiansChallengeTimeout)`
* [ClearGuardiansVoted](https://docs.cryptolegacy.app/documentation/events-reference#clearguardiansvoted-itgp1) — `ClearGuardiansVoted()`

**Reverts if:**

* Distribution already started — [`ICryptoLegacy.DistributionStarted()`](https://docs.cryptolegacy.app/documentation/errors-reference#distributionstarted-icl1)
* Initial fee unpaid — [`ICryptoLegacy.InitialFeeNotPaid()`](https://docs.cryptolegacy.app/documentation/errors-reference#initialfeenotpaid-icl1)
* Caller is not the owner — [`ICryptoLegacy.NotTheOwner()`](https://docs.cryptolegacy.app/documentation/errors-reference#nottheowner-icl1)
* Challenge timeout exceeds the cap — [`MaxGuardiansTimeout(uint64)`](https://docs.cryptolegacy.app/documentation/errors-reference#maxguardianstimeout-itgp1)
* Challenge timeout is zero — [`GuardiansTimeoutCantBeZero()`](https://docs.cryptolegacy.app/documentation/errors-reference#guardianstimeoutcantbezero-itgp1)
* Threshold exceeds guardian count — [`ThresholdTooBig()`](https://docs.cryptolegacy.app/documentation/errors-reference#thresholdtoobig-itgp1)

**Overrides:** None

**Function Calls:**

* [LibTrustedGuardiansPlugin.getPluginStorage()](#getpluginstorage-ltgp1) — LibTrustedGuardiansPlugin, internal
* [\_setGuardians(ICryptoLegacy.CryptoLegacyStorage,ITrustedGuardiansPlugin.PluginStorage,GuardianToChange\[\])](#_setguardiansconfig-tgp1) — TrustedGuardiansPlugin, internal
* [LibCryptoLegacy.getCryptoLegacyStorage()](#getcryptolegacystorage-lcl1) — LibCryptoLegacy, internal
* [\_afterGuardiansSet(ICryptoLegacy.CryptoLegacyStorage,ITrustedGuardiansPlugin.PluginStorage)](#_afterguardiansset-tgp1) — TrustedGuardiansPlugin, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Owner tightens the required guardian quorum after expanding council membership.

***

### \_setGuardiansConfig (TGP1)

**Contract/Library:** TrustedGuardiansPlugin

**Description:** Writes guardian threshold and timeout parameters with validation.

**Detailed Description:** Checks that the challenge timeout is non-zero and not above [`MAX_GUARDIANS_CHALLENGE_TIMEOUT`](https://docs.cryptolegacy.app/documentation/data-structures-reference#max_guardians_challenge_timeout-tgp1-d2), updates storage fields, and emits `SetGuardiansConfig`.

**Parameters:**

* \_pluginStorage (ITrustedGuardiansPlugin.PluginStorage, storage): Guardians plugin storage
* \_guardiansThreshold (uint128): Required confirmations
* \_guardiansChallengeTimeout (uint64): Challenge timeout in seconds

**Returns:** None

**Modifiers / Visibility / Mutability:**

* internal nonpayable

**Access Control:**

* Unrestricted (internal)

**Side Effects:**

* Updates stored threshold and timeout values

**Emits:**

* [SetGuardiansConfig](https://docs.cryptolegacy.app/documentation/events-reference#setguardiansconfig-itgp1) — `SetGuardiansConfig(uint128 guardiansThreshold, uint64 guardiansChallengeTimeout)`

**Reverts if:**

* Challenge timeout exceeds the cap — [`MaxGuardiansTimeout(uint64)`](https://docs.cryptolegacy.app/documentation/errors-reference#maxguardianstimeout-itgp1)
* Challenge timeout is zero — [`GuardiansTimeoutCantBeZero()`](https://docs.cryptolegacy.app/documentation/errors-reference#guardianstimeoutcantbezero-itgp1)

**Overrides:** None

**Function Calls:** None

**Called by:**

* [initializeGuardians](#initializeguardians-tgp1) — TrustedGuardiansPlugin
* [setGuardiansConfig](#setguardiansconfig-tgp1) — TrustedGuardiansPlugin

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### \_afterGuardiansSet (TGP1)

**Contract/Library:** TrustedGuardiansPlugin

**Description:** Validates quorum bounds and clears guardian vote progress.

**Detailed Description:** Ensures the stored threshold does not exceed the current guardian count, resets `guardiansVoted` to an empty array, and emits `ClearGuardiansVoted`.

**Parameters:**

* cls (ICryptoLegacy.CryptoLegacyStorage, storage): Core storage reference
* \_pluginStorage (ITrustedGuardiansPlugin.PluginStorage, storage): Guardians plugin storage

**Returns:** None

**Modifiers / Visibility / Mutability:**

* internal nonpayable

**Access Control:**

* Unrestricted (internal)

**Side Effects:**

* Verifies threshold fits guardian count
* Clears the `guardiansVoted` array

**Emits:**

* [ClearGuardiansVoted](https://docs.cryptolegacy.app/documentation/events-reference#clearguardiansvoted-itgp1) — `ClearGuardiansVoted()`

**Reverts if:**

* Threshold exceeds guardian count — [`ThresholdTooBig()`](https://docs.cryptolegacy.app/documentation/errors-reference#thresholdtoobig-itgp1)

**Overrides:** None

**Function Calls:**

* [\_getGuardians(ICryptoLegacy.CryptoLegacyStorage,ITrustedGuardiansPlugin.PluginStorage)](#_getguardians-tgp1) — TrustedGuardiansPlugin, internal

**Called by:**

* [initializeGuardians](#initializeguardians-tgp1) — TrustedGuardiansPlugin
* [setGuardians](#setguardians-tgp1) — TrustedGuardiansPlugin
* [setGuardiansConfig](#setguardiansconfig-tgp1) — TrustedGuardiansPlugin

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### guardiansVoteForDistribution (TGP1)

**Contract/Library:** TrustedGuardiansPlugin

**Description:** Records a guardian vote and optionally accelerates distribution start.

**Detailed Description:** Verifies the caller is an unactioned guardian, appends their hash to `guardiansVoted`, computes the active threshold and challenge timeout, and when quorum is met updates `distributionStartAt` (capped sooner) before clearing the vote array. Emits vote and, when applicable, distribution events.

**Parameters:** None

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external nonpayable nonReentrant

**Access Control:**

* Guardians with initial fee paid

**Side Effects:**

* Appends the caller hash to `guardiansVoted`
* May update `distributionStartAt` and reset vote history

**Emits:**

* [GuardiansDistributionStartSet](https://docs.cryptolegacy.app/documentation/events-reference#guardiansdistributionstartset-itgp1) — `GuardiansDistributionStartSet(bytes32 indexed guardian, uint256 distributionStartAt)` (on quorum)
* [GuardiansVoteForDistribution](https://docs.cryptolegacy.app/documentation/events-reference#guardiansvotefordistribution-itgp1) — `GuardiansVoteForDistribution(bytes32 indexed guardian, uint256 votedCount)`

**Reverts if:**

* Caller hash not listed as guardian — [`NotGuardian()`](https://docs.cryptolegacy.app/documentation/errors-reference#notguardian-itgp1)
* Initial fee unpaid — [`ICryptoLegacy.InitialFeeNotPaid()`](https://docs.cryptolegacy.app/documentation/errors-reference#initialfeenotpaid-icl1)
* Guardian already has an active vote — [`GuardianAlreadyVoted()`](https://docs.cryptolegacy.app/documentation/errors-reference#guardianalreadyvoted-itgp1)

**Overrides:** None

**Function Calls:**

* [\_checkGuardianNotVoted()](#_checkguardiannotvoted-tgp1) — TrustedGuardiansPlugin, internal
* [\_getGuardiansThreshold(ICryptoLegacy.CryptoLegacyStorage,ITrustedGuardiansPlugin.PluginStorage)](#_getguardiansthreshold-tgp1) — TrustedGuardiansPlugin, internal
* [\_getGuardiansChallengeTimeout(ITrustedGuardiansPlugin.PluginStorage)](#_getguardianschallengetimeout-tgp1) — TrustedGuardiansPlugin, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(v) by current vote count

**Example:** Guardian casts a vote to start distribution, potentially triggering the start timer when quorum is met.

***

### guardiansTransferTreasuryTokensToLegacy (TGP1)

**Contract/Library:** TrustedGuardiansPlugin

**Description:** Allows guardians to move treasury ERC20 balances into the CryptoLegacy contract once distribution is live.

**Detailed Description:** Confirms the caller is a guardian, checks that distribution has begun, then forwards `_holders` and `_tokens` to LibCryptoLegacy.\_transferTreasuryTokensToLegacy(#\_transfertreasurytokenstolegacy-lcl1), which sweeps allowances and updates distribution accounting.

**Parameters:**

* \_holders (address\[], memory): Addresses whose ERC20 balances should be transferred
* \_tokens (address\[], memory): Token contracts to sweep into the CryptoLegacy contract

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external nonpayable nonReentrant

**Access Control:**

* Guardians with initial fee paid and distribution started

**Side Effects:**

* Transfers ERC20 balances from specified holders to the CryptoLegacy contract
* Updates token distribution tracking and transfer history

**Emits:**

* [TransferTreasuryTokensToLegacy](https://docs.cryptolegacy.app/documentation/events-reference#transfertreasurytokenstolegacy-icl1) — `TransferTreasuryTokensToLegacy(address[] holders, address[] tokens)`

**Reverts if:**

* Caller hash not listed as guardian — [`NotGuardian()`](https://docs.cryptolegacy.app/documentation/errors-reference#notguardian-itgp1)
* Initial fee unpaid — [`ICryptoLegacy.InitialFeeNotPaid()`](https://docs.cryptolegacy.app/documentation/errors-reference#initialfeenotpaid-icl1)
* Distribution not ready — [`TooEarly()`](https://docs.cryptolegacy.app/documentation/errors-reference#tooearly-icl1)
* `IERC20(_tokensi).balanceOf(_holdersj)` — may revert per token implementation
* `IERC20(_tokensi).transferFrom(_holdersj, address(this), availableBalance)` — may revert per token implementation (via SafeERC20)

**Overrides:** None

**Function Calls:**

* [\_checkGuardian()](#_checkguardian-tgp1) — TrustedGuardiansPlugin, internal
* [LibCryptoLegacy.\_checkDistributionReady(ICryptoLegacy.CryptoLegacyStorage)](#_checkdistributionready-lcl1) — LibCryptoLegacy, internal
* [\_transferTreasuryTokensToLegacy(ICryptoLegacy.CryptoLegacyStorage,address\[\],address\[\])](#_transfertreasurytokenstolegacy-lcl1) — LibCryptoLegacy, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(t·h) where t = `_tokens.length`, h = `_holders.length`

**Example:** Guardians sweep remaining treasury balances into the CryptoLegacy contract after distribution opens.

***

### resetGuardianVoting (TGP1)

**Contract/Library:** TrustedGuardiansPlugin

**Description:** Owner-controlled reset that clears guardian votes, resets distribution start, and processes the upkeep fee.

**Detailed Description:** Retrieves core storage and delegates to `LibTrustedGuardiansPlugin._resetGuardianVoting`, which empties `guardiansVoted`, zeroes `distributionStartAt`, and invokes the fee logic `_takeFee` with empty parameters before emitting `ResetGuardiansVoting`.

**Parameters:** None

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external payable onlyOwner nonReentrant

**Access Control:**

* Owner only

**Side Effects:**

* Clears guardian vote history and distribution start timestamp
* Triggers the standard fee payment flow via `_takeFee`

**Emits:**

* [ResetGuardiansVoting](https://docs.cryptolegacy.app/documentation/events-reference#resetguardiansvoting-itgp1) — `ResetGuardiansVoting()`
* [FeePaidByLifetime](https://docs.cryptolegacy.app/documentation/events-reference#feepaidbylifetime-icl1) — `FeePaidByLifetime(bytes8 indexed refCode, bool indexed initial, address factory, uint64 lastFeePaidAt)`
* [FeePaidByDefault](https://docs.cryptolegacy.app/documentation/events-reference#feepaidbydefault-icl1) — `FeePaidByDefault(bytes8 indexed refCode, bool indexed initial, uint256 value, uint256 returnedValue, address factory, uint64 lastFeePaidAt)`
* [FeePaidByTransfer](https://docs.cryptolegacy.app/documentation/events-reference#feepaidbytransfer-icl1) — `FeePaidByTransfer(bytes8 indexed refCode, bool indexed initial, uint256 value, address factory, uint64 lastFeePaidAt)`
* [SkipSendFeeByTransfer](https://docs.cryptolegacy.app/documentation/events-reference#skipsendfeebytransfer-icl1) — `SkipSendFeeByTransfer(address buildManagerAddress, uint256 value)`
* [GetUpdateFeeCatch](https://docs.cryptolegacy.app/documentation/events-reference#getupdatefeecatch-icl1) — `GetUpdateFeeCatch(bytes reason)`
* [PayFeeCatch](https://docs.cryptolegacy.app/documentation/events-reference#payfeecatch-icl1) — `PayFeeCatch(bytes reason)`
* [IsLifetimeNftLockedAndUpdateCatch](https://docs.cryptolegacy.app/documentation/events-reference#islifetimenftlockedandupdatecatch-icl1) — `IsLifetimeNftLockedAndUpdateCatch(bytes reason)`

**Reverts if:**

* Distribution already started — [`ICryptoLegacy.DistributionStarted()`](https://docs.cryptolegacy.app/documentation/errors-reference#distributionstarted-icl1)
* Initial fee unpaid — [`ICryptoLegacy.InitialFeeNotPaid()`](https://docs.cryptolegacy.app/documentation/errors-reference#initialfeenotpaid-icl1)
* Caller is not the owner — [`ICryptoLegacy.NotTheOwner()`](https://docs.cryptolegacy.app/documentation/errors-reference#nottheowner-icl1)
* Lifetime NFT fee coverage active while `msg.value > 0` — [`ICryptoLegacy.NoValueAllowed()`](https://docs.cryptolegacy.app/documentation/errors-reference#novalueallowed-icl1)
* Fee amount mismatches the required update fee — [`IncorrectFee(uint256)`](https://docs.cryptolegacy.app/documentation/errors-reference#incorrectfee-icl1)
* ETH transfer during fee payout fails — [`TransferFeeFailed(bytes)`](https://docs.cryptolegacy.app/documentation/errors-reference#transferfeefailed-icl1)
* `ICryptoLegacyBuildManager.isLifetimeNftLockedAndUpdate(...)` — may revert with [`ICryptoLegacyBuildManager.NotRegisteredCryptoLegacy()`](https://docs.cryptolegacy.app/documentation/errors-reference#notregisteredcryptolegacy-iclbm1) (bubbled)
* `ICryptoLegacyBuildManager.isLifetimeNftLockedAndUpdate(...)` — may revert with [`ICryptoLegacyBuildManager.NotOwnerOfCryptoLegacy()`](https://docs.cryptolegacy.app/documentation/errors-reference#notownerofcryptolegacy-iclbm1) (bubbled)

**Overrides:** None

**Function Calls:**

* [LibCryptoLegacy.getCryptoLegacyStorage()](#getcryptolegacystorage-lcl1) — LibCryptoLegacy, internal
* [LibTrustedGuardiansPlugin.\_resetGuardianVoting(ICryptoLegacy.CryptoLegacyStorage)](#_resetguardianvoting-ltgp1) — LibTrustedGuardiansPlugin, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1) excluding fee payment logic

**Example:** Owner resets guardian voting cycles after addressing a contentious proposal.

***

### \_isGuardiansInitialized (TGP1)

**Contract/Library:** TrustedGuardiansPlugin

**Description:** Indicates whether a dedicated guardian set is stored.

**Detailed Description:** Checks if the plugin’s guardian `EnumerableSet` is non-empty, signalling that guardians were explicitly initialised rather than inferred from beneficiaries.

**Parameters:**

* \_pluginStorage (ITrustedGuardiansPlugin.PluginStorage, storage): Guardians plugin storage

**Returns:**

* initialized (bool): True when explicit guardians are defined

**Modifiers / Visibility / Mutability:**

* internal view

**Access Control:**

* Unrestricted (internal)

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:**

* [isGuardiansInitialized](#isguardiansinitialized-tgp1) — TrustedGuardiansPlugin

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### isGuardiansInitialized (TGP1)

**Contract/Library:** TrustedGuardiansPlugin

**Description:** Public getter indicating whether guardians have been explicitly set.

**Detailed Description:** Retrieves plugin storage and delegates to `_isGuardiansInitialized` to answer if the guardian set has been initialised.

**Parameters:** None

**Returns:**

* initialized (bool): True when the guardians set is non-empty

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [LibTrustedGuardiansPlugin.getPluginStorage()](#getpluginstorage-ltgp1) — LibTrustedGuardiansPlugin, internal
* [\_isGuardiansInitialized(ITrustedGuardiansPlugin.PluginStorage)](#_isguardiansinitialized-tgp1) — TrustedGuardiansPlugin, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** UI toggles between default (beneficiaries) and custom guardian views.

***

### getGuardiansData (TGP1)

**Contract/Library:** TrustedGuardiansPlugin

**Description:** Provides a snapshot of guardian hashes, votes, quorum, and timeout.

**Detailed Description:** Loads core and plugin storage, returns the resolved guardian set values, current `guardiansVoted`, and the computed threshold and challenge timeout.

**Parameters:** None

**Returns:**

* guardians (bytes32\[], memory): Active guardian hashes
* guardiansVoted (bytes32\[], memory): Guardian hashes that have already voted
* guardiansThreshold (uint128): Required confirmations for distribution
* guardiansChallengeTimeout (uint64): Additional delay applied once quorum is reached

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [LibCryptoLegacy.getCryptoLegacyStorage()](#getcryptolegacystorage-lcl1) — LibCryptoLegacy, internal
* [LibTrustedGuardiansPlugin.getPluginStorage()](#getpluginstorage-ltgp1) — LibTrustedGuardiansPlugin, internal
* [\_getGuardians(ICryptoLegacy.CryptoLegacyStorage,ITrustedGuardiansPlugin.PluginStorage)](#_getguardians-tgp1) — TrustedGuardiansPlugin, internal
* [\_getGuardiansThreshold(ICryptoLegacy.CryptoLegacyStorage,ITrustedGuardiansPlugin.PluginStorage)](#_getguardiansthreshold-tgp1) — TrustedGuardiansPlugin, internal
* [\_getGuardiansChallengeTimeout(ITrustedGuardiansPlugin.PluginStorage)](#_getguardianschallengetimeout-tgp1) — TrustedGuardiansPlugin, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(g + v) where g = guardians, v = votes (array copies)

**Example:** Analytics endpoint fetches guardian quorum details for monitoring dashboards.

***

### checkGuardiansVotedAndGetGuardiansData (TGP1)

**Contract/Library:** TrustedGuardiansPlugin

**Description:** Guardian-only getter that also reports whether the caller has voted.

**Detailed Description:** Validates the caller with `_checkGuardian`, cleans up stale votes via `_isGuardianVoted`, and returns the guardian list, vote log, quorum configuration, and a boolean indicating if the caller already voted.

**Parameters:** None

**Returns:**

* guardians (bytes32\[], memory): Current guardian hashes
* guardiansVoted (bytes32\[], memory): Guardian hashes with recorded votes
* guardiansThreshold (uint128): Required confirmations
* guardiansChallengeTimeout (uint64): Active challenge timeout in seconds
* isGuardianVoted (bool): True if the caller’s hash already appears in guardiansVoted

**Modifiers / Visibility / Mutability:**

* external nonpayable

**Access Control:**

* Guardians with initial fee paid

**Side Effects:**

* May remove obsolete votes from `guardiansVoted` during normalisation

**Emits:** None

**Reverts if:**

* Caller hash not listed as guardian — [`NotGuardian()`](https://docs.cryptolegacy.app/documentation/errors-reference#notguardian-itgp1)
* Initial fee unpaid — [`ICryptoLegacy.InitialFeeNotPaid()`](https://docs.cryptolegacy.app/documentation/errors-reference#initialfeenotpaid-icl1)

**Overrides:** None

**Function Calls:**

* [\_checkGuardian()](#_checkguardian-tgp1) — TrustedGuardiansPlugin, internal
* [\_isGuardianVoted(ICryptoLegacy.CryptoLegacyStorage,ITrustedGuardiansPlugin.PluginStorage,bytes32)](#_isguardianvoted-tgp1) — TrustedGuardiansPlugin, internal
* [\_getGuardians(ICryptoLegacy.CryptoLegacyStorage,ITrustedGuardiansPlugin.PluginStorage)](#_getguardians-tgp1) — TrustedGuardiansPlugin, internal
* [\_getGuardiansThreshold(ICryptoLegacy.CryptoLegacyStorage,ITrustedGuardiansPlugin.PluginStorage)](#_getguardiansthreshold-tgp1) — TrustedGuardiansPlugin, internal
* [\_getGuardiansChallengeTimeout(ITrustedGuardiansPlugin.PluginStorage)](#_getguardianschallengetimeout-tgp1) — TrustedGuardiansPlugin, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(g + v) where g = guardians, v = votes (clean-up + array copies)

**Example:** Guardian checks quorum progress and learns whether their vote has already been counted.

***

## UpdateRolePlugin (URP1)

### getSigs (URP1)

**Contract/Library:** UpdateRolePlugin

**Description:** Lists external selectors provided by the updater role facet.

**Detailed Description:** Builds a four-element selector array for updater assignment, execution, and read helpers so the diamond can expose these entry points.

**Parameters:** None

**Returns:**

* sigs (bytes4\[], memory): Ordered selectors for setUpdater, updateByUpdater, isUpdater, getUpdaterList

**Modifiers / Visibility / Mutability:**

* external pure

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Plugin registry inspects selectors before wiring the updater facet.

***

### getSetupSigs (URP1)

**Contract/Library:** UpdateRolePlugin

**Description:** Reports setup selectors required during facet installation.

**Detailed Description:** Returns a single-element array containing `isUpdater`, allowing setup scripts to probe configured updaters without executing state changes.

**Parameters:** None

**Returns:**

* sigs (bytes4\[], memory): Array containing the isUpdater selector

**Modifiers / Visibility / Mutability:**

* external pure

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Deployment process includes a static call to confirm updater visibility.

***

### getPluginName (URP1)

**Contract/Library:** UpdateRolePlugin

**Description:** Returns the human-readable name of the updater facet.

**Detailed Description:** Supplies the constant string `"update_role"`, used by registries and dashboards for identification.

**Parameters:** None

**Returns:**

* name (string, memory): Constant plugin name "update\_role"

**Modifiers / Visibility / Mutability:**

* public pure

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:**

* [updateByUpdater](#updatebyupdater-urp1) — UpdateRolePlugin

**Gas / Complexity note:** O(1)

**Example:** UI displays the facet name within updater management sections.

***

### getPluginVer (URP1)

**Contract/Library:** UpdateRolePlugin

**Description:** Reveals the semantic version for the updater role facet.

**Detailed Description:** Returns the hard-coded version `1`, enabling compatibility checks.

**Parameters:** None

**Returns:**

* version (uint16): Constant version identifier 1

**Modifiers / Visibility / Mutability:**

* external pure

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Monitoring compares deployed facet version to expected release numbers.

***

### getPluginStorage (URP1)

**Contract/Library:** UpdateRolePlugin

**Description:** Returns the plugin-specific storage slot used for updater data.

**Detailed Description:** Uses the fixed [`PLUGIN_POSITION`](https://docs.cryptolegacy.app/documentation/data-structures-reference#plugin_position-urp1-d1) hash and inline assembly to map a [`PluginStorage`](https://docs.cryptolegacy.app/documentation/data-structures-reference#pluginstorage-urp1-s1) struct containing the updater `EnumerableSet`.

**Parameters:** None

**Returns:**

* storageStruct (PluginStorage, storage): Storage pointer holding the updater set

**Modifiers / Visibility / Mutability:**

* internal pure

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:**

* [modifier onlyUpdater (URP1)](#modifier-onlyupdater-urp1) — UpdateRolePlugin
* [getUpdaterList](#getupdaterlist-urp1) — UpdateRolePlugin
* [isUpdater](#isupdater-urp1) — UpdateRolePlugin
* [setUpdater](#setupdater-urp1) — UpdateRolePlugin

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### owner (URP1)

**Contract/Library:** UpdateRolePlugin

**Description:** Returns the current diamond owner address.

**Detailed Description:** Delegates to `LibDiamond.contractOwner()` to expose ownership information externally for UI and access control checks.

**Parameters:** None

**Returns:**

* contractOwner (address): Address recorded as diamond owner

**Modifiers / Visibility / Mutability:**

* public view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [LibDiamond.contractOwner()](#contractowner-ld1) — LibDiamond, internal

**Called by:**

* [updateByUpdater](#updatebyupdater-urp1) — UpdateRolePlugin

**Gas / Complexity note:** O(1)

**Example:** Front-end shows who can manage updaters.

***

### modifier onlyOwner (URP1)

**Contract/Library:** UpdateRolePlugin

**Description:** Ensures only the CryptoLegacy owner can invoke protected functions before distribution start.

**Detailed Description:** Calls `LibCryptoLegacy._checkOwner()` to verify ownership, initial fee payment, and distribution status before permitting execution.

**Parameters:** None

**Returns:** None

**Modifiers / Visibility / Mutability:**

* modifier nonpayable

**Access Control:**

* Enforced by the modifier itself

**Side Effects:** None

**Emits:** None

**Reverts if:**

* Distribution already started — [`ICryptoLegacy.DistributionStarted()`](https://docs.cryptolegacy.app/documentation/errors-reference#distributionstarted-icl1)
* Initial fee unpaid — [`ICryptoLegacy.InitialFeeNotPaid()`](https://docs.cryptolegacy.app/documentation/errors-reference#initialfeenotpaid-icl1)
* Caller is not the owner — [`ICryptoLegacy.NotTheOwner()`](https://docs.cryptolegacy.app/documentation/errors-reference#nottheowner-icl1)

**Overrides:** None

**Function Calls:**

* [LibCryptoLegacy.\_checkOwner()](#_checkowner-lcl1) — LibCryptoLegacy, internal

**Called by:**

* [setUpdater](#setupdater-urp1) — UpdateRolePlugin

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### modifier onlyUpdater (URP1)

**Contract/Library:** UpdateRolePlugin

**Description:** Restricts execution to authorised updaters until distribution begins.

**Detailed Description:** Fetches core storage, ensures distribution has **not** begun via `_checkDistributionStart`, looks up the updater set, and reverts with `NotTheUpdater()` if `msg.sender` is not contained.

**Parameters:** None

**Returns:** None

**Modifiers / Visibility / Mutability:**

* modifier nonpayable

**Access Control:**

* Enforced by the modifier itself (authorised updater before distribution start)

**Side Effects:** None

**Emits:** None

**Reverts if:**

* Distribution already started — [`ICryptoLegacy.DistributionStarted()`](https://docs.cryptolegacy.app/documentation/errors-reference#distributionstarted-icl1) (bubbled via `_checkDistributionStart`)
* Caller not in updater set — [`ICryptoLegacyUpdaterPlugin.NotTheUpdater()`](https://docs.cryptolegacy.app/documentation/errors-reference#nottheupdater-iclup1)

**Overrides:** None

**Function Calls:**

* [LibCryptoLegacy.getCryptoLegacyStorage()](#getcryptolegacystorage-lcl1) — LibCryptoLegacy, internal
* [getPluginStorage()](#getpluginstorage-urp1) — UpdateRolePlugin, internal
* [LibCryptoLegacy.\_checkDistributionStart(ICryptoLegacy.CryptoLegacyStorage)](#_checkdistributionstart-lcl1) — LibCryptoLegacy, internal

**Called by:**

* [updateByUpdater](#updatebyupdater-urp1) — UpdateRolePlugin

**Gas / Complexity note:** O(1)

**Example:** Not applicable

***

### getUpdaterList (URP1)

**Contract/Library:** UpdateRolePlugin

**Description:** Returns the full set of updater addresses.

**Detailed Description:** Reads the updater `EnumerableSet` and copies the addresses into memory for external callers.

**Parameters:** None

**Returns:**

* updaters (address\[], memory): Addresses authorised to trigger updates

**Modifiers / Visibility / Mutability:**

* public view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [getPluginStorage()](#getpluginstorage-urp1) — UpdateRolePlugin, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(u) by number of updaters

**Example:** Watcher retrieves the updater roster to audit permissions.

***

### isUpdater (URP1)

**Contract/Library:** UpdateRolePlugin

**Description:** Checks whether a given address currently has update permissions.

**Detailed Description:** Queries the updater `EnumerableSet` to determine if `_acc` is present.

**Parameters:**

* \_acc (address): Address to check

**Returns:**

* isAuthorized (bool): True if \_acc is in the updater set

**Modifiers / Visibility / Mutability:**

* public view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [getPluginStorage()](#getpluginstorage-urp1) — UpdateRolePlugin, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Backend verifies whether a service account retains updater permissions.

***

### setUpdater (URP1)

**Contract/Library:** UpdateRolePlugin

**Description:** Adds or removes authorised updaters.

**Detailed Description:** Owner-only function that updates the updater set; on addition it emits `AddUpdater`, on removal `RemoveUpdater`. Supports payable context for flexibly covering fees, though this function does not consume `msg.value`.

**Parameters:**

* \_updater (address): Address to add or remove
* \_toAdd (bool): True to add the address, false to remove

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external payable onlyOwner nonReentrant

**Access Control:**

* Owner only

**Side Effects:**

* Inserts or removes `_updater` from the updater set

**Emits:**

* [AddUpdater](https://docs.cryptolegacy.app/documentation/events-reference#addupdater-iclup1) — `AddUpdater(address indexed owner, address indexed updater)` (when `_toAdd` is true)
* [RemoveUpdater](https://docs.cryptolegacy.app/documentation/events-reference#removeupdater-iclup1) — `RemoveUpdater(address indexed owner, address indexed updater)` (when `_toAdd` is false)

**Reverts if:**

* Distribution already started — [`ICryptoLegacy.DistributionStarted()`](https://docs.cryptolegacy.app/documentation/errors-reference#distributionstarted-icl1)
* Initial fee unpaid — [`ICryptoLegacy.InitialFeeNotPaid()`](https://docs.cryptolegacy.app/documentation/errors-reference#initialfeenotpaid-icl1)
* Caller is not the owner — [`ICryptoLegacy.NotTheOwner()`](https://docs.cryptolegacy.app/documentation/errors-reference#nottheowner-icl1)
* Reentrant call — "ReentrancyGuard: reentrant call"

**Overrides:** None

**Function Calls:**

* [getPluginStorage()](#getpluginstorage-urp1) — UpdateRolePlugin, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Owner onboards a new service key to run scheduled updates.

***

### updateByUpdater (URP1)

**Contract/Library:** UpdateRolePlugin

**Description:** Lets authorised updaters execute the `update` flow while paying required fees before distribution begins.

**Detailed Description:** After verifying updater status and that distribution has not started, forwards the fee payment parameters to `LibCryptoLegacy._takeFee`, then refreshes `lastUpdateAt`, resets `distributionStartAt`, and emits the standard `Update` event keyed by the plugin name hash.

**Parameters:**

* \_lockToChainIds (uint256\[], memory): Chain IDs for cross-chain fee locking
* \_crossChainFees (uint256\[], memory): Fees per chain matching \_lockToChainIds

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external payable onlyUpdater nonReentrant

**Access Control:**

* Authorised updaters before distribution start

**Side Effects:**

* Pays the update fee via `_takeFee`
* Updates `lastUpdateAt` and clears `distributionStartAt`

**Emits:**

* [Update](https://docs.cryptolegacy.app/documentation/events-reference#update-icl1) — `Update(uint256 updateFee, bytes32 indexed byPlugin)`

**Reverts if:**

* Distribution already started — [`ICryptoLegacy.DistributionStarted()`](https://docs.cryptolegacy.app/documentation/errors-reference#distributionstarted-icl1)
* Caller not in updater set — [`ICryptoLegacyUpdaterPlugin.NotTheUpdater()`](https://docs.cryptolegacy.app/documentation/errors-reference#nottheupdater-iclup1)
* Lifetime NFT active while `msg.value != 0` — [`ICryptoLegacy.NoValueAllowed()`](https://docs.cryptolegacy.app/documentation/errors-reference#novalueallowed-icl1)
* `_lockToChainIds.length` exceeds [`MAX_CHAINS_ARRAY_LENGTH`](https://docs.cryptolegacy.app/documentation/data-structures-reference#max_chains_array_length-lcl1-d2) — [`ICryptoLegacy.TooLongArray(uint256)`](https://docs.cryptolegacy.app/documentation/errors-reference#toolongarray-icl1)
* Fee amount invalid — [`IncorrectFee(uint256)`](https://docs.cryptolegacy.app/documentation/errors-reference#incorrectfee-icl1)
* ETH transfer during fee payout fails — [`TransferFeeFailed(bytes)`](https://docs.cryptolegacy.app/documentation/errors-reference#transferfeefailed-icl1)
* `LibCryptoLegacy._takeFee(...)` — may revert via `ICryptoLegacyBuildManager.isLifetimeNftLockedAndUpdate(...)` with [`ICryptoLegacyBuildManager.NotRegisteredCryptoLegacy()`](https://docs.cryptolegacy.app/documentation/errors-reference#notregisteredcryptolegacy-iclbm1) or [`ICryptoLegacyBuildManager.NotOwnerOfCryptoLegacy()`](https://docs.cryptolegacy.app/documentation/errors-reference#notownerofcryptolegacy-iclbm1) (bubbled)
* Reentrant call — "ReentrancyGuard: reentrant call"

**Overrides:** None

**Function Calls:**

* [LibCryptoLegacy.getCryptoLegacyStorage()](#getcryptolegacystorage-lcl1) — LibCryptoLegacy, internal
* [owner()](#owner-urp1) — UpdateRolePlugin, internal
* [\_takeFee(ICryptoLegacy.CryptoLegacyStorage,address,address,uint256,uint256\[\],uint256\[\])](#_takefee-lcl1) — LibCryptoLegacy, internal
* [getPluginName()](#getpluginname-urp1) — UpdateRolePlugin, internal
* `keccak256(bytes memory)` — Solidity builtin, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1) plus fee payment cost; `_lockToChainIds.length` influences `_takeFee` complexity

**Example:** Automated updater pays the fee and resets the distribution timer for the CryptoLegacy instance.

***

## DiamondLoupeFacet (DLF1)

### facets (DLF1)

**Contract/Library:** DiamondLoupeFacet

**Description:** Lists every facet installed on the diamond along with their selectors.

**Detailed Description:** Reads `LibDiamond.diamondStorage()` to obtain the facet address array. Allocates a [`Facet[]`](https://docs.cryptolegacy.app/documentation/data-structures-reference#facet-idl1-s1) result and, for each facet, copies its address and queries `ICryptoLegacyPlugin(facet).getSigs()` to populate selectors.

**Parameters:** None

**Returns:**

* facets\_ ([Facet](https://docs.cryptolegacy.app/documentation/data-structures-reference#facet-idl1-s1)\[], memory): Array of facet metadata with selector lists

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:**

* `ICryptoLegacyPlugin(facetAddress_).getSigs()` — may revert per facet implementation (bubbled)

**Overrides:**

* IDiamondLoupe.facets

**Function Calls:**

* [diamondStorage()](#diamondstorage-ld1) — LibDiamond, internal
* `ICryptoLegacyPlugin.getSigs()` — `ICryptoLegacyPlugin` *(at `facetAddress_`)*, external (staticcall)

**Called by:** None (entry point)

**Gas / Complexity note:** O(f + s) where f = facet count, s = total selectors returned

**Example:** Block explorer surfaces every diamond facet and its exposed selectors.

***

### facetFunctionSelectors (DLF1)

**Contract/Library:** DiamondLoupeFacet

**Description:** Returns the selectors exposed by a single facet.

**Detailed Description:** Delegates to `ICryptoLegacyPlugin(_facet).getSigs()` to retrieve the facet’s advertised selector list.

**Parameters:**

* \_facet (address): Facet address to inspect

**Returns:**

* facetFunctionSelectors\_ (bytes4\[], memory): Selectors reported by the facet

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Owner only (caller must match `diamondStorage().contractOwner`)

**Side Effects:** None

**Emits:** None

**Reverts if:**

* `ICryptoLegacyPlugin(_facet).getSigs()` — may revert per facet implementation (bubbled)

**Overrides:**

* IDiamondLoupe.facetFunctionSelectors

**Function Calls:**

* `ICryptoLegacyPlugin.getSigs()` — `ICryptoLegacyPlugin` *(at `_facet`)*, external (staticcall)

**Called by:** None (entry point)

**Gas / Complexity note:** O(s) where s = selector count returned by the facet

**Example:** Client inspects which methods a specific facet exposes.

***

### facetAddresses (DLF1)

**Contract/Library:** DiamondLoupeFacet

**Description:** Returns the ordered list of facet addresses in the diamond.

**Detailed Description:** Reads and returns the `facetAddresses` array stored in diamond storage without modification.

**Parameters:** None

**Returns:**

* facetAddresses\_ (address\[], memory): Installed facet addresses

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:**

* IDiamondLoupe.facetAddresses

**Function Calls:**

* [diamondStorage()](#diamondstorage-ld1) — LibDiamond, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(f) to copy facet addresses

**Example:** Auditor retrieves the list of active facets for verification.

***

### facetAddress (DLF1)

**Contract/Library:** DiamondLoupeFacet

**Description:** Resolves the facet address implementing a given selector, with plugin-aware fallback.

**Detailed Description:** First checks `selectorToFacetAndPosition_functionSelector`. If unset, invokes `LibCryptoLegacyPlugins._findFacetBySelector` to search each facet’s `getSigs()` output until a match is found, returning `address(0)` if none resolve.

**Parameters:**

* \_functionSelector (bytes4): Selector to locate

**Returns:**

* facetAddress\_ (address): Facet that exposes the selector, or zero address when absent

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:**

* `LibCryptoLegacyPlugins._findFacetBySelector(...)` — may revert via `ICryptoLegacyPlugin.getSigs()` for inspected facets (bubbled)

**Overrides:**

* IDiamondLoupe.facetAddress

**Function Calls:**

* [diamondStorage()](#diamondstorage-ld1) — LibDiamond, internal
* [\_findFacetBySelector(LibDiamond.DiamondStorage,bytes4)](#_findfacetbyselector-lclp1) — LibCryptoLegacyPlugins, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1) when selector cached; worst case O(f + s) when scanning all facets

**Example:** Tool resolves which facet implements a specific selector for routing debugging.

***

### storageFacetAddress (DLF1)

**Contract/Library:** DiamondLoupeFacet

**Description:** Reads the raw facet address mapped to a selector without plugin fallback.

**Detailed Description:** Returns `selectorToFacetAndPosition_functionSelector.facetAddress` directly from diamond storage, enabling diagnostics of the canonical selector mapping.

**Parameters:**

* \_functionSelector (bytes4): Selector to inspect

**Returns:**

* facetAddress\_ (address): Facet recorded in storage, zero if unmapped

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [diamondStorage()](#diamondstorage-ld1) — LibDiamond, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Operator audits selector mappings without invoking plugin logic.

***

### supportsInterface (DLF1)

**Contract/Library:** DiamondLoupeFacet

**Description:** Reports ERC-165 interface support flags for the diamond.

**Detailed Description:** Reads `supportedInterfaces_interfaceId` from diamond storage to indicate whether the diamond claims support for the interface.

**Parameters:**

* \_interfaceId (bytes4): Interface identifier per ERC-165

**Returns:**

* supported (bool): True if the interface flag is set

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:**

* IERC165.supportsInterface

**Function Calls:**

* [diamondStorage()](#diamondstorage-ld1) — LibDiamond, internal

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** Client verifies ERC-165 support for loupe and other interfaces.

***

## WethUnwrap (WU1)

### constructor (WU1)

**Contract/Library:** WethUnwrap

**Description:** Stores the canonical WETH contract address used for unwrap operations.

**Detailed Description:** Initializes the helper with the wrapped-ETH token that will be pulled from callers and unwrapped into native ETH during `unwrap_weth`.

**Parameters:**

* weth (address): WETH contract address used by the helper

**Returns:** None

**Modifiers / Visibility / Mutability:**

* constructor nonpayable

**Access Control:**

* Unrestricted at deployment time

**Side Effects:**

* Sets [`WETH (WU-D1)`](https://docs.cryptolegacy.app/documentation/data-structures-reference#weth-wu1-d1) once as an immutable configuration value

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:** None (deployment only)

**Gas / Complexity note:** O(1)

**Example:** `new WethUnwrap(weth);`

***

### unwrap\_weth (WU1)

**Contract/Library:** WethUnwrap

**Description:** Pulls WETH from the caller, unwraps it to ETH, and immediately forwards the ETH back with callback calldata.

**Detailed Description:** The helper transfers `amount` of WETH from `msg.sender`, unwraps the received WETH into native ETH, then executes a low-level callback back into `msg.sender` with `amount` wei attached. CryptoLegacy's Lido plugin uses this helper to bridge from wrapped ETH to raw ETH without keeping ETH custody in a long-lived contract.

**Parameters:**

* amount (uint256): Amount of WETH to transfer in and unwrap
* callback (bytes, calldata): Calldata forwarded back to `msg.sender` with `amount` wei attached

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external nonpayable

**Access Control:**

* Unrestricted at the helper surface; the caller must have approved `amount` of WETH to this contract

**Side Effects:**

* Pulls `amount` of WETH from `msg.sender` into this helper
* Burns/unlocks the received WETH into native ETH
* Forwards `amount` wei and `callback` back to `msg.sender`

**Emits:** None

**Reverts if:**

* [WethUnwrapIWETH.transferFrom(address,address,uint256)](#transferfrom-wui1) fails — bubbled from the WETH implementation
* [WethUnwrapIWETH.withdraw(uint256)](#withdraw-wui1) fails — bubbled from the WETH implementation
* The callback to `msg.sender` returns `false` — [`CallbackCallFailed()`](https://docs.cryptolegacy.app/documentation/errors-reference#callbackcallfailed-wu1)

**Overrides:** None

**Function Calls:**

* [WethUnwrapIWETH.transferFrom(address,address,uint256)](#transferfrom-wui1) — WethUnwrapIWETH, external
* [WethUnwrapIWETH.withdraw(uint256)](#withdraw-wui1) — WethUnwrapIWETH, external
* `msg.sender.call(bytes)` — address, external

**Called by:** None (entry point)

**Gas / Complexity note:** O(1) plus downstream callback cost

**Example:** `wethUnwrap.unwrap_weth(amount, abi.encodeWithSelector(this.afterUnwrap.selector));`

***

### receive (WU1)

**Contract/Library:** WethUnwrap

**Description:** Accepts native ETH released by the WETH contract during an unwrap.

**Detailed Description:** Provides the payable receive hook needed for `WETH.withdraw(amount)` to send native ETH into the helper before the callback forwards that ETH back to the original caller.

**Parameters:** None

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external payable

**Access Control:**

* Unrestricted

**Side Effects:**

* Accepts native ETH into the helper contract balance

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:**

* [WethUnwrapIWETH.withdraw(uint256)](#withdraw-wui1) — WethUnwrapIWETH

**Gas / Complexity note:** O(1)

**Example:** Triggered implicitly when the configured WETH implementation sends ETH to the helper during `unwrap_weth`.

***

## LibCreate3 (LC31)

### codeSize (LC31)

**Contract/Library:** LibCreate3

**Description:** Returns the bytecode size at a target address.

**Detailed Description:** Uses `extcodesize` via inline assembly to compute the deployed code size for `_addr`, assisting deterministic deployment helpers in verifying existing contracts.

**Parameters:**

* \_addr (address): Address to inspect for deployed code

**Returns:**

* size (uint256): Code size in bytes present at `_addr`

**Modifiers / Visibility / Mutability:**

* internal view

**Access Control:**

* Unrestricted (internal)

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:**

* [create3(bytes32,bytes,uint256)](#create3bytes32bytesuint256-lc31) — LibCreate3

**Gas / Complexity note:** O(1) — single `extcodesize` opcode

**Example:** Not applicable

***

### create3(bytes32,bytes) (LC31)

**Contract/Library:** LibCreate3

**Description:** Deploys bytecode deterministically with CREATE3 forwarding zero ether.

**Detailed Description:** Thin wrapper around the value-aware overload, invoking `create3(_salt, _creationCode, 0)` to deploy while enforcing uniqueness and proxy bootstrap semantics.

**Parameters:**

* \_salt (bytes32): Salt controlling the resulting address
* \_creationCode (bytes, memory): Constructor bytecode for the target contract

**Returns:**

* addr (address): Deterministic address of the deployed contract

**Modifiers / Visibility / Mutability:**

* internal nonpayable

**Access Control:**

* Unrestricted

**Side Effects:**

* Deploys a CREATE3 proxy and target contract (delegated to overload)

**Emits:** None

**Reverts if:**

* Target address already has code — [`TargetAlreadyExists()`](https://docs.cryptolegacy.app/documentation/errors-reference#targetalreadyexists-lc31)
* CREATE2 proxy deployment fails — [`ErrorCreatingProxy()`](https://docs.cryptolegacy.app/documentation/errors-reference#errorcreatingproxy-lc31)
* Proxy call fails or target bytecode absent — [`ErrorCreatingContract()`](https://docs.cryptolegacy.app/documentation/errors-reference#errorcreatingcontract-lc31)

**Overrides:** None

**Function Calls:**

* [create3(bytes32,bytes,uint256)](#create3bytes32bytesuint256-lc31) — LibCreate3, internal

**Called by:**

* [build](#build-c3f1) — Create3Factory
* [build](#build-pb1) — ProxyBuilder
* [\_deployByCreate3](#_deploybycreate3-lcld1) — LibCryptoLegacyDeploy

**Gas / Complexity note:** O(1) plus cost of the overloaded deployment path

**Example:** Factory deploys a deterministic helper contract without forwarding ETH.

***

### create3(bytes32,bytes,uint256) (LC31)

**Contract/Library:** LibCreate3

**Description:** Deterministically deploys contracts using the CREATE3 pattern, optionally forwarding ETH.

**Detailed Description:** Derives the final address via `addressOf(_salt)` and ensures it is vacant. Deploys a minimal proxy with `create2`, then calls the proxy with `_creationCode` and `_value` to deploy the target. Validates deployment success by re-checking `codeSize(addr)` and reverts with custom errors when conditions fail.

**Parameters:**

* \_salt (bytes32): Salt controlling both proxy and final contract addresses
* \_creationCode (bytes, memory): Constructor bytecode for the final contract
* \_value (uint256): Ether (wei) forwarded to the constructor call

**Returns:**

* addr (address): Address of the deployed contract

**Modifiers / Visibility / Mutability:**

* internal nonpayable

**Access Control:**

* Unrestricted

**Side Effects:**

* Deploys a transient CREATE2 proxy
* Deploys the target contract with supplied bytecode/value

**Emits:** None

**Reverts if:**

* Target address already has code — [`TargetAlreadyExists()`](https://docs.cryptolegacy.app/documentation/errors-reference#targetalreadyexists-lc31)
* CREATE2 proxy deployment fails — [`ErrorCreatingProxy()`](https://docs.cryptolegacy.app/documentation/errors-reference#errorcreatingproxy-lc31)
* Proxy call fails or target bytecode absent — [`ErrorCreatingContract()`](https://docs.cryptolegacy.app/documentation/errors-reference#errorcreatingcontract-lc31)

**Overrides:** None

**Function Calls:**

* [addressOf(bytes32)](#addressof-lc31) — LibCreate3, internal
* [codeSize(address)](#codesize-lc31) — LibCreate3, internal
* `create2(...)` — EVM assembly CREATE2 to deploy proxy, internal
* `proxy.call{value: _value}(_creationCode)` — proxy, external

**Called by:**

* [create3(bytes32,bytes)](#create3bytes32bytes-lc31) — LibCreate3

**Gas / Complexity note:** O(p + c) where p = proxy deployment (constant), c = constructor bytecode execution cost

**Example:** Factory deploys a fee-collecting contract at a predetermined address while forwarding setup ETH.

***

### addressOf (LC31)

**Contract/Library:** LibCreate3

**Description:** Computes the deterministic address yielded by CREATE3 for a given salt.

**Detailed Description:** Recreates the CREATE3 address derivation by hashing the CREATE2 proxy address (computed from `address(this)`, `_salt`, and proxy bytecode hash) and then applying the CREATE pattern for the proxy’s child deployment (`0xd6_94 … 01`).

**Parameters:**

* \_salt (bytes32): Salt used when deploying via CREATE3

**Returns:**

* addr (address): Predicted final contract address associated with `_salt`

**Modifiers / Visibility / Mutability:**

* internal view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* `keccak256(bytes memory)` — Solidity builtin, internal

**Called by:**

* [create3(bytes32,bytes,uint256)](#create3bytes32bytesuint256-lc31) — LibCreate3
* [computeAddress](#computeaddress-c3f1) — Create3Factory
* [computeAddress](#computeaddress-pb1) — ProxyBuilder
* [\_computeAddress](#_computeaddress-lcld1) — LibCryptoLegacyDeploy

**Gas / Complexity note:** O(1) — fixed hashing work

**Example:** Off-chain tooling predicts the deployment address before invoking `create3`.

***

## LibCLUtils (LCLU1)

### approveToken (LCLU1)

**Contract/Library:** LibCLUtils

**Description:** Performs a low-level ERC-20 approval call and normalizes non-standard return behavior.

**Detailed Description:** Calls `token.approve(spender, amount)` through `token.call(...)`, then accepts either an empty return payload or a 32-byte `true` value as success. The helper exists to support tokens that do not strictly follow the standard ERC-20 boolean-return convention.

**Parameters:**

* token (address): ERC-20 token being approved
* spender (address): Address receiving the allowance
* amount (uint256): Allowance amount to set

**Returns:** None

**Modifiers / Visibility / Mutability:**

* internal nonpayable

**Access Control:**

* Inherits caller permissions

**Side Effects:**

* Executes a low-level approval call against `token`
* Updates allowance state in the token contract when the call succeeds

**Emits:** None

**Reverts if:**

* The low-level call fails or returns an explicit `false` approval result — [`ApprovalFailed()`](https://docs.cryptolegacy.app/documentation/errors-reference#approvalfailed-lclu1)

**Overrides:** None

**Function Calls:**

* `token.call(bytes)` — address, external

**Called by:**

* [baavesSupply(address,uint256,uint16)](#baavessupply-balp1) — BeneficiaryAaveV3SupplyPlugin
* [baavesWrapATokenToStataToken(address,uint256)](#baaveswrapatokentostatatoken-balp1) — BeneficiaryAaveV3SupplyPlugin
* [baavesDepositToStataToken(address,uint256)](#baavesdeposittostatatoken-balp1) — BeneficiaryAaveV3SupplyPlugin
* [bunisSwapExactInputSingle((address,address,uint24,int24,address),bool,uint128,uint128,bytes)](#bunisswapexactinputsingle-bu4sp1) — BeneficiaryUniswapV4SwapPlugin
* [bunisSwapExactInput(address,(address,uint24,int24,address,bytes)\[\],uint256\[\],uint128,uint128)](#bunisswapexactinput-bu4sp1) — BeneficiaryUniswapV4SwapPlugin

**Gas / Complexity note:** O(1) plus token-call cost

**Example:** `LibCLUtils.approveToken(token, spender, amount);`

***

## LibClaimMigrationCore (LCMC1)

### calculateFractionAndRatio (LCMC1)

**Contract/Library:** LibClaimMigrationCore

**Description:** Calculates the migration fraction and exchange ratio for a conversion step.

**Detailed Description:** Normalizes a token-conversion step into two fixed-point numbers scaled by [`MIGRATION_SCALE (LCMC-D1)`](https://docs.cryptolegacy.app/documentation/data-structures-reference#migration_scale-lcmc1-d1): the fraction of the source pool that was converted and the ratio of destination tokens received per converted source token.

**Parameters:**

* outBalanceBefore (uint256): Source-token balance before conversion
* amountOut (uint256): Amount of source token that left the contract
* amountIn (uint256): Amount of destination token that arrived

**Returns:**

* fraction (uint256): Portion of the source pool converted, scaled by `MIGRATION_SCALE`
* ratio (uint256): Destination-token-per-source-token exchange ratio, scaled by `MIGRATION_SCALE`

**Modifiers / Visibility / Mutability:**

* internal pure

**Access Control:**

* Inherits caller permissions

**Side Effects:** None

**Emits:** None

**Reverts if:**

* Any of `outBalanceBefore`, `amountOut`, or `amountIn` is zero — [`MigrationInvalidDelta(uint256,uint256,uint256)`](https://docs.cryptolegacy.app/documentation/errors-reference#migrationinvaliddelta-lcmc1)
* The computed fraction or ratio rounds to zero — [`MigrationAmountTooSmall(uint256,uint256,uint256,uint256,uint256)`](https://docs.cryptolegacy.app/documentation/errors-reference#migrationamounttoosmall-lcmc1)

**Overrides:** None

**Function Calls:** None

**Called by:**

* [migrate](#migrate-loscm1) — LibOneStepClaimMigration
* [\_applyPendingMigration](#_applypendingmigration-ltscm1) — LibTwoStepClaimMigration

**Gas / Complexity note:** O(1)

**Example:** `(fraction, ratio) = LibClaimMigrationCore.calculateFractionAndRatio(outBefore, amountOut, amountIn);`

***

### applyMigrationFormula (LCMC1)

**Contract/Library:** LibClaimMigrationCore

**Description:** Reallocates one beneficiary's claimed balances across a migration boundary.

**Detailed Description:** Reduces the beneficiary's `claimedOut` balance proportionally to `fraction` and credits the converted share into `claimedIn` using `ratio`. This is the core per-beneficiary claim-migration formula reused by both one-step and two-step flows.

**Parameters:**

* claimedOut (uint256): Existing claimed amount for the source token
* claimedIn (uint256): Existing claimed amount for the destination token
* fraction (uint256): Portion of the source pool converted, scaled by `MIGRATION_SCALE`
* ratio (uint256): Destination-token-per-source-token exchange ratio, scaled by `MIGRATION_SCALE`

**Returns:**

* newClaimedOut (uint256): Updated claimed amount for the source token
* newClaimedIn (uint256): Updated claimed amount for the destination token

**Modifiers / Visibility / Mutability:**

* internal pure

**Access Control:**

* Inherits caller permissions

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:**

* [\_migrateClaims](#_migrateclaims-loscm1) — LibOneStepClaimMigration
* [\_applyPendingMigration](#_applypendingmigration-ltscm1) — LibTwoStepClaimMigration

**Gas / Complexity note:** O(1)

**Example:** `(newOut, newIn) = LibClaimMigrationCore.applyMigrationFormula(claimedOut, claimedIn, fraction, ratio);`

***

### syncDistributions (LCMC1)

**Contract/Library:** LibClaimMigrationCore

**Description:** Updates distribution totals and last-balance snapshots after a migration.

**Detailed Description:** Refreshes `amountToDistribute` and `lastBalance` for both migration legs so the CryptoLegacy storage view matches post-conversion balances and migrated claim totals.

**Parameters:**

* cls (ICryptoLegacy.CryptoLegacyStorage, storage): CryptoLegacy storage reference
* tokenOut (address): Source token whose balance decreased
* tokenIn (address): Destination token whose balance increased
* outBalance (uint256): Post-migration source-token balance
* inBalance (uint256): Post-migration destination-token balance
* totalClaimedOut (uint256): Aggregate claimed amount for `tokenOut` after migration
* totalClaimedIn (uint256): Aggregate claimed amount for `tokenIn` after migration

**Returns:** None

**Modifiers / Visibility / Mutability:**

* internal nonpayable

**Access Control:**

* Inherits caller permissions

**Side Effects:**

* Updates `cls.tokenDistribution[tokenOut].amountToDistribute` and `lastBalance`
* Updates `cls.tokenDistribution[tokenIn].amountToDistribute` and `lastBalance`

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:**

* [migrate](#migrate-loscm1) — LibOneStepClaimMigration
* [complete](#complete-ltscm1) — LibTwoStepClaimMigration

**Gas / Complexity note:** O(1)

**Example:** `LibClaimMigrationCore.syncDistributions(cls, tokenOut, tokenIn, outAfter, inAfter, totalOut, totalIn);`

***

## LibOneStepClaimMigration (LOSCM1)

### migrate (LOSCM1)

**Contract/Library:** LibOneStepClaimMigration

**Description:** Migrates beneficiary claim accounting for an atomic token conversion.

**Detailed Description:** Used when `tokenOut` leaves and `tokenIn` arrives in the same transaction, such as staking or swap flows. The helper computes conversion deltas, reapportions each beneficiary's claimed balances, and then synchronizes distribution totals.

**Parameters:**

* cls (ICryptoLegacy.CryptoLegacyStorage, storage): CryptoLegacy storage reference
* tokenOut (address): Source token whose balance decreased
* tokenIn (address): Destination token whose balance increased
* outBalanceBefore (uint256): Source-token balance before conversion
* outBalanceAfter (uint256): Source-token balance after conversion
* inBalanceBefore (uint256): Destination-token balance before conversion
* inBalanceAfter (uint256): Destination-token balance after conversion

**Returns:** None

**Modifiers / Visibility / Mutability:**

* internal nonpayable

**Access Control:**

* Inherits caller permissions

**Side Effects:**

* Updates per-beneficiary claimed balances for `tokenOut` and `tokenIn`
* Updates token-distribution totals and balance snapshots through `syncDistributions`

**Emits:** None

**Reverts if:**

* The conversion delta is invalid — [`MigrationInvalidDelta(uint256,uint256,uint256)`](https://docs.cryptolegacy.app/documentation/errors-reference#migrationinvaliddelta-lcmc1)
* The computed migration ratio rounds to zero — [`MigrationAmountTooSmall(uint256,uint256,uint256,uint256,uint256)`](https://docs.cryptolegacy.app/documentation/errors-reference#migrationamounttoosmall-lcmc1)

**Overrides:** None

**Function Calls:**

* [LibClaimMigrationCore.calculateFractionAndRatio(uint256,uint256,uint256)](#calculatefractionandratio-lcmc1) — LibClaimMigrationCore, internal
* [\_migrateClaims](#_migrateclaims-loscm1) — LibOneStepClaimMigration, internal
* [LibClaimMigrationCore.syncDistributions(ICryptoLegacy.CryptoLegacyStorage,address,address,uint256,uint256,uint256,uint256)](#syncdistributions-lcmc1) — LibClaimMigrationCore, internal

**Called by:**

* [baavesSupply(address,uint256,uint16)](#baavessupply-balp1) — BeneficiaryAaveV3SupplyPlugin
* [baavesWithdraw(address,uint256)](#baaveswithdraw-balp1) — BeneficiaryAaveV3SupplyPlugin
* [baavesWrapATokenToStataToken(address,uint256)](#baaveswrapatokentostatatoken-balp1) — BeneficiaryAaveV3SupplyPlugin
* [baavesUnwrapStataTokenToAToken(address,uint256)](#baavesunwrapstatatokentoatoken-balp1) — BeneficiaryAaveV3SupplyPlugin
* [baavesDepositToStataToken(address,uint256)](#baavesdeposittostatatoken-balp1) — BeneficiaryAaveV3SupplyPlugin
* [baavesRedeemFromStataToken(address,uint256)](#baavesredeemfromstatatoken-balp1) — BeneficiaryAaveV3SupplyPlugin
* [bunisSwapExactInputSingle((address,address,uint24,int24,address),bool,uint128,uint128,bytes)](#bunisswapexactinputsingle-bu4sp1) — BeneficiaryUniswapV4SwapPlugin
* [bunisSwapExactInput(address,(address,uint24,int24,address,bytes)\[\],uint256\[\],uint128,uint128)](#bunisswapexactinput-bu4sp1) — BeneficiaryUniswapV4SwapPlugin
* [blsLidoWrapStEthToWstEth(uint256)](#blslidowrapstethtowsteth-blsp1) — BeneficiaryLidoStakingPlugin
* [blsLidoUnwrapWstEthToStEth(uint256)](#blslidounwrapwstethtosteth-blsp1) — BeneficiaryLidoStakingPlugin

**Gas / Complexity note:** O(n) by beneficiary count

**Example:** `LibOneStepClaimMigration.migrate(cls, tokenOut, tokenIn, outBefore, outAfter, inBefore, inAfter);`

***

### \_migrateClaims (LOSCM1)

**Contract/Library:** LibOneStepClaimMigration

**Description:** Applies the migration formula to every beneficiary in the current CryptoLegacy set.

**Detailed Description:** Iterates through `beneficiaries`, recalculates each beneficiary's claim split between `tokenOut` and `tokenIn`, writes the updated values back into storage, and accumulates the new global claimed totals for both tokens.

**Parameters:**

* cls (ICryptoLegacy.CryptoLegacyStorage, storage): CryptoLegacy storage reference
* beneficiaries (bytes32\[], memory): Beneficiary hashes participating in the migration
* tokenOut (address): Source token whose balance decreased
* tokenIn (address): Destination token whose balance increased
* fraction (uint256): Portion of the source pool converted
* ratio (uint256): Destination-token-per-source-token exchange ratio

**Returns:**

* totalClaimedOut (uint256): Aggregate claimed amount for `tokenOut` after migration
* totalClaimedIn (uint256): Aggregate claimed amount for `tokenIn` after migration

**Modifiers / Visibility / Mutability:**

* private nonpayable

**Access Control:**

* Internal helper only

**Side Effects:**

* Updates `claimed` accounting for every beneficiary on both migration legs

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [LibCryptoLegacy.\_getBeneficiaryClaimed(ICryptoLegacy.CryptoLegacyStorage,bytes32,address)](#_getbeneficiaryclaimed-lcl1) — LibCryptoLegacy, internal
* [LibClaimMigrationCore.applyMigrationFormula(uint256,uint256,uint256,uint256)](#applymigrationformula-lcmc1) — LibClaimMigrationCore, internal
* [LibCryptoLegacy.\_setBeneficiaryClaimed(ICryptoLegacy.CryptoLegacyStorage,bytes32,address,uint256)](#_setbeneficiaryclaimed-lcl1) — LibCryptoLegacy, internal

**Called by:**

* [migrate](#migrate-loscm1) — LibOneStepClaimMigration

**Gas / Complexity note:** O(n) by beneficiary count

**Example:** Internal helper used by `migrate` after `fraction` and `ratio` are computed.

***

## LibTwoStepClaimMigration (LTSCM1)

### isActive (LTSCM1)

**Contract/Library:** LibTwoStepClaimMigration

**Description:** Returns whether a pending two-step migration is currently active.

**Detailed Description:** Reads the `active` flag from [`PendingMigrationStorage (LTSCM-S3)`](https://docs.cryptolegacy.app/documentation/data-structures-reference#pendingmigrationstorage-ltscm1-s3) so callers can decide whether a delayed migration flow is in progress.

**Parameters:**

* pms (LibTwoStepClaimMigration.PendingMigrationStorage, storage): Pending-migration storage reference

**Returns:**

* active (bool): `true` when a migration is pending

**Modifiers / Visibility / Mutability:**

* internal view

**Access Control:**

* Inherits caller permissions

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:**

* [blsLidoUnsafeClaimWithdrawals(uint256\[\],uint256\[\])](#blslidounsafeclaimwithdrawals-blsp1) — BeneficiaryLidoStakingPlugin

**Gas / Complexity note:** O(1)

**Example:** `bool active = LibTwoStepClaimMigration.isActive(pms);`

***

### getPendingTokens (LTSCM1)

**Contract/Library:** LibTwoStepClaimMigration

**Description:** Returns the token pair involved in the active pending migration.

**Detailed Description:** Exposes `tokenOut` and `tokenIn` from the pending-migration record so callers can read the source and destination token addresses before completing the delayed flow.

**Parameters:**

* pms (LibTwoStepClaimMigration.PendingMigrationStorage, storage): Pending-migration storage reference

**Returns:**

* tokenOut (address): Source token whose balance previously decreased
* tokenIn (address): Destination token expected to arrive later

**Modifiers / Visibility / Mutability:**

* internal view

**Access Control:**

* Inherits caller permissions

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:**

* [blsLidoClaimWithdrawals(uint256\[\])](#blslidoclaimwithdrawals-blsp1) — BeneficiaryLidoStakingPlugin

**Gas / Complexity note:** O(1)

**Example:** `(tokenOut, tokenIn) = LibTwoStepClaimMigration.getPendingTokens(pms);`

***

### start (LTSCM1)

**Contract/Library:** LibTwoStepClaimMigration

**Description:** Starts a delayed claim migration when the source token leaves before the destination token arrives.

**Detailed Description:** Caches each beneficiary's claimed balances for the source and destination tokens, locks both claim slots with [`CLAIM_LOCK_AMOUNT (LTSCM-D1)`](https://docs.cryptolegacy.app/documentation/data-structures-reference#claim_lock_amount-ltscm1-d1), and records the pending migration parameters used later by `complete`.

**Parameters:**

* cls (ICryptoLegacy.CryptoLegacyStorage, storage): CryptoLegacy storage reference
* pms (LibTwoStepClaimMigration.PendingMigrationStorage, storage): Pending-migration storage reference
* tokenOut (address): Source token whose balance decreased
* tokenIn (address): Destination token expected later
* outBalanceBefore (uint256): Source-token balance before the withdrawal request
* outBalanceAfter (uint256): Source-token balance after the withdrawal request

**Returns:** None

**Modifiers / Visibility / Mutability:**

* internal nonpayable

**Access Control:**

* Inherits caller permissions

**Side Effects:**

* Clears cached beneficiary-hash ordering for the new migration
* Caches each beneficiary's pre-migration claimed balances
* Locks both claim slots with `CLAIM_LOCK_AMOUNT`
* Stores the pending migration metadata in [`PendingMigrationStorage (LTSCM-S3)`](https://docs.cryptolegacy.app/documentation/data-structures-reference#pendingmigrationstorage-ltscm1-s3)

**Emits:** None

**Reverts if:**

* A migration is already active — [`PendingMigrationAlreadyExists(address)`](https://docs.cryptolegacy.app/documentation/errors-reference#pendingmigrationalreadyexists-ltscm1)
* The source-token delta is invalid — [`MigrationInvalidDelta(uint256,uint256,uint256)`](https://docs.cryptolegacy.app/documentation/errors-reference#migrationinvaliddelta-lcmc1)
* Either token is already claim-locked — [`TokenAlreadyLocked(address)`](https://docs.cryptolegacy.app/documentation/errors-reference#tokenalreadylocked-ltscm1)

**Overrides:** None

**Function Calls:**

* `EnumerableSet.Bytes32Set.values()` — OpenZeppelin EnumerableSet, internal
* [LibCryptoLegacy.\_getBeneficiaryClaimed(ICryptoLegacy.CryptoLegacyStorage,bytes32,address)](#_getbeneficiaryclaimed-lcl1) — LibCryptoLegacy, internal
* [LibCryptoLegacy.\_setBeneficiaryClaimed(ICryptoLegacy.CryptoLegacyStorage,bytes32,address,uint256)](#_setbeneficiaryclaimed-lcl1) — LibCryptoLegacy, internal

**Called by:**

* [blsLidoRequestStEthWithdrawal(uint256\[\])](#blslidorequeststethwithdrawal-blsp1) — BeneficiaryLidoStakingPlugin
* [blsLidoRequestWstEthWithdrawal(uint256\[\])](#blslidorequestwstethwithdrawal-blsp1) — BeneficiaryLidoStakingPlugin

**Gas / Complexity note:** O(n) by beneficiary count

**Example:** `LibTwoStepClaimMigration.start(cls, pms, tokenOut, tokenIn, outBefore, outAfter);`

***

### complete (LTSCM1)

**Contract/Library:** LibTwoStepClaimMigration

**Description:** Completes a delayed migration after the destination token arrives.

**Detailed Description:** Verifies that a pending migration exists, reapplies cached beneficiary claims using the newly observed `amountIn`, synchronizes token-distribution totals, and clears the pending migration record.

**Parameters:**

* cls (ICryptoLegacy.CryptoLegacyStorage, storage): CryptoLegacy storage reference
* pms (LibTwoStepClaimMigration.PendingMigrationStorage, storage): Pending-migration storage reference
* outBalanceAfter (uint256): Source-token balance after the delayed flow finishes
* inBalanceAfter (uint256): Destination-token balance after the delayed flow finishes
* amountIn (uint256): Amount of destination token received during completion

**Returns:** None

**Modifiers / Visibility / Mutability:**

* internal nonpayable

**Access Control:**

* Inherits caller permissions

**Side Effects:**

* Restores and migrates beneficiary claim balances from the cached snapshot
* Updates distribution totals through `syncDistributions`
* Clears the active pending migration record

**Emits:** None

**Reverts if:**

* No migration is active — [`NoPendingMigration()`](https://docs.cryptolegacy.app/documentation/errors-reference#nopendingmigration-ltscm1)
* The completion delta is invalid — [`MigrationInvalidDelta(uint256,uint256,uint256)`](https://docs.cryptolegacy.app/documentation/errors-reference#migrationinvaliddelta-lcmc1)
* The computed migration ratio rounds to zero — [`MigrationAmountTooSmall(uint256,uint256,uint256,uint256,uint256)`](https://docs.cryptolegacy.app/documentation/errors-reference#migrationamounttoosmall-lcmc1)

**Overrides:** None

**Function Calls:**

* [\_applyPendingMigration](#_applypendingmigration-ltscm1) — LibTwoStepClaimMigration, internal
* [LibClaimMigrationCore.syncDistributions(ICryptoLegacy.CryptoLegacyStorage,address,address,uint256,uint256,uint256,uint256)](#syncdistributions-lcmc1) — LibClaimMigrationCore, internal

**Called by:**

* [blsLidoClaimWithdrawals(uint256\[\])](#blslidoclaimwithdrawals-blsp1) — BeneficiaryLidoStakingPlugin

**Gas / Complexity note:** O(n) by cached beneficiary count

**Example:** `LibTwoStepClaimMigration.complete(cls, pms, outAfter, inAfter, amountIn);`

***

### abandon (LTSCM1)

**Contract/Library:** LibTwoStepClaimMigration

**Description:** Abandons an active pending migration and restores cached claim state.

**Detailed Description:** Acts as an escape hatch for delayed flows that can no longer be completed fairly. It restores each beneficiary's cached `tokenOut` and `tokenIn` claimed balances, clears cached migration state, and returns the token pair that was being migrated.

**Parameters:**

* cls (ICryptoLegacy.CryptoLegacyStorage, storage): CryptoLegacy storage reference
* pms (LibTwoStepClaimMigration.PendingMigrationStorage, storage): Pending-migration storage reference

**Returns:**

* tokenOut (address): Source token from the abandoned migration
* tokenIn (address): Destination token from the abandoned migration

**Modifiers / Visibility / Mutability:**

* internal nonpayable

**Access Control:**

* Inherits caller permissions

**Side Effects:**

* Restores cached claimed balances for every beneficiary
* Deletes cached migration state and deactivates the pending migration record

**Emits:** None

**Reverts if:**

* No migration is active — [`NoPendingMigration()`](https://docs.cryptolegacy.app/documentation/errors-reference#nopendingmigration-ltscm1)

**Overrides:** None

**Function Calls:**

* [LibCryptoLegacy.\_setBeneficiaryClaimed(ICryptoLegacy.CryptoLegacyStorage,bytes32,address,uint256)](#_setbeneficiaryclaimed-lcl1) — LibCryptoLegacy, internal

**Called by:**

* [blsLidoAbandonMigration()](#blslidoabandonmigration-blsp1) — BeneficiaryLidoStakingPlugin

**Gas / Complexity note:** O(n) by cached beneficiary count

**Example:** `(tokenOut, tokenIn) = LibTwoStepClaimMigration.abandon(cls, pms);`

***

### \_applyPendingMigration (LTSCM1)

**Contract/Library:** LibTwoStepClaimMigration

**Description:** Applies the cached pending-migration snapshot to all beneficiaries.

**Detailed Description:** Uses the stored `PendingMigration` record plus the newly received `amountIn` to compute the migration ratio, reapplies migrated claim balances to every cached beneficiary, accumulates the new global claimed totals, and clears cached claim records.

**Parameters:**

* cls (ICryptoLegacy.CryptoLegacyStorage, storage): CryptoLegacy storage reference
* pms (LibTwoStepClaimMigration.PendingMigrationStorage, storage): Pending-migration storage reference
* pending (LibTwoStepClaimMigration.PendingMigration, storage): Active pending-migration record
* amountIn (uint256): Destination-token amount received during completion

**Returns:**

* totalClaimedOut (uint256): Aggregate claimed amount for the source token after migration
* totalClaimedIn (uint256): Aggregate claimed amount for the destination token after migration

**Modifiers / Visibility / Mutability:**

* private nonpayable

**Access Control:**

* Internal helper only

**Side Effects:**

* Rewrites each cached beneficiary's claimed balances for `pending.tokenOut` and `pending.tokenIn`
* Deletes cached claim records and beneficiary-hash ordering once applied

**Emits:** None

**Reverts if:**

* The pending migration delta is invalid — [`MigrationInvalidDelta(uint256,uint256,uint256)`](https://docs.cryptolegacy.app/documentation/errors-reference#migrationinvaliddelta-lcmc1)
* The computed ratio rounds to zero — [`MigrationAmountTooSmall(uint256,uint256,uint256,uint256,uint256)`](https://docs.cryptolegacy.app/documentation/errors-reference#migrationamounttoosmall-lcmc1)

**Overrides:** None

**Function Calls:**

* [LibClaimMigrationCore.calculateFractionAndRatio(uint256,uint256,uint256)](#calculatefractionandratio-lcmc1) — LibClaimMigrationCore, internal
* [LibClaimMigrationCore.applyMigrationFormula(uint256,uint256,uint256,uint256)](#applymigrationformula-lcmc1) — LibClaimMigrationCore, internal
* [LibCryptoLegacy.\_setBeneficiaryClaimed(ICryptoLegacy.CryptoLegacyStorage,bytes32,address,uint256)](#_setbeneficiaryclaimed-lcl1) — LibCryptoLegacy, internal

**Called by:**

* [complete](#complete-ltscm1) — LibTwoStepClaimMigration

**Gas / Complexity note:** O(n) by cached beneficiary count

**Example:** Internal helper used by `complete` after the destination-token receipt is known.

***

## LibCryptoLegacy (LCL1)

### getCryptoLegacyStorage (LCL1)

**Contract/Library:** LibCryptoLegacy

**Description:** Returns the storage slot backing the CryptoLegacy diamond data.

**Detailed Description:** Uses the fixed [`CRYPTO_LEGACY_STORAGE_POSITION`](https://docs.cryptolegacy.app/documentation/data-structures-reference#crypto_legacy_storage_position-lcl1-d6) and inline assembly to bind a [`ICryptoLegacy.CryptoLegacyStorage`](https://docs.cryptolegacy.app/documentation/data-structures-reference#cryptolegacystorage-icl1-s4) pointer, letting library helpers read and mutate shared state.

**Parameters:** None

**Returns:**

* storageStruct ([ICryptoLegacy.CryptoLegacyStorage](https://docs.cryptolegacy.app/documentation/data-structures-reference#cryptolegacystorage-icl1-s4), storage): Pointer to the diamond’s storage layout

**Modifiers / Visibility / Mutability:**

* internal pure

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:**

* [constructor](#constructor-cl1) — CryptoLegacy
* [replacePlugin](#replaceplugin-cl1) — CryptoLegacy
* [addPluginList](#addpluginlist-cl1) — CryptoLegacy
* [removePluginList](#removepluginlist-cl1) — CryptoLegacy
* [externalLens](#externallens-cl1) — CryptoLegacy
* [fallback](#fallback-cldb1) — CryptoLegacyDiamondBase
* [acceptOwnership](#acceptownership-clo1) — CryptoLegacyOwnable
* [setPause](#setpause-clo1) — CryptoLegacyOwnable
* [pendingOwner](#pendingowner-clo1) — CryptoLegacyOwnable
* [\_checkOwner](#_checkowner-lcl1) — LibCryptoLegacy
* [\_getVotersAndConfirmations](#_getvotersandconfirmations-lsmb1) — LibSafeMinimalBeneficiaryMultisig
* [\_initializeIfNot](#_initializeifnot-lsmb1) — LibSafeMinimalBeneficiaryMultisig
* [\_propose](#_propose-lsmb1) — LibSafeMinimalBeneficiaryMultisig
* [\_confirm](#_confirm-lsmb1) — LibSafeMinimalBeneficiaryMultisig
* [\_cancel](#_cancel-lsmb1) — LibSafeMinimalBeneficiaryMultisig
* [barSetMultisigConfig](#barsetmultisigconfig-bpar1) — BeneficiaryPluginAddRights
* [barAddPluginList(address\[\])](#baraddpluginlist-bpar1) — BeneficiaryPluginAddRights
* [barWithdrawHeldEth](#barwithdrawheldeth-bpar1) — BeneficiaryPluginAddRights
* [initializeByBuildManager(uint256,uint256,bytes32\[\],BeneficiaryConfig\[\],bytes8,uint64,uint64)](#initializebybuildmanager-clbp1) — CryptoLegacyBasePlugin
* [transferOwnership](#transferownership-clbp1) — CryptoLegacyBasePlugin
* [payInitialFee](#payinitialfee-clbp1) — CryptoLegacyBasePlugin
* [setGasLimitMultiplier](#setgaslimitmultiplier-clbp1) — CryptoLegacyBasePlugin
* [initiateChallenge](#initiatechallenge-clbp1) — CryptoLegacyBasePlugin
* [transferTreasuryTokensToLegacy](#transfertreasurytokenstolegacy-clbp1) — CryptoLegacyBasePlugin
* [beneficiaryClaim](#beneficiaryclaim-clbp1) — CryptoLegacyBasePlugin
* [beneficiarySwitch](#beneficiaryswitch-clbp1) — CryptoLegacyBasePlugin
* [lrSetMultisigConfig(bytes32\[\],uint8)](#lrsetmultisigconfig-lrp1) — LegacyRecoveryPlugin
* [lrPropose](#lrpropose-lrp1) — LegacyRecoveryPlugin
* [lrConfirm](#lrconfirm-lrp1) — LegacyRecoveryPlugin
* [lrCancel](#lrcancel-lrp1) — LegacyRecoveryPlugin
* [lrResetGuardianVoting](#lrresetguardianvoting-lrp1) — LegacyRecoveryPlugin

**Gas / Complexity note:** O(1)

**Example:** Internal helpers call this to obtain the shared storage pointer before enforcing permissions.

***

### \_checkDisabledFunc (LCL1)

**Contract/Library:** LibCryptoLegacy

**Description:** Ensures a flagged core function is not disabled by configuration.

**Detailed Description:** Performs a bitwise AND between `cls.defaultFuncDisabled` and `_funcFlag`; if non-zero the helper reverts, blocking execution of disabled workflows (for example, beneficiary claims).

**Parameters:**

* cls ([ICryptoLegacy.CryptoLegacyStorage](https://docs.cryptolegacy.app/documentation/data-structures-reference#cryptolegacystorage-icl1-s4), storage): CryptoLegacy storage reference
* \_funcFlag (uint8): Bitmask representing the guarded function

**Returns:** None

**Modifiers / Visibility / Mutability:**

* internal view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:**

* Flag is enabled in `defaultFuncDisabled` — [`ICryptoLegacy.DisabledFunc()`](https://docs.cryptolegacy.app/documentation/errors-reference#disabledfunc-icl1)

**Overrides:** None

**Function Calls:** None

**Called by:**

* [beneficiaryClaim](#beneficiaryclaim-clbp1) — CryptoLegacyBasePlugin

**Gas / Complexity note:** O(1)

**Example:** Stops a claim attempt when the owner has disabled beneficiary withdrawals.

***

### \_checkDistributionStart (LCL1)

**Contract/Library:** LibCryptoLegacy

**Description:** Guards flows that must execute before distribution begins.

**Detailed Description:** Delegates to `_isDistributionStarted`; if distribution has already begun it reverts, preventing pre-distribution management actions.

**Parameters:**

* cls ([ICryptoLegacy.CryptoLegacyStorage](https://docs.cryptolegacy.app/documentation/data-structures-reference#cryptolegacystorage-icl1-s4), storage): CryptoLegacy storage reference

**Returns:** None

**Modifiers / Visibility / Mutability:**

* internal view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:**

* Distribution already started — [`ICryptoLegacy.DistributionStarted()`](https://docs.cryptolegacy.app/documentation/errors-reference#distributionstarted-icl1)

**Overrides:** None

**Function Calls:**

* [\_isDistributionStarted(ICryptoLegacy.CryptoLegacyStorage)](#_isdistributionstarted-lcl1) — LibCryptoLegacy, internal

**Called by:**

* [\_checkOwner](#_checkowner-lcl1) — LibCryptoLegacy
* [lrResetGuardianVoting](#lrresetguardianvoting-lrp1) — LegacyRecoveryPlugin
* [modifier onlyUpdater](#modifier-onlyupdater-urp1) — UpdateRolePlugin

**Gas / Complexity note:** O(1)

**Example:** Owner attempts to reconfigure beneficiaries before distribution starts.

***

### \_isDistributionStarted (LCL1)

**Contract/Library:** LibCryptoLegacy

**Description:** Reports whether the distribution window is active.

**Detailed Description:** Returns true when `distributionStartAt` is set and earlier than the current block timestamp, signalling that beneficiaries may claim.

**Parameters:**

* cls ([ICryptoLegacy.CryptoLegacyStorage](https://docs.cryptolegacy.app/documentation/data-structures-reference#cryptolegacystorage-icl1-s4), storage): CryptoLegacy storage reference

**Returns:**

* started (bool): True once distribution has begun

**Modifiers / Visibility / Mutability:**

* internal view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:**

* [\_checkDistributionStart](#_checkdistributionstart-lcl1) — LibCryptoLegacy
* [\_checkDistributionReady](#_checkdistributionready-lcl1) — LibCryptoLegacy
* [\_takeFee(ICryptoLegacy.CryptoLegacyStorage,address,address,uint256,uint256\[\],uint256\[\])](#_takefee-lcl1) — LibCryptoLegacy

**Gas / Complexity note:** O(1)

**Example:** Helper logic branches on this flag to enable post-distribution behaviour.

***

### \_checkOwner (LCL1)

**Contract/Library:** LibCryptoLegacy

**Description:** Enforces that the caller is the diamond owner and the initial fee was paid.

**Detailed Description:** Loads storage via `getCryptoLegacyStorage`, ensures distribution has not started, checks `lastFeePaidAt != 0`, then verifies the caller through `_checkSenderOwner`.

**Parameters:** None

**Returns:** None

**Modifiers / Visibility / Mutability:**

* internal view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:**

* Distribution already started — [`ICryptoLegacy.DistributionStarted()`](https://docs.cryptolegacy.app/documentation/errors-reference#distributionstarted-icl1)
* Initial fee unpaid — [`ICryptoLegacy.InitialFeeNotPaid()`](https://docs.cryptolegacy.app/documentation/errors-reference#initialfeenotpaid-icl1)
* Caller is not the owner — [`ICryptoLegacy.NotTheOwner()`](https://docs.cryptolegacy.app/documentation/errors-reference#nottheowner-icl1)

**Overrides:** None

**Function Calls:**

* [getCryptoLegacyStorage()](#getcryptolegacystorage-lcl1) — LibCryptoLegacy, internal
* [\_checkDistributionStart(ICryptoLegacy.CryptoLegacyStorage)](#_checkdistributionstart-lcl1) — LibCryptoLegacy, internal
* [\_checkSenderOwner()](#_checksenderowner-lcl1) — LibCryptoLegacy, internal

**Called by:**

* [modifier onlyOwner](#modifier-onlyowner-clo1) — CryptoLegacyOwnable
* [modifier onlyOwner](#modifier-onlyowner-bpar1) — BeneficiaryPluginAddRights
* [barSetMultisigConfig](#barsetmultisigconfig-bpar1) — BeneficiaryPluginAddRights
* [modifier onlyOwner](#modifier-onlyowner-lrp1) — LegacyRecoveryPlugin
* [modifier onlyOwner](#modifier-onlyowner-nlp1) — NftLegacyPlugin
* [modifier onlyOwner](#modifier-onlyowner-tgp1) — TrustedGuardiansPlugin
* [modifier onlyOwner](#modifier-onlyowner-urp1) — UpdateRolePlugin

**Gas / Complexity note:** O(1)

**Example:** Owner-gated admin flows invoke this helper before executing sensitive changes.

***

### \_checkSenderOwner (LCL1)

**Contract/Library:** LibCryptoLegacy

**Description:** Validates that `msg.sender` matches the diamond owner.

**Detailed Description:** Reads `LibDiamond.contractOwner()` and reverts with `NotTheOwner` if the caller differs.

**Parameters:** None

**Returns:** None

**Modifiers / Visibility / Mutability:**

* internal view

**Access Control:**

* Owner only (enforced via LibDiamond.contractOwner())

**Side Effects:** None

**Emits:** None

**Reverts if:**

* Caller is not the owner — [`ICryptoLegacy.NotTheOwner()`](https://docs.cryptolegacy.app/documentation/errors-reference#nottheowner-icl1)

**Overrides:** None

**Function Calls:**

* [contractOwner()](#contractowner-ld1) — LibDiamond, internal

**Called by:**

* [\_checkOwner](#_checkowner-lcl1) — LibCryptoLegacy

**Gas / Complexity note:** O(1)

**Example:** Used internally after verifying distribution timing and fee status.

***

### \_checkPause (LCL1)

**Contract/Library:** LibCryptoLegacy

**Description:** Blocks execution when the CryptoLegacy contract is paused.

**Detailed Description:** Reads the cached pause flag via `_getPause`; if true, reverts to prevent state changes while paused.

**Parameters:**

* cls ([ICryptoLegacy.CryptoLegacyStorage](https://docs.cryptolegacy.app/documentation/data-structures-reference#cryptolegacystorage-icl1-s4), storage): CryptoLegacy storage reference

**Returns:** None

**Modifiers / Visibility / Mutability:**

* internal view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:**

* Pause flag enabled — [`ICryptoLegacy.Pause()`](https://docs.cryptolegacy.app/documentation/errors-reference#pause-icl1)

**Overrides:** None

**Function Calls:**

* [\_getPause(ICryptoLegacy.CryptoLegacyStorage)](#_getpause-lcl1) — LibCryptoLegacy, internal

**Called by:**

* [initiateChallenge](#initiatechallenge-clbp1) — CryptoLegacyBasePlugin
* [transferTreasuryTokensToLegacy](#transfertreasurytokenstolegacy-clbp1) — CryptoLegacyBasePlugin
* [beneficiaryClaim](#beneficiaryclaim-clbp1) — CryptoLegacyBasePlugin

**Gas / Complexity note:** O(1)

**Example:** Critical flows exit early when the owner pauses the CryptoLegacy contract.

***

### \_setPause (LCL1)

**Contract/Library:** LibCryptoLegacy

**Description:** Updates the pause flag while distribution is inactive.

**Detailed Description:** Requires `distributionStartAt` to be unset, toggles `cls.isPaused`, and emits `PauseSet`.

**Parameters:**

* cls ([ICryptoLegacy.CryptoLegacyStorage](https://docs.cryptolegacy.app/documentation/data-structures-reference#cryptolegacystorage-icl1-s4), storage): CryptoLegacy storage reference
* \_isPaused (bool): Desired pause status

**Returns:** None

**Modifiers / Visibility / Mutability:**

* internal nonpayable

**Access Control:**

* Unrestricted

**Side Effects:**

* Updates `cls.isPaused`

**Emits:**

* [PauseSet](https://docs.cryptolegacy.app/documentation/events-reference#pauseset-icl1) — `PauseSet(bool indexed isPaused)`

**Reverts if:**

* Challenge period already scheduled — [`ICryptoLegacy.ChallengePeriodStarted()`](https://docs.cryptolegacy.app/documentation/errors-reference#challengeperiodstarted-icl1)

**Overrides:** None

**Function Calls:** None

**Called by:**

* [setPause](#setpause-clo1) — CryptoLegacyOwnable
* [initializeByBuildManager(uint256,uint256,bytes32\[\],BeneficiaryConfig\[\],bytes8,uint64,uint64)](#initializebybuildmanager-clbp1) — CryptoLegacyBasePlugin
* [payInitialFee](#payinitialfee-clbp1) — CryptoLegacyBasePlugin

**Gas / Complexity note:** O(1)

**Example:** Owner pauses the CryptoLegacy contract for emergency maintenance.

***

### \_getPause (LCL1)

**Contract/Library:** LibCryptoLegacy

**Description:** Reads the pause status from storage.

**Detailed Description:** Returns the cached pause flag stored in `cls.isPaused`.

**Parameters:**

* cls ([ICryptoLegacy.CryptoLegacyStorage](https://docs.cryptolegacy.app/documentation/data-structures-reference#cryptolegacystorage-icl1-s4), storage): CryptoLegacy storage reference

**Returns:**

* isPaused (bool): Current pause state

**Modifiers / Visibility / Mutability:**

* internal view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:**

* [\_checkPause](#_checkpause-lcl1) — LibCryptoLegacy
* [isPaused](#ispaused-clbp1) — CryptoLegacyBasePlugin

**Gas / Complexity note:** O(1)

**Example:** Read helper used by frontends to display paused state.

***

### \_checkAddressIsBeneficiary (LCL1)

**Contract/Library:** LibCryptoLegacy

**Description:** Verifies that an address corresponds to a registered beneficiary.

**Detailed Description:** Converts `_addr` to its beneficiary hash via `_addressToHash` and checks membership in `cls.beneficiaries`, reverting if absent. Returns the hash for downstream use.

**Parameters:**

* cls ([ICryptoLegacy.CryptoLegacyStorage](https://docs.cryptolegacy.app/documentation/data-structures-reference#cryptolegacystorage-icl1-s4), storage): CryptoLegacy storage reference
* \_addr (address): Address asserted to be a beneficiary

**Returns:**

* beneficiary (bytes32): Beneficiary hash tied to `_addr`

**Modifiers / Visibility / Mutability:**

* internal view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:**

* `_addr` not present in the beneficiary set — [`ICryptoLegacy.NotTheBeneficiary()`](https://docs.cryptolegacy.app/documentation/errors-reference#notthebeneficiary-icl1)

**Overrides:** None

**Function Calls:**

* [\_addressToHash(address)](#_addresstohash-lcl1) — LibCryptoLegacy, internal

**Called by:**

* [initiateChallenge](#initiatechallenge-clbp1) — CryptoLegacyBasePlugin
* [beneficiarySwitch](#beneficiaryswitch-clbp1) — CryptoLegacyBasePlugin
* [\_checkDistributionReadyForBeneficiary](#_checkdistributionreadyforbeneficiary-lcl1) — LibCryptoLegacy

**Gas / Complexity note:** O(1)

**Example:** Beneficiary-level actions invoke this to confirm the sender is registered.

***

### \_checkDistributionReadyForBeneficiary (LCL1)

**Contract/Library:** LibCryptoLegacy

**Description:** Ensures the caller is a registered beneficiary and distribution is active.

**Detailed Description:** Calls `_checkAddressIsBeneficiary` on `msg.sender`, then `_checkDistributionReady` to confirm distribution has started; returns the caller’s beneficiary hash.

**Parameters:**

* cls ([ICryptoLegacy.CryptoLegacyStorage](https://docs.cryptolegacy.app/documentation/data-structures-reference#cryptolegacystorage-icl1-s4), storage): CryptoLegacy storage reference

**Returns:**

* beneficiary (bytes32): Hash of `msg.sender` as a beneficiary

**Modifiers / Visibility / Mutability:**

* internal view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:**

* Caller is not a beneficiary — [`ICryptoLegacy.NotTheBeneficiary()`](https://docs.cryptolegacy.app/documentation/errors-reference#notthebeneficiary-icl1) (via `_checkAddressIsBeneficiary`)
* Distribution not yet started — [`ICryptoLegacy.TooEarly()`](https://docs.cryptolegacy.app/documentation/errors-reference#tooearly-icl1) (via `_checkDistributionReady`)

**Overrides:** None

**Function Calls:**

* [\_checkAddressIsBeneficiary(ICryptoLegacy.CryptoLegacyStorage,address)](#_checkaddressisbeneficiary-lcl1) — LibCryptoLegacy, internal
* [\_checkDistributionReady(ICryptoLegacy.CryptoLegacyStorage)](#_checkdistributionready-lcl1) — LibCryptoLegacy, internal

**Called by:**

* [transferTreasuryTokensToLegacy](#transfertreasurytokenstolegacy-clbp1) — CryptoLegacyBasePlugin
* [beneficiaryClaim](#beneficiaryclaim-clbp1) — CryptoLegacyBasePlugin

**Gas / Complexity note:** O(1)

**Example:** A beneficiary claim checks both identity and distribution readiness via this helper.

***

### \_checkDistributionReady (LCL1)

**Contract/Library:** LibCryptoLegacy

**Description:** Validates that the distribution window is open.

**Detailed Description:** Delegates to `_isDistributionStarted` and reverts with `TooEarly` when distribution has not yet begun.

**Parameters:**

* cls ([ICryptoLegacy.CryptoLegacyStorage](https://docs.cryptolegacy.app/documentation/data-structures-reference#cryptolegacystorage-icl1-s4), storage): CryptoLegacy storage reference

**Returns:** None

**Modifiers / Visibility / Mutability:**

* internal view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:**

* Distribution not started — [`ICryptoLegacy.TooEarly()`](https://docs.cryptolegacy.app/documentation/errors-reference#tooearly-icl1)

**Overrides:** None

**Function Calls:**

* [\_isDistributionStarted(ICryptoLegacy.CryptoLegacyStorage)](#_isdistributionstarted-lcl1) — LibCryptoLegacy, internal

**Called by:**

* [\_checkDistributionReadyForBeneficiary](#_checkdistributionreadyforbeneficiary-lcl1) — LibCryptoLegacy
* [barSetMultisigConfig](#barsetmultisigconfig-bpar1) — BeneficiaryPluginAddRights
* [barPropose](#barpropose-bpar1) — BeneficiaryPluginAddRights
* [barConfirm](#barconfirm-bpar1) — BeneficiaryPluginAddRights
* [barCancel](#barcancel-bpar1) — BeneficiaryPluginAddRights
* [barAddPluginList(address\[\])](#baraddpluginlist-bpar1) — BeneficiaryPluginAddRights
* [transferTreasuryTokensToLegacy](#transfertreasurytokenstolegacy-clbp1) — CryptoLegacyBasePlugin
* [transferNftTokensToLegacy](#transfernfttokenstolegacy-nlp1) — NftLegacyPlugin
* [beneficiaryClaimNft](#beneficiaryclaimnft-nlp1) — NftLegacyPlugin
* [guardiansTransferTreasuryTokensToLegacy](#guardianstransfertreasurytokenstolegacy-tgp1) — TrustedGuardiansPlugin

**Gas / Complexity note:** O(1)

**Example:** Used to confirm the claim window before moving assets from treasury to the CryptoLegacy contract.

***

### \_getBeneficiariesCount (LCL1)

**Contract/Library:** LibCryptoLegacy

**Description:** Returns the number of registered beneficiaries.

**Detailed Description:** Reads the beneficiary `EnumerableSet` length, exposing how many beneficiaries are tracked.

**Parameters:**

* cls ([ICryptoLegacy.CryptoLegacyStorage](https://docs.cryptolegacy.app/documentation/data-structures-reference#cryptolegacystorage-icl1-s4), storage): CryptoLegacy storage reference

**Returns:**

* count (uint256): Number of beneficiary hashes stored

**Modifiers / Visibility / Mutability:**

* internal view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:**

* [\_getDefaultRequiredConfirmations](#_getdefaultrequiredconfirmations-lsmb1) — LibSafeMinimalBeneficiaryMultisig

**Gas / Complexity note:** O(1)

**Example:** Used to size data structures when iterating beneficiaries.

***

### \_isLifetimeActiveAndUpdate (LCL1)

**Contract/Library:** LibCryptoLegacy

**Description:** Queries the build manager to determine if a lifetime NFT is locked and updates state accordingly.

**Detailed Description:** Calls `buildManager.isLifetimeNftLockedAndUpdate` with a tuned gas limit. If the call succeeds, returns the boolean result. If it reverts with known errors, the helper rethrows them; otherwise it emits `IsLifetimeNftLockedAndUpdateCatch` with the raw revert reason and returns `false`.

**Parameters:**

* cls ([ICryptoLegacy.CryptoLegacyStorage](https://docs.cryptolegacy.app/documentation/data-structures-reference#cryptolegacystorage-icl1-s4), storage): CryptoLegacy storage reference
* \_owner (address): CryptoLegacy owner whose lifetime NFT status is checked

**Returns:**

* isNftLocked (bool): True when a lifetime NFT lock is active

**Modifiers / Visibility / Mutability:**

* internal nonpayable

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:**

* [IsLifetimeNftLockedAndUpdateCatch](https://docs.cryptolegacy.app/documentation/events-reference#islifetimenftlockedandupdatecatch-icl1) — `IsLifetimeNftLockedAndUpdateCatch(bytes reason)`

**Reverts if:**

* Build manager reports CryptoLegacy not registered — [`ICryptoLegacyBuildManager.NotRegisteredCryptoLegacy()`](https://docs.cryptolegacy.app/documentation/errors-reference#notregisteredcryptolegacy-iclbm1)
* Build manager reports caller not owner — [`ICryptoLegacyBuildManager.NotOwnerOfCryptoLegacy()`](https://docs.cryptolegacy.app/documentation/errors-reference#notownerofcryptolegacy-iclbm1)

**Overrides:** None

**Function Calls:**

* [\_gasBySelector(ICryptoLegacy.CryptoLegacyStorage,bytes4)](#_gasbyselector-lcl1) — LibCryptoLegacy, internal
* `ICryptoLegacyBuildManager.isLifetimeNftLockedAndUpdate(address)` — `ICryptoLegacyBuildManager` *(at `cls.buildManager`)*, external

**Called by:**

* [\_takeFee(ICryptoLegacy.CryptoLegacyStorage,address,address,uint256,uint256\[\],uint256\[\])](#_takefee-lcl1) — LibCryptoLegacy
* [payInitialFee](#payinitialfee-clbp1) — CryptoLegacyBasePlugin

**Gas / Complexity note:** O(1) aside from external build-manager call cost

**Example:** Fee logic checks this flag to bypass payments when a lifetime NFT keeps the plan current.

***

### \_takeFee (LCL1)

**Contract/Library:** LibCryptoLegacy

**Description:** Core fee processing routine covering lifetime, build-manager, and manual transfer paths.

**Detailed Description:** Evaluates lifetime NFT status via `_isLifetimeActiveAndUpdate`; when active, enforces zero `msg.value`, updates `lastFeePaidAt`, and emits `FeePaidByLifetime`. Otherwise it checks whether a fee cycle is due (`mul >= 1 || msg.value != 0`); if not, the helper exits early without changing state. When distribution has started it increments `lastFeePaidAt` by the multiplier and settles the payment through `_sendFeeByTransfer`. In the pre-distribution path it updates `lastFeePaidAt`, optionally refreshes `updateFee` via the build manager, validates cross-chain array length, and attempts to pay through `buildManager.payFee`. On success it refunds any remainder to the caller and emits `FeePaidByDefault`; on failure it validates `msg.value` with `_checkFee`, falls back to `_sendFeeByTransfer` (with referral disabled), and records the revert reason in a catch event.

**Parameters:**

* cls ([ICryptoLegacy.CryptoLegacyStorage](https://docs.cryptolegacy.app/documentation/data-structures-reference#cryptolegacystorage-icl1-s4), storage): CryptoLegacy storage reference
* \_owner (address): Owner address used for lifetime checks and referral accounting
* \_ref (address): Optional referral recipient
* \_refShare (uint256): Referral share in basis points (1e4 base)
* \_lockToChainIds (uint256\[], memory): Chain IDs for cross-chain fee locking
* \_crossChainFees (uint256\[], memory): Fees per chain matching `_lockToChainIds`

**Returns:** None

**Modifiers / Visibility / Mutability:**

* internal nonpayable

**Access Control:**

* Unrestricted

**Side Effects:**

* Updates `cls.lastFeePaidAt`
* Updates `cls.updateFee` when the build manager returns a new value
* Transfers ETH to the build manager, optional referral, and refunds surplus to the caller

**Emits:**

* [FeePaidByLifetime](https://docs.cryptolegacy.app/documentation/events-reference#feepaidbylifetime-icl1) — `FeePaidByLifetime(bytes8 indexed refCode, bool indexed initial, address factory, uint64 lastFeePaidAt)`
* [GetUpdateFeeCatch](https://docs.cryptolegacy.app/documentation/events-reference#getupdatefeecatch-icl1) — `GetUpdateFeeCatch(bytes reason)`
* [FeePaidByDefault](https://docs.cryptolegacy.app/documentation/events-reference#feepaidbydefault-icl1) — `FeePaidByDefault(bytes8 indexed refCode, bool indexed initial, uint256 value, uint256 returnedValue, address factory, uint64 lastFeePaidAt)`
* [PayFeeCatch](https://docs.cryptolegacy.app/documentation/events-reference#payfeecatch-icl1) — `PayFeeCatch(bytes reason)`

**Reverts if:**

* Lifetime NFT check finds caller misconfigured — [`ICryptoLegacyBuildManager.NotRegisteredCryptoLegacy()`](https://docs.cryptolegacy.app/documentation/errors-reference#notregisteredcryptolegacy-iclbm1) (via [\_isLifetimeActiveAndUpdate](#_islifetimeactiveandupdate-lcl1))
* Lifetime NFT check finds caller not owner — [`ICryptoLegacyBuildManager.NotOwnerOfCryptoLegacy()`](https://docs.cryptolegacy.app/documentation/errors-reference#notownerofcryptolegacy-iclbm1) (via [\_isLifetimeActiveAndUpdate](#_islifetimeactiveandupdate-lcl1))
* Lifetime NFT path provided ETH — [`ICryptoLegacy.NoValueAllowed()`](https://docs.cryptolegacy.app/documentation/errors-reference#novalueallowed-icl1) (via [\_checkNoFee](#_checknofee-lcl1))
* `_lockToChainIds.length` exceeds limit — [`ICryptoLegacy.TooLongArray(uint256)`](https://docs.cryptolegacy.app/documentation/errors-reference#toolongarray-icl1)
* Observed fee mismatch — [`ICryptoLegacy.IncorrectFee(uint256)`](https://docs.cryptolegacy.app/documentation/errors-reference#incorrectfee-icl1) (via [\_checkFee](#_checkfee-lcl1))
* Referral share exceeds basis points — [`ICryptoLegacy.IncorrectRefShare()`](https://docs.cryptolegacy.app/documentation/errors-reference#incorrectrefshare-icl1) (via [\_sendFeeByTransfer](#_sendfeebytransfer-lcl1))
* ETH forwarding or refund fails — [`ICryptoLegacy.TransferFeeFailed(bytes)`](https://docs.cryptolegacy.app/documentation/errors-reference#transferfeefailed-icl1) (via [\_transferFee](#_transferfee-lcl1))

**Overrides:** None

**Function Calls:**

* [\_isLifetimeActiveAndUpdate(ICryptoLegacy.CryptoLegacyStorage,address)](#_islifetimeactiveandupdate-lcl1) — LibCryptoLegacy, internal
* [\_checkNoFee()](#_checknofee-lcl1) — LibCryptoLegacy, internal
* [\_isDistributionStarted(ICryptoLegacy.CryptoLegacyStorage)](#_isdistributionstarted-lcl1) — LibCryptoLegacy, internal
* [\_sendFeeByTransfer(ICryptoLegacy.CryptoLegacyStorage,address,address,uint256)](#_sendfeebytransfer-lcl1) — LibCryptoLegacy, internal
* [\_gasBySelector(ICryptoLegacy.CryptoLegacyStorage,bytes4)](#_gasbyselector-lcl1) — LibCryptoLegacy, internal
* `ICryptoLegacyBuildManager.getUpdateFee(bytes8)` — `ICryptoLegacyBuildManager` *(at `cls.buildManager`)*, external
* [\_gasBySelector(ICryptoLegacy.CryptoLegacyStorage,bytes4)](#_gasbyselector-lcl1) — LibCryptoLegacy, internal
* [\_gasBySelector(ICryptoLegacy.CryptoLegacyStorage,bytes4)](#_gasbyselector-lcl1) — LibCryptoLegacy, internal
* `ICryptoLegacyBuildManager.payFee(bytes8,address,uint256,uint256[],uint256[])` — `ICryptoLegacyBuildManager` *(at `cls.buildManager`)*, external
* [\_transferFee(ICryptoLegacy.CryptoLegacyStorage,address,uint256)](#_transferfee-lcl1) — LibCryptoLegacy, internal
* [\_checkFee(uint256)](#_checkfee-lcl1) — LibCryptoLegacy, internal
* [\_sendFeeByTransfer(ICryptoLegacy.CryptoLegacyStorage,address,address,uint256)](#_sendfeebytransfer-lcl1) — LibCryptoLegacy, internal

**Called by:**

* [\_resetGuardianVoting](#_resetguardianvoting-ltgp1) — LibTrustedGuardiansPlugin
* [update](#update-clbp1) — CryptoLegacyBasePlugin
* [beneficiaryClaim](#beneficiaryclaim-clbp1) — CryptoLegacyBasePlugin
* [updateByUpdater](#updatebyupdater-urp1) — UpdateRolePlugin

**Gas / Complexity note:** O(n + m) where n = `_lockToChainIds.length`, m = `_crossChainFees.length`; dominated by external build-manager interactions.

**Example:** Automated upkeep calls this to settle recurring fees and refresh on-chain timestamps.

***

### \_checkFee (LCL1)

**Contract/Library:** LibCryptoLegacy

**Description:** Validates a fee payment matches expectations.

**Detailed Description:** Ensures `msg.value` is at least `_fee` and that any surplus does not exceed 0.00001 ether; otherwise reverts with `IncorrectFee`.

**Parameters:**

* \_fee (uint256): Required fee amount in wei

**Returns:** None

**Modifiers / Visibility / Mutability:**

* internal nonpayable

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:**

* `msg.value` < `_fee` or surplus exceeds tolerance — [`ICryptoLegacy.IncorrectFee(uint256)`](https://docs.cryptolegacy.app/documentation/errors-reference#incorrectfee-icl1)

**Overrides:** None

**Function Calls:** None

**Called by:**

* [\_takeFee(ICryptoLegacy.CryptoLegacyStorage,address,address,uint256,uint256\[\],uint256\[\])](#_takefee-lcl1) — LibCryptoLegacy
* [payInitialFee()](#payinitialfee-clbp1) — CryptoLegacyBasePlugin

**Gas / Complexity note:** O(1)

**Example:** Fallback fee flow checks user-supplied ETH against the billed amount.

***

### \_checkNoFee (LCL1)

**Contract/Library:** LibCryptoLegacy

**Description:** Reverts when `msg.value` is non-zero.

**Detailed Description:** Utility for paths that must receive zero ETH (e.g., lifetime NFT fee waivers).

**Parameters:** None

**Returns:** None

**Modifiers / Visibility / Mutability:**

* internal nonpayable

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:**

* `msg.value != 0` — [`ICryptoLegacy.NoValueAllowed()`](https://docs.cryptolegacy.app/documentation/errors-reference#novalueallowed-icl1)

**Overrides:** None

**Function Calls:** None

**Called by:**

* [\_takeFee(ICryptoLegacy.CryptoLegacyStorage,address,address,uint256,uint256\[\],uint256\[\])](#_takefee-lcl1) — LibCryptoLegacy
* [payInitialFee](#payinitialfee-clbp1) — CryptoLegacyBasePlugin

**Gas / Complexity note:** O(1)

**Example:** Lifetime NFT holders must not send Ether when renewing upkeep.

***

### \_sendFeeByTransfer (LCL1)

**Contract/Library:** LibCryptoLegacy

**Description:** Pays fees via direct ETH transfers, optionally splitting referral amounts.

**Detailed Description:** If `msg.value` is zero, emits `SkipSendFeeByTransfer` and exits. Otherwise it validates `_refShare` bounds, optionally sends the referral payout, then forwards the remainder to the build manager, emitting the corresponding events.

**Parameters:**

* cls ([ICryptoLegacy.CryptoLegacyStorage](https://docs.cryptolegacy.app/documentation/data-structures-reference#cryptolegacystorage-icl1-s4), storage): CryptoLegacy storage reference
* \_buildManagerAddress (address): Fee recipient
* \_ref (address): Referral payout recipient (optional)
* \_refShare (uint256): Referral share in basis points (1e4 base)

**Returns:** None

**Modifiers / Visibility / Mutability:**

* internal nonpayable

**Access Control:**

* Unrestricted

**Side Effects:**

* Transfers ETH to the referral and/or build manager

**Emits:**

* [SkipSendFeeByTransfer](https://docs.cryptolegacy.app/documentation/events-reference#skipsendfeebytransfer-icl1) — `SkipSendFeeByTransfer(address buildManagerAddress, uint256 value)`
* [FeeSentToRefByTransfer](https://docs.cryptolegacy.app/documentation/events-reference#feesenttorefbytransfer-icl1) — `FeeSentToRefByTransfer(bytes8 indexed refCode, uint256 value, address referral)`
* [FeePaidByTransfer](https://docs.cryptolegacy.app/documentation/events-reference#feepaidbytransfer-icl1) — `FeePaidByTransfer(bytes8 indexed refCode, bool indexed initial, uint256 value, address factory, uint64 lastFeePaidAt)`

**Reverts if:**

* `_refShare` exceeds basis points — [`ICryptoLegacy.IncorrectRefShare()`](https://docs.cryptolegacy.app/documentation/errors-reference#incorrectrefshare-icl1)
* ETH transfer helper fails — [`ICryptoLegacy.TransferFeeFailed(bytes)`](https://docs.cryptolegacy.app/documentation/errors-reference#transferfeefailed-icl1) (via [\_transferFee](#_transferfee-lcl1))

**Overrides:** None

**Function Calls:**

* [\_transferFee(ICryptoLegacy.CryptoLegacyStorage,address,uint256)](#_transferfee-lcl1) — LibCryptoLegacy, internal

**Called by:**

* [\_takeFee(ICryptoLegacy.CryptoLegacyStorage,address,address,uint256,uint256\[\],uint256\[\])](#_takefee-lcl1) — LibCryptoLegacy

**Gas / Complexity note:** O(1) aside from value transfers

**Example:** Used as a fallback when the build manager fee hook fails.

***

### \_transferFee (LCL1)

**Contract/Library:** LibCryptoLegacy

**Description:** Performs a low-level ETH transfer with a configurable gas stipend.

**Detailed Description:** Uses `.call{value, gas}` with a selector-specific gas limit, reverting with `TransferFeeFailed` if the transfer fails.

**Parameters:**

* cls ([ICryptoLegacy.CryptoLegacyStorage](https://docs.cryptolegacy.app/documentation/data-structures-reference#cryptolegacystorage-icl1-s4), storage): CryptoLegacy storage reference (used for gas configuration)
* \_recipient (address): Fee recipient
* \_value (uint256): Amount of wei to transfer

**Returns:** None

**Modifiers / Visibility / Mutability:**

* internal nonpayable

**Access Control:**

* Unrestricted

**Side Effects:**

* Transfers ETH to `_recipient`

**Emits:** None

**Reverts if:**

* Low-level transfer fails — [`ICryptoLegacy.TransferFeeFailed(bytes)`](https://docs.cryptolegacy.app/documentation/errors-reference#transferfeefailed-icl1)

**Overrides:** None

**Function Calls:**

* [\_gasBySelector(ICryptoLegacy.CryptoLegacyStorage,bytes4)](#_gasbyselector-lcl1) — LibCryptoLegacy, internal
* `payable(_recipient).call(bytes)` — `_recipient`, external

**Called by:**

* [\_sendFeeByTransfer](#_sendfeebytransfer-lcl1) — LibCryptoLegacy
* [\_takeFee(ICryptoLegacy.CryptoLegacyStorage,address,address,uint256,uint256\[\],uint256\[\])](#_takefee-lcl1) — LibCryptoLegacy
* [payInitialFee](#payinitialfee-clbp1) — CryptoLegacyBasePlugin

**Gas / Complexity note:** O(1)

**Example:** Provides a controlled gas stipend for ETH payouts to external actors.

***

### \_tokenPrepareToDistribute (LCL1)

**Contract/Library:** LibCryptoLegacy

**Description:** Reconciles token distribution state with the contract’s current ERC20 balance.

**Detailed Description:** Fetches the distribution struct and the CryptoLegacy contract's current token balance, then compares that balance to the tracked supply (`amountToDistribute - totalClaimed`). It first aggregates historic claims via `_getTotalClaimed`. If the balance is zero or the deviation is below 0.000001 of the balance, it exits early. When a negative rebase is detected, the helper scales every beneficiary’s claimed amount proportionally using `_setBeneficiaryClaimed`. Otherwise it increases `amountToDistribute` by the surplus balance. The caller is expected to snapshot `td.lastBalance` after reconciliation.

**Parameters:**

* cls ([ICryptoLegacy.CryptoLegacyStorage](https://docs.cryptolegacy.app/documentation/data-structures-reference#cryptolegacystorage-icl1-s4), storage): CryptoLegacy storage reference
* \_token (address): ERC20 token being reconciled

**Returns:**

* td ([ICryptoLegacy.TokenDistribution](https://docs.cryptolegacy.app/documentation/data-structures-reference#tokendistribution-icl1-s3), storage): Updated token distribution entry

**Modifiers / Visibility / Mutability:**

* internal nonpayable

**Access Control:**

* Unrestricted

**Side Effects:**

* Updates `td.amountToDistribute`
* Adjusts beneficiary claimed totals during negative rebases

**Emits:** None

**Reverts if:**

* `IERC20(_token).balanceOf(address(this))` — may revert per token implementation

**Overrides:** None

**Function Calls:**

* `IERC20.balanceOf(address)` — `IERC20` *(at `_token`)*, external (staticcall)
* [\_getTotalClaimed(ICryptoLegacy.CryptoLegacyStorage,address)](#_gettotalclaimed-lcl1) — LibCryptoLegacy, internal
* `cls.beneficiaries.values()` — EnumerableSet, internal
* [\_getBeneficiaryClaimed(ICryptoLegacy.CryptoLegacyStorage,bytes32,address)](#_getbeneficiaryclaimed-lcl1) — LibCryptoLegacy, internal
* [\_setBeneficiaryClaimed(ICryptoLegacy.CryptoLegacyStorage,bytes32,address,uint256)](#_setbeneficiaryclaimed-lcl1) — LibCryptoLegacy, internal

**Called by:**

* [\_transferTreasuryTokensToLegacy(ICryptoLegacy.CryptoLegacyStorage,address\[\],address\[\])](#_transfertreasurytokenstolegacy-lcl1) — LibCryptoLegacy
* [beneficiaryClaim](#beneficiaryclaim-clbp1) — CryptoLegacyBasePlugin

**Gas / Complexity note:** O(b) when negative rebase requires iterating beneficiaries; otherwise O(1)

**Example:** Executed before distributing tokens to ensure internal accounting matches actual holdings.

***

### \_getBeneficiaryClaimed (LCL1)

**Contract/Library:** LibCryptoLegacy

**Description:** Reads the claimed amount for a beneficiary/token pair.

**Detailed Description:** Fetches the claimed amount from the `beneficiaryVesting` mapping keyed by the beneficiary’s original hash.

**Parameters:**

* cls ([ICryptoLegacy.CryptoLegacyStorage](https://docs.cryptolegacy.app/documentation/data-structures-reference#cryptolegacystorage-icl1-s4), storage): CryptoLegacy storage reference
* \_hash (bytes32): Beneficiary hash (current identifier)
* \_token (address): Token address

**Returns:**

* claimed (uint): Amount already claimed by the beneficiary

**Modifiers / Visibility / Mutability:**

* internal view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:**

* [\_tokenPrepareToDistribute](#_tokenpreparetodistribute-lcl1) — LibCryptoLegacy
* [\_getTotalClaimed](#_gettotalclaimed-lcl1) — LibCryptoLegacy

**Gas / Complexity note:** O(1)

**Example:** Used to compute vesting deltas when tokens rebase.

***

### \_setBeneficiaryClaimed (LCL1)

**Contract/Library:** LibCryptoLegacy

**Description:** Updates the claimed amount for a beneficiary/token pair.

**Detailed Description:** Stores `_amount` in the beneficiary’s vesting mapping keyed by the original hash.

**Parameters:**

* cls ([ICryptoLegacy.CryptoLegacyStorage](https://docs.cryptolegacy.app/documentation/data-structures-reference#cryptolegacystorage-icl1-s4), storage): CryptoLegacy storage reference
* \_hash (bytes32): Beneficiary hash (current identifier)
* \_token (address): Token address
* \_amount (uint): Claimed amount to persist

**Returns:** None

**Modifiers / Visibility / Mutability:**

* internal nonpayable

**Access Control:**

* Unrestricted

**Side Effects:**

* Updates beneficiary vesting state

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:**

* [\_tokenPrepareToDistribute](#_tokenpreparetodistribute-lcl1) — LibCryptoLegacy

**Gas / Complexity note:** O(1)

**Example:** Scales down claimed balances during negative token rebases.

***

### \_getTotalClaimed (LCL1)

**Contract/Library:** LibCryptoLegacy

**Description:** Aggregates claimed amounts for a token across all beneficiaries.

**Detailed Description:** Iterates the beneficiary set and sums `_getBeneficiaryClaimed` for `_token`.

**Parameters:**

* cls ([ICryptoLegacy.CryptoLegacyStorage](https://docs.cryptolegacy.app/documentation/data-structures-reference#cryptolegacystorage-icl1-s4), storage): CryptoLegacy storage reference
* \_token (address): Token to aggregate

**Returns:**

* totalClaimed (uint): Sum of claimed amounts across beneficiaries

**Modifiers / Visibility / Mutability:**

* internal view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:**

* `cls.beneficiaries.values()` — may revert if storage corrupted (EnumerableSet)

**Overrides:** None

**Function Calls:**

* `cls.beneficiaries.values()` — EnumerableSet, internal
* [\_getBeneficiaryClaimed(ICryptoLegacy.CryptoLegacyStorage,bytes32,address)](#_getbeneficiaryclaimed-lcl1) — LibCryptoLegacy, internal

**Called by:**

* [\_tokenPrepareToDistribute](#_tokenpreparetodistribute-lcl1) — LibCryptoLegacy

**Gas / Complexity note:** O(b) where b = beneficiary count

**Example:** Used to compute outstanding balances when reconciling token distributions.

***

### \_getStartAndEndDate (LCL1)

**Contract/Library:** LibCryptoLegacy

**Description:** Calculates a beneficiary’s vesting window based on distribution start.

**Detailed Description:** Returns `startDate = distributionStartAt + bc.claimDelay` and `endDate = startDate + bc.vestingPeriod`.

**Parameters:**

* cls ([ICryptoLegacy.CryptoLegacyStorage](https://docs.cryptolegacy.app/documentation/data-structures-reference#cryptolegacystorage-icl1-s4), storage): CryptoLegacy storage reference
* bc ([ICryptoLegacy.BeneficiaryConfig](https://docs.cryptolegacy.app/documentation/data-structures-reference#beneficiaryconfig-icl1-s1), storage): Beneficiary configuration

**Returns:**

* startDate (uint64): Vesting start timestamp
* endDate (uint64): Vesting end timestamp

**Modifiers / Visibility / Mutability:**

* internal view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:**

* [beneficiaryClaim()](#beneficiaryclaim-clbp1) — CryptoLegacyBasePlugin
* [getVestedAndClaimedData](#getvestedandclaimeddata-lp1) — LensPlugin

**Gas / Complexity note:** O(1)

**Example:** Feeding these timestamps into vesting calculations for claimable amounts.

***

### \_getVestedAndClaimedAmount (LCL1)

**Contract/Library:** LibCryptoLegacy

**Description:** Computes vesting progress and claimable amounts for a beneficiary/token pair.

**Detailed Description:** Derives vesting basis points based on `_startDate`/`_endDate`, calculates total allocation from `td.amountToDistribute` and `bc.shareBps`, subtracts previously claimed amounts, and clamps the claimable value to the contract’s current balance. Also returns the prior (unclamped) claimable amount for reporting.

**Parameters:**

* td ([ICryptoLegacy.TokenDistribution](https://docs.cryptolegacy.app/documentation/data-structures-reference#tokendistribution-icl1-s3), storage): Token distribution data
* bc ([ICryptoLegacy.BeneficiaryConfig](https://docs.cryptolegacy.app/documentation/data-structures-reference#beneficiaryconfig-icl1-s1), storage): Beneficiary config
* bv ([ICryptoLegacy.BeneficiaryVesting](https://docs.cryptolegacy.app/documentation/data-structures-reference#beneficiaryvesting-icl1-s2), storage): Vesting record storing claimed amounts
* \_token (address): Token address
* \_startDate (uint64): Vesting start timestamp
* \_endDate (uint64): Vesting end timestamp

**Returns:**

* totalAmount (uint256): Beneficiary’s total allocation
* vestedAmount (uint256): Portion vested so far
* claimableAmount (uint256): Currently claimable amount (after balance clamp)
* prevClaimableAmount (uint256): Claimable amount before balance clamping

**Modifiers / Visibility / Mutability:**

* internal view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:**

* `IERC20(_token).balanceOf(address(this))` — may revert per token implementation

**Overrides:** None

**Function Calls:**

* `IERC20.balanceOf(address)` — `IERC20` *(at `_token`)*, external (staticcall)

**Called by:**

* [beneficiaryClaim()](#beneficiaryclaim-clbp1) — CryptoLegacyBasePlugin
* [getVestedAndClaimedData](#getvestedandclaimeddata-lp1) — LensPlugin

**Gas / Complexity note:** O(1) per token

**Example:** Determines the amount a beneficiary can withdraw during a claim call.

***

### \_getBeneficiaryConfigAndVesting (LCL1)

**Contract/Library:** LibCryptoLegacy

**Description:** Retrieves config and vesting storage for a beneficiary, enforcing existence.

**Detailed Description:** Loads the beneficiary config; if `shareBps` is zero it reverts with `BeneficiaryNotExist`. Otherwise returns both the config and the vesting record keyed by the original hash.

**Parameters:**

* cls ([ICryptoLegacy.CryptoLegacyStorage](https://docs.cryptolegacy.app/documentation/data-structures-reference#cryptolegacystorage-icl1-s4), storage): CryptoLegacy storage reference
* \_beneficiary (bytes32): Beneficiary hash (current identifier)

**Returns:**

* bc ([ICryptoLegacy.BeneficiaryConfig](https://docs.cryptolegacy.app/documentation/data-structures-reference#beneficiaryconfig-icl1-s1), storage): Configuration struct
* bv ([ICryptoLegacy.BeneficiaryVesting](https://docs.cryptolegacy.app/documentation/data-structures-reference#beneficiaryvesting-icl1-s2), storage): Vesting record struct

**Modifiers / Visibility / Mutability:**

* internal view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:**

* Beneficiary not registered — [`ICryptoLegacy.BeneficiaryNotExist()`](https://docs.cryptolegacy.app/documentation/errors-reference#beneficiarynotexist-icl1)

**Overrides:** None

**Function Calls:** None

**Called by:**

* [beneficiaryClaim](#beneficiaryclaim-clbp1) — CryptoLegacyBasePlugin
* [getVestedAndClaimedData](#getvestedandclaimeddata-lp1) — LensPlugin

**Gas / Complexity note:** O(1)

**Example:** Used before computing vesting to ensure the beneficiary record exists.

***

### \_setCryptoLegacyToBeneficiaryRegistry (LCL1)

**Contract/Library:** LibCryptoLegacy

**Description:** Adds or removes a single entity from the external BeneficiaryRegistry.

**Detailed Description:** Obtains the registry via `_getBeneficiaryRegistry`; if undefined it emits `BeneficiaryRegistryNotDefined` and exits. Otherwise it selects the appropriate registry method (owner/beneficiary/guardian) based on `_entityType`, invokes it with a tuned gas stipend, and emits catch events on failure.

**Parameters:**

* cls ([ICryptoLegacy.CryptoLegacyStorage](https://docs.cryptolegacy.app/documentation/data-structures-reference#cryptolegacystorage-icl1-s4), storage): CryptoLegacy storage reference
* \_hash (bytes32): Entity hash to register/unregister
* \_entityType ([IBeneficiaryRegistry.EntityType](https://docs.cryptolegacy.app/documentation/data-structures-reference#entitytype-ibr1-e1)): Role being updated
* \_isAdd (bool): True to add, false to remove

**Returns:** None

**Modifiers / Visibility / Mutability:**

* internal nonpayable

**Access Control:**

* Unrestricted

**Side Effects:**

* Mirrors owner/beneficiary/guardian changes into the external registry

**Emits:**

* [BeneficiaryRegistryNotDefined](https://docs.cryptolegacy.app/documentation/events-reference#beneficiaryregistrynotdefined-icl1) — `BeneficiaryRegistryNotDefined()`
* [SetCryptoLegacyOwnerCatch](https://docs.cryptolegacy.app/documentation/events-reference#setcryptolegacyownercatch-icl1) — `SetCryptoLegacyOwnerCatch(bytes reason)`
* [SetCryptoLegacyBeneficiaryCatch](https://docs.cryptolegacy.app/documentation/events-reference#setcryptolegacybeneficiarycatch-icl1) — `SetCryptoLegacyBeneficiaryCatch(bytes reason)`
* [SetCryptoLegacyGuardianCatch](https://docs.cryptolegacy.app/documentation/events-reference#setcryptolegacyguardiancatch-icl1) — `SetCryptoLegacyGuardianCatch(bytes reason)`

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [\_getBeneficiaryRegistry(ICryptoLegacy.CryptoLegacyStorage)](#_getbeneficiaryregistry-lcl1) — LibCryptoLegacy, internal
* [\_gasBySelector(ICryptoLegacy.CryptoLegacyStorage,bytes4)](#_gasbyselector-lcl1) — LibCryptoLegacy, internal
* `IBeneficiaryRegistry.setCryptoLegacyOwner(bytes32,bool)` — `IBeneficiaryRegistry` *(at `br`)*, external
* `IBeneficiaryRegistry.setCryptoLegacyBeneficiary(bytes32,bool)` — `IBeneficiaryRegistry` *(at `br`)*, external
* `IBeneficiaryRegistry.setCryptoLegacyGuardian(bytes32,bool)` — `IBeneficiaryRegistry` *(at `br`)*, external

**Called by:**

* [initializeByBuildManager(uint256,uint256,bytes32\[\],BeneficiaryConfig\[\],bytes8,uint64,uint64)](#initializebybuildmanager-clbp1) — CryptoLegacyBasePlugin
* [\_setBeneficiaries(bytes32\[\],BeneficiaryConfig\[\])](#_setbeneficiaries-clbp1) — CryptoLegacyBasePlugin
* [beneficiarySwitch](#beneficiaryswitch-clbp1) — CryptoLegacyBasePlugin
* [\_setGuardians(ICryptoLegacy.CryptoLegacyStorage,ITrustedGuardiansPlugin.PluginStorage,GuardianToChange\[\])](#_setguardians-tgp1) — TrustedGuardiansPlugin
* [\_updateOwnerInBeneficiaryRegistry](#_updateownerinbeneficiaryregistry-lcl1) — LibCryptoLegacy

**Gas / Complexity note:** O(1) plus external registry call cost

**Example:** Synchronises owner hash changes with the shared BeneficiaryRegistry.

***

### \_setCryptoLegacyListToBeneficiaryRegistry (LCL1)

**Contract/Library:** LibCryptoLegacy

**Description:** Updates recovery address lists in the BeneficiaryRegistry.

**Detailed Description:** Fetches the registry; if absent emits `BeneficiaryRegistryNotDefined`. For `RECOVERY` entityType it scales the gas limit based on list lengths and calls `setCryptoLegacyRecoveryAddresses`, emitting a catch event on failure.

**Parameters:**

* cls ([ICryptoLegacy.CryptoLegacyStorage](https://docs.cryptolegacy.app/documentation/data-structures-reference#cryptolegacystorage-icl1-s4), storage): CryptoLegacy storage reference
* \_oldHashes (bytes32\[], memory): Recovery hashes to remove
* \_newHashes (bytes32\[], memory): Recovery hashes to add
* \_entityType ([IBeneficiaryRegistry.EntityType](https://docs.cryptolegacy.app/documentation/data-structures-reference#entitytype-ibr1-e1)): Must be `RECOVERY`

**Returns:** None

**Modifiers / Visibility / Mutability:**

* internal nonpayable

**Access Control:**

* Unrestricted

**Side Effects:**

* Synchronises recovery hashes with the registry

**Emits:**

* [BeneficiaryRegistryNotDefined](https://docs.cryptolegacy.app/documentation/events-reference#beneficiaryregistrynotdefined-icl1) — `BeneficiaryRegistryNotDefined()`
* [SetCryptoLegacyRecoveryAddressesCatch](https://docs.cryptolegacy.app/documentation/events-reference#setcryptolegacyrecoveryaddressescatch-icl1) — `SetCryptoLegacyRecoveryAddressesCatch(bytes reason)`

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [\_getBeneficiaryRegistry(ICryptoLegacy.CryptoLegacyStorage)](#_getbeneficiaryregistry-lcl1) — LibCryptoLegacy, internal
* [\_gasBySelector(ICryptoLegacy.CryptoLegacyStorage,bytes4)](#_gasbyselector-lcl1) — LibCryptoLegacy, internal
* `IBeneficiaryRegistry.setCryptoLegacyRecoveryAddresses(bytes32[],bytes32[])` — `IBeneficiaryRegistry` *(at `br`)*, external

**Called by:**

* [lrSetMultisigConfig(bytes32\[\],uint8)](#lrsetmultisigconfig-lrp1) — LegacyRecoveryPlugin

**Gas / Complexity note:** O(n+m) where n = `_oldHashes.length`, m = `_newHashes.length`

**Example:** Used when rotating recovery hashes to keep the shared registry in sync.

***

### \_getBeneficiaryRegistry (LCL1)

**Contract/Library:** LibCryptoLegacy

**Description:** Retrieves the BeneficiaryRegistry from the build manager, swallowing errors.

**Detailed Description:** Calls `buildManager.beneficiaryRegistry()` with a calibrated gas limit. Returns the registry on success, otherwise emits `BeneficiaryRegistryCatch` with the revert reason and returns the zero address.

**Parameters:**

* cls ([ICryptoLegacy.CryptoLegacyStorage](https://docs.cryptolegacy.app/documentation/data-structures-reference#cryptolegacystorage-icl1-s4), storage): CryptoLegacy storage reference

**Returns:**

* br (IBeneficiaryRegistry): Registry instance or zero address if unavailable

**Modifiers / Visibility / Mutability:**

* internal nonpayable

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:**

* [BeneficiaryRegistryCatch](https://docs.cryptolegacy.app/documentation/events-reference#beneficiaryregistrycatch-icl1) — `BeneficiaryRegistryCatch(bytes reason)`

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [\_gasBySelector(ICryptoLegacy.CryptoLegacyStorage,bytes4)](#_gasbyselector-lcl1) — LibCryptoLegacy, internal
* `ICryptoLegacyBuildManager.beneficiaryRegistry()` — `ICryptoLegacyBuildManager` *(at `bm`)*, external (staticcall)

**Called by:**

* [\_setCryptoLegacyToBeneficiaryRegistry](#_setcryptolegacytobeneficiaryregistry-lcl1) — LibCryptoLegacy
* [\_setCryptoLegacyListToBeneficiaryRegistry](#_setcryptolegacylisttobeneficiaryregistry-lcl1) — LibCryptoLegacy

**Gas / Complexity note:** O(1) aside from external call

**Example:** Utility for retrieving the registry before pushing membership updates.

***

### \_gasBySelector (LCL1)

**Contract/Library:** LibCryptoLegacy

**Description:** Computes the gas stipend for an external call, applying the configured multiplier.

**Detailed Description:** Fetches the base gas from `_gasWithoutMultiplierBySelector` and multiplies it by `cls.gasLimitMultiplier` (defaulting to 1).

**Parameters:**

* cls ([ICryptoLegacy.CryptoLegacyStorage](https://docs.cryptolegacy.app/documentation/data-structures-reference#cryptolegacystorage-icl1-s4), storage): CryptoLegacy storage reference
* \_selector (bytes4): Function selector being called

**Returns:**

* gasLimit (uint): Gas allowance for the call

**Modifiers / Visibility / Mutability:**

* internal view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [\_gasWithoutMultiplierBySelector(ICryptoLegacy.CryptoLegacyStorage,bytes4)](#_gaswithoutmultiplierbyselector-lcl1) — LibCryptoLegacy, internal

**Called by:**

* [\_isLifetimeActiveAndUpdate](#_islifetimeactiveandupdate-lcl1) — LibCryptoLegacy
* [\_takeFee(ICryptoLegacy.CryptoLegacyStorage,address,address,uint256,uint256\[\],uint256\[\])](#_takefee-lcl1) — LibCryptoLegacy
* [\_setCryptoLegacyToBeneficiaryRegistry](#_setcryptolegacytobeneficiaryregistry-lcl1) — LibCryptoLegacy
* [\_setCryptoLegacyListToBeneficiaryRegistry](#_setcryptolegacylisttobeneficiaryregistry-lcl1) — LibCryptoLegacy
* [\_getBeneficiaryRegistry](#_getbeneficiaryregistry-lcl1) — LibCryptoLegacy
* [\_transferFee](#_transferfee-lcl1) — LibCryptoLegacy
* [getGasBySelector](#getgasbyselector-clbp1) — CryptoLegacyBasePlugin

**Gas / Complexity note:** O(1)

**Example:** Keeps external calls within predetermined gas budgets.

***

### \_gasWithoutMultiplierBySelector (LCL1)

**Contract/Library:** LibCryptoLegacy

**Description:** Provides base gas estimates for known external calls.

**Detailed Description:** Matches `_selector` against known build-manager and registry methods, returning hard-coded gas values: 1.2M for `payFee`, 600k for `getUpdateFee` and `isLifetimeNftLockedAndUpdate`, 40k for [`transferValueSelector`](https://docs.cryptolegacy.app/documentation/data-structures-reference#transfervalueselector-lcl1-d7), 400k for [`lockNftSelector`](https://docs.cryptolegacy.app/documentation/data-structures-reference#locknftselector-lcl1-d8) and registry writes, otherwise 200k fallback.

**Parameters:**

* cls ([ICryptoLegacy.CryptoLegacyStorage](https://docs.cryptolegacy.app/documentation/data-structures-reference#cryptolegacystorage-icl1-s4), storage): Storage (used to access build-manager selectors)
* \_selector (bytes4): Target function selector

**Returns:**

* gasBase (uint): Baseline gas before multiplier

**Modifiers / Visibility / Mutability:**

* internal view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:**

* [\_gasBySelector](#_gasbyselector-lcl1) — LibCryptoLegacy

**Gas / Complexity note:** O(1)

**Example:** Supports consistent gas budgeting for external hooks.

***

### \_updateOwnerInBeneficiaryRegistry (LCL1)

**Contract/Library:** LibCryptoLegacy

**Description:** Swaps the owner entry in the BeneficiaryRegistry.

**Detailed Description:** Fetches the previous owner via `LibDiamond.contractOwner()`, unregisters that hash, and registers the new owner by calling `_setCryptoLegacyToBeneficiaryRegistry` twice.

**Parameters:**

* cls ([ICryptoLegacy.CryptoLegacyStorage](https://docs.cryptolegacy.app/documentation/data-structures-reference#cryptolegacystorage-icl1-s4), storage): CryptoLegacy storage reference
* \_newOwner (address): Address of the new owner

**Returns:** None

**Modifiers / Visibility / Mutability:**

* internal nonpayable

**Access Control:**

* Unrestricted

**Side Effects:**

* Updates owner records in the external beneficiary registry

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [contractOwner()](#contractowner-ld1) — LibDiamond, internal
* [\_addressToHash(address)](#_addresstohash-lcl1) — LibCryptoLegacy, internal
* [\_setCryptoLegacyToBeneficiaryRegistry(ICryptoLegacy.CryptoLegacyStorage,bytes32,IBeneficiaryRegistry.EntityType,bool)](#_setcryptolegacytobeneficiaryregistry-lcl1) — LibCryptoLegacy, internal

**Called by:**

* [acceptOwnership](#acceptownership-clo1) — CryptoLegacyOwnable

**Gas / Complexity note:** O(1) plus registry update cost

**Example:** Keeps external guardian/beneficiary tooling aware of ownership changes.

***

### \_transferTreasuryTokensToLegacy (LCL1)

**Contract/Library:** LibCryptoLegacy

**Description:** Moves ERC20 balances from guardians/holders into the CryptoLegacy contract.

**Detailed Description:** For each token and holder, transfers the lesser of balance and allowance using `SafeERC20.safeTransferFrom`. After processing each token it reconciles token accounting via `_tokenPrepareToDistribute`, sets `lastBalance`, emits `TransferTreasuryTokensToLegacy`, and records the block number (Arbitrum-aware).

**Parameters:**

* cls ([ICryptoLegacy.CryptoLegacyStorage](https://docs.cryptolegacy.app/documentation/data-structures-reference#cryptolegacystorage-icl1-s4), storage): CryptoLegacy storage reference
* \_holders (address\[], memory): Addresses supplying tokens
* \_tokens (address\[], memory): Tokens to sweep

**Returns:** None

**Modifiers / Visibility / Mutability:**

* internal nonpayable

**Access Control:**

* Unrestricted

**Side Effects:**

* Transfers ERC20 assets into the CryptoLegacy contract
* Updates `td.lastBalance` for each processed token
* Appends the current block reference to `cls.transfersGotByBlockNumber`

**Emits:**

* [TransferTreasuryTokensToLegacy](https://docs.cryptolegacy.app/documentation/events-reference#transfertreasurytokenstolegacy-icl1) — `TransferTreasuryTokensToLegacy(address[] holders, address[] tokens)`

**Reverts if:**

* `SafeERC20.safeTransferFrom(...)` — may revert per token implementation

**Overrides:** None

**Function Calls:**

* `IERC20.balanceOf(address)` — `IERC20` *(at `t`)*, external (staticcall)
* `IERC20.allowance(address,address)` — `IERC20` *(at `t`)*, external (staticcall)
* `SafeERC20.safeTransferFrom(IERC20,address,address,uint256)` — SafeERC20, internal
* [\_tokenPrepareToDistribute(ICryptoLegacy.CryptoLegacyStorage,address)](#_tokenpreparetodistribute-lcl1) — LibCryptoLegacy, internal
* `IERC20.balanceOf(address)` — `IERC20` *(at `IERC20(_tokensi)`)*, external (staticcall)
* `ArbSys.arbBlockNumber()` — `ArbSys` *(at `ArbSys(address(100))`)*, external (staticcall)

**Called by:**

* [transferTreasuryTokensToLegacy](#transfertreasurytokenstolegacy-clbp1) — CryptoLegacyBasePlugin
* [lrTransferTreasuryTokensToLegacy](#lrtransfertreasurytokenstolegacy-lrp1) — LegacyRecoveryPlugin
* [guardiansTransferTreasuryTokensToLegacy](#guardianstransfertreasurytokenstolegacy-tgp1) — TrustedGuardiansPlugin

**Gas / Complexity note:** O(t·h) where t = `_tokens.length`, h = `_holders.length`

**Example:** Guardians sweep treasury tokens into the CryptoLegacy contract before initiating distribution.

***

### \_transferTokensFromLegacy (LCL1)

**Contract/Library:** LibCryptoLegacy

**Description:** Sends ERC20 tokens from the CryptoLegacy contract to specified recipients.

**Detailed Description:** Iterates `_transfers`, invoking `SafeERC20.safeTransfer` for each entry, emits `TransferTokensFromLegacy`, and records the block number (with Arbitrum support).

**Parameters:**

* cls ([ICryptoLegacy.CryptoLegacyStorage](https://docs.cryptolegacy.app/documentation/data-structures-reference#cryptolegacystorage-icl1-s4), storage): CryptoLegacy storage reference
* \_transfers ([ICryptoLegacy.TokenTransferTo](https://docs.cryptolegacy.app/documentation/data-structures-reference#tokentransferto-icl1-s5)\[], memory): Transfer instructions

**Returns:** None

**Modifiers / Visibility / Mutability:**

* internal nonpayable

**Access Control:**

* Unrestricted

**Side Effects:**

* Transfers ERC20 balances to recipients
* Appends the current block reference to `cls.transfersGotByBlockNumber`

**Emits:**

* [TransferTokensFromLegacy](https://docs.cryptolegacy.app/documentation/events-reference#transfertokensfromlegacy-icl1) — `TransferTokensFromLegacy(ICryptoLegacy.TokenTransferTo[] transfers)`

**Reverts if:**

* `SafeERC20.safeTransfer(...)` — may revert per token implementation

**Overrides:** None

**Function Calls:**

* `SafeERC20.safeTransfer(IERC20,address,uint256)` — SafeERC20, internal
* `ArbSys.arbBlockNumber()` — `ArbSys` *(at `ArbSys(address(100))`)*, external (staticcall)

**Called by:**

* [lrWithdrawTokensFromLegacy](#lrwithdrawtokensfromlegacy-lrp1) — LegacyRecoveryPlugin

**Gas / Complexity note:** O(n) where n = `_transfers.length`

**Example:** Recovery workflows use this helper to release funds after guardian approval.

***

### \_addressToHash (LCL1)

**Contract/Library:** LibCryptoLegacy

**Description:** Returns the keccak256 hash of an address.

**Detailed Description:** Hashes `_addr` using `abi.encode`, producing the beneficiary identifier used throughout the system.

**Parameters:**

* \_addr (address): Address to hash

**Returns:**

* hash (bytes32): Hashed identifier

**Modifiers / Visibility / Mutability:**

* internal pure

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* `keccak256(bytes memory)` — Solidity builtin, internal

**Called by:**

* [\_checkAddressIsBeneficiary](#_checkaddressisbeneficiary-lcl1) — LibCryptoLegacy
* [\_updateOwnerInBeneficiaryRegistry](#_updateownerinbeneficiaryregistry-lcl1) — LibCryptoLegacy
* [initializeByBuildManager(uint256,uint256,bytes32\[\],BeneficiaryConfig\[\],bytes8,uint64,uint64)](#initializebybuildmanager-clbp1) — CryptoLegacyBasePlugin
* [transferNftTokensToLegacy](#transfernfttokenstolegacy-nlp1) — NftLegacyPlugin
* [beneficiaryClaimNft](#beneficiaryclaimnft-nlp1) — NftLegacyPlugin
* [\_checkGuardian](#_checkguardian-tgp1) — TrustedGuardiansPlugin
* [\_checkIsSenderAllowed](#_checkissenderallowed-lsm1) — LibSafeMinimalMultisig

**Gas / Complexity note:** O(1)

**Example:** Generates the canonical storage key for beneficiaries.

***

### \_addressWithSaltToHash (LCL1)

**Contract/Library:** LibCryptoLegacy

**Description:** Hashes an address together with an additional salt.

**Detailed Description:** Produces `keccak256(abi.encodePacked(_addr, _salt))`, used for generating identifiers that incorporate extra entropy.

**Parameters:**

* \_addr (address): Address input
* \_salt (bytes32): Salt value

**Returns:**

* hash (bytes32): Resulting hash

**Modifiers / Visibility / Mutability:**

* internal pure

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* `keccak256(bytes memory)` — Solidity builtin, internal

**Called by:**

* [\_checkIsSenderAllowed](#_checkissenderallowed-lsm1) — LibSafeMinimalMultisig

**Gas / Complexity note:** O(1)

**Example:** A multisig voter derives a unique identifier by passing a custom salt to `_checkIsSenderAllowed`.

***

## LibCryptoLegacyDeploy (LCLD1)

### \_deployByCreate3 (LCLD1)

**Contract/Library:** LibCryptoLegacyDeploy

**Description:** Deterministically deploys a contract via CREATE3 and records the deployment event.

**Detailed Description:** Verifies `_contractBytecode` is not empty, substitutes `blockhash(block.number - 1)` when `_factorySalt` is zero, predicts the target address through `_computeAddress`, and checks it against `_contractAddress` if supplied. It then derives an owner-specific salt, invokes `LibCreate3.create3` to perform the deployment, and emits `CryptoLegacyCreation`.

**Parameters:**

* \_contractOwner (address): Expected owner associated with the deployment
* \_factorySalt (bytes32): Base salt controlling the deterministic address
* \_contractAddress (address): Optional expected address for validation
* \_contractBytecode (bytes, memory): Constructor bytecode to deploy

**Returns:**

* addr (address): Deployed contract address

**Modifiers / Visibility / Mutability:**

* internal nonpayable

**Access Control:**

* Unrestricted

**Side Effects:**

* Performs a CREATE3 deployment

**Emits:**

* [CryptoLegacyCreation](https://docs.cryptolegacy.app/documentation/events-reference#cryptolegacycreation-lcld1) — `CryptoLegacyCreation(address addr, bytes32 salt, bytes32 userSalt)`

**Reverts if:**

* `_contractBytecode.length == 0` — [`BytecodeEmpty()`](https://docs.cryptolegacy.app/documentation/errors-reference#bytecodeempty-lcld1)
* `_contractAddress` provided but mismatched — [`AddressMismatch()`](https://docs.cryptolegacy.app/documentation/errors-reference#addressmismatch-lcld1)
* `_factorySalt == 0` and `block.number == 0` — `panic(0x11)`
* `LibCreate3.create3(...)` — may revert with [`TargetAlreadyExists()`](https://docs.cryptolegacy.app/documentation/errors-reference#targetalreadyexists-lc31), [`ErrorCreatingProxy()`](https://docs.cryptolegacy.app/documentation/errors-reference#errorcreatingproxy-lc31), or [`ErrorCreatingContract()`](https://docs.cryptolegacy.app/documentation/errors-reference#errorcreatingcontract-lc31)

**Overrides:** None

**Function Calls:**

* `blockhash(uint256)` — global function, internal
* [\_computeAddress(bytes32,address)](#_computeaddress-lcld1) — LibCryptoLegacyDeploy, internal
* [\_getContractOwnerSalt(bytes32,address)](#_getcontractownersalt-lcld1) — LibCryptoLegacyDeploy, internal
* [LibCreate3.create3(bytes32,bytes)](#create3bytes32bytes-lc31) — LibCreate3, internal

**Called by:**

* [createCryptoLegacy(address,address\[\],Create2Args)](#createcryptolegacy-clf1) — CryptoLegacyFactory

**Gas / Complexity note:** Dominated by CREATE3 deployment; other work is O(1)

**Example:** Factory uses this helper to deploy each CryptoLegacy instance at a deterministic address.

***

### \_getContractOwnerSalt (LCLD1)

**Contract/Library:** LibCryptoLegacyDeploy

**Description:** Derives an owner-specific salt for CREATE3 deployments.

**Detailed Description:** Returns `keccak256(abi.encodePacked(_salt, _contractOwner))`, ensuring salts are unique per owner while producing deterministic results.

**Parameters:**

* \_salt (bytes32): Base factory salt
* \_contractOwner (address): Owner linked to the deployment

**Returns:**

* derivedSalt (bytes32): Salt fed into `LibCreate3.create3`

**Modifiers / Visibility / Mutability:**

* internal pure

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* `keccak256(bytes memory)` — Solidity builtin, internal

**Called by:**

* [\_deployByCreate3](#_deploybycreate3-lcld1) — LibCryptoLegacyDeploy
* [\_computeAddress](#_computeaddress-lcld1) — LibCryptoLegacyDeploy

**Gas / Complexity note:** O(1)

**Example:** Used to guarantee unique salts when multiple owners deploy through the same factory.

***

### \_computeAddress (LCLD1)

**Contract/Library:** LibCryptoLegacyDeploy

**Description:** Predicts the deterministic CREATE3 deployment address.

**Detailed Description:** Computes the derived owner salt via `_getContractOwnerSalt` and passes it to `LibCreate3.addressOf` to reproduce the final CREATE3 address.

**Parameters:**

* \_salt (bytes32): Base factory salt
* \_contractOwner (address): Owner input for address derivation

**Returns:**

* predicted (address): Deterministic address for the deployment

**Modifiers / Visibility / Mutability:**

* internal view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [\_getContractOwnerSalt(bytes32,address)](#_getcontractownersalt-lcld1) — LibCryptoLegacyDeploy, internal
* [LibCreate3.addressOf(bytes32)](#addressof-lc31) — LibCreate3, internal

**Called by:**

* [\_deployByCreate3](#_deploybycreate3-lcld1) — LibCryptoLegacyDeploy
* [CryptoLegacyFactory.computeAddress](#computeaddress-clf1) — CryptoLegacyFactory

**Gas / Complexity note:** O(1)

**Example:** Factories compute this address ahead of time to confirm it matches the desired value.

***

## LibCryptoLegacyPlugins (LCLP1)

### \_validatePlugin (LCLP1)

**Contract/Library:** LibCryptoLegacyPlugins

**Description:** Ensures a plugin address is approved by the build manager.

**Detailed Description:** Queries `_cls.buildManager.isPluginRegistered(_plugin)` and reverts if the registry does not recognise the plugin, preventing unapproved facets from being wired in.

**Parameters:**

* \_cls ([ICryptoLegacy.CryptoLegacyStorage](https://docs.cryptolegacy.app/documentation/data-structures-reference#cryptolegacystorage-icl1-s4), storage): CryptoLegacy storage reference containing the build manager
* \_plugin (address): Candidate plugin facet to validate

**Returns:** None

**Modifiers / Visibility / Mutability:**

* internal view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:**

* Plugin not registered in the build manager — [`ICryptoLegacy.PluginNotRegistered()`](https://docs.cryptolegacy.app/documentation/errors-reference#pluginnotregistered-icl1)

**Overrides:** None

**Function Calls:**

* `ICryptoLegacyBuildManager.isPluginRegistered(address)` — ICryptoLegacyBuildManager *(at \_cls.buildManager)*, external (staticcall)

**Called by:**

* [\_addPluginList(ICryptoLegacy.CryptoLegacyStorage,address\[\])](#_addpluginlist-lclp1) — LibCryptoLegacyPlugins

**Gas / Complexity note:** O(1)

**Example:** Guards plugin onboarding against unapproved implementations.

***

### \_addPluginList (LCLP1)

**Contract/Library:** LibCryptoLegacyPlugins

**Description:** Wires a batch of plugins into the diamond.

**Detailed Description:** Iterates `_plugins`, validating each address, fetching its setup selectors via `getSetupSigs`, and registering them through `addFunctions`. Emits `AddFunctions` per plugin so tooling can detect the newly exposed methods.

**Parameters:**

* \_cls ([ICryptoLegacy.CryptoLegacyStorage](https://docs.cryptolegacy.app/documentation/data-structures-reference#cryptolegacystorage-icl1-s4), storage): CryptoLegacy storage reference
* \_plugins (address\[], memory): Plugin facet addresses to install

**Returns:** None

**Modifiers / Visibility / Mutability:**

* internal nonpayable

**Access Control:**

* Unrestricted

**Side Effects:**

* Adds new facet addresses to `ds.facetAddresses` as needed
* Updates selector-to-facet mappings for every returned setup selector

**Emits:**

* [AddFunctions](https://docs.cryptolegacy.app/documentation/events-reference#addfunctions-icl1) — AddFunctions(address \_facetAddress, bytes4\[] \_functionSelectors, uint16 selectorPosition)

**Reverts if:**

* `_cls.buildManager.isPluginRegistered(_pluginsi)` is false — [`ICryptoLegacy.PluginNotRegistered()`](https://docs.cryptolegacy.app/documentation/errors-reference#pluginnotregistered-icl1)
* `_pluginsi == address(0)` — [`ICryptoLegacy.FacetCantBeZero()`](https://docs.cryptolegacy.app/documentation/errors-reference#facetcantbezero-icl1)
* `_pluginsi` lacks bytecode — "NO\_CODE"
* Selector already mapped to another facet — [`ICryptoLegacy.CantAddFunctionThatAlreadyExists()`](https://docs.cryptolegacy.app/documentation/errors-reference#cantaddfunctionthatalreadyexists-icl1)
* `ICryptoLegacyPlugin(_pluginsi).getSetupSigs()` — may revert per plugin implementation

**Overrides:** None

**Function Calls:**

* [\_validatePlugin(ICryptoLegacy.CryptoLegacyStorage,address)](#_validateplugin-lclp1) — LibCryptoLegacyPlugins, internal
* `ICryptoLegacyPlugin.getSetupSigs()` — ICryptoLegacyPlugin *(at \_pluginsi)*, external (staticcall)
* [addFunctions(address,bytes4\[\])](#addfunctions-lclp1) — LibCryptoLegacyPlugins, internal

**Called by:**

* [constructor](#constructor-cl1) — CryptoLegacy
* [replacePlugin](#replaceplugin-cl1) — CryptoLegacy
* [addPluginList](#addpluginlist-cl1) — CryptoLegacy
* [barAddPluginList(address\[\])](#baraddpluginlist-bpar1) — BeneficiaryPluginAddRights

**Gas / Complexity note:** O(p × n + Σs) where p = `_plugins.length`, n = facet count scanned per `_addFacetAddressIfNotExists`, Σs = total setup selectors processed

**Example:** Seeding a freshly deployed CryptoLegacy instance with its baseline plugin set.

***

### \_removePlugin (LCLP1)

**Contract/Library:** LibCryptoLegacyPlugins

**Description:** Removes a plugin’s selectors from the diamond.

**Detailed Description:** Fetches the plugin’s published selector list via `getSigs()` and forwards them to `removeFunctions`, which clears selector mappings and prunes the facet address if no selectors remain. Emits `RemoveFunctions` to signal the removal.

**Parameters:**

* \_plugin (ICryptoLegacyPlugin): Plugin instance to detach

**Returns:** None

**Modifiers / Visibility / Mutability:**

* internal nonpayable

**Access Control:**

* Unrestricted

**Side Effects:**

* Deletes selector assignments for the plugin
* May shrink `ds.facetAddresses` when the plugin contributed the last selectors

**Emits:**

* [RemoveFunctions](https://docs.cryptolegacy.app/documentation/events-reference#removefunctions-icl1) — RemoveFunctions(address \_facetAddress, bytes4\[] \_functionSelectors)

**Reverts if:**

* `address(_plugin) == address(0)` — [`ICryptoLegacy.FacetCantBeZero()`](https://docs.cryptolegacy.app/documentation/errors-reference#facetcantbezero-icl1)
* Plugin facet equals the diamond contract — [`ICryptoLegacy.CantRemoveImmutableFunctions()`](https://docs.cryptolegacy.app/documentation/errors-reference#cantremoveimmutablefunctions-icl1)
* Plugin address not present in facet list — [`ICryptoLegacy.FacetNotFound()`](https://docs.cryptolegacy.app/documentation/errors-reference#facetnotfound-icl1)
* `ICryptoLegacyPlugin(_plugin).getSigs()` — may revert per plugin implementation

**Overrides:** None

**Function Calls:**

* `ICryptoLegacyPlugin.getSigs()` — ICryptoLegacyPlugin *(at \_plugin)*, external (staticcall)
* [removeFunctions(address,bytes4\[\])](#removefunctions-lclp1) — LibCryptoLegacyPlugins, internal

**Called by:**

* [replacePlugin](#replaceplugin-cl1) — CryptoLegacy
* [removePluginList](#removepluginlist-cl1) — CryptoLegacy

**Gas / Complexity note:** O(n + s) where n = facet count lookup, s = selector count reported by the plugin

**Example:** Decommissioning legacy facets before rolling out an upgraded implementation.

***

### \_getFacetAddressPosition (LCLP1)

**Contract/Library:** LibCryptoLegacyPlugins

**Description:** Locates a facet’s index within diamond storage.

**Detailed Description:** Linearly scans `ds.facetAddresses` for `_facetAddress`; if absent, reverts with `FacetNotFound`. The index is used by higher-level helpers to perform swap-and-pop removals.

**Parameters:**

* ds ([LibDiamond.DiamondStorage](https://docs.cryptolegacy.app/documentation/data-structures-reference#diamondstorage-ld1-s3), storage): Diamond storage struct
* \_facetAddress (address): Facet address to look up

**Returns:**

* position (uint256): Index of `_facetAddress` in `ds.facetAddresses`

**Modifiers / Visibility / Mutability:**

* private view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:**

* `_facetAddress` absent from storage — [`ICryptoLegacy.FacetNotFound()`](https://docs.cryptolegacy.app/documentation/errors-reference#facetnotfound-icl1)

**Overrides:** None

**Function Calls:** None

**Called by:**

* [\_removeFacetAddress](#_removefacetaddress-lclp1) — LibCryptoLegacyPlugins

**Gas / Complexity note:** O(n) by facet count

**Example:** Prepares indices for swap-and-pop removal logic.

***

### \_addFacetAddressIfNotExists (LCLP1)

**Contract/Library:** LibCryptoLegacyPlugins

**Description:** Appends a new facet address to storage when necessary.

**Detailed Description:** Checks whether `_facetAddress` already exists in `ds.facetAddresses`. If missing, verifies that the address hosts contract code via `LibDiamond.enforceHasContractCode` and pushes it onto the array.

**Parameters:**

* ds ([LibDiamond.DiamondStorage](https://docs.cryptolegacy.app/documentation/data-structures-reference#diamondstorage-ld1-s3), storage): Diamond storage struct
* \_facetAddress (address): Facet candidate to add

**Returns:** None

**Modifiers / Visibility / Mutability:**

* private nonpayable

**Access Control:**

* Unrestricted

**Side Effects:**

* May append `_facetAddress` to `ds.facetAddresses`

**Emits:** None

**Reverts if:**

* `_facetAddress` has no deployed code — "NO\_CODE"

**Overrides:** None

**Function Calls:**

* [enforceHasContractCode(address,string)](#enforcehascontractcode-ld1) — LibDiamond, internal

**Called by:**

* [addFunctions(address,bytes4\[\])](#addfunctions-lclp1) — LibCryptoLegacyPlugins

**Gas / Complexity note:** O(n) by facet count when scanning for duplicates

**Example:** Guarantees that freshly added plugins become discoverable via loupe queries.

***

### \_removeFacetAddress (LCLP1)

**Contract/Library:** LibCryptoLegacyPlugins

**Description:** Removes a facet address from storage using swap-and-pop.

**Detailed Description:** Determines the target index through `_getFacetAddressPosition`, swaps it with the last entry when needed, and pops the tail element to keep the array compact.

**Parameters:**

* ds ([LibDiamond.DiamondStorage](https://docs.cryptolegacy.app/documentation/data-structures-reference#diamondstorage-ld1-s3), storage): Diamond storage struct
* \_facetAddress (address): Facet address to remove

**Returns:** None

**Modifiers / Visibility / Mutability:**

* private nonpayable

**Access Control:**

* Unrestricted

**Side Effects:**

* Mutates `ds.facetAddresses`

**Emits:** None

**Reverts if:**

* `_facetAddress` not present — [`ICryptoLegacy.FacetNotFound()`](https://docs.cryptolegacy.app/documentation/errors-reference#facetnotfound-icl1)

**Overrides:** None

**Function Calls:**

* [\_getFacetAddressPosition(LibDiamond.DiamondStorage,address)](#_getfacetaddressposition-lclp1) — LibCryptoLegacyPlugins, internal

**Called by:**

* [removeFunctions(address,bytes4\[\])](#removefunctions-lclp1) — LibCryptoLegacyPlugins

**Gas / Complexity note:** O(n) by facet count

**Example:** Clears orphan facet addresses after their selectors are deleted.

***

### addFunctions (LCLP1)

**Contract/Library:** LibCryptoLegacyPlugins

**Description:** Registers selectors from a facet in diamond storage.

**Detailed Description:** Rejects the zero address, loads diamond storage, ensures the facet is tracked via `_addFacetAddressIfNotExists`, then for each selector verifies no mapping exists before recording the new facet address. Emits `AddFunctions` with the full selector batch.

**Parameters:**

* \_facetAddress (address): Facet supplying the functions
* \_functionSelectors (bytes4\[], memory): Selectors to install

**Returns:** None

**Modifiers / Visibility / Mutability:**

* internal nonpayable

**Access Control:**

* Unrestricted

**Side Effects:**

* May append `_facetAddress` to the facet list
* Updates `ds.selectorToFacetAndPosition` for each selector

**Emits:**

* [AddFunctions](https://docs.cryptolegacy.app/documentation/events-reference#addfunctions-icl1) — AddFunctions(address \_facetAddress, bytes4\[] \_functionSelectors, uint16 selectorPosition)

**Reverts if:**

* `_facetAddress == address(0)` — [`ICryptoLegacy.FacetCantBeZero()`](https://docs.cryptolegacy.app/documentation/errors-reference#facetcantbezero-icl1)
* `_facetAddress` lacks bytecode — "NO\_CODE"
* A selector is already assigned — [`ICryptoLegacy.CantAddFunctionThatAlreadyExists()`](https://docs.cryptolegacy.app/documentation/errors-reference#cantaddfunctionthatalreadyexists-icl1)

**Overrides:** None

**Function Calls:**

* [LibDiamond.diamondStorage()](#diamondstorage-ld1) — LibDiamond, internal
* [\_addFacetAddressIfNotExists(LibDiamond.DiamondStorage,address)](#_addfacetaddressifnotexists-lclp1) — LibCryptoLegacyPlugins, internal

**Called by:**

* [\_addPluginList(ICryptoLegacy.CryptoLegacyStorage,address\[\])](#_addpluginlist-lclp1) — LibCryptoLegacyPlugins

**Gas / Complexity note:** O(n + s) where n = facet count scan, s = `_functionSelectors.length`

**Example:** Onboards setup routines for a newly approved plugin.

***

### removeFunctions (LCLP1)

**Contract/Library:** LibCryptoLegacyPlugins

**Description:** Unregisters selectors associated with a facet.

**Detailed Description:** Ensures the facet address is valid and not the diamond itself, obtains diamond storage, excises the facet address via `_removeFacetAddress`, then deletes each selector mapping. Emits `RemoveFunctions` covering the removed selectors.

**Parameters:**

* \_facetAddress (address): Facet being detached
* \_functionSelectors (bytes4\[], memory): Selectors to purge

**Returns:** None

**Modifiers / Visibility / Mutability:**

* internal nonpayable

**Access Control:**

* Unrestricted

**Side Effects:**

* Removes selector entries and may shrink `ds.facetAddresses`

**Emits:**

* [RemoveFunctions](https://docs.cryptolegacy.app/documentation/events-reference#removefunctions-icl1) — RemoveFunctions(address \_facetAddress, bytes4\[] \_functionSelectors)

**Reverts if:**

* `_facetAddress == address(0)` — [`ICryptoLegacy.FacetCantBeZero()`](https://docs.cryptolegacy.app/documentation/errors-reference#facetcantbezero-icl1)
* `_facetAddress == address(this)` — [`ICryptoLegacy.CantRemoveImmutableFunctions()`](https://docs.cryptolegacy.app/documentation/errors-reference#cantremoveimmutablefunctions-icl1)
* `_facetAddress` missing from storage — [`ICryptoLegacy.FacetNotFound()`](https://docs.cryptolegacy.app/documentation/errors-reference#facetnotfound-icl1)

**Overrides:** None

**Function Calls:**

* [LibDiamond.diamondStorage()](#diamondstorage-ld1) — LibDiamond, internal
* [\_removeFacetAddress(LibDiamond.DiamondStorage,address)](#_removefacetaddress-lclp1) — LibCryptoLegacyPlugins, internal

**Called by:**

* [\_removePlugin](#_removeplugin-lclp1) — LibCryptoLegacyPlugins

**Gas / Complexity note:** O(n + s) where n = facet count lookup, s = `_functionSelectors.length`

**Example:** Clearing selectors for a plugin that is no longer authorised.

***

### \_findFacetBySelector (LCLP1)

**Contract/Library:** LibCryptoLegacyPlugins

**Description:** Searches installed plugins for a selector match.

**Detailed Description:** Loops through `ds.facetAddresses`, querying each plugin’s `getSigs()` list until `_selector` is found. Returns the corresponding facet or zero if no match exists, enabling fallback logic to lazily populate selector caches.

**Parameters:**

* ds ([LibDiamond.DiamondStorage](https://docs.cryptolegacy.app/documentation/data-structures-reference#diamondstorage-ld1-s3), storage): Diamond storage struct
* \_selector (bytes4): Function selector to resolve

**Returns:**

* facetAddress (address): Facet implementing `_selector`, or address(0)

**Modifiers / Visibility / Mutability:**

* internal view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:**

* `ICryptoLegacyPlugin(facet).getSigs()` — may revert per plugin implementation

**Overrides:** None

**Function Calls:**

* `ICryptoLegacyPlugin.getSigs()` — ICryptoLegacyPlugin *(at ds.facetAddressesi)*, external (staticcall)

**Called by:**

* [fallback](#fallback-cldb1) — CryptoLegacyDiamondBase
* [facetAddress](#facetaddress-dlf1) — DiamondLoupeFacet

**Gas / Complexity note:** O(f × s) where f = facet count, s = selectors per facet

**Example:** Fallback resolver uses it to warm the selector cache when a plugin was recently installed.

***

## LibDiamond (LD1)

### diamondStorage (LD1)

**Contract/Library:** LibDiamond

**Description:** Returns the Diamond storage struct anchored at the EIP-2535 slot.

**Detailed Description:** Loads the [`DiamondStorage`](https://docs.cryptolegacy.app/documentation/data-structures-reference#diamondstorage-ld1-s3) pointer from the constant [`DIAMOND_STORAGE_POSITION`](https://docs.cryptolegacy.app/documentation/data-structures-reference#diamond_storage_position-ld1-d1) via inline assembly, enabling all facets and helpers to share state without explicit storage variables.

**Parameters:** None

**Returns:**

* ds ([DiamondStorage](https://docs.cryptolegacy.app/documentation/data-structures-reference#diamondstorage-ld1-s3), storage): Diamond-wide storage reference

**Modifiers / Visibility / Mutability:**

* internal pure

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:**

* [facets](#facets-dlf1) — DiamondLoupeFacet
* [facetAddresses](#facetaddresses-dlf1) — DiamondLoupeFacet
* [facetAddress](#facetaddress-dlf1) — DiamondLoupeFacet
* [storageFacetAddress](#storagefacetaddress-dlf1) — DiamondLoupeFacet
* [supportsInterface](#supportsinterface-dlf1) — DiamondLoupeFacet
* [\_getPluginInfoList](#_getplugininfolist-lp1) — LensPlugin
* [fallback](#fallback-cldb1) — CryptoLegacyDiamondBase
* [setContractOwner](#setcontractowner-ld1) — LibDiamond
* [contractOwner](#contractowner-ld1) — LibDiamond
* [enforceIsContractOwner](#enforceiscontractowner-ld1) — LibDiamond
* [diamondCut](#diamondcut-ld1) — LibDiamond
* [addFunctions(address,bytes4\[\])](#addfunctions-ld1) — LibDiamond
* [removeFunctions(address,bytes4\[\])](#removefunctions-ld1) — LibDiamond
* [replaceFunctions](#replacefunctions-ld1) — LibDiamond
* [addFunctions(address,bytes4\[\])](#addfunctions-lclp1) — LibCryptoLegacyPlugins
* [removeFunctions(address,bytes4\[\])](#removefunctions-lclp1) — LibCryptoLegacyPlugins

**Gas / Complexity note:** O(1)

**Example:** Facets consistently read and mutate shared diamond state through this helper.

***

### setContractOwner (LD1)

**Contract/Library:** LibDiamond

**Description:** Updates the diamond owner and emits the ownership transfer event.

**Detailed Description:** Reads the current owner from storage, overwrites it with `_newOwner`, and emits `OwnershipTransferred(previousOwner, _newOwner)` so off-chain tooling can track governance changes.

**Parameters:**

* \_newOwner (address): Address that becomes the new diamond owner

**Returns:** None

**Modifiers / Visibility / Mutability:**

* internal nonpayable

**Access Control:**

* Unrestricted

**Side Effects:**

* Mutates `LibDiamond.[DiamondStorage](https://docs.cryptolegacy.app/documentation/data-structures-reference#diamondstorage-ld1-s3).contractOwner`

**Emits:**

* [OwnershipTransferred](https://docs.cryptolegacy.app/documentation/events-reference#ownershiptransferred-ld1) — `OwnershipTransferred(address indexed previousOwner, address indexed newOwner)`

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [diamondStorage](#diamondstorage-ld1) — LibDiamond, internal

**Called by:**

* [constructor](#constructor-cl1) — CryptoLegacy
* [acceptOwnership](#acceptownership-clo1) — CryptoLegacyOwnable

**Gas / Complexity note:** O(1)

**Example:** Triggered when a pending owner accepts control of a deployed CryptoLegacy diamond.

***

### contractOwner (LD1)

**Contract/Library:** LibDiamond

**Description:** Reads the current diamond owner from storage.

**Detailed Description:** Returns the cached owner address stored under the diamond storage slot, providing a common accessor for access-control helpers and view methods.

**Parameters:** None

**Returns:**

* contractOwner\_ (address): Stored owner address

**Modifiers / Visibility / Mutability:**

* internal view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [diamondStorage](#diamondstorage-ld1) — LibDiamond, internal

**Called by:**

* [\_checkSenderOwner](#_checksenderowner-lcl1) — LibCryptoLegacy
* [\_transferOwnership](#_transferownership-clo1) — CryptoLegacyOwnable
* [\_updateOwnerInBeneficiaryRegistry](#_updateownerinbeneficiaryregistry-lcl1) — LibCryptoLegacy
* [\_resetGuardianVoting](#_resetguardianvoting-ltgp1) — LibTrustedGuardiansPlugin
* [owner](#owner-clbp1) — CryptoLegacyBasePlugin
* [owner](#owner-urp1) — UpdateRolePlugin

**Gas / Complexity note:** O(1)

**Example:** Used by plugins and base contracts to surface the diamond owner to UIs.

***

### enforceIsContractOwner (LD1)

**Contract/Library:** LibDiamond

**Description:** Reverts unless the caller is the diamond owner.

**Detailed Description:** Fetches `contractOwner()` and requires `msg.sender` to match, throwing with a descriptive message if not. Provides a lightweight gating helper for facets.

**Parameters:** None

**Returns:** None

**Modifiers / Visibility / Mutability:**

* internal view

**Access Control:**

* Owner only (caller must match `diamondStorage().contractOwner`)

**Side Effects:** None

**Emits:** None

**Reverts if:**

* Caller ≠ diamond owner — `"LibDiamond: Must be contract owner"`

**Overrides:** None

**Function Calls:**

* [diamondStorage](#diamondstorage-ld1) — LibDiamond, internal

**Called by:** None

**Gas / Complexity note:** O(1)

**Example:** Intended for custom facets that require strict owner-only execution.

***

### diamondCut (LD1)

**Contract/Library:** LibDiamond

**Description:** Applies a batch of facet modifications and optionally executes initialization logic.

**Detailed Description:** Iterates the supplied `IDiamondCut.FacetCut[]`, dispatching each entry to `addFunctions`, `replaceFunctions`, or `removeFunctions` depending on the action. After processing, emits `DiamondCut` and calls `initializeDiamondCut` to run any provided delegatecall initializer. Invalid actions revert immediately.

**Parameters:**

* \_diamondCut ([IDiamondCut.FacetCut](https://docs.cryptolegacy.app/documentation/data-structures-reference#facetcut-idc1-s1)\[], memory): Facet modifications to apply
* \_init (address): Optional initializer contract to delegatecall
* \_calldata (bytes, memory): Initialization payload executed against `_init`

**Returns:** None

**Modifiers / Visibility / Mutability:**

* internal nonpayable

**Access Control:**

* Unrestricted

**Side Effects:**

* Mutates selector mappings and facet address lists
* May execute an initialization delegatecall

**Emits:**

* [DiamondCut](https://docs.cryptolegacy.app/documentation/events-reference#diamondcut-ld1) — `DiamondCut(IDiamondCut.FacetCut[] _diamondCut, address _init, bytes _calldata)`

**Reverts if:**

* `_diamondCuti.action` is unknown — `"LibDiamondCut: Incorrect FacetCutAction"`
* `_diamondCuti.functionSelectors.length == 0` when action is Add/Replace/Remove — `"LibDiamondCut: No selectors in facet to cut"`
* `_diamondCuti.facetAddress == address(0)` when action is Add/Replace — `"LibDiamondCut: Add facet can't be address(0)"`
* `_diamondCuti.functionSelectorsj` already registered when action is Add — `"LibDiamondCut: Can't add function that already exists"`
* Existing selector already points to `_diamondCuti.facetAddress` during Replace — `"LibDiamondCut: Can't replace function with same function"`
* `_diamondCuti.facetAddress != address(0)` when action is Remove — `"LibDiamondCut: Remove facet address must be address(0)"`
* `_diamondCuti.facetAddress` lacks code during Add/Replace — `"LibDiamondCut: New facet has no code"`
* Selector removal targets `address(0)` — `"LibDiamondCut: Can't remove function that doesn't exist"`
* Selector removal targets the diamond itself — `"LibDiamondCut: Can't remove immutable function"`
* `_init` has no code — `"LibDiamondCut: _init address has no code"`
* Delegatecall fails without revert data — `InitializationFunctionReverted(_init, _calldata)`
* `delegatecall(gas(), _init, _calldata)` — bubbled revert reason

**Overrides:** None

**Function Calls:**

* [addFunctions(address,bytes4\[\])](#addfunctions-ld1) — LibDiamond, internal
* [replaceFunctions](#replacefunctions-ld1) — LibDiamond, internal
* [removeFunctions(address,bytes4\[\])](#removefunctions-ld1) — LibDiamond, internal
* [initializeDiamondCut](#initializediamondcut-ld1) — LibDiamond, internal

**Called by:** None

**Gas / Complexity note:** Dependent on number of facet operations and selectors processed

**Example:** During an upgrade, governance submits a cut that adds new plugin selectors and runs a setup initializer.

***

### addFunctions (LD1)

**Contract/Library:** LibDiamond

**Description:** Adds new selectors for a facet during a diamond cut.

**Detailed Description:** Validates selector list length and `_facetAddress`, optionally registers the facet via `addFacet`, and then ensures each selector is unused before recording it with `addFunction`.

**Parameters:**

* \_facetAddress (address): Facet providing the selectors
* \_functionSelectors (bytes4\[], memory): Selector list to install

**Returns:** None

**Modifiers / Visibility / Mutability:**

* internal nonpayable

**Access Control:**

* Unrestricted

**Side Effects:**

* Extends selector mappings and possibly facet address list

**Emits:** None

**Reverts if:**

* `_functionSelectors.length == 0` — `"LibDiamondCut: No selectors in facet to cut"`
* `_facetAddress == address(0)` — `"LibDiamondCut: Add facet can't be address(0)"`
* Selector already registered — `"LibDiamondCut: Can't add function that already exists"`
* `_facetAddress` lacks contract code — `"LibDiamondCut: New facet has no code"`

**Overrides:** None

**Function Calls:**

* [diamondStorage](#diamondstorage-ld1) — LibDiamond, internal
* [addFacet](#addfacet-ld1) — LibDiamond, internal
* [addFunction](#addfunction-ld1) — LibDiamond, internal

**Called by:**

* [diamondCut](#diamondcut-ld1) — LibDiamond

**Gas / Complexity note:** O(s) where s = `_functionSelectors.length`

**Example:** Adds fresh selectors for a plugin facet during an upgrade transaction.

***

### replaceFunctions (LD1)

**Contract/Library:** LibDiamond

**Description:** Swaps existing selectors to point at a new facet implementation.

**Detailed Description:** Validates input similarly to `addFunctions`, ensuring `_facetAddress` is non-zero. For each selector it removes the old mapping via `removeFunction` and then re-adds it pointing to the new facet.

**Parameters:**

* \_facetAddress (address): Replacement facet address
* \_functionSelectors (bytes4\[], memory): Selectors to migrate

**Returns:** None

**Modifiers / Visibility / Mutability:**

* internal nonpayable

**Access Control:**

* Unrestricted

**Side Effects:**

* Updates selector mappings and may register the facet if unseen

**Emits:** None

**Reverts if:**

* `_functionSelectors.length == 0` — `"LibDiamondCut: No selectors in facet to cut"`
* `_facetAddress == address(0)` — `"LibDiamondCut: Add facet can't be address(0)"`
* Existing selector already points to `_facetAddress` — `"LibDiamondCut: Can't replace function with same function"`
* `_facetAddress` lacks contract code when first seen — `"LibDiamondCut: New facet has no code"`
* Selector mapping missing during removal — `"LibDiamondCut: Can't remove function that doesn't exist"`
* Selector implemented directly in the diamond — `"LibDiamondCut: Can't remove immutable function"`

**Overrides:** None

**Function Calls:**

* [diamondStorage](#diamondstorage-ld1) — LibDiamond, internal
* [addFacet](#addfacet-ld1) — LibDiamond, internal
* [removeFunction](#removefunction-ld1) — LibDiamond, internal
* [addFunction](#addfunction-ld1) — LibDiamond, internal

**Called by:**

* [diamondCut](#diamondcut-ld1) — LibDiamond

**Gas / Complexity note:** O(s) where s = `_functionSelectors.length`

**Example:** Redirects existing API selectors to a newly deployed facet during an upgrade.

***

### removeFunctions (LD1)

**Contract/Library:** LibDiamond

**Description:** Removes selectors from the diamond’s routing table.

**Detailed Description:** Checks selector list length, requires `_facetAddress` to be zero as mandated by EIP-2535 when performing removals, and iterates selectors to delete them via `removeFunction`.

**Parameters:**

* \_facetAddress (address): Must be `address(0)` per specification
* \_functionSelectors (bytes4\[], memory): Selectors to remove

**Returns:** None

**Modifiers / Visibility / Mutability:**

* internal nonpayable

**Access Control:**

* Unrestricted

**Side Effects:**

* Deletes selector mappings and may shrink facet address list through `removeFunction`

**Emits:** None

**Reverts if:**

* `_functionSelectors.length == 0` — `"LibDiamondCut: No selectors in facet to cut"`
* `_facetAddress != address(0)` — `"LibDiamondCut: Remove facet address must be address(0)"`
* Selector mapping missing — `"LibDiamondCut: Can't remove function that doesn't exist"`
* Selector implemented directly in the diamond — `"LibDiamondCut: Can't remove immutable function"`

**Overrides:** None

**Function Calls:**

* [diamondStorage](#diamondstorage-ld1) — LibDiamond, internal
* [removeFunction](#removefunction-ld1) — LibDiamond, internal

**Called by:**

* [diamondCut](#diamondcut-ld1) — LibDiamond

**Gas / Complexity note:** O(s) where s = `_functionSelectors.length`

**Example:** Used during upgrades to retire obsolete selectors declared by earlier facets.

***

### addFacet (LD1)

**Contract/Library:** LibDiamond

**Description:** Registers a facet address in diamond storage.

**Detailed Description:** Verifies that `_facetAddress` hosts bytecode using `enforceHasContractCode`, records its position, and appends it to `ds.facetAddresses`.

**Parameters:**

* ds ([DiamondStorage](https://docs.cryptolegacy.app/documentation/data-structures-reference#diamondstorage-ld1-s3), storage): Diamond storage struct
* \_facetAddress (address): Facet to register

**Returns:** None

**Modifiers / Visibility / Mutability:**

* internal nonpayable

**Access Control:**

* Unrestricted

**Side Effects:**

* Extends `ds.facetAddresses` and sets index metadata

**Emits:** None

**Reverts if:**

* `_facetAddress` lacks contract code — `"LibDiamondCut: New facet has no code"`

**Overrides:** None

**Function Calls:**

* [enforceHasContractCode](#enforcehascontractcode-ld1) — LibDiamond, internal

**Called by:**

* [addFunctions(address,bytes4\[\])](#addfunctions-ld1) — LibDiamond
* [replaceFunctions](#replacefunctions-ld1) — LibDiamond

**Gas / Complexity note:** O(1)

**Example:** Executed the first time a plugin facet contributes selectors to the diamond.

***

### addFunction (LD1)

**Contract/Library:** LibDiamond

**Description:** Records a selector → facet mapping within diamond storage.

**Detailed Description:** Stores the selector’s position and facet address, and pushes the selector into the facet’s selector array to keep metadata synchronized.

**Parameters:**

* ds ([DiamondStorage](https://docs.cryptolegacy.app/documentation/data-structures-reference#diamondstorage-ld1-s3), storage): Diamond storage struct
* \_selector (bytes4): Function selector being installed
* \_selectorPosition (uint96): Position index within the facet’s selector array
* \_facetAddress (address): Facet that implements `_selector`

**Returns:** None

**Modifiers / Visibility / Mutability:**

* internal nonpayable

**Access Control:**

* Unrestricted

**Side Effects:**

* Updates selector metadata and facet selector arrays

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:**

* [addFunctions(address,bytes4\[\])](#addfunctions-ld1) — LibDiamond
* [replaceFunctions](#replacefunctions-ld1) — LibDiamond

**Gas / Complexity note:** O(1) per selector

**Example:** Executed while onboarding selectors during an add or replace cut.

***

### removeFunction (LD1)

**Contract/Library:** LibDiamond

**Description:** Deletes a selector mapping and tidies facet metadata.

**Detailed Description:** Ensures the facet address is valid and not the diamond itself, swap-pops the selector from the facet’s selector array, clears the selector mapping, and, if no selectors remain, removes the facet address from `ds.facetAddresses`.

**Parameters:**

* ds ([DiamondStorage](https://docs.cryptolegacy.app/documentation/data-structures-reference#diamondstorage-ld1-s3), storage): Diamond storage struct
* \_facetAddress (address): Facet currently owning the selector
* \_selector (bytes4): Selector to delete

**Returns:** None

**Modifiers / Visibility / Mutability:**

* internal nonpayable

**Access Control:**

* Unrestricted

**Side Effects:**

* Mutates facet selector arrays and `selectorToFacetAndPosition` mapping
* May prune facet address from storage

**Emits:** None

**Reverts if:**

* `_facetAddress == address(0)` — `"LibDiamondCut: Can't remove function that doesn't exist"`
* `_facetAddress == address(this)` — `"LibDiamondCut: Can't remove immutable function"`

**Overrides:** None

**Function Calls:** None

**Called by:**

* [replaceFunctions](#replacefunctions-ld1) — LibDiamond
* [removeFunctions(address,bytes4\[\])](#removefunctions-ld1) — LibDiamond

**Gas / Complexity note:** O(1)

**Example:** Automatically removes selectors for facets slated for replacement or deletion.

***

### initializeDiamondCut (LD1)

**Contract/Library:** LibDiamond

**Description:** Runs optional initialization logic after a diamond cut.

**Detailed Description:** If `_init` is non-zero, verifies the address has code, delegates `_calldata` to it, and bubbles up any revert data. Empty `_init` short-circuits without action.

**Parameters:**

* \_init (address): Target for delegatecall initialization
* \_calldata (bytes, memory): ABI-encoded initializer payload

**Returns:** None

**Modifiers / Visibility / Mutability:**

* internal nonpayable

**Access Control:**

* Unrestricted

**Side Effects:**

* May mutate state through delegatecall into `_init`

**Emits:** None

**Reverts if:**

* `_init` has no code — `"LibDiamondCut: _init address has no code"`
* Delegatecall fails without revert data — `InitializationFunctionReverted(_init, _calldata)`
* `delegatecall(gas(), _init, _calldata)` — bubbled revert reason

**Overrides:** None

**Function Calls:**

* [enforceHasContractCode](#enforcehascontractcode-ld1) — LibDiamond, internal
* `delegatecall(gas(), _init, _calldata)` — `_init`, delegatecall

**Called by:**

* [diamondCut](#diamondcut-ld1) — LibDiamond

**Gas / Complexity note:** Dominated by delegatecall execution cost

**Example:** Initializes newly added facets by seeding configuration after an upgrade.

***

### enforceHasContractCode (LD1)

**Contract/Library:** LibDiamond

**Description:** Asserts that a target address contains contract bytecode.

**Detailed Description:** Uses `extcodesize` to ensure `_contract` is deployed; reverts with `_errorMessage` otherwise. Protects diamond operations from referencing EOAs or undeployed addresses.

**Parameters:**

* \_contract (address): Address to inspect
* \_errorMessage (string, memory): Error message used when reverting

**Returns:** None

**Modifiers / Visibility / Mutability:**

* internal view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:**

* `_contract` has zero bytecode — reverts with `_errorMessage`

**Overrides:** None

**Function Calls:** None

**Called by:**

* [addFacet](#addfacet-ld1) — LibDiamond
* [initializeDiamondCut](#initializediamondcut-ld1) — LibDiamond
* [\_addFacetAddressIfNotExists](#_addfacetaddressifnotexists-lclp1) — LibCryptoLegacyPlugins

**Gas / Complexity note:** O(1)

**Example:** Prevents governance from registering undeployed plugin addresses during a diamond cut.

***

## LibSafeMinimalBeneficiaryMultisig (LSMB1)

### \_checkIsMultisigExecutor (LSMB1)

**Contract/Library:** LibSafeMinimalBeneficiaryMultisig

**Description:** Verifies that the caller is the multisig executor (the contract itself).

**Detailed Description:** Forwards to `LibSafeMinimalMultisig._checkIsMultisigExecutor()`, which requires `msg.sender == address(this)`. Used to guard privileged flows that should only be triggered internally (e.g., via executed proposals).

**Parameters:** None

**Returns:** None

**Modifiers / Visibility / Mutability:**

* internal view

**Access Control:**

* Only `address(this)` (multisig executor)

**Side Effects:** None

**Emits:** None

**Reverts if:**

* Caller is not the contract itself — [`ISafeMinimalMultisig.MultisigOnlyExecutor()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisigonlyexecutor-ism1)

**Overrides:** None

**Function Calls:**

* [\_checkIsMultisigExecutor](#_checkismultisigexecutor-lsm1) — LibSafeMinimalMultisig, internal

**Called by:**

* [barAddPluginList(address\[\])](#baraddpluginlist-bpar1) — BeneficiaryPluginAddRights

**Gas / Complexity note:** O(1)

**Example:** Prevents external callers from invoking executor-only flows that should originate from successfully executed proposals.

***

### \_initializationStatus (LSMB1)

**Contract/Library:** LibSafeMinimalBeneficiaryMultisig

**Description:** Reports whether multisig storage has been fully initialised.

**Detailed Description:** Checks `s.requiredConfirmations`; returns `INITIALIZED` if non-zero, otherwise `NOT_INITIALIZED_NO_NEED`, signalling that confirmations will be lazily bootstrapped.

**Parameters:**

* s ([ISafeMinimalMultisig.Storage](https://docs.cryptolegacy.app/documentation/data-structures-reference#storage-ism1-s1), storage): Multisig storage slot managed by the plugin

**Returns:**

* status ([ISafeMinimalMultisig.InitializationStatus](https://docs.cryptolegacy.app/documentation/data-structures-reference#initializationstatus-ism1-e2)): Current init status flag

**Modifiers / Visibility / Mutability:**

* internal view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:**

* [barGetInitializationStatus](#bargetinitializationstatus-bpar1) — BeneficiaryPluginAddRights

**Gas / Complexity note:** O(1)

**Example:** Used by dashboards to display whether the beneficiary multisig has been configured.

***

### \_getVotersAndConfirmations (LSMB1)

**Contract/Library:** LibSafeMinimalBeneficiaryMultisig

**Description:** Returns the beneficiary voter list and active confirmation threshold.

**Detailed Description:** Pulls the current beneficiaries from `LibCryptoLegacy.getCryptoLegacyStorage()`, then computes the effective confirmation requirement via [\_getRequiredConfirmations](#_getrequiredconfirmations-lsmb1).

**Parameters:**

* s ([ISafeMinimalMultisig.Storage](https://docs.cryptolegacy.app/documentation/data-structures-reference#storage-ism1-s1), storage): Multisig storage slot

**Returns:**

* voters (bytes32\[], memory): Hash identifiers for each beneficiary voter
* requiredConfirmations (uint128): Confirmation threshold after applying defaults/clamping

**Modifiers / Visibility / Mutability:**

* internal view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [getCryptoLegacyStorage()](#getcryptolegacystorage-lcl1) — LibCryptoLegacy, internal
* [\_getVoters(ICryptoLegacy.CryptoLegacyStorage)](#_getvoters-lsmb1) — LibSafeMinimalBeneficiaryMultisig, internal
* [\_getRequiredConfirmations](#_getrequiredconfirmations-lsmb1) — LibSafeMinimalBeneficiaryMultisig, internal

**Called by:**

* [barGetVotersAndConfirmations](#bargetvotersandconfirmations-bpar1) — BeneficiaryPluginAddRights

**Gas / Complexity note:** O(b) where b = beneficiary count

**Example:** Exposes multisig configuration to front-ends so beneficiaries know how many votes are required.

***

### \_getProposalListWithStatuses (LSMB1)

**Contract/Library:** LibSafeMinimalBeneficiaryMultisig

**Description:** Builds a list of all multisig proposals along with confirmation metadata.

**Detailed Description:** Retrieves the beneficiary voter set, calculates the current confirmation requirement, and iterates proposals stored in `s.proposals`, delegating to `LibSafeMinimalMultisig._getProposalWithStatus` to assemble each status struct.

**Parameters:**

* cls ([ICryptoLegacy.CryptoLegacyStorage](https://docs.cryptolegacy.app/documentation/data-structures-reference#cryptolegacystorage-icl1-s4), storage): CryptoLegacy storage with beneficiary state
* s ([ISafeMinimalMultisig.Storage](https://docs.cryptolegacy.app/documentation/data-structures-reference#storage-ism1-s1), storage): Multisig storage slot

**Returns:**

* voters (bytes32\[], memory): Eligible voter identifiers
* requiredConfirmations (uint128): Confirmation threshold
* proposalsWithStatuses ([ISafeMinimalMultisig.ProposalWithStatus](https://docs.cryptolegacy.app/documentation/data-structures-reference#proposalwithstatus-ism1-s3)\[], memory): Proposal data plus per-voter confirmations

**Modifiers / Visibility / Mutability:**

* internal view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [\_getVoters(ICryptoLegacy.CryptoLegacyStorage)](#_getvoters-lsmb1) — LibSafeMinimalBeneficiaryMultisig, internal
* [\_getRequiredConfirmations](#_getrequiredconfirmations-lsmb1) — LibSafeMinimalBeneficiaryMultisig, internal
* [\_getProposalWithStatus(ISafeMinimalMultisig.Storage,bytes32\[\],uint256)](#_getproposalwithstatus-lsm1) — LibSafeMinimalMultisig, internal

**Called by:**

* [barGetProposalListWithStatuses](#bargetproposallistwithstatuses-bpar1) — BeneficiaryPluginAddRights

**Gas / Complexity note:** O(p · b) where p = proposal count, b = beneficiary count

**Example:** Feeds UI components that display every outstanding proposal with individual confirmation flags.

***

### \_getProposalWithStatus (LSMB1)

**Contract/Library:** LibSafeMinimalBeneficiaryMultisig

**Description:** Returns a single proposal enriched with confirmation flags and derived metadata.

**Detailed Description:** Loads the beneficiary voter list, delegates to `LibSafeMinimalMultisig._getProposalWithStatus` for status assembly, and computes the effective confirmation requirement.

**Parameters:**

* cls ([ICryptoLegacy.CryptoLegacyStorage](https://docs.cryptolegacy.app/documentation/data-structures-reference#cryptolegacystorage-icl1-s4), storage): CryptoLegacy storage reference
* s ([ISafeMinimalMultisig.Storage](https://docs.cryptolegacy.app/documentation/data-structures-reference#storage-ism1-s1), storage): Multisig storage slot
* \_proposalId (uint256): Index of the proposal to inspect

**Returns:**

* voters (bytes32\[], memory): Eligible voter identifiers
* requiredConfirmations (uint128): Confirmation threshold
* proposalWithStatus ([ISafeMinimalMultisig.ProposalWithStatus](https://docs.cryptolegacy.app/documentation/data-structures-reference#proposalwithstatus-ism1-s3), memory): Proposal payload and per-voter confirmations

**Modifiers / Visibility / Mutability:**

* internal view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:**

* `_proposalId >= s.proposals.length` — `panic(0x32)`

**Overrides:** None

**Function Calls:**

* [\_getVoters(ICryptoLegacy.CryptoLegacyStorage)](#_getvoters-lsmb1) — LibSafeMinimalBeneficiaryMultisig, internal
* [\_getProposalWithStatus(ISafeMinimalMultisig.Storage,bytes32\[\],uint256)](#_getproposalwithstatus-lsm1) — LibSafeMinimalMultisig, internal
* [\_getRequiredConfirmations](#_getrequiredconfirmations-lsmb1) — LibSafeMinimalBeneficiaryMultisig, internal

**Called by:**

* [barGetProposalWithStatus](#bargetproposalwithstatus-bpar1) — BeneficiaryPluginAddRights

**Gas / Complexity note:** O(b) where b = beneficiary count

**Example:** Used when a beneficiary inspects a specific proposal before casting a vote.

***

### \_getRequiredConfirmations (LSMB1)

**Contract/Library:** LibSafeMinimalBeneficiaryMultisig

**Description:** Derives the confirmation threshold, applying defaults and clamping.

**Detailed Description:** If multisig storage is uninitialised, returns the default threshold from [\_getDefaultRequiredConfirmations](#_getdefaultrequiredconfirmations-lsmb1). When initialised, returns the stored `requiredConfirmations` but clamps it to the current voter count to avoid impossible thresholds without mutating storage.

**Parameters:**

* s ([ISafeMinimalMultisig.Storage](https://docs.cryptolegacy.app/documentation/data-structures-reference#storage-ism1-s1), storage): Multisig storage slot
* cls ([ICryptoLegacy.CryptoLegacyStorage](https://docs.cryptolegacy.app/documentation/data-structures-reference#cryptolegacystorage-icl1-s4), storage): CryptoLegacy storage reference
* \_votersLength (uint256): Current voter count

**Returns:**

* requiredConfirmations (uint128): Effective confirmation threshold

**Modifiers / Visibility / Mutability:**

* internal view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [\_initializationStatus(ISafeMinimalMultisig.Storage)](#_initializationstatus-lsm1) — LibSafeMinimalMultisig, internal
* [\_getDefaultRequiredConfirmations](#_getdefaultrequiredconfirmations-lsmb1) — LibSafeMinimalBeneficiaryMultisig, internal

**Called by:**

* [\_getVotersAndConfirmations](#_getvotersandconfirmations-lsmb1) — LibSafeMinimalBeneficiaryMultisig
* [\_getProposalListWithStatuses](#_getproposallistwithstatuses-lsmb1) — LibSafeMinimalBeneficiaryMultisig
* [\_getProposalWithStatus(ISafeMinimalMultisig.Storage,bytes32\[\],uint256)](#_getproposalwithstatus-lsmb1) — LibSafeMinimalBeneficiaryMultisig
* [\_propose](#_propose-lsmb1) — LibSafeMinimalBeneficiaryMultisig
* [\_confirm](#_confirm-lsmb1) — LibSafeMinimalBeneficiaryMultisig
* [\_cancel](#_cancel-lsmb1) — LibSafeMinimalBeneficiaryMultisig

**Gas / Complexity note:** O(1)

**Example:** Prevents stale configuration from requiring more confirmations than there are beneficiaries.

***

### \_getVoters (LSMB1)

**Contract/Library:** LibSafeMinimalBeneficiaryMultisig

**Description:** Retrieves the current beneficiary voter identifiers.

**Detailed Description:** Returns the enumerable set of beneficiary hashes stored in `cls.beneficiaries`.

**Parameters:**

* cls ([ICryptoLegacy.CryptoLegacyStorage](https://docs.cryptolegacy.app/documentation/data-structures-reference#cryptolegacystorage-icl1-s4), storage): CryptoLegacy storage reference

**Returns:**

* voters (bytes32\[], memory): Beneficiary identifiers used in multisig voting

**Modifiers / Visibility / Mutability:**

* internal view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* `EnumerableSet.values()` — EnumerableSet.Bytes32Set, internal

**Called by:**

* [\_getVotersAndConfirmations](#_getvotersandconfirmations-lsmb1) — LibSafeMinimalBeneficiaryMultisig
* [\_getProposalListWithStatuses](#_getproposallistwithstatuses-lsmb1) — LibSafeMinimalBeneficiaryMultisig
* [\_getProposalWithStatus(ISafeMinimalMultisig.Storage,bytes32\[\],uint256)](#_getproposalwithstatus-lsmb1) — LibSafeMinimalBeneficiaryMultisig
* [\_propose](#_propose-lsmb1) — LibSafeMinimalBeneficiaryMultisig
* [\_confirm](#_confirm-lsmb1) — LibSafeMinimalBeneficiaryMultisig
* [\_cancel](#_cancel-lsmb1) — LibSafeMinimalBeneficiaryMultisig

**Gas / Complexity note:** O(b) where b = beneficiary count

**Example:** Keeps multisig membership aligned with the active beneficiary registry.

***

### \_getDefaultRequiredConfirmations (LSMB1)

**Contract/Library:** LibSafeMinimalBeneficiaryMultisig

**Description:** Computes the default confirmation threshold for the current beneficiary set.

**Detailed Description:** Uses `LibCryptoLegacy._getBeneficiariesCount` to determine voter count, then defers to `LibSafeMinimalMultisig._calcDefaultConfirmations` (majority: floor(count/2) + 1).

**Parameters:**

* cls ([ICryptoLegacy.CryptoLegacyStorage](https://docs.cryptolegacy.app/documentation/data-structures-reference#cryptolegacystorage-icl1-s4), storage): CryptoLegacy storage reference

**Returns:**

* defaultConfirmations (uint128): Majority-based confirmation requirement

**Modifiers / Visibility / Mutability:**

* internal view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [\_getBeneficiariesCount(ICryptoLegacy.CryptoLegacyStorage)](#_getbeneficiariescount-lcl1) — LibCryptoLegacy, internal
* [\_calcDefaultConfirmations(uint128)](#_calcdefaultconfirmations-lsm1) — LibSafeMinimalMultisig, internal

**Called by:**

* [\_getRequiredConfirmations](#_getrequiredconfirmations-lsmb1) — LibSafeMinimalBeneficiaryMultisig
* [\_initializeIfNot](#_initializeifnot-lsmb1) — LibSafeMinimalBeneficiaryMultisig

**Gas / Complexity note:** O(1)

**Example:** Ensures a reasonable default threshold when multisig configuration is set up automatically.

***

### \_setConfirmations (LSMB1)

**Contract/Library:** LibSafeMinimalBeneficiaryMultisig

**Description:** Persists an explicit confirmation threshold for the current voter set.

**Detailed Description:** Validates `_requiredConfirmations` is within `(0, _voters.length]`, updates `s.requiredConfirmations`, and emits the `SetConfirmations` event. Built-in validation prevents impossible quorum settings.

**Parameters:**

* s ([ISafeMinimalMultisig.Storage](https://docs.cryptolegacy.app/documentation/data-structures-reference#storage-ism1-s1), storage): Multisig storage slot
* \_voters (bytes32\[], memory): Current voter list
* \_requiredConfirmations (uint128): New confirmation threshold

**Returns:** None

**Modifiers / Visibility / Mutability:**

* internal nonpayable

**Access Control:**

* Unrestricted

**Side Effects:**

* Updates `s.requiredConfirmations`

**Emits:**

* [SetConfirmations](https://docs.cryptolegacy.app/documentation/events-reference#setconfirmations-ism1) — `SetConfirmations(uint128 requiredConfirmations)`

**Reverts if:**

* `_requiredConfirmations > _voters.length` — [`ISafeMinimalMultisig.MultisigIncorrectRequiredConfirmations()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisigincorrectrequiredconfirmations-ism1)
* `_requiredConfirmations == 0` — [`ISafeMinimalMultisig.MultisigIncorrectRequiredConfirmations()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisigincorrectrequiredconfirmations-ism1)

**Overrides:** None

**Function Calls:** None

**Called by:**

* [\_initializeIfNot](#_initializeifnot-lsmb1) — LibSafeMinimalBeneficiaryMultisig
* [barSetMultisigConfig](#barsetmultisigconfig-bpar1) — BeneficiaryPluginAddRights

**Gas / Complexity note:** O(1)

**Example:** Owners raise the confirmation threshold after onboarding additional beneficiaries.

***

### \_initializeIfNot (LSMB1)

**Contract/Library:** LibSafeMinimalBeneficiaryMultisig

**Description:** Lazily initialises multisig settings when first needed.

**Detailed Description:** If `_initializationStatus` is not `INITIALIZED`, fetches CryptoLegacy storage and seeds `requiredConfirmations` using [\_setConfirmations](#_setconfirmations-lsmb1) with the majority default.

**Parameters:**

* s ([ISafeMinimalMultisig.Storage](https://docs.cryptolegacy.app/documentation/data-structures-reference#storage-ism1-s1), storage): Multisig storage slot
* \_voters (bytes32\[], memory): Current voter list

**Returns:** None

**Modifiers / Visibility / Mutability:**

* internal nonpayable

**Access Control:**

* Unrestricted

**Side Effects:**

* May update `s.requiredConfirmations`

**Emits:**

* [SetConfirmations](https://docs.cryptolegacy.app/documentation/events-reference#setconfirmations-ism1) — `SetConfirmations(uint128 requiredConfirmations)`

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [\_initializationStatus(ISafeMinimalMultisig.Storage)](#_initializationstatus-lsm1) — LibSafeMinimalMultisig, internal
* [getCryptoLegacyStorage()](#getcryptolegacystorage-lcl1) — LibCryptoLegacy, internal
* [\_getDefaultRequiredConfirmations](#_getdefaultrequiredconfirmations-lsmb1) — LibSafeMinimalBeneficiaryMultisig, internal
* [\_setConfirmations](#_setconfirmations-lsmb1) — LibSafeMinimalBeneficiaryMultisig, internal

**Called by:**

* [\_propose](#_propose-lsmb1) — LibSafeMinimalBeneficiaryMultisig
* [\_confirm](#_confirm-lsmb1) — LibSafeMinimalBeneficiaryMultisig

**Gas / Complexity note:** O(1)

**Example:** Automatically configures multisig thresholds the first time a beneficiary submits a proposal.

***

### \_propose (LSMB1)

**Contract/Library:** LibSafeMinimalBeneficiaryMultisig

**Description:** Creates a multisig proposal on behalf of the caller.

**Detailed Description:** Fetches the active voter list, initialises multisig if needed, and calls `LibSafeMinimalMultisig._propose` with salt `0`. Underlying logic validates the caller, checks the selector against `_allowedMethods`, records the proposal, and auto-confirms it for the proposer (executing immediately when only one confirmation is required).

**Parameters:**

* s ([ISafeMinimalMultisig.Storage](https://docs.cryptolegacy.app/documentation/data-structures-reference#storage-ism1-s1), storage): Multisig storage slot
* \_allowedMethods (bytes4\[], memory): Whitelist of permitted selectors
* \_selector (bytes4): Target function selector to execute if approved
* \_params (bytes, memory): ABI-encoded call data for the proposal

**Returns:**

* proposalId (uint256): Index of the newly created proposal

**Modifiers / Visibility / Mutability:**

* internal nonpayable

**Access Control:**

* Unrestricted

**Side Effects:**

* Appends to `s.proposals` and updates confirmation tracking
* May execute the proposal immediately when threshold == 1
* Credits `s.heldEth` for the proposer when execution leaves residual ETH

**Emits:**

* [CreateSafeMinimalMultisigProposal](https://docs.cryptolegacy.app/documentation/events-reference#createsafeminimalmultisigproposal-ism1) — `CreateSafeMinimalMultisigProposal(uint256 proposalId, bytes32 voter, uint128 reqConfirmations)`
* [ExecuteSafeMinimalMultisigProposal](https://docs.cryptolegacy.app/documentation/events-reference#executesafeminimalmultisigproposal-ism1) — `ExecuteSafeMinimalMultisigProposal(uint256 proposalId, bytes32 voter, bool executed, bytes returnData)`
* [AddHeldEth](https://docs.cryptolegacy.app/documentation/events-reference#addheldeth-ism1) — `AddHeldEth(bytes32 voter, uint256 value)`

**Reverts if:**

* Caller not an allowed voter — [`ISafeMinimalMultisig.MultisigVoterNotAllowed()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisigvoternotallowed-ism1)
* `_selector` not in `_allowedMethods` — [`ISafeMinimalMultisig.MultisigMethodNotAllowed()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisigmethodnotallowed-ism1)
* Proposal execution low-level call fails — [`ISafeMinimalMultisig.MultisigExecutionFailed()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisigexecutionfailed-ism1)

**Overrides:** None

**Function Calls:**

* [getCryptoLegacyStorage()](#getcryptolegacystorage-lcl1) — LibCryptoLegacy, internal
* [\_getVoters(ICryptoLegacy.CryptoLegacyStorage)](#_getvoters-lsmb1) — LibSafeMinimalBeneficiaryMultisig, internal
* [\_initializeIfNot](#_initializeifnot-lsmb1) — LibSafeMinimalBeneficiaryMultisig, internal
* [\_getRequiredConfirmations](#_getrequiredconfirmations-lsmb1) — LibSafeMinimalBeneficiaryMultisig, internal
* [\_propose(...)](#_propose-lsm1) — LibSafeMinimalMultisig, internal

**Called by:**

* [barPropose](#barpropose-bpar1) — BeneficiaryPluginAddRights

**Gas / Complexity note:** O(b) for voter gathering + underlying proposal logic

**Example:** A beneficiary proposes adding a new plugin; the proposer’s confirmation is recorded automatically.

***

### \_confirm (LSMB1)

**Contract/Library:** LibSafeMinimalBeneficiaryMultisig

**Description:** Records a beneficiary confirmation for a proposal.

**Detailed Description:** Ensures multisig is initialised, fetches voters, computes the current threshold, and passes control to `LibSafeMinimalMultisig._confirm`. Underlying logic authorises the caller, updates confirmation tracking, executes the proposal when quorum is met, and credits any leftover ETH to the voter.

**Parameters:**

* s ([ISafeMinimalMultisig.Storage](https://docs.cryptolegacy.app/documentation/data-structures-reference#storage-ism1-s1), storage): Multisig storage slot
* \_proposalId (uint256): Proposal index to confirm

**Returns:** None

**Modifiers / Visibility / Mutability:**

* internal nonpayable

**Access Control:**

* Unrestricted

**Side Effects:**

* Updates confirmation tracking and may execute the proposal
* Credits `s.heldEth` for the confirming voter when execution leaves residual ETH

**Emits:**

* [ConfirmSafeMinimalMultisigProposal](https://docs.cryptolegacy.app/documentation/events-reference#confirmsafeminimalmultisigproposal-ism1) — `ConfirmSafeMinimalMultisigProposal(uint256 proposalId, bytes32 voter, uint128 reqConfirmations, uint256 confirms)`
* [ExecuteSafeMinimalMultisigProposal](https://docs.cryptolegacy.app/documentation/events-reference#executesafeminimalmultisigproposal-ism1) — `ExecuteSafeMinimalMultisigProposal(uint256 proposalId, bytes32 voter, bool executed, bytes returnData)`
* [AddHeldEth](https://docs.cryptolegacy.app/documentation/events-reference#addheldeth-ism1) — `AddHeldEth(bytes32 voter, uint256 value)`

**Reverts if:**

* Caller not an allowed voter — [`ISafeMinimalMultisig.MultisigVoterNotAllowed()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisigvoternotallowed-ism1)
* Proposal already executed/canceled — [`ISafeMinimalMultisig.MultisigProposalNotPending()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisigproposalnotpending-ism1)
* Proposal execution low-level call fails — [`ISafeMinimalMultisig.MultisigExecutionFailed()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisigexecutionfailed-ism1)

**Overrides:** None

**Function Calls:**

* [getCryptoLegacyStorage()](#getcryptolegacystorage-lcl1) — LibCryptoLegacy, internal
* [\_getVoters(ICryptoLegacy.CryptoLegacyStorage)](#_getvoters-lsmb1) — LibSafeMinimalBeneficiaryMultisig, internal
* [\_initializeIfNot](#_initializeifnot-lsmb1) — LibSafeMinimalBeneficiaryMultisig, internal
* [\_getRequiredConfirmations](#_getrequiredconfirmations-lsmb1) — LibSafeMinimalBeneficiaryMultisig, internal
* [\_confirm(...)](#_confirm-lsm1) — LibSafeMinimalMultisig, internal

**Called by:**

* [barConfirm](#barconfirm-bpar1) — BeneficiaryPluginAddRights

**Gas / Complexity note:** O(b) where b = beneficiary count

**Example:** A second beneficiary confirms a pending plugin addition, triggering execution when quorum is satisfied.

***

### \_cancel (LSMB1)

**Contract/Library:** LibSafeMinimalBeneficiaryMultisig

**Description:** Allows a voter to withdraw their confirmation (and potentially cancel the proposal).

**Detailed Description:** Retrieves the beneficiary list, computes the threshold, and calls `LibSafeMinimalMultisig._cancel` with salt `0`. The underlying helper verifies the caller previously confirmed, removes their approval, recomputes the count, and cancels the proposal if no confirmations remain.

**Parameters:**

* s ([ISafeMinimalMultisig.Storage](https://docs.cryptolegacy.app/documentation/data-structures-reference#storage-ism1-s1), storage): Multisig storage slot
* \_proposalId (uint256): Proposal index to update

**Returns:** None

**Modifiers / Visibility / Mutability:**

* internal nonpayable

**Access Control:**

* Unrestricted

**Side Effects:**

* Updates `s.confirmedBy` and proposal status

**Emits:**

* [CancelSafeMinimalMultisigProposal](https://docs.cryptolegacy.app/documentation/events-reference#cancelsafeminimalmultisigproposal-ism1) — `CancelSafeMinimalMultisigProposal(uint256 proposalId, bytes32 voter, uint128 reqConfirmations, ISafeMinimalMultisig.ProposalStatus status)`

**Reverts if:**

* Caller not an allowed voter — [`ISafeMinimalMultisig.MultisigVoterNotAllowed()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisigvoternotallowed-ism1)
* Proposal not pending — [`ISafeMinimalMultisig.MultisigProposalNotPending()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisigproposalnotpending-ism1)
* Caller had not confirmed — [`ISafeMinimalMultisig.MultisigNotConfirmed()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisignotconfirmed-ism1)

**Overrides:** None

**Function Calls:**

* [getCryptoLegacyStorage()](#getcryptolegacystorage-lcl1) — LibCryptoLegacy, internal
* [\_getVoters(ICryptoLegacy.CryptoLegacyStorage)](#_getvoters-lsmb1) — LibSafeMinimalBeneficiaryMultisig, internal
* [\_getRequiredConfirmations](#_getrequiredconfirmations-lsmb1) — LibSafeMinimalBeneficiaryMultisig, internal
* [\_cancel(...)](#_cancel-lsm1) — LibSafeMinimalMultisig, internal

**Called by:**

* [barCancel](#barcancel-bpar1) — BeneficiaryPluginAddRights

**Gas / Complexity note:** O(b) where b = beneficiary count

**Example:** If a beneficiary changes their mind, they can retract their approval; if no confirmations remain, the proposal is canceled.

***

### \_withdrawHeldEth (LSMB1)

**Contract/Library:** LibSafeMinimalBeneficiaryMultisig

**Description:** Transfers accumulated ETH credits for a voter to a recipient.

**Detailed Description:** Delegates to `LibSafeMinimalMultisig._withdrawHeldEth` with salt `0`. The underlying helper authenticates the caller, reads their `heldEth` balance, resets it, and performs a plain ETH transfer to `_recipient`.

**Parameters:**

* s ([ISafeMinimalMultisig.Storage](https://docs.cryptolegacy.app/documentation/data-structures-reference#storage-ism1-s1), storage): Multisig storage slot
* \_allVoters (bytes32\[], memory): Allowed voter identifiers used for auth
* \_recipient (address): Destination for withdrawn ETH

**Returns:** None

**Modifiers / Visibility / Mutability:**

* internal nonpayable

**Access Control:**

* Only beneficiaries whose hash appears in `_allVoters`

**Side Effects:**

* Decrements `s.heldEth` for the caller
* Performs an external ETH transfer

**Emits:**

* [WithdrawHeldEth](https://docs.cryptolegacy.app/documentation/events-reference#withdrawheldeth-ism1) — `WithdrawHeldEth(bytes32 voter, uint256 value)`

**Reverts if:**

* Caller not an allowed voter — [`ISafeMinimalMultisig.MultisigVoterNotAllowed()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisigvoternotallowed-ism1)
* No ETH to withdraw — [`ISafeMinimalMultisig.MultisigNothingToWithdraw()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisignothingtowithdraw-ism1)
* ETH transfer fails — [`ISafeMinimalMultisig.TransferFeeFailed(bytes)`](https://docs.cryptolegacy.app/documentation/errors-reference#transferfeefailed-ism1)

**Overrides:** None

**Function Calls:**

* [\_withdrawHeldEth(ISafeMinimalMultisig.Storage,bytes32,bytes32\[\],address)](#_withdrawheldeth-lsm1) — LibSafeMinimalMultisig, internal

**Called by:**

* [barWithdrawHeldEth](#barwithdrawheldeth-bpar1) — BeneficiaryPluginAddRights

**Gas / Complexity note:** O(b) for voter auth + O(1) transfer

**Example:** After a proposal executes and leaves residual ETH, beneficiaries can withdraw their credited share to a chosen recipient address.

***

## LibSafeMinimalMultisig (LSM1)

### \_checkIsMultisigExecutor (LSM1)

**Contract/Library:** LibSafeMinimalMultisig

**Description:** Rejects calls from anything other than the multisig executor contract.

**Detailed Description:** Ensures `msg.sender` equals `address(this)` and reverts with `MultisigOnlyExecutor()` otherwise. Used by plugins to guard sensitive entry points that must be reached only through executed proposals (i.e., via delegatecall/self-call).

**Parameters:** None

**Returns:** None

**Modifiers / Visibility / Mutability:**

* internal view

**Access Control:**

* Only `address(this)` (multisig executor self-call)

**Side Effects:** None

**Emits:** None

**Reverts if:**

* `msg.sender != address(this)` — [`ISafeMinimalMultisig.MultisigOnlyExecutor()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisigonlyexecutor-ism1)

**Overrides:** None

**Function Calls:** None

**Called by:**

* [\_checkIsMultisigExecutor()](#_checkismultisigexecutor-lsmb1) — LibSafeMinimalBeneficiaryMultisig
* [lrTransferTreasuryTokensToLegacy](#lrtransfertreasurytokenstolegacy-lrp1) — LegacyRecoveryPlugin
* [lrWithdrawTokensFromLegacy](#lrwithdrawtokensfromlegacy-lrp1) — LegacyRecoveryPlugin
* [lrResetGuardianVoting](#lrresetguardianvoting-lrp1) — LegacyRecoveryPlugin

**Gas / Complexity note:** O(1)

**Example:** Prevents an external account from bypassing the multisig by calling executor-only helpers directly.

***

### \_checkIsSenderAllowed (LSM1)

**Contract/Library:** LibSafeMinimalMultisig

**Description:** Authenticates the caller against the allowed voter list.

**Detailed Description:** Derives the caller’s voter hash (LibCryptoLegacy.\_addressToHash(#\_addresstohash-lcl1)), optionally salted via `_salt`, and verifies membership in `_allVoters`. Returns the voter hash for downstream bookkeeping.

**Parameters:**

* \_allVoters (bytes32\[], memory): Whitelisted voter identifiers
* \_salt (bytes32): Optional salt combined with `msg.sender` before hashing

**Returns:**

* voter (bytes32): Authorised voter identifier corresponding to the caller

**Modifiers / Visibility / Mutability:**

* internal view

**Access Control:**

* Only callers whose hash exists in `_allVoters`

**Side Effects:** None

**Emits:** None

**Reverts if:**

* Caller hash absent from `_allVoters` — [`ISafeMinimalMultisig.MultisigVoterNotAllowed()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisigvoternotallowed-ism1)

**Overrides:** None

**Function Calls:**

* [\_addressToHash(address)](#_addresstohash-lcl1) — LibCryptoLegacy, internal
* [\_addressWithSaltToHash(address,bytes32)](#_addresswithsalttohash-lcl1) — LibCryptoLegacy, internal
* [\_isVoterAllowed()](#_isvoterallowed-lsm1) — LibSafeMinimalMultisig, internal

**Called by:**

* [\_propose()](#_propose-lsm1) — LibSafeMinimalMultisig
* [\_getPendingProposalForVoter()](#_getpendingproposalforvoter-lsm1) — LibSafeMinimalMultisig
* [\_withdrawHeldEth(ISafeMinimalMultisig.Storage,bytes32,bytes32\[\],address)](#_withdrawheldeth-lsm1) — LibSafeMinimalMultisig

**Gas / Complexity note:** O(v) where v = `_allVoters.length`

**Example:** Guarantees that only recognised guardians/beneficiaries can create or action multisig proposals.

***

### \_setVotersAndConfirmations (LSM1)

**Contract/Library:** LibSafeMinimalMultisig

**Description:** Stores the authoritative voter list and quorum threshold.

**Detailed Description:** Validates `_requiredConfirmations` is within `(0, _voters.length]`, persists both voters and threshold in storage, and emits `SetVotersAndConfirmations`.

**Parameters:**

* s ([ISafeMinimalMultisig.Storage](https://docs.cryptolegacy.app/documentation/data-structures-reference#storage-ism1-s1), storage): Multisig storage struct
* \_voters (bytes32\[], memory): Voter identifiers to install
* \_requiredConfirmations (uint128): Required confirmations for execution

**Returns:** None

**Modifiers / Visibility / Mutability:**

* internal nonpayable

**Access Control:**

* Unrestricted

**Side Effects:**

* Updates `s.voters` and `s.requiredConfirmations`

**Emits:**

* [SetVotersAndConfirmations](https://docs.cryptolegacy.app/documentation/events-reference#setvotersandconfirmations-ism1) — `SetVotersAndConfirmations(bytes32[] voters, uint128 requiredConfirmations)`

**Reverts if:**

* `_requiredConfirmations == 0` — [`ISafeMinimalMultisig.MultisigIncorrectRequiredConfirmations()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisigincorrectrequiredconfirmations-ism1)
* `_requiredConfirmations > _voters.length` — [`ISafeMinimalMultisig.MultisigIncorrectRequiredConfirmations()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisigincorrectrequiredconfirmations-ism1)

**Overrides:** None

**Function Calls:** None

**Called by:**

* [lrSetMultisigConfig(bytes32\[\],uint8)](#lrsetmultisigconfig-lrp1) — LegacyRecoveryPlugin

**Gas / Complexity note:** O(v) to copy `_voters` into storage

**Example:** Owners can rotate recovery guardians and quorum requirements atomically.

***

### \_initializationStatus (LSM1)

**Contract/Library:** LibSafeMinimalMultisig

**Description:** Indicates whether multisig storage has been initialised.

**Detailed Description:** Returns `INITIALIZED` when `s.requiredConfirmations` is non-zero; otherwise returns `NOT_INITIALIZED_BUT_NEED`, signalling that default configuration must be applied before proposals can execute.

**Parameters:**

* s ([ISafeMinimalMultisig.Storage](https://docs.cryptolegacy.app/documentation/data-structures-reference#storage-ism1-s1), storage): Multisig storage struct

**Returns:**

* status ([ISafeMinimalMultisig.InitializationStatus](https://docs.cryptolegacy.app/documentation/data-structures-reference#initializationstatus-ism1-e2)): Current status flag

**Modifiers / Visibility / Mutability:**

* internal view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:**

* [\_initializeIfNot()](#_initializeifnot-lsmb1) — LibSafeMinimalBeneficiaryMultisig
* [\_getRequiredConfirmations()](#_getrequiredconfirmations-lsmb1) — LibSafeMinimalBeneficiaryMultisig
* [lrGetInitializationStatus](#lrgetinitializationstatus-lrp1) — LegacyRecoveryPlugin

**Gas / Complexity note:** O(1)

**Example:** Allows plugins to detect whether they must seed default confirmations before processing proposals.

***

### \_calcDefaultConfirmations (LSM1)

**Contract/Library:** LibSafeMinimalMultisig

**Description:** Computes a majority quorum for a given voter count.

**Detailed Description:** Implements the rule `(voterCount / 2) + 1`, yielding a simple majority threshold regardless of parity.

**Parameters:**

* \_voterCount (uint128): Total voters participating in multisig

**Returns:**

* confirmations (uint128): Calculated default quorum

**Modifiers / Visibility / Mutability:**

* internal pure

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:**

* [\_getDefaultRequiredConfirmations()](#_getdefaultrequiredconfirmations-lsmb1) — LibSafeMinimalBeneficiaryMultisig
* [\_getGuardiansThreshold()](#_getguardiansthreshold-tgp1) — TrustedGuardiansPlugin

**Gas / Complexity note:** O(1)

**Example:** When four guardians are registered, the default quorum becomes three.

***

### \_isMethodAllowed (LSM1)

**Contract/Library:** LibSafeMinimalMultisig

**Description:** Checks whether a selector is permitted for multisig execution.

**Detailed Description:** Iterates `_allowedMethods` to confirm `_selector` is present. Prevents unauthorised function calls from being packaged into proposals.

**Parameters:**

* \_allowedMethods (bytes4\[], memory): Whitelisted selectors
* \_selector (bytes4): Candidate selector

**Returns:**

* allowed (bool): True when selector is present

**Modifiers / Visibility / Mutability:**

* internal pure

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:**

* [\_propose()](#_propose-lsm1) — LibSafeMinimalMultisig

**Gas / Complexity note:** O(m) where m = `_allowedMethods.length`

**Example:** Blocks proposals attempting to call functions outside the plugin’s approved checklist.

***

### \_isVoterAllowed (LSM1)

**Contract/Library:** LibSafeMinimalMultisig

**Description:** Determines whether a voter hash exists in the authorised set.

**Detailed Description:** Linear scan across `_allVoters` comparing each entry to `_voter`. Supports both unsalted and salted hashes.

**Parameters:**

* \_allVoters (bytes32\[], memory): Allowed voter list
* \_voter (bytes32): Candidate voter identifier

**Returns:**

* allowed (bool): True if `_voter` is present

**Modifiers / Visibility / Mutability:**

* internal pure

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:**

* [\_checkIsSenderAllowed()](#_checkissenderallowed-lsm1) — LibSafeMinimalMultisig

**Gas / Complexity note:** O(v) where v = `_allVoters.length`

**Example:** Ensures a salted guardian identifier truly belongs to the configured multisig committee.

***

### \_getConfirmedCount (LSM1)

**Contract/Library:** LibSafeMinimalMultisig

**Description:** Counts confirmations recorded for a proposal.

**Detailed Description:** Iterates the allowed voter list and sums up `true` entries in `s.confirmedBy_proposalId`. Used to derive quorum progress and update cached counts.

**Parameters:**

* s ([ISafeMinimalMultisig.Storage](https://docs.cryptolegacy.app/documentation/data-structures-reference#storage-ism1-s1), storage): Multisig storage struct
* \_allVoters (bytes32\[], memory): Allowed voter list
* \_proposalId (uint256): Proposal index

**Returns:**

* confirmed (uint128): Number of approvals currently recorded

**Modifiers / Visibility / Mutability:**

* internal view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:**

* [\_cancel()](#_cancel-lsm1) — LibSafeMinimalMultisig
* [\_confirm()](#_confirm-lsm1) — LibSafeMinimalMultisig

**Gas / Complexity note:** O(v) where v = `_allVoters.length`

**Example:** Keeps the proposal’s `confirms` field in sync after votes are added or removed.

***

### \_getProposalListWithStatusesAndStorageVoters (LSM1)

**Contract/Library:** LibSafeMinimalMultisig

**Description:** Returns every proposal alongside stored voter metadata.

**Detailed Description:** Uses the voter list saved in `s.voters`, loops across `s.proposals`, and builds [`ProposalWithStatus`](https://docs.cryptolegacy.app/documentation/data-structures-reference#proposalwithstatus-ism1-s3) entries via `_getProposalWithStatus`. Also returns the persisted quorum value.

**Parameters:**

* s ([ISafeMinimalMultisig.Storage](https://docs.cryptolegacy.app/documentation/data-structures-reference#storage-ism1-s1), storage): Multisig storage struct

**Returns:**

* voters (bytes32\[], memory): Stored voter list
* requiredConfirmations (uint128): Stored confirmation threshold
* proposalsWithStatuses ([ISafeMinimalMultisig.ProposalWithStatus](https://docs.cryptolegacy.app/documentation/data-structures-reference#proposalwithstatus-ism1-s3)\[], memory): Proposal data plus confirmation flags

**Modifiers / Visibility / Mutability:**

* internal view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* [\_getProposalWithStatus(ISafeMinimalMultisig.Storage,bytes32\[\],uint256)](#_getproposalwithstatus-lsm1) — LibSafeMinimalMultisig, internal

**Called by:**

* [lrGetProposalListWithStatuses](#lrgetproposallistwithstatuses-lrp1) — LegacyRecoveryPlugin

**Gas / Complexity note:** O(p · v) where p = proposal count, v = voter count

**Example:** Supports backend APIs that fetch all recovery proposals in a single call.

***

### \_getProposalWithStatus (LSM1)

**Contract/Library:** LibSafeMinimalMultisig

**Description:** Derives a proposal’s confirmation status relative to a voter set.

**Detailed Description:** Builds a boolean `confirmedBy` array by checking `s.confirmedBy` against each voter, recomputes the live confirmation count (storing it inside the in-memory copy of `proposal` when the proposal is pending), and returns the augmented struct.

**Parameters:**

* s ([ISafeMinimalMultisig.Storage](https://docs.cryptolegacy.app/documentation/data-structures-reference#storage-ism1-s1), storage): Multisig storage struct
* voters (bytes32\[], memory): Eligible voters
* \_proposalId (uint256): Proposal index

**Returns:**

* proposalWithStatus ([ISafeMinimalMultisig.ProposalWithStatus](https://docs.cryptolegacy.app/documentation/data-structures-reference#proposalwithstatus-ism1-s3), memory): Proposal data plus confirmation flags

**Modifiers / Visibility / Mutability:**

* internal view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:**

* `_proposalId` out of bounds — panic (array index)

**Overrides:** None

**Function Calls:** None

**Called by:**

* [\_getProposalListWithStatusesAndStorageVoters()](#_getproposallistwithstatusesandstoragevoters-lsm1) — LibSafeMinimalMultisig
* [\_getProposalWithStatus(ISafeMinimalMultisig.Storage,bytes32\[\],uint256)](#_getproposalwithstatus-lsmb1) — LibSafeMinimalBeneficiaryMultisig
* [lrGetProposalWithStatus](#lrgetproposalwithstatus-lrp1) — LegacyRecoveryPlugin

**Gas / Complexity note:** O(v) where v = voter count

**Example:** Enables UI to highlight which guardians have already confirmed a recovery proposal.

***

### \_propose (LSM1)

**Contract/Library:** LibSafeMinimalMultisig

**Description:** Creates a proposal and records the proposer’s confirmation.

**Detailed Description:** Authenticates the caller, validates the selector against `_allowedMethods`, stores the proposal (initialising `confirms` to 1), and logs the creation. If `_requiredConfirmations == 1`, `_execute` runs immediately. Regardless, `_updateHeldEth` credits any ETH generated during execution.

**Parameters:**

* s ([ISafeMinimalMultisig.Storage](https://docs.cryptolegacy.app/documentation/data-structures-reference#storage-ism1-s1), storage): Multisig storage struct
* \_salt (bytes32): Optional salt used in voter authentication
* \_requiredConfirmations (uint128): Current quorum threshold
* \_allVoters (bytes32\[], memory): Allowed voter list
* \_allowedMethods (bytes4\[], memory): Whitelisted selectors
* \_selector (bytes4): Target function selector
* \_params (bytes, memory): ABI-encoded call data

**Returns:**

* proposalId (uint256): Index assigned to the new proposal

**Modifiers / Visibility / Mutability:**

* internal nonpayable

**Access Control:**

* Only whitelisted voters (validated via [\_checkIsSenderAllowed()](#_checkissenderallowed-lsm1))

**Side Effects:**

* Appends to `s.proposals` and marks the proposer as confirmed
* May execute the proposal instantly when quorum is 1
* May credit held ETH for the proposer

**Emits:**

* [CreateSafeMinimalMultisigProposal](https://docs.cryptolegacy.app/documentation/events-reference#createsafeminimalmultisigproposal-ism1) — `CreateSafeMinimalMultisigProposal(uint256 proposalId, bytes32 voter, uint128 reqConfirmations)`
* [ExecuteSafeMinimalMultisigProposal](https://docs.cryptolegacy.app/documentation/events-reference#executesafeminimalmultisigproposal-ism1) — `ExecuteSafeMinimalMultisigProposal(uint256 proposalId, bytes32 voter, bool executed, bytes returnData)`
* [AddHeldEth](https://docs.cryptolegacy.app/documentation/events-reference#addheldeth-ism1) — `AddHeldEth(bytes32 voter, uint256 value)`

**Reverts if:**

* Caller unauthorised — [`ISafeMinimalMultisig.MultisigVoterNotAllowed()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisigvoternotallowed-ism1)
* `_selector` not permitted — [`ISafeMinimalMultisig.MultisigMethodNotAllowed()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisigmethodnotallowed-ism1)
* `_execute` fails — [`ISafeMinimalMultisig.MultisigExecutionFailed()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisigexecutionfailed-ism1)

**Overrides:** None

**Function Calls:**

* [\_checkIsSenderAllowed()](#_checkissenderallowed-lsm1) — LibSafeMinimalMultisig, internal
* [\_isMethodAllowed()](#_ismethodallowed-lsm1) — LibSafeMinimalMultisig, internal
* [\_execute()](#_execute-lsm1) — LibSafeMinimalMultisig, internal
* [\_updateHeldEth()](#_updateheldeth-lsm1) — LibSafeMinimalMultisig, internal

**Called by:**

* [\_propose()](#_propose-lsmb1) — LibSafeMinimalBeneficiaryMultisig
* [lrPropose](#lrpropose-lrp1) — LegacyRecoveryPlugin

**Gas / Complexity note:** O(v) for voter scans + cost of executing `_selector`

**Example:** Guardian proposes resetting recovery guardians; the proposal is stored and auto-confirmed.

***

### \_getPendingProposalForVoter (LSM1)

**Contract/Library:** LibSafeMinimalMultisig

**Description:** Fetches a proposal and authenticated voter, ensuring it is still pending.

**Detailed Description:** Authenticates the caller (via `_checkIsSenderAllowed`), loads the proposal reference, and requires that its status is `PENDING`. Returns both the storage pointer and voter hash for further processing.

**Parameters:**

* s ([ISafeMinimalMultisig.Storage](https://docs.cryptolegacy.app/documentation/data-structures-reference#storage-ism1-s1), storage): Multisig storage struct
* \_salt (bytes32): Optional voter salt
* \_allVoters (bytes32\[], memory): Allowed voter identifiers
* \_proposalId (uint256): Proposal index

**Returns:**

* p ([ISafeMinimalMultisig.Proposal](https://docs.cryptolegacy.app/documentation/data-structures-reference#proposal-ism1-s2), storage): Proposal storage reference
* voter (bytes32): Authenticated voter hash

**Modifiers / Visibility / Mutability:**

* internal view

**Access Control:**

* Only whitelisted voters (caller authenticated during lookup)

**Side Effects:** None

**Emits:** None

**Reverts if:**

* Caller unauthorised — [`ISafeMinimalMultisig.MultisigVoterNotAllowed()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisigvoternotallowed-ism1)
* Proposal status not pending — [`ISafeMinimalMultisig.MultisigProposalNotPending()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisigproposalnotpending-ism1)
* `_proposalId` ≥ `s.proposals.length` — panic (array out of bounds)

**Overrides:** None

**Function Calls:**

* [\_checkIsSenderAllowed()](#_checkissenderallowed-lsm1) — LibSafeMinimalMultisig, internal

**Called by:**

* [\_cancel()](#_cancel-lsm1) — LibSafeMinimalMultisig
* [\_confirm()](#_confirm-lsm1) — LibSafeMinimalMultisig

**Gas / Complexity note:** Dominated by voter authentication O(v)

**Example:** Ensures only pending proposals can be confirmed or cancelled by authorised guardians.

***

### \_cancel (LSM1)

**Contract/Library:** LibSafeMinimalMultisig

**Description:** Removes a voter’s confirmation and cancels the proposal if no approvals remain.

**Detailed Description:** Leverages `_getPendingProposalForVoter` to authenticate and fetch the proposal, ensures the voter had previously confirmed, clears their approval, recomputes confirmation count, and cancels when the count drops to zero.

**Parameters:**

* s ([ISafeMinimalMultisig.Storage](https://docs.cryptolegacy.app/documentation/data-structures-reference#storage-ism1-s1), storage): Multisig storage struct
* \_salt (bytes32): Optional voter salt
* \_requiredConfirmations (uint128): Quorum threshold (used for event emission)
* \_allVoters (bytes32\[], memory): Allowed voter identifiers
* \_proposalId (uint256): Proposal index

**Returns:** None

**Modifiers / Visibility / Mutability:**

* internal nonpayable

**Access Control:**

* Only whitelisted voters with an existing confirmation

**Side Effects:**

* Updates confirmation mapping and proposal status

**Emits:**

* [CancelSafeMinimalMultisigProposal](https://docs.cryptolegacy.app/documentation/events-reference#cancelsafeminimalmultisigproposal-ism1) — `CancelSafeMinimalMultisigProposal(uint256 proposalId, bytes32 voter, uint128 reqConfirmations, ISafeMinimalMultisig.ProposalStatus status)`

**Reverts if:**

* Caller unauthorised — [`ISafeMinimalMultisig.MultisigVoterNotAllowed()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisigvoternotallowed-ism1)
* Proposal not pending — [`ISafeMinimalMultisig.MultisigProposalNotPending()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisigproposalnotpending-ism1)
* Caller never confirmed — [`ISafeMinimalMultisig.MultisigNotConfirmed()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisignotconfirmed-ism1)
* `_proposalId` ≥ `s.proposals.length` — panic (array out of bounds)

**Overrides:** None

**Function Calls:**

* [\_getPendingProposalForVoter()](#_getpendingproposalforvoter-lsm1) — LibSafeMinimalMultisig, internal
* [\_getConfirmedCount()](#_getconfirmedcount-lsm1) — LibSafeMinimalMultisig, internal

**Called by:**

* [\_cancel()](#_cancel-lsmb1) — LibSafeMinimalBeneficiaryMultisig
* [lrCancel](#lrcancel-lrp1) — LegacyRecoveryPlugin

**Gas / Complexity note:** O(v) to recompute confirmations

**Example:** A guardian rescinds their approval, leaving the proposal with zero confirmations and therefore canceled.

***

### \_confirm (LSM1)

**Contract/Library:** LibSafeMinimalMultisig

**Description:** Records a voter’s confirmation and executes the proposal upon quorum.

**Detailed Description:** Authenticates the voter, ensures the proposal is pending, stores their approval, recomputes the confirmation count, emits the confirmation event, executes the proposal once quorum is met, and updates held ETH for the caller.

**Parameters:**

* s ([ISafeMinimalMultisig.Storage](https://docs.cryptolegacy.app/documentation/data-structures-reference#storage-ism1-s1), storage): Multisig storage struct
* \_salt (bytes32): Optional voter salt
* \_requiredConfirmations (uint128): Quorum threshold
* \_allVoters (bytes32\[], memory): Allowed voter list
* \_proposalId (uint256): Proposal index

**Returns:** None

**Modifiers / Visibility / Mutability:**

* internal nonpayable

**Access Control:**

* Only whitelisted voters (caller authenticated during confirmation)

**Side Effects:**

* Updates confirmation mapping, may execute proposal, may credit held ETH

**Emits:**

* [ConfirmSafeMinimalMultisigProposal](https://docs.cryptolegacy.app/documentation/events-reference#confirmsafeminimalmultisigproposal-ism1) — `ConfirmSafeMinimalMultisigProposal(uint256 proposalId, bytes32 voter, uint128 reqConfirmations, uint256 confirms)`
* [ExecuteSafeMinimalMultisigProposal](https://docs.cryptolegacy.app/documentation/events-reference#executesafeminimalmultisigproposal-ism1) — `ExecuteSafeMinimalMultisigProposal(uint256 proposalId, bytes32 voter, bool executed, bytes returnData)`
* [AddHeldEth](https://docs.cryptolegacy.app/documentation/events-reference#addheldeth-ism1) — `AddHeldEth(bytes32 voter, uint256 value)`

**Reverts if:**

* Caller unauthorised — [`ISafeMinimalMultisig.MultisigVoterNotAllowed()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisigvoternotallowed-ism1)
* Proposal not pending — [`ISafeMinimalMultisig.MultisigProposalNotPending()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisigproposalnotpending-ism1)
* Target call fails — [`ISafeMinimalMultisig.MultisigExecutionFailed()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisigexecutionfailed-ism1)
* `_proposalId` ≥ `s.proposals.length` — panic (array out of bounds)

**Overrides:** None

**Function Calls:**

* [\_getPendingProposalForVoter()](#_getpendingproposalforvoter-lsm1) — LibSafeMinimalMultisig, internal
* [\_getConfirmedCount()](#_getconfirmedcount-lsm1) — LibSafeMinimalMultisig, internal
* [\_execute()](#_execute-lsm1) — LibSafeMinimalMultisig, internal
* [\_updateHeldEth()](#_updateheldeth-lsm1) — LibSafeMinimalMultisig, internal

**Called by:**

* [\_confirm()](#_confirm-lsmb1) — LibSafeMinimalBeneficiaryMultisig
* [lrConfirm](#lrconfirm-lrp1) — LegacyRecoveryPlugin

**Gas / Complexity note:** O(v) to recompute confirmations + execution cost

**Example:** Final guardian confirmation triggers token recovery once quorum is hit.

***

### \_execute (LSM1)

**Contract/Library:** LibSafeMinimalMultisig

**Description:** Performs the proposal’s target call once quorum is achieved.

**Detailed Description:** Marks the proposal as executed, then issues a low-level call to `address(this)` forwarding `msg.value` and concatenated selector/params. A failed call reverts with `MultisigExecutionFailed()`.

**Parameters:**

* s ([ISafeMinimalMultisig.Storage](https://docs.cryptolegacy.app/documentation/data-structures-reference#storage-ism1-s1), storage): Multisig storage struct
* \_voter (bytes32): Voter triggering execution (used for event emission)
* \_proposalId (uint256): Proposal index being executed

**Returns:** None

**Modifiers / Visibility / Mutability:**

* private nonpayable

**Access Control:**

* Unrestricted

**Side Effects:**

* Changes `proposal.status` to `EXECUTED`
* Executes arbitrary logic in the multisig contract context

**Emits:**

* [ExecuteSafeMinimalMultisigProposal](https://docs.cryptolegacy.app/documentation/events-reference#executesafeminimalmultisigproposal-ism1) — `ExecuteSafeMinimalMultisigProposal(uint256 proposalId, bytes32 voter, bool executed, bytes returnData)`

**Reverts if:**

* Target call fails — [`ISafeMinimalMultisig.MultisigExecutionFailed()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisigexecutionfailed-ism1)
* `_proposalId` ≥ `s.proposals.length` — panic (array out of bounds)

**Overrides:** None

**Function Calls:**

* `address(this).call(bytes)` — calling contract, external

**Called by:**

* [\_propose()](#_propose-lsm1) — LibSafeMinimalMultisig
* [\_confirm()](#_confirm-lsm1) — LibSafeMinimalMultisig

**Gas / Complexity note:** Dominated by the delegated proposal logic

**Example:** Executes a whitelisted token transfer after enough guardians approve.

***

### \_updateHeldEth (LSM1)

**Contract/Library:** LibSafeMinimalMultisig

**Description:** Credits any leftover ETH from proposal execution to a voter.

**Detailed Description:** Calculates the difference between the current contract balance and `_initialBalance`; if positive, increments `s.heldEth_voter` and emits `AddHeldEth`.

**Parameters:**

* s ([ISafeMinimalMultisig.Storage](https://docs.cryptolegacy.app/documentation/data-structures-reference#storage-ism1-s1), storage): Multisig storage struct
* \_voter (bytes32): Voter to credit
* \_initialBalance (uint256): Contract balance snapshot taken before execution

**Returns:** None

**Modifiers / Visibility / Mutability:**

* internal nonpayable

**Access Control:**

* Unrestricted

**Side Effects:**

* Updates `s.heldEth` mapping

**Emits:**

* [AddHeldEth](https://docs.cryptolegacy.app/documentation/events-reference#addheldeth-ism1) — `AddHeldEth(bytes32 voter, uint256 value)`

**Reverts if:**

* `address(this).balance < _initialBalance` — panic (arithmetic underflow)

**Overrides:** None

**Function Calls:** None

**Called by:**

* [\_propose()](#_propose-lsm1) — LibSafeMinimalMultisig
* [\_confirm()](#_confirm-lsm1) — LibSafeMinimalMultisig

**Gas / Complexity note:** O(1)

**Example:** Credits the executing guardian with ETH refunded during a successful plugin call.

***

### \_withdrawHeldEth (LSM1)

**Contract/Library:** LibSafeMinimalMultisig

**Description:** Withdraws a voter’s accumulated ETH balance to a recipient.

**Detailed Description:** Authenticates the caller, reads and zeroes their `heldEth` balance, transfers ETH to `_recipient`, and emits the withdrawal event. Reverts if balance is zero or the transfer fails.

**Parameters:**

* s ([ISafeMinimalMultisig.Storage](https://docs.cryptolegacy.app/documentation/data-structures-reference#storage-ism1-s1), storage): Multisig storage struct
* \_salt (bytes32): Optional voter salt
* \_allVoters (bytes32\[], memory): Allowed voter list
* \_recipient (address): Destination address for the ETH

**Returns:** None

**Modifiers / Visibility / Mutability:**

* internal nonpayable

**Access Control:**

* Only whitelisted voter hashes present in `_allVoters`

**Side Effects:**

* Performs an external ETH transfer
* Resets the caller’s `heldEth` balance

**Emits:**

* [WithdrawHeldEth](https://docs.cryptolegacy.app/documentation/events-reference#withdrawheldeth-ism1) — `WithdrawHeldEth(bytes32 voter, uint256 value)`

**Reverts if:**

* Caller unauthorised — [`ISafeMinimalMultisig.MultisigVoterNotAllowed()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisigvoternotallowed-ism1)
* No ETH owed — [`ISafeMinimalMultisig.MultisigNothingToWithdraw()`](https://docs.cryptolegacy.app/documentation/errors-reference#multisignothingtowithdraw-ism1)
* Transfer fails — [`ISafeMinimalMultisig.TransferFeeFailed(bytes)`](https://docs.cryptolegacy.app/documentation/errors-reference#transferfeefailed-ism1)

**Overrides:** None

**Function Calls:**

* [\_checkIsSenderAllowed()](#_checkissenderallowed-lsm1) — LibSafeMinimalMultisig, internal
* `payable(_recipient).call(bytes)` — `_recipient`, external

**Called by:**

* [\_withdrawHeldEth(ISafeMinimalMultisig.Storage,bytes32,bytes32\[\],address)](#_withdrawheldeth-lsmb1) — LibSafeMinimalBeneficiaryMultisig
* [lrWithdrawHeldEth](#lrwithdrawheldeth-lrp1) — LegacyRecoveryPlugin

**Gas / Complexity note:** O(v) for auth + cost of ETH transfer

**Example:** A guardian withdraws fees accumulated while executing proposals to a designated withdrawal address.

***

## LibTrustedGuardiansPlugin (LTGP1)

### getPluginStorage (LTGP1)

**Contract/Library:** LibTrustedGuardiansPlugin

**Description:** Provides typed storage access for the Trusted Guardians plugin.

**Detailed Description:** Uses a fixed slot (`keccak256("trusted_guardians.plugin.storage")`) and inline assembly to return the plugin storage struct, ensuring facet code consistently reaches the same layout in upgradeable deployments.

**Parameters:** None

**Returns:**

* storageStruct ([ITrustedGuardiansPlugin.PluginStorage](https://docs.cryptolegacy.app/documentation/data-structures-reference#pluginstorage-urp1-s1), storage): Guardians plugin storage pointer

**Modifiers / Visibility / Mutability:**

* internal pure

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:**

* [\_resetGuardianVoting()](#_resetguardianvoting-ltgp1) — LibTrustedGuardiansPlugin
* [initializeGuardians](#initializeguardians-tgp1) — TrustedGuardiansPlugin
* [setGuardians](#setguardians-tgp1) — TrustedGuardiansPlugin
* [setGuardiansConfig](#setguardiansconfig-tgp1) — TrustedGuardiansPlugin
* [\_checkGuardian()](#_checkguardian-tgp1) — TrustedGuardiansPlugin
* [isGuardiansInitialized](#isguardiansinitialized-tgp1) — TrustedGuardiansPlugin
* [getGuardiansData](#getguardiansdata-tgp1) — TrustedGuardiansPlugin

**Gas / Complexity note:** O(1)

**Example:** Every Trusted Guardians action starts by loading this storage struct via the helper.

***

### \_resetGuardianVoting (LTGP1)

**Contract/Library:** LibTrustedGuardiansPlugin

**Description:** Clears guardian voting state and resets the distribution schedule.

**Detailed Description:** Fetches plugin storage, clears `guardiansVoted`, zeroes `cls.distributionStartAt`, and then calls `LibCryptoLegacy._takeFee` with the contract owner so billing timestamps stay in sync. Depending on fee state this helper may refresh `cls.lastFeePaidAt`, emit fee-payment events, or forward ETH to the build manager/referral before emitting `ResetGuardiansVoting`. This flow lets governance restart guardian approval after changes or cancellations without drifting fee accounting.

**Parameters:**

* cls ([ICryptoLegacy.CryptoLegacyStorage](https://docs.cryptolegacy.app/documentation/data-structures-reference#cryptolegacystorage-icl1-s4), storage): Global CryptoLegacy storage reference

**Returns:** None

**Modifiers / Visibility / Mutability:**

* internal nonpayable

**Access Control:**

* Unrestricted

**Side Effects:**

* Resets guardian vote tracking
* Sets `distributionStartAt` back to zero
* May update `cls.lastFeePaidAt` and emit fee payment events via `_takeFee`
* May transfer ETH to the build manager and/or referral through `_takeFee`

**Emits:**

* [ResetGuardiansVoting](https://docs.cryptolegacy.app/documentation/events-reference#resetguardiansvoting-itgp1) — `ResetGuardiansVoting()`

**Reverts if:**

* Build manager rejects lifetime NFT update — [`ICryptoLegacyBuildManager.NotRegisteredCryptoLegacy()`](https://docs.cryptolegacy.app/documentation/errors-reference#notregisteredcryptolegacy-iclbm1) (bubbled)
* Caller is not recognised as the contract owner for lifetime NFT update — [`ICryptoLegacyBuildManager.NotOwnerOfCryptoLegacy()`](https://docs.cryptolegacy.app/documentation/errors-reference#notownerofcryptolegacy-iclbm1) (bubbled)
* Fee payment lacks the required value after guardian reset — [`IncorrectFee(uint256)`](https://docs.cryptolegacy.app/documentation/errors-reference#incorrectfee-icl1)

**Overrides:** None

**Function Calls:**

* [getPluginStorage()](#getpluginstorage-ltgp1) — LibTrustedGuardiansPlugin, internal
* [\_takeFee(ICryptoLegacy.CryptoLegacyStorage,address,address,uint256,uint256\[\],uint256\[\])](#_takefee-lcl1) — LibCryptoLegacy, internal
* [contractOwner()](#contractowner-ld1) — LibDiamond, internal

**Called by:**

* [resetGuardianVoting](#resetguardianvoting-tgp1) — TrustedGuardiansPlugin
* [lrResetGuardianVoting](#lrresetguardianvoting-lrp1) — LegacyRecoveryPlugin

**Gas / Complexity note:** O(g) where g = guardian count (due to array reallocation)

**Example:** After a stalled distribution vote, guardians invoke this helper to wipe previous approvals and reopen voting.

***

## ArbSys (AS1)

### arbBlockNumber (AS1)

**Contract/Library:** ArbSys (Arbitrum precompile)

**Description:** Returns the current Arbitrum L2 block number.

**Detailed Description:** ArbSys lives at `address(100)` on all Arbitrum chains. `arbBlockNumber()` exposes the L2 block height (genesis = 0). Callers first confirm `block.chainid` matches an Arbitrum network (e.g., 42161) before static-calling this precompile; otherwise they fall back to `block.number`.

**Parameters:** None

**Returns:**

* blockNumber (uint): Current Arbitrum block index

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted (system precompile)

**Side Effects:** None

**Emits:** None

**Reverts if:**

* Called on non-Arbitrum chains without guarding the address (precompile absent)

**Overrides:** None

**Function Calls:** None

**Called by:**

* [\_setBlockNumberChange()](#_setblocknumberchange-br1) — BeneficiaryRegistry
* [sendMessagesTo(address,bytes32\[\],bytes32\[\],bytes\[\],bytes\[\],uint256)](#sendmessagesto-lm1) — LegacyMessenger
* [addPlugin](#addplugin-pr1) — PluginsRegistry
* [addPluginDescription](#addplugindescription-pr1) — PluginsRegistry
* [sendMessagesTo(address,bytes32\[\],bytes32\[\],bytes\[\],bytes\[\],uint256)](#sendmessagestobeneficiary-clbp1) — CryptoLegacyBasePlugin
* [\_transferTreasuryTokensToLegacy(ICryptoLegacy.CryptoLegacyStorage,address\[\],address\[\])](#_transfertreasurytokenstolegacy-lcl1) — LibCryptoLegacy
* [\_transferTokensFromLegacy(ICryptoLegacy.CryptoLegacyStorage,ICryptoLegacy.TokenTransferTo\[\])](#_transfertokensfromlegacy-lcl1) — LibCryptoLegacy

**Gas / Complexity note:** O(1); single staticcall to the precompile.

**Example:** Contracts on Arbitrum One call `ArbSys(address(100)).arbBlockNumber()` to timestamp events with the L2 block number instead of the L1 shadow block.

***

## Flags (FLG1)

### getFlag (FLG1)

**Contract/Library:** Flags

**Description:** Tests whether a specific bit is enabled inside a packed flags word.

**Detailed Description:** Right-shifts `_packedFlags` by `_flag` (bit index) and masks the least significant bit to determine if the toggle is set (`1`). Used wherever behaviour toggles are stored compactly in a `uint256`.

**Parameters:**

* \_packedFlags (uint256): Packed bitfield containing all toggles
* \_flag (uint256): Bit position to inspect (e.g., [`Flags.REVERT_IF_EXTERNAL_FAIL`](https://docs.cryptolegacy.app/documentation/data-structures-reference#revert_if_external_fail-flg1-d2))

**Returns:**

* enabled (bool): `true` when the referenced bit is set

**Modifiers / Visibility / Mutability:**

* internal pure

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** `bool shouldRevert = Flags.getFlag(flags, Flags.REVERT_IF_EXTERNAL_FAIL);`

***

### setFlag (FLG1)

**Contract/Library:** Flags

**Description:** Returns a new flags word with a specific bit set or cleared.

**Detailed Description:** If `_value` is true, ORs `_packedFlags` with `1 << _flag`; otherwise clears the bit using an inverted mask. This pattern keeps configuration toggles compact while remaining easy to manipulate.

**Parameters:**

* \_packedFlags (uint256): Original packed flags value
* \_flag (uint256): Bit index to modify
* \_value (bool): Desired bit state (`true` = 1, `false` = 0)

**Returns:**

* updated (uint256): New packed flags value with the bit adjusted

**Modifiers / Visibility / Mutability:**

* internal pure

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:**

* [\_send()](#_send-lcg1) — LockChainGate

**Gas / Complexity note:** O(1)

**Example:** `uint256 flags = Flags.setFlag(0, Flags.REVERT_IF_EXTERNAL_FAIL, true);`

***

## IAaveV3Pool (IAV3P1)

### supply (IAV3P1)

**Contract/Library:** IAaveV3Pool

**Description:** Supplies an asset into the Aave V3 pool on behalf of a target account.

**Detailed Description:** Pulls `amount` of `asset` from the caller, credits the deposit to `onBehalfOf`, and mints the corresponding aTokens inside the Aave reserve implementation. CryptoLegacy uses this surface when the beneficiary Aave plugin moves treasury assets into Aave.

**Parameters:**

* asset (address): Reserve asset to supply into Aave
* amount (uint256): Amount of `asset` to deposit
* onBehalfOf (address): Address that receives the resulting aToken position
* referralCode (uint16): Aave referral code forwarded to the pool

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external nonpayable

**Access Control:**

* Unrestricted at the interface surface; Aave validates reserve state, approvals, and balances internally

**Side Effects:**

* Aave pool transfers `amount` of `asset` from the caller
* Aave pool mints the corresponding aToken balance to `onBehalfOf`

**Emits:** None

**Reverts if:**

* Aave reserve checks fail (e.g. paused reserve, insufficient allowance, insufficient balance) — bubbled from the pool implementation

**Overrides:** None

**Function Calls:** None

**Called by:** None (external protocol surface)

**Gas / Complexity note:** Implementation-dependent; typically O(1) for a single reserve supply

**Example:** `IAaveV3Pool(pool).supply(asset, amount, address(this), referralCode);`

***

### withdraw (IAV3P1)

**Contract/Library:** IAaveV3Pool

**Description:** Withdraws a reserve asset from Aave V3 to a recipient address.

**Detailed Description:** Burns the caller's aToken position for `asset` and releases the underlying reserve asset to `to`. Integrators use this entry to redeem supplied assets from Aave back into the CryptoLegacy treasury.

**Parameters:**

* asset (address): Reserve asset to withdraw
* amount (uint256): Requested amount to withdraw; may be `type(uint256).max` in implementations that support full-balance withdrawal
* to (address): Recipient address receiving the underlying asset

**Returns:**

* withdrawn (uint256): Amount of underlying asset released by the pool

**Modifiers / Visibility / Mutability:**

* external nonpayable

**Access Control:**

* Unrestricted at the interface surface; Aave enforces balance and reserve rules internally

**Side Effects:**

* Burns the caller's aToken balance for `asset`
* Transfers the underlying reserve asset to `to`

**Emits:** None

**Reverts if:**

* Aave reserve checks fail (e.g. insufficient balance or reserve restrictions) — bubbled from the pool implementation

**Overrides:** None

**Function Calls:** None

**Called by:** None (external protocol surface)

**Gas / Complexity note:** Implementation-dependent; typically O(1) for a single reserve withdrawal

**Example:** `uint256 redeemed = IAaveV3Pool(pool).withdraw(asset, amount, address(this));`

***

## IAaveV3PoolDataProvider (IAV3PDP1)

### getReserveTokensAddresses (IAV3PDP1)

**Contract/Library:** IAaveV3PoolDataProvider

**Description:** Returns the token-contract addresses associated with an Aave reserve.

**Detailed Description:** Resolves the reserve's aToken, stable-debt token, and variable-debt token contracts for `asset`. CryptoLegacy uses this helper to map an underlying reserve asset to its aToken before wrapping or unwrapping Aave positions.

**Parameters:**

* asset (address): Underlying reserve asset to inspect

**Returns:**

* aTokenAddress (address): aToken contract for `asset`
* stableDebtTokenAddress (address): Stable-debt token contract for `asset`
* variableDebtTokenAddress (address): Variable-debt token contract for `asset`

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:**

* Implementation-specific provider lookups fail — bubbled from the data-provider implementation

**Overrides:** None

**Function Calls:** None

**Called by:** None (external protocol surface)

**Gas / Complexity note:** O(1)

**Example:** `(address aToken,,) = IAaveV3PoolDataProvider(provider).getReserveTokensAddresses(asset);`

***

## IBeneficiaryRegistry (IBR1)

### setCryptoLegacyBeneficiary (IBR1)

**Contract/Library:** IBeneficiaryRegistry

**Description:** Registers or removes a CryptoLegacy contract for a beneficiary hash.

**Detailed Description:** Interface method invoked by CryptoLegacy diamonds to toggle their membership under `_beneficiary`. Implementations update registry mappings and emit `AddCryptoLegacyForBeneficiary` / `RemoveCryptoLegacyForBeneficiary`.

**Parameters:**

* \_beneficiary (bytes32): Beneficiary identifier hash
* \_isAdd (bool): `true` to add, `false` to remove

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external nonpayable

**Access Control:**

* Restricted: only a CryptoLegacy built by an added build manager (`_checkBuildManagerValid(msg.sender, address(0))`)

**Side Effects:**

* Updates [`cryptoLegacyByBeneficiary`](https://docs.cryptolegacy.app/documentation/data-structures-reference#cryptolegacybybeneficiary-br1-d1)\[\_beneficiary]
* Updates [`blockNumberChangesByCryptoLegacy`](https://docs.cryptolegacy.app/documentation/data-structures-reference#blocknumberchangesbycryptolegacy-br1-d5)\[msg.sender]

**Emits:**

* [AddCryptoLegacyForBeneficiary](https://docs.cryptolegacy.app/documentation/events-reference#addcryptolegacyforbeneficiary-ibr1) — `AddCryptoLegacyForBeneficiary(bytes32 indexed beneficiary, address indexed cryptoLegacy)`
* [RemoveCryptoLegacyForBeneficiary](https://docs.cryptolegacy.app/documentation/events-reference#removecryptolegacyforbeneficiary-ibr1) — `RemoveCryptoLegacyForBeneficiary(bytes32 indexed beneficiary, address indexed cryptoLegacy)`

**Reverts if:**

* `ICryptoLegacy(msg.sender).buildManager()` — may revert per CryptoLegacy implementation (bubbled)
* `ICryptoLegacyBuildManager(buildManager).isCryptoLegacyBuilt(address)` — may revert per build manager implementation (bubbled)
* `CryptoLegacy` is not registered by its build manager — [`CryptoLegacyNotRegistered()`](https://docs.cryptolegacy.app/documentation/errors-reference#cryptolegacynotregistered-ibmo1)
* The build manager of `CryptoLegacy` is not added — [`BuildManagerNotAdded()`](https://docs.cryptolegacy.app/documentation/errors-reference#buildmanagernotadded-ibmo1)

**Overrides:** None

**Function Calls:**

* [\_checkBuildManagerValid(address,address)](#_checkbuildmanagervalid-bmo1) — BuildManagerOwnable, internal
* `EnumerableSet.AddressSet.add(address)` — OpenZeppelin EnumerableSet, internal
* `EnumerableSet.AddressSet.remove(address)` — OpenZeppelin EnumerableSet, internal
* [\_setBlockNumberChange(address)](#_setblocknumberchange-br1) — BeneficiaryRegistry, internal

**Called by:**

* [\_setCryptoLegacyToBeneficiaryRegistry()](#_setcryptolegacytobeneficiaryregistry-lcl1) — LibCryptoLegacy

**Gas / Complexity note:** O(1)

**Example:** `registry.setCryptoLegacyBeneficiary(beneficiaryHash, true);`

***

### setCryptoLegacyOwner (IBR1)

**Contract/Library:** IBeneficiaryRegistry

**Description:** Registers or removes a CryptoLegacy contract for an owner hash.

**Detailed Description:** Companion to the beneficiary setter, maintaining owner role mappings and emitting owner-role events.

**Parameters:**

* \_owner (bytes32): Owner identifier hash
* \_isAdd (bool): `true` to add, `false` to remove

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external nonpayable

**Access Control:**

* Restricted: only a CryptoLegacy built by an added build manager

**Side Effects:**

* Updates [`cryptoLegacyByOwner`](https://docs.cryptolegacy.app/documentation/data-structures-reference#cryptolegacybyowner-br1-d2)\[\_owner]
* Updates [`blockNumberChangesByCryptoLegacy`](https://docs.cryptolegacy.app/documentation/data-structures-reference#blocknumberchangesbycryptolegacy-br1-d5)\[msg.sender]

**Emits:**

* [AddCryptoLegacyForOwner](https://docs.cryptolegacy.app/documentation/events-reference#addcryptolegacyforowner-ibr1) — `AddCryptoLegacyForOwner(bytes32 indexed owner, address indexed cryptoLegacy)`
* [RemoveCryptoLegacyForOwner](https://docs.cryptolegacy.app/documentation/events-reference#removecryptolegacyforowner-ibr1) — `RemoveCryptoLegacyForOwner(bytes32 indexed owner, address indexed cryptoLegacy)`

**Reverts if:**

* `ICryptoLegacy(msg.sender).buildManager()` — may revert per CryptoLegacy implementation (bubbled)
* `ICryptoLegacyBuildManager(buildManager).isCryptoLegacyBuilt(address)` — may revert per build manager implementation (bubbled)
* `CryptoLegacy` is not registered by its build manager — [`CryptoLegacyNotRegistered()`](https://docs.cryptolegacy.app/documentation/errors-reference#cryptolegacynotregistered-ibmo1)
* The build manager of `CryptoLegacy` is not added — [`BuildManagerNotAdded()`](https://docs.cryptolegacy.app/documentation/errors-reference#buildmanagernotadded-ibmo1)

**Overrides:** None

**Function Calls:**

* [\_checkBuildManagerValid(address,address)](#_checkbuildmanagervalid-bmo1) — BuildManagerOwnable, internal
* `EnumerableSet.AddressSet.add(address)` — OpenZeppelin EnumerableSet, internal
* `EnumerableSet.AddressSet.remove(address)` — OpenZeppelin EnumerableSet, internal
* [\_setBlockNumberChange(address)](#_setblocknumberchange-br1) — BeneficiaryRegistry, internal

**Called by:**

* [\_setCryptoLegacyToBeneficiaryRegistry()](#_setcryptolegacytobeneficiaryregistry-lcl1) — LibCryptoLegacy

**Gas / Complexity note:** O(1)

**Example:** `registry.setCryptoLegacyOwner(ownerHash, true);`

***

### setCryptoLegacyGuardian (IBR1)

**Contract/Library:** IBeneficiaryRegistry

**Description:** Toggles guardian-role membership for a CryptoLegacy contract.

**Detailed Description:** Implementations map `_guardian` to the calling contract when `_isAdd` is true and remove otherwise, emitting guardian role events.

**Parameters:**

* \_guardian (bytes32): Guardian identifier hash
* \_isAdd (bool): `true` to add, `false` to remove

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external nonpayable

**Access Control:**

* Restricted: only a CryptoLegacy built by an added build manager

**Side Effects:**

* Updates [`cryptoLegacyByGuardian`](https://docs.cryptolegacy.app/documentation/data-structures-reference#cryptolegacybyguardian-br1-d3)\[\_guardian]
* Updates [`blockNumberChangesByCryptoLegacy`](https://docs.cryptolegacy.app/documentation/data-structures-reference#blocknumberchangesbycryptolegacy-br1-d5)\[msg.sender]

**Emits:**

* [AddCryptoLegacyForGuardian](https://docs.cryptolegacy.app/documentation/events-reference#addcryptolegacyforguardian-ibr1) — `AddCryptoLegacyForGuardian(bytes32 indexed guardian, address indexed cryptoLegacy)`
* [RemoveCryptoLegacyForGuardian](https://docs.cryptolegacy.app/documentation/events-reference#removecryptolegacyforguardian-ibr1) — `RemoveCryptoLegacyForGuardian(bytes32 indexed guardian, address indexed cryptoLegacy)`

**Reverts if:**

* `ICryptoLegacy(msg.sender).buildManager()` — may revert per CryptoLegacy implementation (bubbled)
* `ICryptoLegacyBuildManager(buildManager).isCryptoLegacyBuilt(address)` — may revert per build manager implementation (bubbled)
* `CryptoLegacy` is not registered by its build manager — [`CryptoLegacyNotRegistered()`](https://docs.cryptolegacy.app/documentation/errors-reference#cryptolegacynotregistered-ibmo1)
* The build manager of `CryptoLegacy` is not added — [`BuildManagerNotAdded()`](https://docs.cryptolegacy.app/documentation/errors-reference#buildmanagernotadded-ibmo1)

**Overrides:** None

**Function Calls:**

* [\_checkBuildManagerValid(address,address)](#_checkbuildmanagervalid-bmo1) — BuildManagerOwnable, internal
* `EnumerableSet.AddressSet.add(address)` — OpenZeppelin EnumerableSet, internal
* `EnumerableSet.AddressSet.remove(address)` — OpenZeppelin EnumerableSet, internal
* [\_setBlockNumberChange(address)](#_setblocknumberchange-br1) — BeneficiaryRegistry, internal

**Called by:**

* [\_setCryptoLegacyToBeneficiaryRegistry()](#_setcryptolegacytobeneficiaryregistry-lcl1) — LibCryptoLegacy

**Gas / Complexity note:** O(1)

**Example:** `registry.setCryptoLegacyGuardian(guardianHash, false);`

***

### setCryptoLegacyRecoveryAddresses (IBR1)

**Contract/Library:** IBeneficiaryRegistry

**Description:** Batch updates recovery-role mappings for a CryptoLegacy contract.

**Detailed Description:** Accepts arrays of hashes to remove and add, keeping recovery role mappings in sync. Implementations emit removal and addition events for each hash.

**Parameters:**

* \_oldRecoveryAddresses (bytes32\[], memory): Hashes to remove
* \_newRecoveryAddresses (bytes32\[], memory): Hashes to add

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external nonpayable

**Access Control:**

* Restricted: only a CryptoLegacy built by an added build manager

**Side Effects:**

* Updates [`cryptoLegacyByRecovery`](https://docs.cryptolegacy.app/documentation/data-structures-reference#cryptolegacybyrecovery-br1-d4)\[\_oldRecoveryAddresses\[i]]
* Updates [`cryptoLegacyByRecovery`](https://docs.cryptolegacy.app/documentation/data-structures-reference#cryptolegacybyrecovery-br1-d4)\[\_newRecoveryAddresses\[i]]
* Updates [`blockNumberChangesByCryptoLegacy`](https://docs.cryptolegacy.app/documentation/data-structures-reference#blocknumberchangesbycryptolegacy-br1-d5)\[msg.sender]

**Emits:**

* [RemoveCryptoLegacyForRecovery](https://docs.cryptolegacy.app/documentation/events-reference#removecryptolegacyforrecovery-ibr1) — `RemoveCryptoLegacyForRecovery(bytes32 indexed recovery, address indexed cryptoLegacy)`
* [AddCryptoLegacyForRecovery](https://docs.cryptolegacy.app/documentation/events-reference#addcryptolegacyforrecovery-ibr1) — `AddCryptoLegacyForRecovery(bytes32 indexed recovery, address indexed cryptoLegacy)`

**Reverts if:**

* `ICryptoLegacy(msg.sender).buildManager()` — may revert per CryptoLegacy implementation (bubbled)
* `ICryptoLegacyBuildManager(buildManager).isCryptoLegacyBuilt(address)` — may revert per build manager implementation (bubbled)
* `CryptoLegacy` is not registered by its build manager — [`CryptoLegacyNotRegistered()`](https://docs.cryptolegacy.app/documentation/errors-reference#cryptolegacynotregistered-ibmo1)
* The build manager of `CryptoLegacy` is not added — [`BuildManagerNotAdded()`](https://docs.cryptolegacy.app/documentation/errors-reference#buildmanagernotadded-ibmo1)

**Overrides:** None

**Function Calls:**

* [\_checkBuildManagerValid(address,address)](#_checkbuildmanagervalid-bmo1) — BuildManagerOwnable, internal
* `EnumerableSet.AddressSet.remove(address)` — OpenZeppelin EnumerableSet, internal
* `EnumerableSet.AddressSet.add(address)` — OpenZeppelin EnumerableSet, internal
* [\_setBlockNumberChange(address)](#_setblocknumberchange-br1) — BeneficiaryRegistry, internal

**Called by:**

* [\_setCryptoLegacyListToBeneficiaryRegistry()](#_setcryptolegacylisttobeneficiaryregistry-lcl1) — LibCryptoLegacy

**Gas / Complexity note:** O(n) by `_oldRecoveryAddresses.length + _newRecoveryAddresses.length`

**Example:** `registry.setCryptoLegacyRecoveryAddresses(oldHashes, newHashes);`

***

### getAllCryptoLegacyListByRoles (IBR1)

**Contract/Library:** IBeneficiaryRegistry

**Description:** Returns all CryptoLegacy addresses associated with a hash across roles.

**Detailed Description:** Provides beneficiary, owner, guardian, and recovery lists for `_hash`. Lens utilities consume this to show user-related deployments and guardian status.

**Parameters:**

* \_hash (bytes32): Role identifier hash

**Returns:**

* listByBeneficiary (address\[], memory): CryptoLegacy contracts where `_hash` is registered as a beneficiary
* listByOwner (address\[], memory): Contracts that recognise `_hash` as the owner
* listByGuardian (address\[], memory): Entries in which `_hash` acts as guardian
* listByRecovery (address\[], memory): Deployments using `_hash` as a recovery contact

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:**

* `EnumerableSet.AddressSet.values()` — OpenZeppelin EnumerableSet, internal
* `EnumerableSet.AddressSet.values()` — OpenZeppelin EnumerableSet, internal
* `EnumerableSet.AddressSet.values()` — OpenZeppelin EnumerableSet, internal
* `EnumerableSet.AddressSet.values()` — OpenZeppelin EnumerableSet, internal

**Called by:**

* [getCryptoLegacyListWithStatuses](#getcryptolegacylistwithstatuses-clexl1) — CryptoLegacyExternalLens

**Gas / Complexity note:** O(nb + no + ng + nr), where each n\* is the set size for the corresponding role

**Example:** `registry.getAllCryptoLegacyListByRoles(userHash);`

***

## IBuildManagerOwnable (IBMO1)

**No functions declared on this interface. See events-reference.md, errors-reference.md, and data-structures-reference.md for the interface's published surface.**

***

## ICallProxy (ICP1)

### submissionChainIdFrom (ICP1)

**Contract/Library:** ICallProxy

**Description:** Returns the source chain ID for the current cross-chain submission.

**Detailed Description:** Used by destination contracts to verify the origin of a deBridge submission. The LockChainGate handler reads this value and checks it against the expected `_fromChainID` before accepting a message.

**Parameters:** None

**Returns:**

* chainIdFrom (uint256): ID of the originating chain reported by the call proxy

**Modifiers / Visibility / Mutability:**

* external nonpayable

**Access Control:**

* Implementation-defined (set by call proxy)

**Side Effects:** None

**Emits:** None

**Reverts if:**

* Proxy implementation-specific

**Overrides:** None

**Function Calls:** None

**Called by:**

* [LockChainGate cross-chain receiver](#lockchaingate-lcg1) — LockChainGate

**Gas / Complexity note:** O(1)

**Example:** `uint256 chainIdFrom = callProxy.submissionChainIdFrom();`

***

### submissionNativeSender (ICP1)

**Contract/Library:** ICallProxy

**Description:** Returns the original sender (encoded as bytes) of the cross-chain submission.

**Detailed Description:** Destination handlers compare the returned value against whitelisted source contract addresses (usually via `abi.encodePacked`). In LockChainGate the bytes are hashed and matched to configured `sourceChainsContracts`.

**Parameters:** None

**Returns:**

* nativeSender (bytes, memory): ABI-encoded address of the sender from the source chain

**Modifiers / Visibility / Mutability:**

* external nonpayable

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:**

* Implementation-specific

**Overrides:** None

**Function Calls:** None

**Called by:**

* [LockChainGate cross-chain receiver](#lockchaingate-lcg1) — LockChainGate

**Gas / Complexity note:** O(1)

**Example:** `bytes memory nativeSender = callProxy.submissionNativeSender();`

***

### call (ICP1)

**Contract/Library:** ICallProxy

**Description:** Executes a cross-chain call with optional native asset transfer.

**Detailed Description:** The call proxy forwards the encoded payload to `_receiver`, optionally using reserved funds when `_receiver` reverts, and honours behaviour toggles packed in `_flags` (see the `Flags` library). CryptoLegacy contracts do not invoke this function directly, but the interface documents the expected parameters when the proxy executes on their behalf.

**Parameters:**

* \_reserveAddress (address): Fallback recipient if the call fails
* \_receiver (address): Destination contract to execute
* \_data (bytes, memory): Calldata to forward
* \_flags (uint256): Bitmask controlling behaviour (e.g., [`Flags.REVERT_IF_EXTERNAL_FAIL`](https://docs.cryptolegacy.app/documentation/data-structures-reference#revert_if_external_fail-flg1-d2))
* \_nativeSender (bytes, memory): Encoded original sender
* \_chainIdFrom (uint256): Origin chain ID

**Returns:**

* success (bool): `true` if the proxy call succeeded

**Modifiers / Visibility / Mutability:**

* external payable

**Access Control:**

* Implemented within the call proxy (typically restricted to trusted bridge executors)

**Side Effects:**

* Performs a low-level call to `_receiver`
* May transfer native assets alongside the call

**Emits:** None

**Reverts if:**

* Proxy-enforced checks fail or `_receiver` reverts when flags request propagation

**Overrides:** None

**Function Calls:** None

**Called by:** None (entry point)

**Gas / Complexity note:** Dependent on target call; interface itself is O(1)

**Example:** `bool ok = callProxy.call(reserve, target, payload, flags, senderBytes, sourceChain);`

***

### callERC20 (ICP1)

**Contract/Library:** ICallProxy

**Description:** Executes a cross-chain call that also transfers ERC20 tokens.

**Detailed Description:** Similar to `call`, but supports ERC20 transfers by pulling tokens from the proxy and forwarding them to `_receiver`. Behaviour toggles are also controlled via `_flags`.

**Parameters:**

* \_token (address): ERC20 token to transfer
* \_reserveAddress (address): Fallback recipient if the call fails
* \_receiver (address): Destination contract
* \_data (bytes, memory): Calldata for the destination contract
* \_flags (uint256): Behaviour bitmask
* \_nativeSender (bytes, memory): Encoded original sender
* \_chainIdFrom (uint256): Origin chain ID

**Returns:**

* success (bool): `true` on successful execution

**Modifiers / Visibility / Mutability:**

* external nonpayable

**Access Control:**

* Proxy implementation controls access

**Side Effects:**

* Transfers ERC20 tokens prior to executing `_receiver`

**Emits:** None

**Reverts if:**

* Token transfer or destination call fails (subject to `_flags`)

**Overrides:** None

**Function Calls:** None

**Called by:** None (entry point)

**Gas / Complexity note:** Dependent on token transfer and target call

**Example:** `bool ok = callProxy.callERC20(token, reserve, target, payload, flags, senderBytes, sourceChain);`

***

## ICryptoLegacy (ICL1)

### buildManager (ICL1)

**Contract/Library:** ICryptoLegacy

**Description:** Returns the build manager contract associated with the CryptoLegacy instance.

**Detailed Description:** Used by lens helpers and plugins to inspect which `ICryptoLegacyBuildManager` governs this diamond (for fee queries, registry lookups, etc.).

**Parameters:** None

**Returns:**

* manager (ICryptoLegacyBuildManager): Build manager interface bound to the diamond

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:**

* [\_checkBuildManagerValid()](#_checkbuildmanagervalid-bmo1) — BuildManagerOwnable
* [buildManager()](#buildmanager-clexl1) — CryptoLegacyExternalLens

**Gas / Complexity note:** O(1)

**Example:** `ICryptoLegacyBuildManager bm = ICryptoLegacy(cl).buildManager();`

***

### owner (ICL1)

**Contract/Library:** ICryptoLegacy

**Description:** Returns the current diamond owner address.

**Detailed Description:** Exposes the LibDiamond owner, enabling UIs and helper contracts to verify control.

**Parameters:** None

**Returns:**

* ownerAddr (address): Diamond owner

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:**

* [\_checkBuildManagerValid()](#_checkbuildmanagervalid-bmo1) — BuildManagerOwnable
* [isLifetimeNftLockedAndUpdate()](#islifetimenftlockedandupdate-iclbm1) — ICryptoLegacyBuildManager
* [owner()](#owner-clexl1) — CryptoLegacyExternalLens

**Gas / Complexity note:** O(1)

**Example:** `address currentOwner = ICryptoLegacy(cl).owner();`

***

## ICryptoLegacyBuildManager (ICLBM1)

### payInitialFee (ICLBM1)

**Contract/Library:** ICryptoLegacyBuildManager

**Description:** Collects the initial protocol fee when a CryptoLegacy instance is created.

**Detailed Description:** Called by `CryptoLegacyBasePlugin.payInitialFee`. Accepts the referral code, destination holder, and optional cross-chain fee data. Returns the unused portion of `msg.value` so the caller can refund excess.

**Parameters:**

* \_code (bytes8): Referral code applied to the payment
* \_toHolder (address): Address receiving any lifetime NFT mint
* \_lockToChainIds (uint256\[], memory): Destination chain IDs for cross-chain fees
* \_crossChainFees (uint256\[], memory): Fee amounts per chain

**Returns:**

* returnValue (uint256): Unused ETH returned to the caller

**Modifiers / Visibility / Mutability:**

* external payable

**Access Control:**

* Unrestricted

**Side Effects:**

* Charges protocol fees, may mint lifetime NFT depending on configuration

**Emits:** None

**Reverts if:**

* Insufficient `msg.value` for required build/lifetime fee — [`IncorrectFee(uint256)`](https://docs.cryptolegacy.app/documentation/errors-reference#incorrectfee-iclbm1)
* [`feeRegistry.getContractCaseFeeForCode(...)`](https://docs.cryptolegacy.app/documentation/data-structures-reference#feeregistry-clbm1-d1) — may revert with [`TooBigPct()`](https://docs.cryptolegacy.app/documentation/errors-reference#toobigpct-ifr1) (bubbled)
* [`feeRegistry.takeFee(...)`](https://docs.cryptolegacy.app/documentation/data-structures-reference#feeregistry-clbm1-d1) — may revert with [`IncorrectFee(uint256)`](https://docs.cryptolegacy.app/documentation/errors-reference#incorrectfee-iclbm1) or [`TooBigPct()`](https://docs.cryptolegacy.app/documentation/errors-reference#toobigpct-ifr1) (bubbled)
* [`lifetimeNft.mint(...)`](https://docs.cryptolegacy.app/documentation/data-structures-reference#lifetimenft-clbm1-d4) — may revert per token implementation (bubbled)
* [`lifetimeNft.approve(...)`](https://docs.cryptolegacy.app/documentation/data-structures-reference#lifetimenft-clbm1-d4) — may revert per token implementation (bubbled)
* `ILockChainGate.lockLifetimeNft(...)` — may revert with `"ERC721: transfer from incorrect owner"` or per ERC721 implementation, [`AlreadyLocked()`](https://docs.cryptolegacy.app/documentation/errors-reference#alreadylocked-ilcg1), [`ArrayLengthMismatch()`](https://docs.cryptolegacy.app/documentation/errors-reference#arraylengthmismatch-ilcg1), [`CrossChainLock()`](https://docs.cryptolegacy.app/documentation/errors-reference#crosschainlock-ilcg1), [`DestinationChainNotSpecified()`](https://docs.cryptolegacy.app/documentation/errors-reference#destinationchainnotspecified-ilcg1), [`AlreadyLockedToChain()`](https://docs.cryptolegacy.app/documentation/errors-reference#alreadylockedtochain-ilcg1), [`IncorrectFee(uint256)`](https://docs.cryptolegacy.app/documentation/errors-reference#incorrectfee-iclbm1), or [`TransferFeeFailed(bytes)`](https://docs.cryptolegacy.app/documentation/errors-reference#transferfeefailed-iclbm1) (bubbled)
* Refund to `msg.sender` fails — [`TransferFeeFailed(bytes)`](https://docs.cryptolegacy.app/documentation/errors-reference#transferfeefailed-iclbm1)

**Overrides:** None

**Function Calls:** None

**Called by:**

* [payInitialFee](#payinitialfee-clbp1) — CryptoLegacyBasePlugin

**Gas / Complexity note:** Depends on registry lookups and fee distribution logic

**Example:** `uint256 refund = buildManager.payInitialFee{value: msg.value}(code, owner, chains, fees);`

***

### payFee (ICLBM1)

**Contract/Library:** ICryptoLegacyBuildManager

**Description:** Processes ongoing registry update fees for an existing CryptoLegacy.

**Detailed Description:** Invoked by `CryptoLegacyBasePlugin._payFee`. Applies multiplier `_mul`, optional cross-chain fees, and returns any unused value.

**Parameters:**

* \_code (bytes8): Referral code
* \_toHolder (address): Recipient for referral rewards / lifetime NFT settlement
* \_mul (uint256): Fee multiplier based on operation type
* \_lockToChainIds (uint256\[], memory): Target chain IDs for cross-chain payments
* \_crossChainFees (uint256\[], memory): Fee amounts per chain

**Returns:**

* returnValue (uint256): Unused ETH returned to caller

**Modifiers / Visibility / Mutability:**

* external payable

**Access Control:**

* Unrestricted

**Side Effects:**

* Settles protocol fees and referral rewards

**Emits:** None

**Reverts if:**

* Insufficient `msg.value` for computed fee — [`IncorrectFee(uint256)`](https://docs.cryptolegacy.app/documentation/errors-reference#incorrectfee-iclbm1)
* [`feeRegistry.getContractCaseFeeForCode(...)`](https://docs.cryptolegacy.app/documentation/data-structures-reference#feeregistry-clbm1-d1) — may revert with [`TooBigPct()`](https://docs.cryptolegacy.app/documentation/errors-reference#toobigpct-ifr1) (bubbled)
* [`feeRegistry.takeFee(...)`](https://docs.cryptolegacy.app/documentation/data-structures-reference#feeregistry-clbm1-d1) — may revert per FeeRegistry implementation (bubbled)
* [`lifetimeNft.mint(...)`](https://docs.cryptolegacy.app/documentation/data-structures-reference#lifetimenft-clbm1-d4) — may revert per token implementation (bubbled)
* [`lifetimeNft.approve(...)`](https://docs.cryptolegacy.app/documentation/data-structures-reference#lifetimenft-clbm1-d4) — may revert per token implementation (bubbled)
* `ILockChainGate.lockLifetimeNft(...)` — may revert per LockChainGate implementation (bubbled)
* Refund to `msg.sender` fails — [`TransferFeeFailed(bytes)`](https://docs.cryptolegacy.app/documentation/errors-reference#transferfeefailed-iclbm1)

**Overrides:** None

**Function Calls:** None

**Called by:**

* [\_takeFee(ICryptoLegacy.CryptoLegacyStorage,address,address,uint256,uint256\[\],uint256\[\])](#_takefee-lcl1) — LibCryptoLegacy

**Gas / Complexity note:** Depends on fee distribution logic

**Example:** `uint256 refund = buildManager.payFee{value: msg.value}(code, owner, mul, chains, fees);`

***

### getUpdateFee (ICLBM1)

**Contract/Library:** ICryptoLegacyBuildManager

**Description:** Returns the configured update fee for a referral code.

**Detailed Description:** Thin wrapper over the fee registry.

**Parameters:**

* \_refCode (bytes8): Referral code to evaluate

**Returns:**

* updateFee (uint256): Update fee in wei

**Modifiers / Visibility / Mutability:**

* external nonpayable

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:**

* [`feeRegistry.getContractCaseFeeForCode(...)`](https://docs.cryptolegacy.app/documentation/data-structures-reference#feeregistry-clbm1-d1) — may revert with [`TooBigPct()`](https://docs.cryptolegacy.app/documentation/errors-reference#toobigpct-ifr1) (bubbled)

**Overrides:** None

**Function Calls:**

* [getContractCaseFeeForCode(address,uint8,bytes8)](#getcontractcasefeeforcode-fr1) — IFeeRegistry *(at* [*`feeRegistry`*](https://docs.cryptolegacy.app/documentation/data-structures-reference#feeregistry-clbm1-d1)*)*, external (staticcall)

**Called by:**

* [\_takeFee(ICryptoLegacy.CryptoLegacyStorage,address,address,uint256,uint256\[\],uint256\[\])](#_takefee-lcl1) — LibCryptoLegacy

**Gas / Complexity note:** O(1)

**Example:** `uint256 fee = buildManager.getUpdateFee(code);`

***

### isLifetimeNftLocked (ICLBM1)

**Contract/Library:** ICryptoLegacyBuildManager

**Description:** Checks whether a Lifetime NFT is locked for `_owner`.

**Detailed Description:** Used by CryptoLegacy logic to validate lifetime NFT state before processing fees or authorising actions.

**Parameters:**

* \_owner (address): Owner address to inspect

**Returns:**

* locked (bool): True if NFT is currently locked

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted view

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:**

* [isLifetimeActive()](#islifetimeactive-clbp1) — CryptoLegacyBasePlugin

**Gas / Complexity note:** O(1)

**Example:** `bool locked = buildManager.isLifetimeNftLocked(owner);`

***

### isLifetimeNftLockedAndUpdate (ICLBM1)

**Contract/Library:** ICryptoLegacyBuildManager

**Description:** Checks and updates lifetime NFT lock status in a single call.

**Detailed Description:** Used when the state transition should update internal tracking (e.g., refreshing lock timestamp).

**Parameters:**

* \_owner (address): Owner address

**Returns:**

* locked (bool): True if NFT remains locked after the update

**Modifiers / Visibility / Mutability:**

* external nonpayable

**Access Control:**

* Registered CryptoLegacy contracts only; `_owner` must equal `ICryptoLegacy(msg.sender).owner()`

**Side Effects:**

* May update lock tracking inside the build manager

**Emits:** None

**Reverts if:**

* `cryptoLegacyBuilt[msg.sender] == false` — [`NotRegisteredCryptoLegacy()`](https://docs.cryptolegacy.app/documentation/errors-reference#notregisteredcryptolegacy-iclbm1)
* `ICryptoLegacy(msg.sender).owner() != _owner` — [`NotOwnerOfCryptoLegacy()`](https://docs.cryptolegacy.app/documentation/errors-reference#notownerofcryptolegacy-iclbm1)
* `ILockChainGate.isNftLockedAndUpdate(...)` — may revert with [`NotAllowed()`](https://docs.cryptolegacy.app/documentation/errors-reference#notallowed-ilcg1) (bubbled)

**Overrides:** None

**Function Calls:** None

**Called by:**

* [CryptoLegacyBasePlugin.isLifetimeActive](#islifetimeactive-clbp1) — CryptoLegacyBasePlugin

**Gas / Complexity note:** O(1)

**Example:** `bool stillLocked = buildManager.isLifetimeNftLockedAndUpdate(owner);`

***

### isPluginRegistered (ICLBM1)

**Contract/Library:** ICryptoLegacyBuildManager

**Description:** Returns whether a plugin address is approved by the build manager.

**Detailed Description:** Queried before installing plugins via `LibCryptoLegacyPlugins._validatePlugin`.

**Parameters:**

* \_plugin (address): Plugin address to verify

**Returns:**

* registered (bool): True if whitelisted

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted view

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:**

* [LibCryptoLegacyPlugins.\_validatePlugin](#_validateplugin-lclp1) — LibCryptoLegacyPlugins

**Gas / Complexity note:** O(1)

**Example:** `bool ok = buildManager.isPluginRegistered(plugin);`

***

### isCryptoLegacyBuilt (ICLBM1)

**Contract/Library:** ICryptoLegacyBuildManager

**Description:** Indicates whether a CryptoLegacy address was deployed via the build manager.

**Detailed Description:** LibCryptoLegacy uses this when validating authorised senders.

**Parameters:**

* \_cryptoLegacy (address): CryptoLegacy diamond address

**Returns:**

* built (bool): True if recorded as built

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted view

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:**

* [\_checkBuildManagerValid](#_checkbuildmanagervalid-bmo1) — BuildManagerOwnable

**Gas / Complexity note:** O(1)

**Example:** `if (!buildManager.isCryptoLegacyBuilt(cl)) revert;`

***

### pluginsRegistry (ICLBM1)

**Contract/Library:** ICryptoLegacyBuildManager

**Description:** Returns the plugins registry contract address.

**Detailed Description:** Referenced when syncing plugin metadata or validating plugin registrations.

**Parameters:** None

**Returns:**

* registry (IPluginsRegistry): Active plugins registry

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted view

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:**

* [\_getPluginMetadata()](#_getpluginmetadata-lp1) — LensPlugin

**Gas / Complexity note:** O(1)

**Example:** `address pr = address(buildManager.pluginsRegistry());`

***

### getFactoryAddress (ICLBM1)

**Contract/Library:** ICryptoLegacyBuildManager

**Description:** Returns the configured factory contract address.

**Detailed Description:** Used to display deployment pathways and ensure only approved factories are referenced.

**Parameters:** None

**Returns:**

* factory (address): Registered factory address

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted view

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** `address factory = buildManager.getFactoryAddress();`

***

### beneficiaryRegistry (ICLBM1)

**Contract/Library:** ICryptoLegacyBuildManager

**Description:** Returns the beneficiary registry address used by the build manager.

**Detailed Description:** Exposed so that diamonds and lens contracts can interact with the central registry.

**Parameters:** None

**Returns:**

* registry (IBeneficiaryRegistry): Beneficiary registry interface

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted view

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:**

* [\_getBeneficiaryRegistry()](#_getbeneficiaryregistry-lcl1) — LibCryptoLegacy

**Gas / Complexity note:** O(1)

**Example:** `IBeneficiaryRegistry br = buildManager.beneficiaryRegistry();`

***

### externalLens (ICLBM1)

**Contract/Library:** ICryptoLegacyBuildManager

**Description:** Returns the external lens contract used for off-chain queries.

**Detailed Description:** Lets clients discover the companion lens contract for a given build manager.

**Parameters:** None

**Returns:**

* lens (address): External lens contract address

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted view

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:**

* [externalLens()](#externallens-cl1) — CryptoLegacy

**Gas / Complexity note:** O(1)

**Example:** `address lens = buildManager.externalLens();`

***

## ICryptoLegacyDiamondBase (ICLDB1)

**No functions declared on this interface. See events-reference.md, errors-reference.md, and data-structures-reference.md for the interface's published surface.**

***

## ICryptoLegacyFactory (ICLF1)

### createCryptoLegacy (ICLF1)

**Contract/Library:** ICryptoLegacyFactory

**Description:** Deploys a new CryptoLegacy diamond with the supplied owner, plugin list, and optional CREATE2 parameters.

**Detailed Description:** Factory entry point used by governance/build managers. Implementations typically call `LibCreate3`/CREATE2 helpers (see `CryptoLegacyFactory.createCryptoLegacy`).

**Parameters:**

* \_owner (address): Designated owner of the new CryptoLegacy
* \_plugins (address\[], memory): Initial plugin facets
* \_create2Args ([Create2Args](https://docs.cryptolegacy.app/documentation/data-structures-reference#create2args-iclf1-s1), memory): Optional deterministic deployment config

**Returns:**

* cryptoLegacy (address payable): Newly deployed CryptoLegacy diamond

**Modifiers / Visibility / Mutability:**

* external nonpayable

**Access Control:**

* Implementation-defined (factory usually `onlyBuildOperator`)

**Side Effects:**

* Deploys and initialises a CryptoLegacy contract

**Emits:**

* [CryptoLegacyCreation](https://docs.cryptolegacy.app/documentation/events-reference#cryptolegacycreation-lcld1) — `CryptoLegacyCreation(address addr, bytes32 salt, bytes32 userSalt)`

**Reverts if:**

* Deployment prerequisites fail (e.g., caller not operator, invalid args)

**Overrides:** None

**Function Calls:** None

**Called by:**

* [buildCryptoLegacy](#buildcryptolegacy-clbm1) — CryptoLegacyBuildManager

**Gas / Complexity note:** Dominated by deployment cost (∝ bytecode size)

**Example:** `address cl = factory.createCryptoLegacy(newOwner, initialPlugins, create2Args);`

***

### setBuildOperator (ICLF1)

**Contract/Library:** ICryptoLegacyFactory

**Description:** Grants or revokes build-operator permissions for the factory.

**Detailed Description:** Authorised callers toggle `_operator` in the factory's allowlist (see `CryptoLegacyFactory.setBuildOperator`). Required before an address can call `createCryptoLegacy`.

**Parameters:**

* \_operator (address): Address whose permission is being updated
* \_isAdd (bool): `true` to grant operator rights, `false` to revoke

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external nonpayable

**Access Control:**

* Implementation-defined (factory owner/governance)

**Side Effects:**

* Updates internal operator allowlist

**Emits:**

* [AddBuildOperator](https://docs.cryptolegacy.app/documentation/events-reference#addbuildoperator-iclf1) — `AddBuildOperator(address indexed buildOperator)`
* [RemoveBuildOperator](https://docs.cryptolegacy.app/documentation/events-reference#removebuildoperator-iclf1) — `RemoveBuildOperator(address indexed buildOperator)`

**Reverts if:**

* Caller lacks permission or `_operator` invalid (implementation checks)

**Overrides:** None

**Function Calls:** None

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** [`factory.setBuildOperator(operator, true);`](https://docs.cryptolegacy.app/documentation/data-structures-reference#factory-clbm1-d5)

***

## ICryptoLegacyLens (ICLL1)

### getMessagesBlockNumbersByRecipient (ICLL1)

**Contract/Library:** ICryptoLegacyLens

**Description:** Returns the message block numbers recorded for a recipient hash.

**Detailed Description:** Implementations track message history (for example via LegacyMessenger) and return the block numbers associated with messages addressed to the recipient.

**Parameters:**

* \_recipient (bytes32): Recipient hash

**Returns:**

* blockNumbers (uint64\[], memory): Block numbers where messages for the recipient were stored

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:**

* Implementation-defined (lens implementation may revert)

**Overrides:** None

**Function Calls:** None

**Called by:**

* [getMessagesBlockNumbersByRecipient(address,bytes32)](#getmessagesblocknumbersbyrecipient-clexl1) — CryptoLegacyExternalLens
* [getMessagesBlockNumbersByRecipient(bytes32)](#getmessagesblocknumbersbyrecipient-lp1) — LensPlugin

**Gas / Complexity note:** O(n) where n is the number of recorded message blocks

**Example:** `uint64[] memory blocks = ICryptoLegacyLens(cl).getMessagesBlockNumbersByRecipient(recipient);`

***

### getVestedAndClaimedData (ICLL1)

**Contract/Library:** ICryptoLegacyLens

**Description:** Returns per-token vested and claimed data for a beneficiary.

**Detailed Description:** Aggregates vesting and claim totals for each token in `_tokens` and returns the vesting window timestamps alongside the per-token data.

**Parameters:**

* \_beneficiary (bytes32): Beneficiary hash
* \_tokens (address\[], memory): Token addresses to query

**Returns:**

* result ([BeneficiaryTokenData](https://docs.cryptolegacy.app/documentation/data-structures-reference#beneficiarytokendata-icll1-s1)\[], memory): Per-token claimable and claimed data
* startDate (uint64): Vesting start timestamp
* endDate (uint64): Vesting end timestamp

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:**

* Implementation-defined (lens implementation may revert)

**Overrides:** None

**Function Calls:** None

**Called by:**

* [getVestedAndClaimedData(address,bytes32,address\[\])](#getvestedandclaimeddata-clexl1) — CryptoLegacyExternalLens
* [getVestedAndClaimedData(bytes32,address\[\])](#getvestedandclaimeddata-lp1) — LensPlugin

**Gas / Complexity note:** O(n) where n is `_tokens.length`

**Example:** `(data, start, end) = ICryptoLegacyLens(cl).getVestedAndClaimedData(beneficiary, tokens);`

***

### getCryptoLegacyBaseData (ICLL1)

**Contract/Library:** ICryptoLegacyLens

**Description:** Returns the core configuration snapshot for a CryptoLegacy.

**Detailed Description:** Bundles fee, timing, and build-manager metadata into a single struct for UI and tooling consumption.

**Parameters:** None

**Returns:**

* data ([CryptoLegacyBaseData](https://docs.cryptolegacy.app/documentation/data-structures-reference#cryptolegacybasedata-icll1-s3), memory): Base configuration snapshot

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:**

* Implementation-defined (lens implementation may revert)

**Overrides:** None

**Function Calls:** None

**Called by:**

* [getCryptoLegacyBaseData(address)](#getcryptolegacybasedata-clexl1) — CryptoLegacyExternalLens
* [getCryptoLegacyBaseData()](#getcryptolegacybasedata-lp1) — LensPlugin

**Gas / Complexity note:** O(1)

**Example:** `ICryptoLegacyLens.CryptoLegacyBaseData memory data = ICryptoLegacyLens(cl).getCryptoLegacyBaseData();`

***

### getCryptoLegacyListData (ICLL1)

**Contract/Library:** ICryptoLegacyLens

**Description:** Returns aggregated beneficiaries, transfers, plugins, and token distribution data.

**Detailed Description:** Compiles the beneficiary lists, transfer history, plugin metadata, and token distribution snapshots into a single struct.

**Parameters:**

* \_tokens (address\[], memory): Token addresses to include in distribution data

**Returns:**

* data ([CryptoLegacyListData](https://docs.cryptolegacy.app/documentation/data-structures-reference#cryptolegacylistdata-icll1-s5), memory): Aggregated list data

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:**

* Implementation-defined (lens implementation may revert)

**Overrides:** None

**Function Calls:** None

**Called by:**

* [getCryptoLegacyListData(address,address\[\])](#getcryptolegacylistdata-clexl1) — CryptoLegacyExternalLens
* [getCryptoLegacyListData(address\[\])](#getcryptolegacylistdata-lp1) — LensPlugin

**Gas / Complexity note:** O(n) where n is `_tokens.length` plus beneficiary/plugin counts

**Example:** `ICryptoLegacyLens.CryptoLegacyListData memory data = ICryptoLegacyLens(cl).getCryptoLegacyListData(tokens);`

***

## ICryptoLegacyOwnable (ICLO1)

**No functions declared on this interface. See events-reference.md, errors-reference.md, and data-structures-reference.md for the interface's published surface.**

***

## ICryptoLegacyPlugin (ICLP1)

### getSigs (ICLP1)

**Contract/Library:** ICryptoLegacyPlugin

**Description:** Returns the function selectors supported by the plugin.

**Detailed Description:** Selectors are used by the diamond loupe and plugin registry tooling to enumerate the callable functions exposed by the plugin.

**Parameters:** None

**Returns:**

* sigs (bytes4\[], memory): Function selectors implemented by the plugin

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:**

* [facets()](#facets-dlf1) — DiamondLoupeFacet
* [facetFunctionSelectors(address)](#facetfunctionselectors-dlf1) — DiamondLoupeFacet

**Gas / Complexity note:** O(n) where n is the number of selectors returned

**Example:** `bytes4[] memory sigs = ICryptoLegacyPlugin(plugin).getSigs();`

***

### getSetupSigs (ICLP1)

**Contract/Library:** ICryptoLegacyPlugin

**Description:** Returns the setup selectors required when installing the plugin.

**Detailed Description:** Build managers collect these selectors when adding facets so the diamond can expose initialization routines needed by the plugin.

**Parameters:** None

**Returns:**

* sigs (bytes4\[], memory): Setup function selectors

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:**

* [\_addPluginList(address\[\])](#_addpluginlist-lclp1) — LibCryptoLegacyPlugins

**Gas / Complexity note:** O(n) where n is the number of selectors returned

**Example:** `bytes4[] memory setup = ICryptoLegacyPlugin(plugin).getSetupSigs();`

***

### getPluginName (ICLP1)

**Contract/Library:** ICryptoLegacyPlugin

**Description:** Returns the human-readable plugin name.

**Detailed Description:** Used by lens tooling to display plugin metadata alongside active facets.

**Parameters:** None

**Returns:**

* name (string, memory): Plugin name

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:**

* [\_getPluginMetadata(address)](#_getpluginmetadata-lp1) — LensPlugin

**Gas / Complexity note:** O(1)

**Example:** `string memory name = ICryptoLegacyPlugin(plugin).getPluginName();`

***

### getPluginVer (ICLP1)

**Contract/Library:** ICryptoLegacyPlugin

**Description:** Returns the plugin version number.

**Detailed Description:** Reported by lens tooling to track plugin releases and compatibility.

**Parameters:** None

**Returns:**

* version (uint16): Plugin version

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:**

* [\_getPluginMetadata(address)](#_getpluginmetadata-lp1) — LensPlugin

**Gas / Complexity note:** O(1)

**Example:** `uint16 v = ICryptoLegacyPlugin(plugin).getPluginVer();`

***

## IDeBridgeGate (IDBG1)

### isSubmissionUsed (IDBG1)

**Contract/Library:** IDeBridgeGate

**Description:** Reports whether a deBridge submission has already been claimed.

**Detailed Description:** Returns a boolean flag indicating reuse of the specified `submissionId`, enabling CryptoLegacy to guard against replaying the same bridge payload.

**Parameters:**

* submissionId (bytes32): Unique identifier of the deBridge submission to inspect

**Returns:**

* used (bool): `true` if the submission has already been processed

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:**

* Gateway guard conditions fail — may revert per deBridge implementation (bubbled)

**Overrides:** None

**Function Calls:** None

**Called by:** None

**Gas / Complexity note:** O(1)

**Example:** `bool alreadyClaimed = IDeBridgeGate(gate).isSubmissionUsed(submissionId);`

***

### getNativeInfo (IDBG1)

**Contract/Library:** IDeBridgeGate

**Description:** Returns the origin chain metadata for a wrapped asset.

**Detailed Description:** Provides the native chain identifier and native token address bytes associated with a wrapped token, assisting CryptoLegacy when resolving cross-chain asset provenance.

**Parameters:**

* token (address): Wrapped asset address on the current chain

**Returns:**

* nativeChainId (uint256): Origin chain identifier
* nativeAddress (bytes, memory): Encoded native token address

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:**

* Gateway metadata lookup fails — may revert per deBridge implementation (bubbled)

**Overrides:** None

**Function Calls:** None

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** `(uint256 chainId, bytes memory native) = IDeBridgeGate(gate).getNativeInfo(token);`

***

### callProxy (IDBG1)

**Contract/Library:** IDeBridgeGate

**Description:** Exposes the call proxy contract used to execute bridged payloads on the destination chain.

**Detailed Description:** CryptoLegacy queries this address to interact with the deBridge call proxy when sending cross-chain execution requests.

**Parameters:** None

**Returns:**

* proxy (address): deBridge call proxy contract address

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:**

* Gateway state unavailable — may revert per deBridge implementation (bubbled)

**Overrides:** None

**Function Calls:** None

**Called by:**

* [\_send()](#_send-lcg1) — LockChainGate

**Gas / Complexity note:** O(1)

**Example:** `address proxy = IDeBridgeGate(gate).callProxy();`

***

### globalFixedNativeFee (IDBG1)

**Contract/Library:** IDeBridgeGate

**Description:** Returns the global base native fee charged for bridging operations.

**Detailed Description:** CryptoLegacy compares this protocol-wide fee with per-chain overrides to determine the minimal native value required when submitting cross-chain transactions.

**Parameters:** None

**Returns:**

* fee (uint256): Base native fee denominated in wei

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:**

* Gateway fee lookup fails — may revert per deBridge implementation (bubbled)

**Overrides:** None

**Function Calls:** None

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** `uint256 baseFee = IDeBridgeGate(gate).globalFixedNativeFee();`

***

### globalTransferFeeBps (IDBG1)

**Contract/Library:** IDeBridgeGate

**Description:** Returns the global percentage fee (in basis points) applied to bridged transfers.

**Detailed Description:** Used together with `globalFixedNativeFee()` to compute the total native value required when forwarding assets through deBridge.

**Parameters:** None

**Returns:**

* feeBps (uint16): Transfer fee expressed in basis points

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:**

* Gateway fee lookup fails — may revert per deBridge implementation (bubbled)

**Overrides:** None

**Function Calls:** None

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** `uint16 feeBps = IDeBridgeGate(gate).globalTransferFeeBps();`

***

### sendMessage(uint256,bytes,bytes) (IDBG1)

**Contract/Library:** IDeBridgeGate

**Description:** Submits a cross-chain message to a destination contract without transferring assets.

**Detailed Description:** Sends a message to `_dstChainId` instructing deBridge to call `_targetContractAddress` with `_targetContractCalldata`. Uses the gateway default flags (REVERT\_IF\_EXTERNAL\_FAIL and PROXY\_WITH\_SENDER). Requires `msg.value` to cover the protocol fee and optional execution fee.

**Parameters:**

* \_dstChainId (uint256): Destination chain ID
* \_targetContractAddress (bytes, memory): Encoded destination contract address
* \_targetContractCalldata (bytes, memory): Calldata to execute on the destination chain

**Returns:**

* submissionId (bytes32): deBridge submission identifier

**Modifiers / Visibility / Mutability:**

* external payable

**Access Control:**

* Unrestricted

**Side Effects:**

* Submits a cross-chain message and pays the native protocol fee to the deBridge gateway

**Emits:**

* [Sent](https://docs.cryptolegacy.app/documentation/events-reference#sent-idbg1) — `Sent(bytes32 submissionId, bytes32 indexed debridgeId, uint256 amount, bytes receiver, uint256 nonce, uint256 indexed chainIdTo, uint32 referralCode, FeeParams feeParams, bytes autoParams, address nativeSender)`

**Reverts if:**

* Gateway validation fails or fee is insufficient — may revert per deBridge implementation (bubbled)

**Overrides:** None

**Function Calls:** None

**Called by:** None (entry point)

**Gas / Complexity note:** O(1) plus calldata size for `_targetContractCalldata`

**Example:** `IDeBridgeGate(gate).sendMessage{value: fee}(chainId, target, data);`

***

### sendMessage(uint256,bytes,bytes,uint256,uint32) (IDBG1)

**Contract/Library:** IDeBridgeGate

**Description:** Submits a cross-chain message with explicit flags and referral code.

**Detailed Description:** Sends a message to `_dstChainId` instructing deBridge to call `_targetContractAddress` with `_targetContractCalldata`. The caller provides `_flags` (see `Flags`) and a `_referralCode`. Requires `msg.value` to cover the protocol fee and optional execution fee.

**Parameters:**

* \_dstChainId (uint256): Destination chain ID
* \_targetContractAddress (bytes, memory): Encoded destination contract address
* \_targetContractCalldata (bytes, memory): Calldata to execute on the destination chain
* \_flags (uint256): Bitmask of execution flags
* \_referralCode (uint32): Referral code to attribute the submission

**Returns:**

* submissionId (bytes32): deBridge submission identifier

**Modifiers / Visibility / Mutability:**

* external payable

**Access Control:**

* Unrestricted

**Side Effects:**

* Submits a cross-chain message and pays the native protocol fee to the deBridge gateway

**Emits:**

* [Sent](https://docs.cryptolegacy.app/documentation/events-reference#sent-idbg1) — `Sent(bytes32 submissionId, bytes32 indexed debridgeId, uint256 amount, bytes receiver, uint256 nonce, uint256 indexed chainIdTo, uint32 referralCode, FeeParams feeParams, bytes autoParams, address nativeSender)`

**Reverts if:**

* Gateway validation fails or fee is insufficient — may revert per deBridge implementation (bubbled)

**Overrides:** None

**Function Calls:** None

**Called by:**

* [\_send()](#_send-lcg1) — LockChainGate

**Gas / Complexity note:** O(1) plus calldata size for `_targetContractCalldata`

**Example:** `IDeBridgeGate(gate).sendMessage{value: fee}(chainId, target, data, flags, refCode);`

***

### send (IDBG1)

**Contract/Library:** IDeBridgeGate

**Description:** Bridges assets from the native chain to a destination chain.

**Detailed Description:** Locks the specified token on the source chain and submits a transfer to `_chainIdTo`. Optional permit and auto-execution parameters are forwarded to the gateway.

**Parameters:**

* \_tokenAddress (address): Asset to bridge
* \_amount (uint256): Amount to transfer
* \_chainIdTo (uint256): Destination chain ID
* \_receiver (bytes, memory): Encoded receiver address on the destination chain
* \_permitEnvelope (bytes, memory): Permit data for token approval
* \_useAssetFee (bool): Whether to pay the fixed fee in asset units
* \_referralCode (uint32): Referral code to attribute the submission
* \_autoParams (bytes, calldata): Auto-execution parameters for the destination call

**Returns:**

* submissionId (bytes32): deBridge submission identifier

**Modifiers / Visibility / Mutability:**

* external payable

**Access Control:**

* Unrestricted

**Side Effects:**

* Locks assets and submits a cross-chain transfer through the deBridge gateway

**Emits:**

* [Sent](https://docs.cryptolegacy.app/documentation/events-reference#sent-idbg1) — `Sent(bytes32 submissionId, bytes32 indexed debridgeId, uint256 amount, bytes receiver, uint256 nonce, uint256 indexed chainIdTo, uint32 referralCode, FeeParams feeParams, bytes autoParams, address nativeSender)`

**Reverts if:**

* Transfer validation fails or fee is insufficient — may revert per deBridge implementation (bubbled)

**Overrides:** None

**Function Calls:** None

**Called by:** None (entry point)

**Gas / Complexity note:** O(1) plus calldata size for `_autoParams` and `_receiver`

**Example:** `IDeBridgeGate(gate).send{value: fee}(token, amount, chainId, receiver, permit, useAssetFee, refCode, autoParams);`

***

### claim (IDBG1)

**Contract/Library:** IDeBridgeGate

**Description:** Claims bridged assets on the destination chain.

**Detailed Description:** Validates the submission and releases (or mints) assets to `_receiver` for transfers originating from `_chainIdFrom`.

**Parameters:**

* \_debridgeId (bytes32): Asset identifier
* \_amount (uint256): Amount to claim
* \_chainIdFrom (uint256): Source chain ID
* \_receiver (address): Destination receiver address
* \_nonce (uint256): Submission nonce
* \_signatures (bytes, calldata): Validator signatures
* \_autoParams (bytes, calldata): Auto-execution parameters

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external nonpayable

**Access Control:**

* Unrestricted

**Side Effects:**

* Releases bridged assets and updates gateway submission state

**Emits:**

* [Claimed](https://docs.cryptolegacy.app/documentation/events-reference#claimed-idbg1) — `Claimed(bytes32 submissionId, bytes32 indexed debridgeId, uint256 amount, address indexed receiver, uint256 nonce, uint256 indexed chainIdFrom, bytes autoParams, bool isNativeToken)`

**Reverts if:**

* Submission validation fails — may revert per deBridge implementation (bubbled)

**Overrides:** None

**Function Calls:** None

**Called by:** None (entry point)

**Gas / Complexity note:** Implementation-dependent; includes signature verification cost

**Example:** `IDeBridgeGate(gate).claim(debridgeId, amount, chainIdFrom, receiver, nonce, sigs, autoParams);`

***

### withdrawFee (IDBG1)

**Contract/Library:** IDeBridgeGate

**Description:** Withdraws accumulated protocol fees for an asset.

**Detailed Description:** Transfers collected fees associated with `_debridgeId` to the gateway’s fee recipient.

**Parameters:**

* \_debridgeId (bytes32): Asset identifier

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external nonpayable

**Access Control:**

* Implementation-defined (fee recipient or governance)

**Side Effects:**

* Decreases accumulated fees for the specified asset

**Emits:**

* [WithdrawnFee](https://docs.cryptolegacy.app/documentation/events-reference#withdrawnfee-idbg1) — `WithdrawnFee(bytes32 debridgeId, uint256 fee)`

**Reverts if:**

* Fee withdrawal fails — may revert per deBridge implementation (bubbled)

**Overrides:** None

**Function Calls:** None

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** `IDeBridgeGate(gate).withdrawFee(debridgeId);`

***

### getDebridgeChainAssetFixedFee (IDBG1)

**Contract/Library:** IDeBridgeGate

**Description:** Returns the fixed native fee for an asset on a specific chain.

**Detailed Description:** Looks up the chain-specific fixed fee for `_debridgeId` and `_chainId`.

**Parameters:**

* \_debridgeId (bytes32): Asset identifier
* \_chainId (uint256): Chain ID to query

**Returns:**

* fee (uint256): Fixed native fee for the given asset and chain

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:**

* Gateway fee lookup fails — may revert per deBridge implementation (bubbled)

**Overrides:** None

**Function Calls:** None

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** `uint256 fee = IDeBridgeGate(gate).getDebridgeChainAssetFixedFee(debridgeId, chainId);`

***

## IDiamondCut (IDC1)

### diamondCut (IDC1)

**Contract/Library:** IDiamondCut

**Description:** External entry point for applying diamond facet cuts with optional initialization.

**Detailed Description:** Accepts an array of facet operations describing selectors to add, replace, or remove, and may execute an initialization delegatecall after the cut. Access control and cut validation are enforced by the implementing diamond.

**Parameters:**

* \_diamondCut ([FacetCut](https://docs.cryptolegacy.app/documentation/data-structures-reference#facetcut-idc1-s1)\[], calldata): Facet modifications to apply
* \_init (address): Address receiving the optional delegatecall initializer
* \_calldata (bytes, calldata): Encoded initializer payload executed against `_init`

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external nonpayable

**Access Control:**

* Implementation-defined (typically restricted to the diamond owner or governance)

**Side Effects:** None

**Emits:**

* [DiamondCut](https://docs.cryptolegacy.app/documentation/events-reference#diamondcut-idc1) — `DiamondCut(FacetCut[] _diamondCut, address _init, bytes _calldata)`

**Reverts if:**

* Implementation-defined — may revert per diamond cut implementation (e.g., unauthorized caller, invalid facet configuration)

**Overrides:** None

**Function Calls:** None

**Called by:** None (entry point)

**Gas / Complexity note:** Implementation-dependent; typically O(n) where n is the total number of function selectors processed in the cut

**Example:** `diamondCutFacet.diamondCut(cut, initializer, initData);`

***

## IDiamondLoupe (IDL1)

### facets (IDL1)

**Contract/Library:** IDiamondLoupe

**Description:** Returns the full list of facet addresses together with their selectors.

**Detailed Description:** Enables tooling to inspect the diamond by retrieving every facet and its published function selectors in a single call.

**Parameters:** None

**Returns:**

* facets\_ ([Facet](https://docs.cryptolegacy.app/documentation/data-structures-reference#facet-idl1-s1)\[], memory): Array of facet metadata including selector lists

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:**

* Implementation-defined — may revert per diamond implementation (bubbled)

**Overrides:** None

**Function Calls:** None

**Called by:** None (entry point)

**Gas / Complexity note:** Implementation-dependent; typically O(f + s) where f is facet count and s is total selectors returned

**Example:** `IDiamondLoupe(diamond).facets();`

***

### facetFunctionSelectors (IDL1)

**Contract/Library:** IDiamondLoupe

**Description:** Returns the selector list exposed by a specific facet.

**Detailed Description:** Lets callers inspect the functions advertised by `_facet`, aiding auditors and upgrade tooling in mapping selectors to facets.

**Parameters:**

* \_facet (address): Facet address to inspect

**Returns:**

* facetFunctionSelectors\_ (bytes4\[], memory): Selector array reported by the facet

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:**

* Implementation-defined — may revert per diamond implementation (bubbled)

**Overrides:** None

**Function Calls:** None

**Called by:** None (entry point)

**Gas / Complexity note:** Implementation-dependent; typically O(s) where s is the number of selectors returned

**Example:** `IDiamondLoupe(diamond).facetFunctionSelectors(facet);`

***

### facetAddresses (IDL1)

**Contract/Library:** IDiamondLoupe

**Description:** Lists every facet address installed on the diamond.

**Detailed Description:** Provides an ordered snapshot of facet addresses, enabling dashboards and off-chain clients to track installed facets.

**Parameters:** None

**Returns:**

* facetAddresses\_ (address\[], memory): Installed facet addresses

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:**

* Implementation-defined — may revert per diamond implementation (bubbled)

**Overrides:** None

**Function Calls:** None

**Called by:** None (entry point)

**Gas / Complexity note:** Implementation-dependent; typically O(f) where f is the number of facets

**Example:** `address[] memory facets = IDiamondLoupe(diamond).facetAddresses();`

***

### facetAddress (IDL1)

**Contract/Library:** IDiamondLoupe

**Description:** Resolves which facet implements a given selector.

**Detailed Description:** Helps callers map a function selector to the facet responsible for it, returning `address(0)` when the selector is not installed.

**Parameters:**

* \_functionSelector (bytes4): Selector to resolve

**Returns:**

* facetAddress\_ (address): Facet that exposes the selector, or zero address if none

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:**

* Implementation-defined — may revert per diamond implementation (bubbled)

**Overrides:** None

**Function Calls:** None

**Called by:** None (entry point)

**Gas / Complexity note:** Implementation-dependent; typically O(1) with cached selector mapping

**Example:** `address facet = IDiamondLoupe(diamond).facetAddress(selector);`

***

## IFeeRegistry (IFR1)

### getContractCaseFee (IFR1)

**Contract/Library:** IFeeRegistry

**Description:** Returns the configured base fee for a specific contract-case combination.

**Detailed Description:** Provides the raw fee stored in `feeByContractCase_contract_case`, without applying any referral discounts or shares.

**Parameters:**

* \_contract (address): Contract whose fee schedule is queried
* \_case (uint8): Case identifier (e.g., build, update, lifetime)

**Returns:**

* fee (uint256): Stored fee amount in wei

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** `uint256 fee = IFeeRegistry(feeRegistry).getContractCaseFee(address(buildManager), caseId);`

***

### getContractCaseFeeForCode (IFR1)

**Contract/Library:** IFeeRegistry

**Description:** Returns the effective fee for a contract-case after applying a referral code’s discount.

**Detailed Description:** Computes discount and share percentages for `_code`, subtracts the discount from the base fee, and returns the payable amount for the case.

**Parameters:**

* \_contract (address): Contract whose fee is being requested
* \_case (uint8): Case identifier
* \_code (bytes8): Referral code (zero to apply defaults)

**Returns:**

* fee (uint256): Payable fee after applying the discount

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:**

* Discount percentage plus share percentage exceeds 100% — [`TooBigPct()`](https://docs.cryptolegacy.app/documentation/errors-reference#toobigpct-ifr1)

**Overrides:** None

**Function Calls:** None

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** `uint256 fee = IFeeRegistry(feeRegistry).getContractCaseFeeForCode(address(buildManager), caseId, code);`

***

### takeFee (IFR1)

**Contract/Library:** IFeeRegistry

**Description:** Charges the calculated fee for a contract-case and processes referral payouts.

**Detailed Description:** Accepts ETH, enforces the expected fee amount, applies referral discount/share, accrues protocol fees, and attempts to pay the referrer’s share, falling back to accumulation on failure.

**Parameters:**

* \_contract (address): Contract paying the fee
* \_case (uint8): Case identifier
* \_code (bytes8): Referral code to apply
* \_mul (uint256): Multiplier applied to the base fee (e.g., batch payments)

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external payable

**Access Control:**

* Unrestricted

**Side Effects:**

* Increases `accumulatedFee` by the protocol portion of the fee
* Attempts to transfer the referrer share; on failure, accrues it to the referrer’s accumulated balance

**Emits:**

* [SentFee](https://docs.cryptolegacy.app/documentation/events-reference#sentfee-ifr1) — `SentFee(address indexed referrer, bytes8 indexed code, address indexed recipient, uint256 value)`
* [AccumulateFee](https://docs.cryptolegacy.app/documentation/events-reference#accumulatefee-ifr1) — `AccumulateFee(address indexed referrer, bytes8 indexed code, address indexed recipient, uint256 value, bytes transferResponse)`
* [TakeFee](https://docs.cryptolegacy.app/documentation/events-reference#takefee-ifr1) — `TakeFee(address indexed sourceContract, uint8 indexed contractCase, bytes8 indexed code, uint256 discount, uint256 share, uint256 fee, uint256 value)`

**Reverts if:**

* Reentrant call — "ReentrancyGuard: reentrant call"
* Referral discount plus share exceeds 100% — [`TooBigPct()`](https://docs.cryptolegacy.app/documentation/errors-reference#toobigpct-ifr1)
* `msg.value < fee` or `msg.value - fee > 0.00001 ether` — [`IncorrectFee(uint256)`](https://docs.cryptolegacy.app/documentation/errors-reference#incorrectfee-ilcg1)

**Overrides:** None

**Function Calls:** None

**Called by:** None (entry point)

**Gas / Complexity note:** Implementation-dependent; includes constant-time accounting plus one low-gas external transfer attempt

**Example:** `IFeeRegistry(feeRegistry).takeFee{value: msg.value}(address(buildManager), REGISTRY_UPDATE_CASE, code, 1);`

***

### createCustomCode (IFR1)

**Contract/Library:** IFeeRegistry

**Description:** Creates a specific referral code and optionally pushes it to other chains.

**Detailed Description:** Implementations expect the caller to be an authorised code operator; they register `_shortCode` for `_referrer`, configure payouts, broadcast the code cross-chain, and refund unused native value.

**Parameters:**

* \_referrer (address): Owner of the new code
* \_recipient (address): Address receiving referral payouts
* \_shortCode (bytes8): Desired referral code
* \_chainIds (uint256\[], memory): Destination chain IDs for propagation
* \_crossChainFees (uint256\[], memory): Native fee per destination chain (0 to auto-calc)

**Returns:**

* code (bytes8): The created referral code
* totalFee (uint256): Total native fee consumed for cross-chain messaging
* returnValue (uint256): Refunded surplus native value

**Modifiers / Visibility / Mutability:**

* external payable

**Access Control:**

* Implementation-defined (FeeRegistry restricts to code operators)

**Side Effects:**

* Registers the custom referral code and persists operator/referrer metadata
* Spends or reserves native fees for cross-chain propagation and refunds surplus

**Emits:**

* [CreateCode](https://docs.cryptolegacy.app/documentation/events-reference#createcode-ifr1) — `CreateCode(address indexed codeOperator, address indexed referrer, bytes8 indexed code, address recipient, uint256 fromChain, uint32 discountPct, uint32 sharePct)`
* [SendToChain](https://docs.cryptolegacy.app/documentation/events-reference#sendtochain-ilcg1) — `SendToChain(uint256 indexed toChainId, bytes32 indexed submissionId, uint256 value, bytes dstTransactionCall)`
* [SetCrossChainsRef](https://docs.cryptolegacy.app/documentation/events-reference#setcrosschainsref-ifr1) — `SetCrossChainsRef(bytes8 indexed shortCode, bool indexed isCreate, uint256[] toChainIDs, uint256[] crossChainFees)`

**Reverts if:**

* Reentrant call — "ReentrancyGuard: reentrant call"
* Caller lacks operator permission — [`NotOperator()`](https://docs.cryptolegacy.app/documentation/errors-reference#notoperator-ifr1)
* `_shortCode` already exists — [`RefAlreadyCreated()`](https://docs.cryptolegacy.app/documentation/errors-reference#refalreadycreated-ifr1)
* `_shortCode` is zero — [`ZeroCode()`](https://docs.cryptolegacy.app/documentation/errors-reference#zerocode-ifr1)
* `_referrer` already has a code — [`AlreadyReferrer()`](https://docs.cryptolegacy.app/documentation/errors-reference#alreadyreferrer-ifr1)
* `_chainIds.length != _crossChainFees.length` — [`ArrayLengthMismatch()`](https://docs.cryptolegacy.app/documentation/errors-reference#arraylengthmismatch-ilcg1)
* Destination chain contract missing — [`DestinationChainNotSpecified()`](https://docs.cryptolegacy.app/documentation/errors-reference#destinationchainnotspecified-ilcg1)
* `deBridgeGate.globalFixedNativeFee()` — may revert per deBridge implementation (bubbled)
* `deBridgeGate.sendMessage(...)` — may revert per deBridge implementation (bubbled)
* `msg.value < totalFee` or `msg.value - totalFee > 0.00001 ether` — [`IncorrectFee(uint256)`](https://docs.cryptolegacy.app/documentation/errors-reference#incorrectfee-ilcg1)
* Refund transfer fails — [`TransferFeeFailed(bytes)`](https://docs.cryptolegacy.app/documentation/errors-reference#transferfeefailed-ilcg1)

**Overrides:** None

**Function Calls:** None

**Called by:** None (entry point)

**Gas / Complexity note:** Implementation-dependent; typically O(n) where n = `_chainIds.length`

**Example:** `IFeeRegistry(feeRegistry).createCustomCode{value: msg.value}(referrer, recipient, shortCode, chainIds, fees);`

***

### createCode (IFR1)

**Contract/Library:** IFeeRegistry

**Description:** Generates a new referral code and optionally propagates it cross-chain.

**Detailed Description:** Authorised operators invoke this function to mint a fresh code for `_referrer`, configure payout recipients, broadcast to other chains, and refund unused native value.

**Parameters:**

* \_referrer (address): Owner of the generated code
* \_recipient (address): Payout recipient
* \_chainIds (uint256\[], memory): Destination chain IDs for propagation
* \_crossChainFees (uint256\[], memory): Native fee per chain (0 to auto-calc)

**Returns:**

* code (bytes8): Generated referral code
* totalFee (uint256): Total native fee consumed
* returnValue (uint256): Refunded surplus native value

**Modifiers / Visibility / Mutability:**

* external payable

**Access Control:**

* Implementation-defined (FeeRegistry restricts to code operators)

**Side Effects:**

* Creates a new referral code entry with recipient and share configuration
* Consumes native fees to broadcast metadata cross-chain and refunds excess value

**Emits:**

* [CreateCode](https://docs.cryptolegacy.app/documentation/events-reference#createcode-ifr1) — `CreateCode(address indexed codeOperator, address indexed referrer, bytes8 indexed code, address recipient, uint256 fromChain, uint32 discountPct, uint32 sharePct)`
* [SendToChain](https://docs.cryptolegacy.app/documentation/events-reference#sendtochain-ilcg1) — `SendToChain(uint256 indexed toChainId, bytes32 indexed submissionId, uint256 value, bytes dstTransactionCall)`
* [SetCrossChainsRef](https://docs.cryptolegacy.app/documentation/events-reference#setcrosschainsref-ifr1) — `SetCrossChainsRef(bytes8 indexed shortCode, bool indexed isCreate, uint256[] toChainIDs, uint256[] crossChainFees)`

**Reverts if:**

* Reentrant call — "ReentrancyGuard: reentrant call"
* Caller lacks operator permission — [`NotOperator()`](https://docs.cryptolegacy.app/documentation/errors-reference#notoperator-ifr1)
* Code already exists — [`RefAlreadyCreated()`](https://docs.cryptolegacy.app/documentation/errors-reference#refalreadycreated-ifr1)
* generated shortCode == bytes8(0) — [`ZeroCode()`](https://docs.cryptolegacy.app/documentation/errors-reference#zerocode-ifr1)
* `_referrer` already owns a code — [`AlreadyReferrer()`](https://docs.cryptolegacy.app/documentation/errors-reference#alreadyreferrer-ifr1)
* `_chainIds.length != _crossChainFees.length` — [`ArrayLengthMismatch()`](https://docs.cryptolegacy.app/documentation/errors-reference#arraylengthmismatch-ilcg1)
* Destination chain contract missing — [`DestinationChainNotSpecified()`](https://docs.cryptolegacy.app/documentation/errors-reference#destinationchainnotspecified-ilcg1)
* `deBridgeGate.globalFixedNativeFee()` — may revert per deBridge implementation (bubbled)
* `deBridgeGate.sendMessage(...)` — may revert per deBridge implementation (bubbled)
* `msg.value < totalFee` or `msg.value - totalFee > 0.00001 ether` — [`IncorrectFee(uint256)`](https://docs.cryptolegacy.app/documentation/errors-reference#incorrectfee-ilcg1)
* Refund transfer fails — [`TransferFeeFailed(bytes)`](https://docs.cryptolegacy.app/documentation/errors-reference#transferfeefailed-ilcg1)

**Overrides:** None

**Function Calls:** None

**Called by:** None (entry point)

**Gas / Complexity note:** Implementation-dependent; typically O(n) where n = `_chainIds.length`

**Example:** `(bytes8 code,,) = IFeeRegistry(feeRegistry).createCode{value: msg.value}(referrer, recipient, chainIds, fees);`

***

### updateCrossChainsRef (IFR1)

**Contract/Library:** IFeeRegistry

**Description:** Updates cross-chain propagation settings for an existing referral code.

**Detailed Description:** Authorised operators refresh remote chain configuration for `_referrer`’s code, supplying new chain lists and native fees; any unused value is refunded.

**Parameters:**

* \_referrer (address): Referrer whose code is being updated
* \_chainIds (uint256\[], memory): Destination chain IDs
* \_crossChainFees (uint256\[], memory): Native fee per chain (0 to auto-calc)

**Returns:**

* totalFee (uint256): Total native fee consumed
* returnValue (uint256): Refunded surplus native value

**Modifiers / Visibility / Mutability:**

* external payable

**Access Control:**

* Implementation-defined (FeeRegistry restricts to code operators)

**Side Effects:**

* Sends cross-chain update messages via the bridge for each destination chain
* Refunds any surplus native value to the caller

**Emits:**

* [SendToChain](https://docs.cryptolegacy.app/documentation/events-reference#sendtochain-ilcg1) — `SendToChain(uint256 indexed toChainId, bytes32 indexed submissionId, uint256 value, bytes dstTransactionCall)`
* [SetCrossChainsRef](https://docs.cryptolegacy.app/documentation/events-reference#setcrosschainsref-ifr1) — `SetCrossChainsRef(bytes8 indexed shortCode, bool indexed isCreate, uint256[] toChainIDs, uint256[] crossChainFees)`

**Reverts if:**

* Reentrant call — "ReentrancyGuard: reentrant call"
* Caller lacks operator permission — [`NotOperator()`](https://docs.cryptolegacy.app/documentation/errors-reference#notoperator-ifr1)
* `_referrer` has no code — [`CodeNotCreated()`](https://docs.cryptolegacy.app/documentation/errors-reference#codenotcreated-ifr1)
* `_chainIds.length != _crossChainFees.length` — [`ArrayLengthMismatch()`](https://docs.cryptolegacy.app/documentation/errors-reference#arraylengthmismatch-ilcg1)
* Destination chain contract missing — [`DestinationChainNotSpecified()`](https://docs.cryptolegacy.app/documentation/errors-reference#destinationchainnotspecified-ilcg1)
* `deBridgeGate.globalFixedNativeFee()` — may revert per deBridge implementation (bubbled)
* `deBridgeGate.sendMessage(...)` — may revert per deBridge implementation (bubbled)
* `msg.value < totalFee` or `msg.value - totalFee > 0.00001 ether` — [`IncorrectFee(uint256)`](https://docs.cryptolegacy.app/documentation/errors-reference#incorrectfee-ilcg1)
* Refund transfer fails — [`TransferFeeFailed(bytes)`](https://docs.cryptolegacy.app/documentation/errors-reference#transferfeefailed-ilcg1)

**Overrides:** None

**Function Calls:** None

**Called by:** None (entry point)

**Gas / Complexity note:** Implementation-dependent; typically O(n) where n = `_chainIds.length`

**Example:** `(, uint256 refund) = IFeeRegistry(feeRegistry).updateCrossChainsRef{value: msg.value}(referrer, chainIds, fees);`

***

### accumulatedFee (IFR1)

**Contract/Library:** IFeeRegistry

**Description:** Returns the protocol fee balance awaiting distribution.

**Detailed Description:** Exposes the current value of `accumulatedFee`, enabling dashboards or beneficiaries to monitor undistributed earnings.

**Parameters:** None

**Returns:**

* amount (uint128): Accumulated protocol fee in wei

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** `uint128 pool = IFeeRegistry(feeRegistry).accumulatedFee();`

***

### getSupportedRefInChainsList (IFR1)

**Contract/Library:** IFeeRegistry

**Description:** Lists the chain IDs where referral codes are currently supported.

**Detailed Description:** Returns the contents of the FeeRegistry’s `supportedRefInChains` set for off-chain discovery tools.

**Parameters:** None

**Returns:**

* chains (uint256\[], memory): Array of supported chain IDs

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:** None (entry point)

**Gas / Complexity note:** O(n) where n equals the number of supported chains

**Example:** `uint256[] memory chains = IFeeRegistry(feeRegistry).getSupportedRefInChainsList();`

***

## ICryptoLegacyUpdaterPlugin (ICLUP1)

**No functions declared on this interface. See events-reference.md, errors-reference.md, and data-structures-reference.md for the interface's published surface.**

***

## ILockChainGate (ILCG1)

### lockLifetimeNft (ILCG1)

**Contract/Library:** ILockChainGate

**Description:** Locks a lifetime NFT and optionally propagates the lock across chains.

**Detailed Description:** Implementations lock the specified token for the owner, record lock metadata, and may emit cross-chain messages for each destination in `_lockToChainIds`.

**Parameters:**

* \_tokenId (uint256): Lifetime NFT token ID
* \_owner (address): Owner whose lock state is being updated
* \_lockToChainIds (uint256\[], memory): Destination chain IDs to propagate the lock
* \_crossChainFees (uint256\[], memory): Fees to pay per destination chain

**Returns:**

* returnValue (uint256): Unused ETH returned to the caller

**Modifiers / Visibility / Mutability:**

* external payable

**Access Control:**

* Implementation-defined

**Side Effects:**

* Updates lock state and may transfer/move the lifetime NFT

**Emits:**

* [LockNft](https://docs.cryptolegacy.app/documentation/events-reference#locknft-ilcg1) — `LockNft(uint256 lockedAt, uint256 indexed tokenId, address indexed holder)`
* [LockToChain](https://docs.cryptolegacy.app/documentation/events-reference#locktochain-ilcg1) — `LockToChain(address indexed sender, uint256 indexed tokenId, uint256 indexed toChainID, bytes32 submissionId)`
* [SendToChain](https://docs.cryptolegacy.app/documentation/events-reference#sendtochain-ilcg1) — `SendToChain(uint256 indexed toChainId, bytes32 indexed submissionId, uint256 value, bytes dstTransactionCall)`

**Reverts if:**

* ERC721 transfer — may revert with `"ERC721: transfer from incorrect owner"` or per token implementation
* holder already has a lock — [`AlreadyLocked()`](https://docs.cryptolegacy.app/documentation/errors-reference#alreadylocked-ilcg1)
* `_lockToChainIds.length != _crossChainFees.length` — [`ArrayLengthMismatch()`](https://docs.cryptolegacy.app/documentation/errors-reference#arraylengthmismatch-ilcg1)
* token already cross-chain locked — [`CrossChainLock()`](https://docs.cryptolegacy.app/documentation/errors-reference#crosschainlock-ilcg1)
* destination chain not configured — [`DestinationChainNotSpecified()`](https://docs.cryptolegacy.app/documentation/errors-reference#destinationchainnotspecified-ilcg1)
* token already locked to chain — [`AlreadyLockedToChain()`](https://docs.cryptolegacy.app/documentation/errors-reference#alreadylockedtochain-ilcg1)
* `msg.value` too small or too large vs total fee — [`IncorrectFee(uint256)`](https://docs.cryptolegacy.app/documentation/errors-reference#incorrectfee-ilcg1)
* refund transfer fails — [`TransferFeeFailed(bytes)`](https://docs.cryptolegacy.app/documentation/errors-reference#transferfeefailed-ilcg1)

**Overrides:** None

**Function Calls:** None

**Called by:**

* [\_mintAndLockLifetimeNft(address,uint256\[\],uint256\[\],uint256)](#_mintandlocklifetimenft-clbm1) — CryptoLegacyBuildManager

**Gas / Complexity note:** O(n) where n is `_lockToChainIds.length`

**Example:** `ILockChainGate(gate).lockLifetimeNft{value: msg.value}(tokenId, owner, chains, fees);`

***

### isNftLocked (ILCG1)

**Contract/Library:** ILockChainGate

**Description:** Reports whether the owner has an active lifetime NFT lock.

**Detailed Description:** Implementations return `true` when the owner currently holds a locked lifetime NFT.

**Parameters:**

* \_owner (address): Owner address to query

**Returns:**

* isLocked (bool): True if the owner has an active lock

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:**

* [isLifetimeNftLocked(address)](#islifetimenftlocked-clbm1) — CryptoLegacyBuildManager

**Gas / Complexity note:** O(1)

**Example:** `bool locked = ILockChainGate(gate).isNftLocked(owner);`

***

### isNftLockedAndUpdate (ILCG1)

**Contract/Library:** ILockChainGate

**Description:** Checks lock status and updates timing when required.

**Detailed Description:** Implementations return whether a lifetime NFT is locked and may refresh lock metadata as a side effect.

**Parameters:**

* \_owner (address): Owner address to query

**Returns:**

* isLocked (bool): True if the owner has an active lock

**Modifiers / Visibility / Mutability:**

* external nonpayable

**Access Control:**

* Lock operator, holder, or approved on token

**Side Effects:**

* May update lock timestamps and internal tracking

**Emits:** None

**Reverts if:**

* unauthorized caller — [`NotAllowed()`](https://docs.cryptolegacy.app/documentation/errors-reference#notallowed-ilcg1)

**Overrides:** None

**Function Calls:** None

**Called by:**

* [isLifetimeNftLockedAndUpdate(address)](#islifetimenftlockedandupdate-clbm1) — CryptoLegacyBuildManager

**Gas / Complexity note:** O(1)

**Example:** `bool locked = ILockChainGate(gate).isNftLockedAndUpdate(owner);`

***

### calculateCrossChainCreateRefNativeFee (ILCG1)

**Contract/Library:** ILockChainGate

**Description:** Computes the total native fee required for cross-chain referral creation.

**Detailed Description:** Aggregates the provided fee quotes and validates per-chain configuration before returning the total required payment.

**Parameters:**

* \_chainIds (uint256\[], memory): Destination chain IDs
* \_crossChainFees (uint256\[], memory): Fee quote per destination chain

**Returns:**

* totalFee (uint256): Total native fee required

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:**

* Implementation-defined (see ILockChainGate custom errors)

**Overrides:** None

**Function Calls:** None

**Called by:**

* [calculateCrossChainCreateRefFee(uint256\[\],uint256\[\])](#calculatecrosschaincreatereffee-clbm1) — CryptoLegacyBuildManager

**Gas / Complexity note:** O(n) where n is `_chainIds.length`

**Example:** `uint256 fee = ILockChainGate(gate).calculateCrossChainCreateRefNativeFee(chains, fees);`

***

## ILegacyMessenger (ILM1)

**No functions declared on this interface. See events-reference.md, errors-reference.md, and data-structures-reference.md for the interface's published surface.**

***

## ILido (ILD1)

### submit (ILD1)

**Contract/Library:** ILido

**Description:** Stakes ETH into Lido and mints stETH, crediting the caller.

**Detailed Description:** Forwarding integrators deposit native ETH and optionally set a referral address; Lido mints the corresponding amount of stETH based on current exchange rate and returns the minted stETH amount.

**Parameters:**

* \_referral (address): Referral address used by Lido’s referral program (zero address when unused)

**Returns:**

* minted (uint256): Amount of stETH minted to the caller

**Modifiers / Visibility / Mutability:**

* external payable

**Access Control:**

* Unrestricted (Lido handles validation internally)

**Side Effects:**

* Lido implementation stakes supplied ETH and mints stETH to the caller

**Emits:** None

**Reverts if:**

* Lido staking conditions fail (e.g., insufficient deposit) — bubbled from Lido implementation

**Overrides:** None

**Function Calls:** None

**Called by:** None (entry point)

**Gas / Complexity note:** Implementation-dependent; dominated by Lido’s staking logic

**Example:** `uint256 stETH = ILido(stETH).submit{value: 1 ether}(address(0));`

***

### transferShares (ILD1)

**Contract/Library:** ILido

**Description:** Transfers a specified amount of Lido shares to another address.

**Detailed Description:** Allows integrators to move Lido shares (the internal accounting unit behind stETH) directly, preserving staking rewards distribution.

**Parameters:**

* \_recipient (address): Address receiving the shares
* \_sharesAmount (uint256): Number of shares to transfer

**Returns:**

* transferred (uint256): Actual shares transferred

**Modifiers / Visibility / Mutability:**

* external nonpayable

**Access Control:**

* Unrestricted (requires sufficient share balance in the concrete implementation)

**Side Effects:**

* Lido implementation debits caller shares and credits `_recipient`

**Emits:** None

**Reverts if:**

* Implementation enforces balance checks and may revert on insufficient shares (bubbled)

**Overrides:** None

**Function Calls:** None

**Called by:** None (entry point)

**Gas / Complexity note:** Implementation-dependent; typically O(1)

**Example:** `ILido(stETH).transferShares(recipient, shares);`

***

### transferSharesFrom (ILD1)

**Contract/Library:** ILido

**Description:** Transfers Lido shares from one address to another using allowance semantics.

**Detailed Description:** Moves `_sharesAmount` shares from `_sender` to `_recipient`, subject to allowance/approval configured on the stETH contract.

**Parameters:**

* \_sender (address): Address whose shares are moved
* \_recipient (address): Recipient of the shares
* \_sharesAmount (uint256): Number of shares to transfer

**Returns:**

* transferred (uint256): Actual shares transferred

**Modifiers / Visibility / Mutability:**

* external nonpayable

**Access Control:**

* Requires allowance/approval set by `_sender` in the concrete Lido implementation

**Side Effects:**

* Lido implementation moves `_sharesAmount` from `_sender` to `_recipient` subject to allowance

**Emits:** None

**Reverts if:**

* Allowance or balance checks fail — bubbled from Lido implementation

**Overrides:** None

**Function Calls:** None

**Called by:** None (entry point)

**Gas / Complexity note:** Implementation-dependent; typically O(1)

**Example:** `ILido(stETH).transferSharesFrom(sender, recipient, shares);`

***

### sharesOf (ILD1)

**Contract/Library:** ILido

**Description:** Returns the number of Lido shares owned by an account.

**Detailed Description:** Provides the share balance associated with `_account`, allowing integrators to track the stETH stake measured in shares.

**Parameters:**

* \_account (address): Address to query

**Returns:**

* shares (uint256): Share balance held by `_account`

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** `uint256 shares = ILido(stETH).sharesOf(user);`

***

## ILidoWithdrawalQueue (ILWQ1)

### requestWithdrawals (ILWQ1)

**Contract/Library:** ILidoWithdrawalQueue

**Description:** Requests ETH withdrawals for stETH amounts through Lido's withdrawal queue.

**Detailed Description:** Submits one or more stETH withdrawal requests on behalf of `_owner` and returns the created request IDs. CryptoLegacy's Lido plugin uses this surface to move rebasing stETH into delayed ETH exits tracked by the withdrawal queue.

**Parameters:**

* \_amounts (uint256\[], calldata): stETH amounts to withdraw
* \_owner (address): Address that owns the created withdrawal requests

**Returns:**

* requestIds (uint256\[], memory): Withdrawal request IDs created by the queue

**Modifiers / Visibility / Mutability:**

* external nonpayable

**Access Control:**

* Unrestricted at the interface surface; the queue implementation enforces token approvals and queue rules

**Side Effects:**

* Transfers/burns the submitted stETH amount according to Lido queue logic
* Creates new withdrawal request records owned by `_owner`

**Emits:** None

**Reverts if:**

* Queue validation fails (e.g. empty amounts, missing approvals, invalid request sizing) — bubbled from the Lido queue implementation

**Overrides:** None

**Function Calls:** None

**Called by:** None (external protocol surface)

**Gas / Complexity note:** O(n) by `_amounts.length`

**Example:** `uint256[] memory ids = ILidoWithdrawalQueue(queue).requestWithdrawals(amounts, address(this));`

***

### requestWithdrawalsWstETH (ILWQ1)

**Contract/Library:** ILidoWithdrawalQueue

**Description:** Requests ETH withdrawals for wstETH amounts through the Lido queue.

**Detailed Description:** Creates withdrawal requests backed by wstETH balances rather than raw stETH balances, returning the new request IDs owned by `_owner`. CryptoLegacy uses this path when beneficiaries hold wrapped stETH positions.

**Parameters:**

* \_amounts (uint256\[], calldata): wstETH amounts to withdraw
* \_owner (address): Address that owns the created withdrawal requests

**Returns:**

* requestIds (uint256\[], memory): Withdrawal request IDs created by the queue

**Modifiers / Visibility / Mutability:**

* external nonpayable

**Access Control:**

* Unrestricted at the interface surface; the queue implementation enforces token approvals and request constraints

**Side Effects:**

* Transfers/burns the submitted wstETH amount according to Lido queue logic
* Creates new withdrawal request records owned by `_owner`

**Emits:** None

**Reverts if:**

* Queue validation fails (e.g. empty amounts, missing approvals, invalid request sizing) — bubbled from the Lido queue implementation

**Overrides:** None

**Function Calls:** None

**Called by:** None (external protocol surface)

**Gas / Complexity note:** O(n) by `_amounts.length`

**Example:** `uint256[] memory ids = ILidoWithdrawalQueue(queue).requestWithdrawalsWstETH(amounts, address(this));`

***

### claimWithdrawals (ILWQ1)

**Contract/Library:** ILidoWithdrawalQueue

**Description:** Claims finalized Lido withdrawals for previously created request IDs.

**Detailed Description:** Finalizes the specified withdrawal requests using queue-specific hints, releasing the underlying ETH to the caller once the requests are claimable. CryptoLegacy uses this surface to complete delayed Lido exits before wrapping the received ETH back to WETH.

**Parameters:**

* \_requestIds (uint256\[], calldata): Withdrawal request IDs to claim
* \_hints (uint256\[], calldata): Lido queue hints aligned with `_requestIds`

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external nonpayable

**Access Control:**

* Unrestricted at the interface surface; the queue implementation enforces ownership/finality rules

**Side Effects:**

* Marks finalized requests as claimed
* Releases the corresponding ETH to the caller

**Emits:** None

**Reverts if:**

* Requests are not finalized, do not belong to the caller, or hints are invalid — bubbled from the Lido queue implementation

**Overrides:** None

**Function Calls:** None

**Called by:** None (external protocol surface)

**Gas / Complexity note:** O(n) by `_requestIds.length`

**Example:** `ILidoWithdrawalQueue(queue).claimWithdrawals(requestIds, hints);`

***

## ILifetimeNft (ILN1)

### mint (ILN1)

**Contract/Library:** ILifetimeNft

**Description:** Mints a new Lifetime NFT to the specified owner.

**Detailed Description:** Authorized minter operators call this function to mint a new Lifetime NFT, receiving the `tokenId` assigned by the implementation.

**Parameters:**

* \_tokenOwner (address): Recipient of the newly minted NFT

**Returns:**

* tokenId (uint256): Identifier of the minted NFT

**Modifiers / Visibility / Mutability:**

* external nonpayable

**Access Control:**

* Implementation-defined (FeeRegistry implementation restricts to minter operators)

**Side Effects:**

* Implementation mints a new token ID and increases total supply

**Emits:** None

**Reverts if:**

* Caller lacks minter permission — [`NotTheMinter()`](https://docs.cryptolegacy.app/documentation/errors-reference#nottheminter-iln1) (implementation-specific)

**Overrides:** None

**Function Calls:** None

**Called by:**

* [\_mintAndLockLifetimeNft()](#_mintandlocklifetimenft-clbm1) — CryptoLegacyBuildManager
* [payForMultipleLifetimeNft](#payformultiplelifetimenft-clbm1) — CryptoLegacyBuildManager

**Gas / Complexity note:** Implementation-dependent; typically O(1)

**Example:** `uint256 tokenId = ILifetimeNft(lifetimeNft).mint(address(this));`

***

### setMinterOperator (ILN1)

**Contract/Library:** ILifetimeNft

**Description:** Grants or revokes minting permission for an address.

**Detailed Description:** Updates the minter-operator mapping so that `_minter` can (or cannot) invoke `mint`. Implementations usually restrict this function to the contract owner.

**Parameters:**

* \_minter (address): Address whose minting rights are being updated
* \_isActive (bool): `true` to grant minting rights, `false` to revoke

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external nonpayable

**Access Control:**

* Implementation-defined (FeeRegistry implementation uses `onlyOwner`)

**Side Effects:**

* Updates the minter-operator permissions mapping

**Emits:** None

**Reverts if:**

* Implementation-defined (e.g., caller not owner)

**Overrides:** None

**Function Calls:** None

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** `ILifetimeNft(lifetimeNft).setMinterOperator(operator, true);`

***

### setBaseUri (ILN1)

**Contract/Library:** ILifetimeNft

**Description:** Updates the base metadata URI used for token metadata.

**Detailed Description:** Allows authorized callers to change the base URI prepended to token metadata paths.

**Parameters:**

* baseURI\_ (string, memory): New base URI string

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external nonpayable

**Access Control:**

* Implementation-defined (FeeRegistry implementation restricts to owner)

**Side Effects:**

* Stores the new base URI used for token metadata resolution

**Emits:** None

**Reverts if:**

* Implementation-defined (e.g., caller not owner)

**Overrides:** None

**Function Calls:** None

**Called by:** None (entry point)

**Gas / Complexity note:** O(1)

**Example:** `ILifetimeNft(lifetimeNft).setBaseUri("https://cdn.example.com/metadata/");`

***

## IPermit2 (IPM21)

### approve (IPM21)

**Contract/Library:** IPermit2

**Description:** Grants a spender an ERC20 transfer allowance through Permit2.

**Detailed Description:** Approves `spender` to transfer up to `amount` of `token` until `expiration` using Uniswap's Permit2 allowance model. CryptoLegacy's Uniswap V4 plugin uses this surface to authorize the Universal Router without relying on token-specific approval semantics.

**Parameters:**

* token (address): ERC20 token approved for spending
* spender (address): Address allowed to spend the token
* amount (uint160): Maximum approved spend amount
* expiration (uint48): Expiration timestamp for the approval

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external nonpayable

**Access Control:**

* Unrestricted at the interface surface; the Permit2 implementation enforces caller ownership of approvals

**Side Effects:**

* Updates Permit2 allowance state for `token` and `spender`

**Emits:** None

**Reverts if:**

* Permit2 allowance validation fails — bubbled from the Permit2 implementation

**Overrides:** None

**Function Calls:** None

**Called by:** None (external protocol surface)

**Gas / Complexity note:** O(1)

**Example:** `IPermit2(permit2).approve(token, router, uint160(amount), uint48(deadline));`

***

## IPluginsRegistry (IPR1)

### getPluginDescriptionBlockNumbers (IPR1)

**Contract/Library:** IPluginsRegistry

**Description:** Returns the history of description update block numbers for a plugin.

**Detailed Description:** Provides tooling with the block numbers where descriptions were added, enabling reconstruction of description timelines for a given plugin address.

**Parameters:**

* \_plugin (address): Plugin address being inspected

**Returns:**

* descriptionBlocks (uint64\[], memory): Block numbers corresponding to description updates

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:**

* Implementation-defined — may revert per registry implementation (e.g., plugin not present)

**Overrides:** None

**Function Calls:** None

**Called by:**

* [\_getPluginInfoList()](#_getplugininfolist-lp1) — LensPlugin
* [\_getPluginMetadata()](#_getpluginmetadata-lp1) — LensPlugin

**Gas / Complexity note:** O(n) where n = description update count

**Example:** `uint64[] memory updates = IPluginsRegistry(registry).getPluginDescriptionBlockNumbers(plugin);`

***

### isPluginRegistered (IPR1)

**Contract/Library:** IPluginsRegistry

**Description:** Indicates whether a plugin is registered in the registry.

**Detailed Description:** Returns a boolean flag showing if `_plugin` is currently present in the registry’s allowed list.

**Parameters:**

* \_plugin (address): Plugin address to validate

**Returns:**

* registered (bool): `true` when `_plugin` is registered

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:**

* [\_validatePlugin()](#_validateplugin-lclp1) — LibCryptoLegacyPlugins

**Gas / Complexity note:** O(1)

**Example:** `bool ok = IPluginsRegistry(registry).isPluginRegistered(plugin);`

***

### addPlugin (IPR1)

**Contract/Library:** IPluginsRegistry

**Description:** Registers a new plugin address with an accompanying description.

**Detailed Description:** Implementations add `_plugin` to the registry, store metadata/description, and emit `AddPlugin` to signal availability.

**Parameters:**

* \_plugin (address): Plugin contract to register
* \_description (string, memory): Human-readable description text

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external nonpayable

**Access Control:**

* Implementation-defined (PluginsRegistry restricts to owner/governance)

**Side Effects:**

* Adds `_plugin` to the registry and stores its description metadata

**Emits:**

* [AddPlugin](https://docs.cryptolegacy.app/documentation/events-reference#addplugin-ipr1) — `AddPlugin(address indexed plugin, string description)`

**Reverts if:**

* Implementation-defined — e.g., plugin already registered, invalid address

**Overrides:** None

**Function Calls:** None

**Called by:** None (entry point)

**Gas / Complexity note:** Implementation-dependent; typically O(1)

**Example:** `IPluginsRegistry(registry).addPlugin(newPlugin, "Lens v2");`

***

### addPluginDescription (IPR1)

**Contract/Library:** IPluginsRegistry

**Description:** Appends an additional description entry for an existing plugin.

**Detailed Description:** Implementations associate `_description` with `_plugin`, recording the current block for history tracking and emitting `AddPluginDescription`.

**Parameters:**

* \_plugin (address): Plugin being annotated
* \_description (string, memory): Additional description text

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external nonpayable

**Access Control:**

* Implementation-defined (PluginsRegistry restricts to owner/governance)

**Side Effects:**

* Appends a new description entry (with block number) to the plugin’s metadata history

**Emits:**

* [AddPluginDescription](https://docs.cryptolegacy.app/documentation/events-reference#addplugindescription-ipr1) — `AddPluginDescription(address indexed plugin, string description)`

**Reverts if:**

* Implementation-defined — e.g., plugin not registered

**Overrides:** None

**Function Calls:** None

**Called by:** None (entry point)

**Gas / Complexity note:** Implementation-dependent; typically O(1)

**Example:** `IPluginsRegistry(registry).addPluginDescription(plugin, "Added guardian controls");`

***

### removePlugin (IPR1)

**Contract/Library:** IPluginsRegistry

**Description:** Deregisters a plugin and removes it from the registry list.

**Detailed Description:** Implementations delete `_plugin` from the registry, removing associated metadata and emitting `RemovePlugin`.

**Parameters:**

* \_plugin (address): Plugin address to remove

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external nonpayable

**Access Control:**

* Implementation-defined (PluginsRegistry restricts to owner/governance)

**Side Effects:**

* Removes `_plugin` from the registry and clears associated metadata

**Emits:**

* [RemovePlugin](https://docs.cryptolegacy.app/documentation/events-reference#removeplugin-ipr1) — `RemovePlugin(address indexed plugin)`

**Reverts if:**

* Implementation-defined — e.g., plugin not registered

**Overrides:** None

**Function Calls:** None

**Called by:** None (entry point)

**Gas / Complexity note:** Implementation-dependent; typically O(1)

**Example:** `IPluginsRegistry(registry).removePlugin(plugin);`

***

## ISafeMinimalMultisig (ISM1)

**No functions declared on this interface. See events-reference.md, errors-reference.md, and data-structures-reference.md for the interface's published surface.**

***

## ISignatureRoleTimelock (ISRT1)

**No functions declared on this interface. See events-reference.md, errors-reference.md, and data-structures-reference.md for the interface's published surface.**

***

## IStataToken (ISTA1)

### deposit (ISTA1)

**Contract/Library:** IStataToken

**Description:** Deposits reserve assets into a StataToken vault and mints shares.

**Detailed Description:** Accepts `assets` units of the underlying reserve asset, credits the deposit to `receiver`, and returns the minted ERC-4626 share count. CryptoLegacy uses this surface when the Aave beneficiary plugin wraps reserve assets into StataToken positions.

**Parameters:**

* assets (uint256): Amount of underlying asset to deposit
* receiver (address): Address receiving the minted StataToken shares

**Returns:**

* shares (uint256): Amount of shares minted to `receiver`

**Modifiers / Visibility / Mutability:**

* external nonpayable

**Access Control:**

* Unrestricted at the interface surface; the vault enforces approvals and pause state internally

**Side Effects:**

* Pulls `assets` of the underlying reserve asset from the caller
* Mints StataToken shares to `receiver`

**Emits:** None

**Reverts if:**

* Vault approval or state checks fail — bubbled from the StataToken implementation

**Overrides:** None

**Function Calls:** None

**Called by:** None (external protocol surface)

**Gas / Complexity note:** Implementation-dependent; typically O(1)

**Example:** `uint256 shares = IStataToken(stata).deposit(assets, address(this));`

***

### redeem (ISTA1)

**Contract/Library:** IStataToken

**Description:** Redeems StataToken shares for the underlying reserve asset.

**Detailed Description:** Burns `shares` owned by `owner`, transfers the corresponding underlying asset amount to `receiver`, and returns the redeemed asset amount. CryptoLegacy uses this surface when exiting StataToken positions back into the base reserve asset.

**Parameters:**

* shares (uint256): Amount of StataToken shares to redeem
* receiver (address): Address receiving the underlying asset
* owner (address): Address whose shares are burned

**Returns:**

* assets (uint256): Amount of underlying asset returned to `receiver`

**Modifiers / Visibility / Mutability:**

* external nonpayable

**Access Control:**

* Unrestricted at the interface surface; the vault enforces ownership and allowance rules internally

**Side Effects:**

* Burns `owner`'s StataToken shares
* Transfers the corresponding underlying asset to `receiver`

**Emits:** None

**Reverts if:**

* Vault ownership, allowance, or pause checks fail — bubbled from the StataToken implementation

**Overrides:** None

**Function Calls:** None

**Called by:** None (external protocol surface)

**Gas / Complexity note:** Implementation-dependent; typically O(1)

**Example:** `uint256 assets = IStataToken(stata).redeem(shares, address(this), address(this));`

***

### depositATokens (ISTA1)

**Contract/Library:** IStataToken

**Description:** Deposits aTokens into the StataToken vault and mints shares.

**Detailed Description:** Accepts rebasing aTokens instead of the raw reserve asset, credits the vault position to `receiver`, and returns the minted share count. CryptoLegacy uses this entry when wrapping an Aave position directly into StataToken without first redeeming the aTokens.

**Parameters:**

* assets (uint256): Amount of aTokens to deposit
* receiver (address): Address receiving the minted StataToken shares

**Returns:**

* shares (uint256): Amount of shares minted to `receiver`

**Modifiers / Visibility / Mutability:**

* external nonpayable

**Access Control:**

* Unrestricted at the interface surface; the vault enforces approvals and state checks internally

**Side Effects:**

* Pulls aTokens from the caller
* Mints StataToken shares to `receiver`

**Emits:** None

**Reverts if:**

* Vault approval or state checks fail — bubbled from the StataToken implementation

**Overrides:** None

**Function Calls:** None

**Called by:** None (external protocol surface)

**Gas / Complexity note:** Implementation-dependent; typically O(1)

**Example:** `uint256 shares = IStataToken(stata).depositATokens(aTokenAmount, address(this));`

***

### redeemATokens (ISTA1)

**Contract/Library:** IStataToken

**Description:** Redeems StataToken shares directly into aTokens.

**Detailed Description:** Burns `shares` owned by `owner`, transfers the corresponding aToken balance to `receiver`, and returns the amount of aTokens released. CryptoLegacy uses this entry when unwrapping StataToken positions back into Aave aTokens.

**Parameters:**

* shares (uint256): Amount of StataToken shares to redeem
* receiver (address): Address receiving the aTokens
* owner (address): Address whose shares are burned

**Returns:**

* assets (uint256): Amount of aTokens returned to `receiver`

**Modifiers / Visibility / Mutability:**

* external nonpayable

**Access Control:**

* Unrestricted at the interface surface; the vault enforces ownership and allowance rules internally

**Side Effects:**

* Burns `owner`'s StataToken shares
* Transfers the corresponding aTokens to `receiver`

**Emits:** None

**Reverts if:**

* Vault ownership, allowance, or pause checks fail — bubbled from the StataToken implementation

**Overrides:** None

**Function Calls:** None

**Called by:** None (external protocol surface)

**Gas / Complexity note:** Implementation-dependent; typically O(1)

**Example:** `uint256 assets = IStataToken(stata).redeemATokens(shares, address(this), address(this));`

***

### asset (ISTA1)

**Contract/Library:** IStataToken

**Description:** Returns the underlying reserve asset tracked by the StataToken vault.

**Detailed Description:** Exposes the ERC-20 asset address wrapped by the vault so callers can align reserve-asset accounting with the StataToken share position.

**Parameters:** None

**Returns:**

* underlying (address): Reserve asset wrapped by the vault

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:** None (external protocol surface)

**Gas / Complexity note:** O(1)

**Example:** `address underlying = IStataToken(stata).asset();`

***

### balanceOf (ISTA1)

**Contract/Library:** IStataToken

**Description:** Returns the StataToken share balance held by an account.

**Detailed Description:** Reads the ERC-20 balance of vault shares held by `account`, allowing integrators to track how many StataToken shares remain after deposits, redemptions, or migrations.

**Parameters:**

* account (address): Address whose share balance is being queried

**Returns:**

* balance (uint256): Share balance held by `account`

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:** None (external protocol surface)

**Gas / Complexity note:** O(1)

**Example:** `uint256 shares = IStataToken(stata).balanceOf(address(this));`

***

## IStataTokenFactory (ISTF1)

### getStataToken (ISTF1)

**Contract/Library:** IStataTokenFactory

**Description:** Resolves the StataToken vault address for an underlying reserve asset.

**Detailed Description:** Looks up the StataToken deployed for `underlying`, returning the vault address used to wrap that reserve's Aave exposure. CryptoLegacy uses this surface before wrapping or redeeming StataToken positions.

**Parameters:**

* underlying (address): Underlying reserve asset whose StataToken is requested

**Returns:**

* stataToken (address): StataToken vault address for `underlying`

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:** None

**Overrides:** None

**Function Calls:** None

**Called by:** None (external protocol surface)

**Gas / Complexity note:** O(1)

**Example:** `address stata = IStataTokenFactory(factory).getStataToken(asset);`

***

### createStataTokens (ISTF1)

**Contract/Library:** IStataTokenFactory

**Description:** Deploys StataToken vaults for one or more underlying reserve assets.

**Detailed Description:** Creates StataToken vault contracts for each asset in `underlyings` when they do not already exist and returns the resulting vault addresses. Integrations rarely call this on hot paths, but the interface defines the factory's provisioning surface.

**Parameters:**

* underlyings (address\[], calldata): Reserve assets for which to create vaults

**Returns:**

* deployed (address\[], memory): StataToken vault addresses corresponding to `underlyings`

**Modifiers / Visibility / Mutability:**

* external nonpayable

**Access Control:**

* Unrestricted at the interface surface; the factory implementation enforces deployment policy internally

**Side Effects:**

* Deploys new StataToken vault contracts when required

**Emits:** None

**Reverts if:**

* Factory deployment checks fail — bubbled from the factory implementation

**Overrides:** None

**Function Calls:** None

**Called by:** None (external protocol surface)

**Gas / Complexity note:** O(n) by `underlyings.length`

**Example:** `address[] memory vaults = IStataTokenFactory(factory).createStataTokens(assets);`

***

## ITrustedGuardiansPlugin (ITGP1)

### isGuardiansInitialized (ITGP1)

**Contract/Library:** ITrustedGuardiansPlugin

**Description:** Reports whether the guardian configuration has been fully initialised.

**Detailed Description:** Implementations return `true` once guardian addresses and thresholds meet initialization criteria, signalling that default guardian fallbacks are no longer required. Consumers rely on this to differentiate explicitly configured guardian setups from those still using defaults.

**Parameters:** None

**Returns:**

* isInitialized (bool): True when guardians configuration is initialised

**Modifiers / Visibility / Mutability:**

* external view

**Access Control:**

* Implementation-defined

**Side Effects:** None

**Emits:** None

**Reverts if:**

* Implementation-defined — e.g., implementation may revert if guardian storage is unreachable

**Overrides:** None

**Function Calls:** None

**Called by:**

* [getCryptoLegacyListWithStatuses](#getcryptolegacylistwithstatuses-clexl1) — CryptoLegacyExternalLens

**Gas / Complexity note:** O(1)

**Example:** `bool ready = ITrustedGuardiansPlugin(plugin).isGuardiansInitialized();`

***

## IUniversalRouter (IUR1)

### execute (IUR1)

**Contract/Library:** IUniversalRouter

**Description:** Executes a Universal Router command bundle before the deadline expires.

**Detailed Description:** Consumes the encoded command stream in `commands`, decodes the corresponding payloads from `inputs`, and executes the routed sequence before `deadline`. CryptoLegacy's Uniswap V4 beneficiary plugin uses this surface to perform exact-input swap flows.

**Parameters:**

* commands (bytes, calldata): Encoded Universal Router command stream
* inputs (bytes\[], calldata): ABI-encoded payloads for each command
* deadline (uint256): Latest timestamp at which execution remains valid

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external payable

**Access Control:**

* Unrestricted at the interface surface; the router enforces its own command and allowance checks internally

**Side Effects:**

* Executes the command bundle encoded in `commands` / `inputs`
* May transfer tokens and native ETH according to the routed actions

**Emits:** None

**Reverts if:**

* Router command decoding, deadline, allowance, or swap execution checks fail — bubbled from the Universal Router implementation

**Overrides:** None

**Function Calls:** None

**Called by:** None (external protocol surface)

**Gas / Complexity note:** Dependent on the command bundle; scales with the number of routed actions

**Example:** `IUniversalRouter(router).execute(commands, inputs, block.timestamp);`

***

## IWETH (IWETH1)

### deposit (IWETH1)

**Contract/Library:** IWETH

**Description:** Wraps native ETH into WETH.

**Detailed Description:** Accepts native ETH with the call and mints the same amount of WETH to the caller. CryptoLegacy uses this surface when treasury ETH must be normalized into the ERC-20 WETH form.

**Parameters:** None

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external payable

**Access Control:**

* Unrestricted

**Side Effects:**

* Mints WETH to the caller for the supplied native ETH amount

**Emits:** None

**Reverts if:**

* WETH implementation-specific wrapping checks fail — bubbled from the token implementation

**Overrides:** None

**Function Calls:** None

**Called by:** None (external protocol surface)

**Gas / Complexity note:** O(1)

**Example:** `IWETH(weth).deposit{value: amount}();`

***

### withdraw (IWETH1)

**Contract/Library:** IWETH

**Description:** Unwraps WETH back into native ETH.

**Detailed Description:** Burns the specified WETH balance from the caller and releases the same amount of native ETH. CryptoLegacy's unwrap helpers and plugins use this surface before interacting with protocols that require raw ETH.

**Parameters:**

* wad (uint256): Amount of WETH to unwrap

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external nonpayable

**Access Control:**

* Unrestricted

**Side Effects:**

* Burns the caller's WETH balance
* Releases native ETH to the caller

**Emits:** None

**Reverts if:**

* Caller lacks sufficient WETH balance — bubbled from the token implementation

**Overrides:** None

**Function Calls:** None

**Called by:** None (external protocol surface)

**Gas / Complexity note:** O(1)

**Example:** `IWETH(weth).withdraw(amount);`

***

### approve (IWETH1)

**Contract/Library:** IWETH

**Description:** Approves a spender to transfer WETH on the caller's behalf.

**Detailed Description:** Updates the WETH allowance for `guy` to `wad`, enabling downstream protocols or helper contracts to move wrapped ETH from the caller.

**Parameters:**

* guy (address): Spender receiving the allowance
* wad (uint256): Approved spend amount

**Returns:**

* approved (bool): `true` when the approval succeeds

**Modifiers / Visibility / Mutability:**

* external nonpayable

**Access Control:**

* Unrestricted

**Side Effects:**

* Updates ERC-20 allowance state for `guy`

**Emits:** None

**Reverts if:**

* Token approval rules fail — bubbled from the WETH implementation

**Overrides:** None

**Function Calls:** None

**Called by:** None (external protocol surface)

**Gas / Complexity note:** O(1)

**Example:** `bool ok = IWETH(weth).approve(spender, amount);`

***

### balanceOf (IWETH1)

**Contract/Library:** IWETH

**Description:** Returns the WETH token balance held by an address.

**Detailed Description:** Reads the ERC-20 wrapped ETH balance for `guy`, allowing integrations to compare treasury WETH holdings before and after wrap or unwrap operations.

**Parameters:**

* guy (address): Address whose WETH balance is being queried

**Returns:**

* balance (uint256): WETH balance held by `guy`

**Modifiers / Visibility / Mutability:**

* external nonpayable

**Access Control:**

* Unrestricted

**Side Effects:** None

**Emits:** None

**Reverts if:**

* Implementation-specific balance lookup fails — bubbled from the WETH implementation

**Overrides:** None

**Function Calls:** None

**Called by:** None (external protocol surface)

**Gas / Complexity note:** O(1)

**Example:** `uint256 balance = IWETH(weth).balanceOf(address(this));`

***

## IWstETH (IWSTETH1)

### wrap (IWSTETH1)

**Contract/Library:** IWstETH

**Description:** Wraps stETH into non-rebasing wstETH shares.

**Detailed Description:** Consumes `_stETHAmount` of stETH from the caller and mints the corresponding amount of wstETH based on the current Lido exchange rate. CryptoLegacy's Lido plugin uses this surface when converting rebasing stETH into a non-rebasing form.

**Parameters:**

* \_stETHAmount (uint256): Amount of stETH to wrap

**Returns:**

* wrapped (uint256): Amount of wstETH minted to the caller

**Modifiers / Visibility / Mutability:**

* external nonpayable

**Access Control:**

* Unrestricted

**Side Effects:**

* Transfers/burns the caller's stETH according to the wrapper implementation
* Mints wstETH to the caller

**Emits:** None

**Reverts if:**

* Wrapper approval or rate checks fail — bubbled from the wstETH implementation

**Overrides:** None

**Function Calls:** None

**Called by:** None (external protocol surface)

**Gas / Complexity note:** O(1)

**Example:** `uint256 wrapped = IWstETH(wstETH).wrap(stEthAmount);`

***

### unwrap (IWSTETH1)

**Contract/Library:** IWstETH

**Description:** Unwraps wstETH into rebasing stETH.

**Detailed Description:** Burns `_wstETHAmount` of wrapped stETH from the caller and returns the corresponding stETH amount using the current exchange rate. CryptoLegacy uses this surface when exiting the non-rebasing wstETH representation.

**Parameters:**

* \_wstETHAmount (uint256): Amount of wstETH to unwrap

**Returns:**

* unwrapped (uint256): Amount of stETH returned to the caller

**Modifiers / Visibility / Mutability:**

* external nonpayable

**Access Control:**

* Unrestricted

**Side Effects:**

* Burns the caller's wstETH balance
* Transfers the corresponding stETH amount to the caller

**Emits:** None

**Reverts if:**

* Wrapper approval or rate checks fail — bubbled from the wstETH implementation

**Overrides:** None

**Function Calls:** None

**Called by:** None (external protocol surface)

**Gas / Complexity note:** O(1)

**Example:** `uint256 stEthAmount = IWstETH(wstETH).unwrap(wstEthAmount);`

***

## WethUnwrapIWETH (WUI1)

### transferFrom (WUI1)

**Contract/Library:** WethUnwrapIWETH

**Description:** Transfers WETH from one address to another.

**Detailed Description:** Minimal helper-interface entry used by `WethUnwrap` to pull WETH from the caller before unwrapping it into native ETH. The surface mirrors the ERC-20 `transferFrom` semantics exposed by WETH implementations.

**Parameters:**

* from (address): Address whose WETH balance is debited
* to (address): Recipient address
* amount (uint256): Amount of WETH to transfer

**Returns:**

* transferred (bool): `true` when the transfer succeeds

**Modifiers / Visibility / Mutability:**

* external nonpayable

**Access Control:**

* Unrestricted at the interface surface; the token implementation enforces allowance and balance checks

**Side Effects:**

* Moves `amount` of WETH from `from` to `to`

**Emits:** None

**Reverts if:**

* Allowance or balance checks fail — bubbled from the WETH implementation

**Overrides:** None

**Function Calls:** None

**Called by:** None (helper interface surface)

**Gas / Complexity note:** O(1)

**Example:** `bool ok = WethUnwrapIWETH(weth).transferFrom(msg.sender, address(this), amount);`

***

### withdraw (WUI1)

**Contract/Library:** WethUnwrapIWETH

**Description:** Burns WETH and releases the same amount of native ETH.

**Detailed Description:** Helper-interface entry used by `WethUnwrap` after it has custody of WETH, converting the wrapped balance back into native ETH before executing the callback.

**Parameters:**

* amount (uint256): Amount of WETH to unwrap

**Returns:** None

**Modifiers / Visibility / Mutability:**

* external nonpayable

**Access Control:**

* Unrestricted

**Side Effects:**

* Burns `amount` of WETH from the caller
* Releases the same amount of native ETH

**Emits:** None

**Reverts if:**

* Caller lacks sufficient WETH balance — bubbled from the WETH implementation

**Overrides:** None

**Function Calls:** None

**Called by:** None (helper interface surface)

**Gas / Complexity note:** O(1)

**Example:** `WethUnwrapIWETH(weth).withdraw(amount);`

***

**End of Documentation**


# Contracts Data Structures

Below is a clear overview of each major CryptoLegacy contract data structure: purpose, fields, types, relationships, and usage within contracts.

## Table of Contents

1. [BeneficiaryRegistry (BR1)](#beneficiaryregistry-br1)
   * [cryptoLegacyByBeneficiary (BR1-D1)](#cryptolegacybybeneficiary-br1-d1)
   * [cryptoLegacyByOwner (BR1-D2)](#cryptolegacybyowner-br1-d2)
   * [cryptoLegacyByGuardian (BR1-D3)](#cryptolegacybyguardian-br1-d3)
   * [cryptoLegacyByRecovery (BR1-D4)](#cryptolegacybyrecovery-br1-d4)
   * [blockNumberChangesByCryptoLegacy (BR1-D5)](#blocknumberchangesbycryptolegacy-br1-d5)
2. [BuildManagerOwnable (BMO1)](#buildmanagerownable-bmo1)
   * [buildManagerAdded (BMO1-D1)](#buildmanageradded-bmo1-d1)
3. [Create3Factory (C3F1)](#create3factory-c3f1)
4. [CryptoLegacy (CL1)](#cryptolegacy-cl1)
5. [CryptoLegacyBuildManager (CLBM1)](#cryptolegacybuildmanager-clbm1)
   * [feeRegistry (CLBM1-D1)](#feeregistry-clbm1-d1)
   * [pluginsRegistry (CLBM1-D2)](#pluginsregistry-clbm1-d2)
   * [beneficiaryRegistry (CLBM1-D3)](#beneficiaryregistry-clbm1-d3)
   * [lifetimeNft (CLBM1-D4)](#lifetimenft-clbm1-d4)
   * [factory (CLBM1-D5)](#factory-clbm1-d5)
   * [externalLens (CLBM1-D6)](#externallens-clbm1-d6)
   * [minMassMintSupply (CLBM1-D7)](#minmassmintsupply-clbm1-d7)
   * [REGISTRY\_BUILD\_CASE (CLBM1-D8)](#registry_build_case-clbm1-d8)
   * [REGISTRY\_UPDATE\_CASE (CLBM1-D9)](#registry_update_case-clbm1-d9)
   * [REGISTRY\_LIFETIME\_CASE (CLBM1-D10)](#registry_lifetime_case-clbm1-d10)
   * [cryptoLegacyBuilt (CLBM1-D11)](#cryptolegacybuilt-clbm1-d11)
6. [CryptoLegacyDiamondBase (CLDB1)](#cryptolegacydiamondbase-cldb1)
7. [CryptoLegacyExternalLens (CLEXL1)](#cryptolegacyexternallens-clexl1)
8. [CryptoLegacyFactory (CLF1)](#cryptolegacyfactory-clf1)
   * [buildOperators (CLF1-D1)](#buildoperators-clf1-d1)
9. [CryptoLegacyOwnable (CLO1)](#cryptolegacyownable-clo1)
10. [FeeRegistry (FR1)](#feeregistry-fr1)

* [PCT\_BASE (FR1-D1)](#pct_base-fr1-d1)
* [FR\_STORAGE\_POSITION (FR1-D2)](#fr_storage_position-fr1-d2)

11. [LegacyMessenger (LM1)](#legacymessenger-lm1)

* [messagesGotByBlockNumber (LM1-D1)](#messagesgotbyblocknumber-lm1-d1)

12. [LifetimeNft (LN1)](#lifetimenft-ln1)

* [baseURI (LN1-D1)](#baseuri-ln1-d1)
* [minterOperator (LN1-D2)](#minteroperator-ln1-d2)

13. [LockChainGate (LCG1)](#lockchaingate-lcg1)

* [LCG\_STORAGE\_POSITION (LCG1-D1)](#lcg_storage_position-lcg1-d1)

14. [MultiPermit (MP1)](#multipermit-mp1)

* [PermitData (MP1-S1)](#permitdata-mp1-s1)

15. [PluginsRegistry (PR1)](#pluginsregistry-pr1)

* [pluginsList (PR1-D1)](#pluginslist-pr1-d1)
* [pluginDescriptionBlockNumbers (PR1-D2)](#plugindescriptionblocknumbers-pr1-d2)

16. [ProxyBuilder (PB1)](#proxybuilder-pb1)

* [proxyAdmin (PB1-D1)](#proxyadmin-pb1-d1)

17. [ProxyBuilderAdmin (PBA1)](#proxybuilderadmin-pba1)
18. [SignatureRoleTimelock (SRT1)](#signatureroletimelock-srt1)

* [ADMIN\_ROLE (SRT1-D1)](#admin_role-srt1-d1)
* [MAX\_TIMELOCK\_DURATION (SRT1-D2)](#max_timelock_duration-srt1-d2)
* [MAX\_EXECUTION\_PERIOD\_LOWER\_BOUND (SRT1-D3)](#max_execution_period_lower_bound-srt1-d3)
* [MAX\_EXECUTION\_PERIOD\_UPPER\_BOUND (SRT1-D4)](#max_execution_period_upper_bound-srt1-d4)
* [maxExecutionPeriod (SRT1-D5)](#maxexecutionperiod-srt1-d5)
* [roleAccounts (SRT1-D6)](#roleaccounts-srt1-d6)
* [signatureRoles (SRT1-D7)](#signatureroles-srt1-d7)
* [targetSigs (SRT1-D8)](#targetsigs-srt1-d8)
* [targets (SRT1-D9)](#targets-srt1-d9)
* [pendingCalls (SRT1-D10)](#pendingcalls-srt1-d10)
* [callsIds (SRT1-D11)](#callsids-srt1-d11)

19. [ArbSys (AS1)](#arbsys-as1)
20. [Flags (FLG1)](#flags-flg1)

* [UNWRAP\_ETH (FLG1-D1)](#unwrap_eth-flg1-d1)
* [REVERT\_IF\_EXTERNAL\_FAIL (FLG1-D2)](#revert_if_external_fail-flg1-d2)
* [PROXY\_WITH\_SENDER (FLG1-D3)](#proxy_with_sender-flg1-d3)
* [SEND\_HASHED\_DATA (FLG1-D4)](#send_hashed_data-flg1-d4)
* [SEND\_EXTERNAL\_CALL\_GAS\_LIMIT (FLG1-D5)](#send_external_call_gas_limit-flg1-d5)
* [MULTI\_SEND (FLG1-D6)](#multi_send-flg1-d6)

21. [IAaveV3Pool (IAV3P1)](#iaavev3pool-iav3p1)
22. [IAaveV3PoolDataProvider (IAV3PDP1)](#iaavev3pooldataprovider-iav3pdp1)
23. [WethUnwrap (WU1)](#wethunwrap-wu1)

* [WETH (WU1-D1)](#weth-wu1-d1)

24. [IBeneficiaryRegistry (IBR1)](#ibeneficiaryregistry-ibr1)

* [EntityType (IBR1-E1)](#entitytype-ibr1-e1)

25. [IBuildManagerOwnable (IBMO1)](#ibuildmanagerownable-ibmo1)
26. [ICallProxy (ICP1)](#icallproxy-icp1)
27. [ICryptoLegacy (ICL1)](#icryptolegacy-icl1)

* [BeneficiaryConfig (ICL1-S1)](#beneficiaryconfig-icl1-s1)
* [BeneficiaryVesting (ICL1-S2)](#beneficiaryvesting-icl1-s2)
* [TokenDistribution (ICL1-S3)](#tokendistribution-icl1-s3)
* [CryptoLegacyStorage (ICL1-S4)](#cryptolegacystorage-icl1-s4)
* [TokenTransferTo (ICL1-S5)](#tokentransferto-icl1-s5)

28. [ICryptoLegacyBuildManager (ICLBM1)](#icryptolegacybuildmanager-iclbm1)

* [BuildArgs (ICLBM1-S1)](#buildargs-iclbm1-s1)
* [RefArgs (ICLBM1-S2)](#refargs-iclbm1-s2)
* [LifetimeNftMint (ICLBM1-S3)](#lifetimenftmint-iclbm1-s3)

29. [ICryptoLegacyDiamondBase (ICLDB1)](#icryptolegacydiamondbase-icldb1)
30. [ICryptoLegacyFactory (ICLF1)](#icryptolegacyfactory-iclf1)

* [Create2Args (ICLF1-S1)](#create2args-iclf1-s1)

31. [ICryptoLegacyLens (ICLL1)](#icryptolegacylens-icll1)

* [BeneficiaryTokenData (ICLL1-S1)](#beneficiarytokendata-icll1-s1)
* [PluginInfo (ICLL1-S2)](#plugininfo-icll1-s2)
* [CryptoLegacyBaseData (ICLL1-S3)](#cryptolegacybasedata-icll1-s3)
* [LensTokenDistribution (ICLL1-S4)](#lenstokendistribution-icll1-s4)
* [CryptoLegacyListData (ICLL1-S5)](#cryptolegacylistdata-icll1-s5)

32. [ICryptoLegacyOwnable (ICLO1)](#icryptolegacyownable-iclo1)
33. [ICryptoLegacyPlugin (ICLP1)](#icryptolegacyplugin-iclp1)
34. [ICryptoLegacyUpdaterPlugin (ICLUP1)](#icryptolegacyupdaterplugin-iclup1)
35. [IDeBridgeGate (IDBG1)](#idebridgegate-idbg1)

* [TokenInfo (IDBG1-S1)](#tokeninfo-idbg1-s1)
* [DebridgeInfo (IDBG1-S2)](#debridgeinfo-idbg1-s2)
* [DebridgeFeeInfo (IDBG1-S3)](#debridgefeeinfo-idbg1-s3)
* [ChainSupportInfo (IDBG1-S4)](#chainsupportinfo-idbg1-s4)
* [DiscountInfo (IDBG1-S5)](#discountinfo-idbg1-s5)
* [SubmissionAutoParamsTo (IDBG1-S6)](#submissionautoparamsto-idbg1-s6)
* [SubmissionAutoParamsFrom (IDBG1-S7)](#submissionautoparamsfrom-idbg1-s7)
* [FeeParams (IDBG1-S8)](#feeparams-idbg1-s8)

36. [IDiamondCut (IDC1)](#idiamondcut-idc1)

* [FacetCutAction (IDC1-E1)](#facetcutaction-idc1-e1)
* [FacetCut (IDC1-S1)](#facetcut-idc1-s1)

37. [IDiamondLoupe (IDL1)](#idiamondloupe-idl1)

* [Facet (IDL1-S1)](#facet-idl1-s1)

38. [IFeeRegistry (IFR1)](#ifeeregistry-ifr1)

* [FRStorage (IFR1-S1)](#frstorage-ifr1-s1)
* [Referrer (IFR1-S2)](#referrer-ifr1-s2)
* [FeeBeneficiary (IFR1-S3)](#feebeneficiary-ifr1-s3)

39. [ILockChainGate (ILCG1)](#ilockchaingate-ilcg1)

* [LCGStorage (ILCG1-S1)](#lcgstorage-ilcg1-s1)
* [LockedNft (ILCG1-S2)](#lockednft-ilcg1-s2)

40. [ILegacyMessenger (ILM1)](#ilegacymessenger-ilm1)
41. [ILido (ILD1)](#ilido-ild1)
42. [ILidoWithdrawalQueue (ILWQ1)](#ilidowithdrawalqueue-ilwq1)
43. [ILifetimeNft (ILN1)](#ilifetimenft-iln1)

* [Tier (ILN1-E1)](#tier-iln1-e1)

44. [IPermit2 (IPM21)](#ipermit2-ipm21)
45. [IPluginsRegistry (IPR1)](#ipluginsregistry-ipr1)

* [PluginInfo (IPR1-S1)](#plugininfo-ipr1-s1)

46. [ISafeMinimalMultisig (ISM1)](#isafeminimalmultisig-ism1)

* [Storage (ISM1-S1)](#storage-ism1-s1)
* [ProposalStatus (ISM1-E1)](#proposalstatus-ism1-e1)
* [Proposal (ISM1-S2)](#proposal-ism1-s2)
* [ProposalWithStatus (ISM1-S3)](#proposalwithstatus-ism1-s3)
* [InitializationStatus (ISM1-E2)](#initializationstatus-ism1-e2)

47. [ISignatureRoleTimelock (ISRT1)](#isignatureroletimelock-isrt1)

* [CallRequest (ISRT1-S1)](#callrequest-isrt1-s1)
* [AddressRoleInput (ISRT1-S2)](#addressroleinput-isrt1-s2)
* [SignatureAttr (ISRT1-S3)](#signatureattr-isrt1-s3)
* [SignatureToAdd (ISRT1-S4)](#signaturetoadd-isrt1-s4)
* [SignatureToRemove (ISRT1-S5)](#signaturetoremove-isrt1-s5)
* [CallToAdd (ISRT1-S6)](#calltoadd-isrt1-s6)
* [TargetSigRes (ISRT1-S7)](#targetsigres-isrt1-s7)

48. [IStataToken (ISTA1)](#istatatoken-ista1)
49. [IStataTokenFactory (ISTF1)](#istatatokenfactory-istf1)
50. [ITrustedGuardiansPlugin (ITGP1)](#itrustedguardiansplugin-itgp1)

* [PluginStorage (ITGP1-S1)](#pluginstorage-itgp1-s1)
* [GuardianToChange (ITGP1-S2)](#guardiantochange-itgp1-s2)

51. [DiamondLoupeFacet (DLF1)](#diamondloupefacet-dlf1)
52. [IUniversalRouter (IUR1)](#iuniversalrouter-iur1)
53. [IWETH (IWETH1)](#iweth-iweth1)
54. [IWstETH (IWSTETH1)](#iwsteth-iwsteth1)
55. [WethUnwrapIWETH (WUI1)](#wethunwrapiweth-wui1)
56. [LibCLUtils (LCLU1)](#libclutils-lclu1)
57. [LibClaimMigrationCore (LCMC1)](#libclaimmigrationcore-lcmc1)

* [MIGRATION\_SCALE (LCMC1-D1)](#migration_scale-lcmc1-d1)

58. [LibOneStepClaimMigration (LOSCM1)](#libonestepclaimmigration-loscm1)
59. [LibTwoStepClaimMigration (LTSCM1)](#libtwostepclaimmigration-ltscm1)

* [CLAIM\_LOCK\_AMOUNT (LTSCM1-D1)](#claim_lock_amount-ltscm1-d1)
* [CachedClaims (LTSCM1-S1)](#cachedclaims-ltscm1-s1)
* [PendingMigration (LTSCM1-S2)](#pendingmigration-ltscm1-s2)
* [PendingMigrationStorage (LTSCM1-S3)](#pendingmigrationstorage-ltscm1-s3)

60. [LibCreate3 (LC31)](#libcreate3-lc31)

* [PROXY\_CHILD\_BYTECODE (LC31-D1)](#proxy_child_bytecode-lc31-d1)
* [KECCAK256\_PROXY\_CHILD\_BYTECODE (LC31-D2)](#keccak256_proxy_child_bytecode-lc31-d2)

61. [LibCryptoLegacy (LCL1)](#libcryptolegacy-lcl1)

* [SHARE\_BASE (LCL1-D1)](#share_base-lcl1-d1)
* [MAX\_CHAINS\_ARRAY\_LENGTH (LCL1-D2)](#max_chains_array_length-lcl1-d2)
* [BENEFICIARY\_SWITCH\_TIMELOCK\_DURATION (LCL1-D3)](#beneficiary_switch_timelock_duration-lcl1-d3)
* [CLAIM\_FUNC\_FLAG (LCL1-D4)](#claim_func_flag-lcl1-d4)
* [MAX\_GAS\_MULTIPLIER (LCL1-D5)](#max_gas_multiplier-lcl1-d5)
* [CRYPTO\_LEGACY\_STORAGE\_POSITION (LCL1-D6)](#crypto_legacy_storage_position-lcl1-d6)
* [transferValueSelector (LCL1-D7)](#transfervalueselector-lcl1-d7)
* [lockNftSelector (LCL1-D8)](#locknftselector-lcl1-d8)

62. [LibCryptoLegacyDeploy (LCLD1)](#libcryptolegacydeploy-lcld1)
63. [LibCryptoLegacyPlugins (LCLP1)](#libcryptolegacyplugins-lclp1)
64. [LibDiamond (LD1)](#libdiamond-ld1)

* [DIAMOND\_STORAGE\_POSITION (LD1-D1)](#diamond_storage_position-ld1-d1)
* [FacetAddressAndPosition (LD1-S1)](#facetaddressandposition-ld1-s1)
* [FacetFunctionSelectors (LD1-S2)](#facetfunctionselectors-ld1-s2)
* [DiamondStorage (LD1-S3)](#diamondstorage-ld1-s3)

65. [LibSafeMinimalBeneficiaryMultisig (LSMB1)](#libsafeminimalbeneficiarymultisig-lsmb1)
66. [LibSafeMinimalMultisig (LSM1)](#libsafeminimalmultisig-lsm1)
67. [LibTrustedGuardiansPlugin (LTGP1)](#libtrustedguardiansplugin-ltgp1)

* [PLUGIN\_POSITION (LTGP1-D1)](#plugin_position-ltgp1-d1)

68. [BeneficiaryAaveV3SupplyPlugin (BALP1)](#beneficiaryaavev3supplyplugin-balp1)

* [PLUGIN\_MULTISIG\_POSITION (BALP1-D1)](#plugin_multisig_position-balp1-d1)
* [POOL (BALP1-D2)](#pool-balp1-d2)
* [POOL\_DATA\_PROVIDER (BALP1-D3)](#pool_data_provider-balp1-d3)
* [STATA\_TOKEN\_FACTORY (BALP1-D4)](#stata_token_factory-balp1-d4)
* [DEFAULT\_REFERRAL\_CODE (BALP1-D5)](#default_referral_code-balp1-d5)

69. [BeneficiaryLidoStakingPlugin (BLSP1)](#beneficiarylidostakingplugin-blsp1)

* [LidoWithdrawalStorage (BLSP1-S1)](#lidowithdrawalstorage-blsp1-s1)
* [BeneficiarySwitchGuardStorage (BLSP1-S2)](#beneficiaryswitchguardstorage-blsp1-s2)
* [PLUGIN\_MULTISIG\_POSITION (BLSP1-D1)](#plugin_multisig_position-blsp1-d1)
* [PLUGIN\_PENDING\_MIGRATION\_POSITION (BLSP1-D2)](#plugin_pending_migration_position-blsp1-d2)
* [PLUGIN\_LIDO\_WITHDRAWAL\_POSITION (BLSP1-D3)](#plugin_lido_withdrawal_position-blsp1-d3)
* [PLUGIN\_BENEFICIARY\_SWITCH\_GUARD\_POSITION (BLSP1-D4)](#plugin_beneficiary_switch_guard_position-blsp1-d4)
* [WETH (BLSP1-D5)](#weth-blsp1-d5)
* [stETH (BLSP1-D6)](#steth-blsp1-d6)
* [wstETH (BLSP1-D7)](#wsteth-blsp1-d7)
* [LIDO\_WITHDRAWAL\_QUEUE (BLSP1-D8)](#lido_withdrawal_queue-blsp1-d8)
* [WETH\_UNWRAP (BLSP1-D9)](#weth_unwrap-blsp1-d9)
* [LIDO\_REFERRAL (BLSP1-D10)](#lido_referral-blsp1-d10)

70. [BeneficiaryPluginAddRights (BPAR1)](#beneficiarypluginaddrights-bpar1)

* [PLUGIN\_MULTISIG\_POSITION (BPAR1-D1)](#plugin_multisig_position-bpar1-d1)

71. [BeneficiaryUniswapV4SwapPlugin (BU4SP1)](#beneficiaryuniswapv4swapplugin-bu4sp1)

* [PoolKey (BU4SP1-S1)](#poolkey-bu4sp1-s1)
* [PathKey (BU4SP1-S2)](#pathkey-bu4sp1-s2)
* [ExactInputSingleParams (BU4SP1-S3)](#exactinputsingleparams-bu4sp1-s3)
* [ExactInputParams (BU4SP1-S4)](#exactinputparams-bu4sp1-s4)
* [PLUGIN\_MULTISIG\_POSITION (BU4SP1-D1)](#plugin_multisig_position-bu4sp1-d1)
* [V4\_SWAP (BU4SP1-D2)](#v4_swap-bu4sp1-d2)
* [SWAP\_EXACT\_IN\_SINGLE (BU4SP1-D3)](#swap_exact_in_single-bu4sp1-d3)
* [SWAP\_EXACT\_IN (BU4SP1-D4)](#swap_exact_in-bu4sp1-d4)
* [SETTLE\_ALL (BU4SP1-D5)](#settle_all-bu4sp1-d5)
* [TAKE\_ALL (BU4SP1-D6)](#take_all-bu4sp1-d6)
* [UNIVERSAL\_ROUTER (BU4SP1-D7)](#universal_router-bu4sp1-d7)
* [PERMIT2 (BU4SP1-D8)](#permit2-bu4sp1-d8)

72. [CryptoLegacyBasePlugin (CLBP1)](#cryptolegacybaseplugin-clbp1)
73. [LegacyRecoveryPlugin (LRP1)](#legacyrecoveryplugin-lrp1)

* [PLUGIN\_MULTISIG\_POSITION (LRP1-D1)](#plugin_multisig_position-lrp1-d1)

74. [LensPlugin (LP1)](#lensplugin-lp1)
75. [NftLegacyPlugin (NLP1)](#nftlegacyplugin-nlp1)

* [PLUGIN\_POSITION (NLP1-D1)](#plugin_position-nlp1-d1)
* [NftBeneficiary (NLP1-S1)](#nftbeneficiary-nlp1-s1)
* [PluginStorage (NLP1-S2)](#pluginstorage-nlp1-s2)

76. [ReceiveEthPlugin (REP1)](#receiveethplugin-rep1)

* [WETH (REP1-D1)](#weth-rep1-d1)

77. [TrustedGuardiansPlugin (TGP1)](#trustedguardiansplugin-tgp1)

* [DEFAULT\_GUARDIANS\_CHALLENGE\_TIMEOUT (TGP1-D1)](#default_guardians_challenge_timeout-tgp1-d1)
* [MAX\_GUARDIANS\_CHALLENGE\_TIMEOUT (TGP1-D2)](#max_guardians_challenge_timeout-tgp1-d2)

78. [UpdateRolePlugin (URP1)](#updateroleplugin-urp1)

* [PLUGIN\_POSITION (URP1-D1)](#plugin_position-urp1-d1)
* [PluginStorage (URP1-S1)](#pluginstorage-urp1-s1)

79. [Data Types Used](#data-types-used)

## BeneficiaryRegistry (BR1)

### cryptoLegacyByBeneficiary (BR1-D1)

**Data Type:** `mapping(bytes32 => EnumerableSet.AddressSet)` **Visibility / Mutability:** internal, none **Storage Location:** direct storage **Description:** Maps a beneficiary hash to the set of CryptoLegacy contract addresses associated with that beneficiary.

**Modified by:**

* [BeneficiaryRegistry.setCryptoLegacyBeneficiary()](https://docs.cryptolegacy.app/documentation/functions-reference#setcryptolegacybeneficiary-br1)

**Read by:**

* [BeneficiaryRegistry.getCryptoLegacyListByBeneficiary()](https://docs.cryptolegacy.app/documentation/functions-reference#getcryptolegacylistbybeneficiary-br1)
* [BeneficiaryRegistry.getAllCryptoLegacyListByRoles()](https://docs.cryptolegacy.app/documentation/functions-reference#getallcryptolegacylistbyroles-br1)

### cryptoLegacyByOwner (BR1-D2)

**Data Type:** `mapping(bytes32 => EnumerableSet.AddressSet)` **Visibility / Mutability:** internal, none **Storage Location:** direct storage **Description:** Maps an owner hash to the set of CryptoLegacy contract addresses associated with that owner.

**Modified by:**

* [BeneficiaryRegistry.setCryptoLegacyOwner()](https://docs.cryptolegacy.app/documentation/functions-reference#setcryptolegacyowner-br1)

**Read by:**

* [BeneficiaryRegistry.getCryptoLegacyListByOwner()](https://docs.cryptolegacy.app/documentation/functions-reference#getcryptolegacylistbyowner-br1)
* [BeneficiaryRegistry.getAllCryptoLegacyListByRoles()](https://docs.cryptolegacy.app/documentation/functions-reference#getallcryptolegacylistbyroles-br1)

### cryptoLegacyByGuardian (BR1-D3)

**Data Type:** `mapping(bytes32 => EnumerableSet.AddressSet)` **Visibility / Mutability:** internal, none **Storage Location:** direct storage **Description:** Maps a guardian hash to the set of CryptoLegacy contract addresses associated with that guardian.

**Modified by:**

* [BeneficiaryRegistry.setCryptoLegacyGuardian()](https://docs.cryptolegacy.app/documentation/functions-reference#setcryptolegacyguardian-br1)

**Read by:**

* [BeneficiaryRegistry.getCryptoLegacyListByGuardian()](https://docs.cryptolegacy.app/documentation/functions-reference#getcryptolegacylistbyguardian-br1)
* [BeneficiaryRegistry.getAllCryptoLegacyListByRoles()](https://docs.cryptolegacy.app/documentation/functions-reference#getallcryptolegacylistbyroles-br1)

### cryptoLegacyByRecovery (BR1-D4)

**Data Type:** `mapping(bytes32 => EnumerableSet.AddressSet)` **Visibility / Mutability:** internal, none **Storage Location:** direct storage **Description:** Maps a recovery hash to the set of CryptoLegacy contract addresses associated with that recovery address.

**Modified by:**

* [BeneficiaryRegistry.setCryptoLegacyRecoveryAddresses()](https://docs.cryptolegacy.app/documentation/functions-reference#setcryptolegacyrecoveryaddresses-br1)

**Read by:**

* [BeneficiaryRegistry.getCryptoLegacyListByRecovery()](https://docs.cryptolegacy.app/documentation/functions-reference#getcryptolegacylistbyrecovery-br1)
* [BeneficiaryRegistry.getAllCryptoLegacyListByRoles()](https://docs.cryptolegacy.app/documentation/functions-reference#getallcryptolegacylistbyroles-br1)

### blockNumberChangesByCryptoLegacy (BR1-D5)

**Data Type:** `mapping(address => uint256[])` **Visibility / Mutability:** internal, none **Storage Location:** direct storage **Description:** Stores block numbers when a given CryptoLegacy contract updates registry entries.

**Modified by:**

* [BeneficiaryRegistry.\_setBlockNumberChange()](https://docs.cryptolegacy.app/documentation/functions-reference#_setblocknumberchange-br1)

**Read by:**

* [BeneficiaryRegistry.\_setBlockNumberChange()](https://docs.cryptolegacy.app/documentation/functions-reference#_setblocknumberchange-br1)
* [BeneficiaryRegistry.getCryptoLegacyBlockNumberChanges()](https://docs.cryptolegacy.app/documentation/functions-reference#getcryptolegacyblocknumberchanges-br1)

## BuildManagerOwnable (BMO1)

### buildManagerAdded (BMO1-D1)

**Data Type:** `EnumerableSet.AddressSet` **Visibility / Mutability:** internal, none **Storage Location:** direct storage **Description:** Set of build manager addresses that are authorized to register CryptoLegacy contracts.

**Modified by:**

* [BuildManagerOwnable.setBuildManager()](https://docs.cryptolegacy.app/documentation/functions-reference#setbuildmanager-bmo1)

**Read by:**

* [BuildManagerOwnable.\_checkBuildManagerValid()](https://docs.cryptolegacy.app/documentation/functions-reference#_checkbuildmanagervalid-bmo1)
* [BuildManagerOwnable.getBuildManagerAdded()](https://docs.cryptolegacy.app/documentation/functions-reference#getbuildmanageradded-bmo1)

## Create3Factory (C3F1)

**No tracked data items in this contract/library.**

## CryptoLegacy (CL1)

**No tracked data items in this contract/library.**

## CryptoLegacyBuildManager (CLBM1)

### feeRegistry (CLBM1-D1)

**Data Type:** `IFeeRegistry` **Visibility / Mutability:** public, none **Storage Location:** direct storage **Description:** Fee registry contract used to calculate and collect build and update fees.

**Modified by:**

* [CryptoLegacyBuildManager.\_setRegistries()](https://docs.cryptolegacy.app/documentation/functions-reference#_setregistries-clbm1)

**Read by:**

* [CryptoLegacyBuildManager.\_payFee()](https://docs.cryptolegacy.app/documentation/functions-reference#_payfee-clbm1)
* [CryptoLegacyBuildManager.\_getAndPayBuildFee()](https://docs.cryptolegacy.app/documentation/functions-reference#_getandpaybuildfee-clbm1)
* [CryptoLegacyBuildManager.\_mintAndLockLifetimeNft()](https://docs.cryptolegacy.app/documentation/functions-reference#_mintandlocklifetimenft-clbm1)
* [CryptoLegacyBuildManager.payForMultipleLifetimeNft()](https://docs.cryptolegacy.app/documentation/functions-reference#payformultiplelifetimenft-clbm1)
* [CryptoLegacyBuildManager.\_createCustomRef()](https://docs.cryptolegacy.app/documentation/functions-reference#_createcustomref-clbm1)
* [CryptoLegacyBuildManager.\_createRef()](https://docs.cryptolegacy.app/documentation/functions-reference#_createref-clbm1)
* [CryptoLegacyBuildManager.updateCrossChainsRef()](https://docs.cryptolegacy.app/documentation/functions-reference#updatecrosschainsref-clbm1)
* [CryptoLegacyBuildManager.getUpdateFee()](https://docs.cryptolegacy.app/documentation/functions-reference#getupdatefee-clbm1)
* [CryptoLegacyBuildManager.calculateCrossChainCreateRefFee()](https://docs.cryptolegacy.app/documentation/functions-reference#calculatecrosschaincreatereffee-clbm1)
* [CryptoLegacyBuildManager.isLifetimeNftLocked()](https://docs.cryptolegacy.app/documentation/functions-reference#islifetimenftlocked-clbm1)
* [CryptoLegacyBuildManager.isLifetimeNftLockedAndUpdate()](https://docs.cryptolegacy.app/documentation/functions-reference#islifetimenftlockedandupdate-clbm1)

### pluginsRegistry (CLBM1-D2)

**Data Type:** `IPluginsRegistry` **Visibility / Mutability:** public, none **Storage Location:** direct storage **Description:** Plugins registry contract used to validate plugin addresses.

**Modified by:**

* [CryptoLegacyBuildManager.\_setRegistries()](https://docs.cryptolegacy.app/documentation/functions-reference#_setregistries-clbm1)

**Read by:**

* [CryptoLegacyBuildManager.isPluginRegistered()](https://docs.cryptolegacy.app/documentation/functions-reference#ispluginregistered-clbm1)
* [ICryptoLegacyBuildManager.pluginsRegistry()](https://docs.cryptolegacy.app/documentation/functions-reference#pluginsregistry-iclbm1)

### beneficiaryRegistry (CLBM1-D3)

**Data Type:** `IBeneficiaryRegistry` **Visibility / Mutability:** public, none **Storage Location:** direct storage **Description:** Beneficiary registry contract used to register owner, beneficiary, guardian, and recovery hashes.

**Modified by:**

* [CryptoLegacyBuildManager.\_setRegistries()](https://docs.cryptolegacy.app/documentation/functions-reference#_setregistries-clbm1)

**Read by:**

* [ICryptoLegacyBuildManager.beneficiaryRegistry()](https://docs.cryptolegacy.app/documentation/functions-reference#beneficiaryregistry-iclbm1)

### lifetimeNft (CLBM1-D4)

**Data Type:** `ILifetimeNft` **Visibility / Mutability:** public, none **Storage Location:** direct storage **Description:** Lifetime NFT contract used for lifetime fee status and minting.

**Modified by:**

* [CryptoLegacyBuildManager.constructor()](https://docs.cryptolegacy.app/documentation/functions-reference#constructor-clbm1)

**Read by:**

* [CryptoLegacyBuildManager.\_mintAndLockLifetimeNft()](https://docs.cryptolegacy.app/documentation/functions-reference#_mintandlocklifetimenft-clbm1)
* [CryptoLegacyBuildManager.payForMultipleLifetimeNft()](https://docs.cryptolegacy.app/documentation/functions-reference#payformultiplelifetimenft-clbm1)
* [CryptoLegacyBuildManager.transferStuckNft()](https://docs.cryptolegacy.app/documentation/functions-reference#transferstucknft-clbm1)
* [CryptoLegacyBuildManager.onERC721Received()](https://docs.cryptolegacy.app/documentation/functions-reference#onerc721received-clbm1)

### factory (CLBM1-D5)

**Data Type:** `ICryptoLegacyFactory` **Visibility / Mutability:** public, none **Storage Location:** direct storage **Description:** Factory contract used to deploy new CryptoLegacy instances.

**Modified by:**

* [CryptoLegacyBuildManager.\_setFactory()](https://docs.cryptolegacy.app/documentation/functions-reference#_setfactory-clbm1)

**Read by:**

* [CryptoLegacyBuildManager.buildCryptoLegacy()](https://docs.cryptolegacy.app/documentation/functions-reference#buildcryptolegacy-clbm1)
* [CryptoLegacyBuildManager.getFactoryAddress()](https://docs.cryptolegacy.app/documentation/functions-reference#getfactoryaddress-clbm1)

### externalLens (CLBM1-D6)

**Data Type:** `address` **Visibility / Mutability:** public, none **Storage Location:** direct storage **Description:** Optional external lens contract address for off-chain data access.

**Modified by:**

* [CryptoLegacyBuildManager.setExternalLens()](https://docs.cryptolegacy.app/documentation/functions-reference#setexternallens-clbm1)

**Read by:**

* [CryptoLegacy.externalLens()](https://docs.cryptolegacy.app/documentation/functions-reference#externallens-cl1)
* [ICryptoLegacyBuildManager.externalLens()](https://docs.cryptolegacy.app/documentation/functions-reference#externallens-iclbm1)

### minMassMintSupply (CLBM1-D7)

**Data Type:** `uint256` **Visibility / Mutability:** public, none **Storage Location:** direct storage **Description:** Minimum Lifetime NFT total supply required to allow mass minting.

**Modified by:**

* [CryptoLegacyBuildManager.setSupplyLimit()](https://docs.cryptolegacy.app/documentation/functions-reference#setsupplylimit-clbm1)

**Read by:**

* [CryptoLegacyBuildManager.payForMultipleLifetimeNft()](https://docs.cryptolegacy.app/documentation/functions-reference#payformultiplelifetimenft-clbm1)

### REGISTRY\_BUILD\_CASE (CLBM1-D8)

**Data Type:** `uint8` **Visibility / Mutability:** public, constant **Storage Location:** inlined constant **Description:** Fee registry case identifier for build fees.

**Modified by:** None

**Read by:**

* [CryptoLegacyBuildManager.payInitialFee()](https://docs.cryptolegacy.app/documentation/functions-reference#payinitialfee-clbm1)
* [CryptoLegacyBuildManager.\_getAndPayBuildFee()](https://docs.cryptolegacy.app/documentation/functions-reference#_getandpaybuildfee-clbm1)

### REGISTRY\_UPDATE\_CASE (CLBM1-D9)

**Data Type:** `uint8` **Visibility / Mutability:** public, constant **Storage Location:** inlined constant **Description:** Fee registry case identifier for update fees.

**Modified by:** None

**Read by:**

* [CryptoLegacyBuildManager.payFee()](https://docs.cryptolegacy.app/documentation/functions-reference#payfee-clbm1)
* [CryptoLegacyBuildManager.getUpdateFee()](https://docs.cryptolegacy.app/documentation/functions-reference#getupdatefee-clbm1)
* [CryptoLegacyBuildManager.\_getAndPayBuildFee()](https://docs.cryptolegacy.app/documentation/functions-reference#_getandpaybuildfee-clbm1)

### REGISTRY\_LIFETIME\_CASE (CLBM1-D10)

**Data Type:** `uint8` **Visibility / Mutability:** public, constant **Storage Location:** inlined constant **Description:** Fee registry case identifier for lifetime NFT fees.

**Modified by:** None

**Read by:**

* [CryptoLegacyBuildManager.\_payFee()](https://docs.cryptolegacy.app/documentation/functions-reference#_payfee-clbm1)
* [CryptoLegacyBuildManager.payForMultipleLifetimeNft()](https://docs.cryptolegacy.app/documentation/functions-reference#payformultiplelifetimenft-clbm1)

### cryptoLegacyBuilt (CLBM1-D11)

**Data Type:** `mapping(address => bool)` **Visibility / Mutability:** internal, none **Storage Location:** direct storage **Description:** Tracks whether a CryptoLegacy contract address has been built and registered.

**Modified by:**

* [CryptoLegacyBuildManager.buildCryptoLegacy()](https://docs.cryptolegacy.app/documentation/functions-reference#buildcryptolegacy-clbm1)

**Read by:**

* [CryptoLegacyBuildManager.isLifetimeNftLockedAndUpdate()](https://docs.cryptolegacy.app/documentation/functions-reference#islifetimenftlockedandupdate-clbm1)
* [CryptoLegacyBuildManager.isCryptoLegacyBuilt()](https://docs.cryptolegacy.app/documentation/functions-reference#iscryptolegacybuilt-clbm1)

## CryptoLegacyDiamondBase (CLDB1)

**No tracked data items in this contract/library.**

## CryptoLegacyExternalLens (CLEXL1)

**No tracked data items in this contract/library.**

## CryptoLegacyFactory (CLF1)

### buildOperators (CLF1-D1)

**Data Type:** `EnumerableSet.AddressSet` **Visibility / Mutability:** private, none **Storage Location:** direct storage **Description:** Set of addresses authorized to deploy new CryptoLegacy contracts.

**Modified by:**

* [CryptoLegacyFactory.setBuildOperator()](https://docs.cryptolegacy.app/documentation/functions-reference#setbuildoperator-clf1)

**Read by:**

* [CryptoLegacyFactory.createCryptoLegacy()](https://docs.cryptolegacy.app/documentation/functions-reference#createcryptolegacy-clf1)

## CryptoLegacyOwnable (CLO1)

**No tracked data items in this contract/library.**

## FeeRegistry (FR1)

### PCT\_BASE (FR1-D1)

**Data Type:** `uint32` **Visibility / Mutability:** public, constant **Storage Location:** inlined constant **Description:** Fixed 10,000 denominator for fee-registry discount and referral-share percentage calculations.

**Modified by:** None

**Read by:**

* [FeeRegistry.setFeeBeneficiaries()](https://docs.cryptolegacy.app/documentation/functions-reference#setfeebeneficiaries-fr1)
* [FeeRegistry.setRefererSpecificPct()](https://docs.cryptolegacy.app/documentation/functions-reference#setrefererspecificpct-fr1)
* [FeeRegistry.withdrawAccumulatedFee()](https://docs.cryptolegacy.app/documentation/functions-reference#withdrawaccumulatedfee-fr1)
* [FeeRegistry.\_calculateFee()](https://docs.cryptolegacy.app/documentation/functions-reference#_calculatefee-fr1)

### FR\_STORAGE\_POSITION (FR1-D2)

**Data Type:** `bytes32` **Visibility / Mutability:** internal, constant **Storage Location:** diamond storage slot **Description:** Storage slot identifier for FeeRegistry FRStorage.

**Modified by:** None

**Read by:**

* [FeeRegistry.lockFeeRegistryStorage()](https://docs.cryptolegacy.app/documentation/functions-reference#lockfeeregistrystorage-fr1)

## LegacyMessenger (LM1)

### messagesGotByBlockNumber (LM1-D1)

**Data Type:** `mapping(bytes32 => uint64[])` **Visibility / Mutability:** public, none **Storage Location:** direct storage **Description:** Maps recipient hashes to block numbers when messages were sent.

**Modified by:**

* [LegacyMessenger.sendMessagesTo()](https://docs.cryptolegacy.app/documentation/functions-reference#sendmessagesto-lm1)

**Read by:**

* [LegacyMessenger.getMessagesBlockNumbersByRecipient()](https://docs.cryptolegacy.app/documentation/functions-reference#getmessagesblocknumbersbyrecipient-lm1)

## LifetimeNft (LN1)

### baseURI (LN1-D1)

**Data Type:** `string` **Visibility / Mutability:** internal, none **Storage Location:** direct storage **Description:** Base URI used to build token metadata URLs.

**Modified by:**

* [LifetimeNft.\_setBaseUri()](https://docs.cryptolegacy.app/documentation/functions-reference#_setbaseuri-ln1)

**Read by:**

* [LifetimeNft.\_baseURI()](https://docs.cryptolegacy.app/documentation/functions-reference#_baseuri-ln1)

### minterOperator (LN1-D2)

**Data Type:** `mapping(address => bool)` **Visibility / Mutability:** public, none **Storage Location:** direct storage **Description:** Tracks which addresses are authorized to mint Lifetime NFTs.

**Modified by:**

* [LifetimeNft.setMinterOperator()](https://docs.cryptolegacy.app/documentation/functions-reference#setminteroperator-ln1)

**Read by:**

* [LifetimeNft.mint()](https://docs.cryptolegacy.app/documentation/functions-reference#mint-ln1)

## LockChainGate (LCG1)

### LCG\_STORAGE\_POSITION (LCG1-D1)

**Data Type:** `bytes32` **Visibility / Mutability:** internal, constant **Storage Location:** diamond storage slot **Description:** Storage slot identifier for LockChainGate LCGStorage.

**Modified by:** None

**Read by:**

* [LockChainGate.lockChainGateStorage()](https://docs.cryptolegacy.app/documentation/functions-reference#lockchaingatestorage-lcg1)

## MultiPermit (MP1)

### PermitData (MP1-S1)

**Type:** `struct` **Fields:**

* `token (address)`: Token contract address.
* `owner (address)`: Token owner address.
* `spender (address)`: Spender address to approve.
* `value (uint256)`: Amount to approve.
* `deadline (uint256)`: Permit deadline timestamp.
* `v (uint8)`: Signature v value.
* `r (bytes32)`: Signature r value.
* `s (bytes32)`: Signature s value.

**Used by:**

* [MultiPermit.approveTreasuryTokensToLegacy()](https://docs.cryptolegacy.app/documentation/functions-reference#approvetreasurytokenstolegacy-mp1)

**Notes / Edge cases:** None

## PluginsRegistry (PR1)

### pluginsList (PR1-D1)

**Data Type:** `EnumerableSet.AddressSet` **Visibility / Mutability:** private, none **Storage Location:** direct storage **Description:** Set of registered plugin addresses.

**Modified by:**

* [PluginsRegistry.addPlugin()](https://docs.cryptolegacy.app/documentation/functions-reference#addplugin-pr1)
* [PluginsRegistry.removePlugin()](https://docs.cryptolegacy.app/documentation/functions-reference#removeplugin-pr1)

**Read by:**

* [PluginsRegistry.isPluginRegistered()](https://docs.cryptolegacy.app/documentation/functions-reference#ispluginregistered-pr1)
* [PluginsRegistry.getPluginAddressList()](https://docs.cryptolegacy.app/documentation/functions-reference#getpluginaddresslist-pr1)

### pluginDescriptionBlockNumbers (PR1-D2)

**Data Type:** `mapping(address => uint64[])` **Visibility / Mutability:** public, none **Storage Location:** direct storage **Description:** Records block numbers when plugin descriptions are added or updated.

**Modified by:**

* [PluginsRegistry.addPlugin()](https://docs.cryptolegacy.app/documentation/functions-reference#addplugin-pr1)
* [PluginsRegistry.addPluginDescription()](https://docs.cryptolegacy.app/documentation/functions-reference#addplugindescription-pr1)

**Read by:**

* [PluginsRegistry.getPluginMetadata()](https://docs.cryptolegacy.app/documentation/functions-reference#getpluginmetadata-pr1)
* [PluginsRegistry.getPluginDescriptionBlockNumbers()](https://docs.cryptolegacy.app/documentation/functions-reference#getplugindescriptionblocknumbers-pr1)

## ProxyBuilder (PB1)

### proxyAdmin (PB1-D1)

**Data Type:** `ProxyAdmin` **Visibility / Mutability:** public, none **Storage Location:** direct storage **Description:** Optional ProxyAdmin contract used to manage built proxies; constructor writes it only when `_proxyAdmin != address(0)`.

**Modified by:**

* [ProxyBuilder.constructor()](https://docs.cryptolegacy.app/documentation/functions-reference#constructor-pb1)
* [ProxyBuilder.setProxyAdmin()](https://docs.cryptolegacy.app/documentation/functions-reference#setproxyadmin-pb1)

**Read by:**

* [ProxyBuilder.build()](https://docs.cryptolegacy.app/documentation/functions-reference#build-pb1)

## ProxyBuilderAdmin (PBA1)

**No tracked data items in this contract/library.**

## SignatureRoleTimelock (SRT1)

### ADMIN\_ROLE (SRT1-D1)

**Data Type:** `bytes32` **Visibility / Mutability:** public, constant **Storage Location:** inlined constant **Description:** Identifier for the administrator role.

**Modified by:** None

**Read by:**

* [SignatureRoleTimelock.constructor()](https://docs.cryptolegacy.app/documentation/functions-reference#constructor-srt1)
* [SignatureRoleTimelock.cancelCallList()](https://docs.cryptolegacy.app/documentation/functions-reference#cancelcalllist-srt1)

### MAX\_TIMELOCK\_DURATION (SRT1-D2)

**Data Type:** `uint128` **Visibility / Mutability:** public, constant **Storage Location:** inlined constant **Description:** 7-day upper bound for signature-role timelocks accepted during constructor seeding and signature-role updates.

**Modified by:** None

**Read by:**

* [SignatureRoleTimelock.addSignatureRoleList()](https://docs.cryptolegacy.app/documentation/functions-reference#addsignaturerolelist-srt1)

### MAX\_EXECUTION\_PERIOD\_LOWER\_BOUND (SRT1-D3)

**Data Type:** `uint128` **Visibility / Mutability:** public, constant **Storage Location:** inlined constant **Description:** 7-day minimum allowed when setting the execution window for scheduled calls.

**Modified by:** None

**Read by:**

* [SignatureRoleTimelock.setMaxExecutionPeriod()](https://docs.cryptolegacy.app/documentation/functions-reference#setmaxexecutionperiod-srt1)

### MAX\_EXECUTION\_PERIOD\_UPPER\_BOUND (SRT1-D4)

**Data Type:** `uint128` **Visibility / Mutability:** public, constant **Storage Location:** inlined constant **Description:** 21-day maximum allowed when setting the execution window for scheduled calls.

**Modified by:** None

**Read by:**

* [SignatureRoleTimelock.setMaxExecutionPeriod()](https://docs.cryptolegacy.app/documentation/functions-reference#setmaxexecutionperiod-srt1)

### maxExecutionPeriod (SRT1-D5)

**Data Type:** `uint128` **Visibility / Mutability:** public, none **Storage Location:** direct storage **Description:** Maximum period during which a scheduled call can be executed.

**Modified by:**

* [SignatureRoleTimelock.setMaxExecutionPeriod()](https://docs.cryptolegacy.app/documentation/functions-reference#setmaxexecutionperiod-srt1)

**Read by:**

* [SignatureRoleTimelock.\_scheduleCall()](https://docs.cryptolegacy.app/documentation/functions-reference#_schedulecall-srt1)

### roleAccounts (SRT1-D6)

**Data Type:** `mapping(bytes32 => address[])` **Visibility / Mutability:** public, none **Storage Location:** direct storage **Description:** Maps role identifiers to the list of accounts with that role.

**Modified by:**

* [SignatureRoleTimelock.\_addRoleAccount()](https://docs.cryptolegacy.app/documentation/functions-reference#_addroleaccount-srt1)
* [SignatureRoleTimelock.\_removeRoleAccount()](https://docs.cryptolegacy.app/documentation/functions-reference#_removeroleaccount-srt1)

**Read by:**

* [SignatureRoleTimelock.\_addRoleAccount()](https://docs.cryptolegacy.app/documentation/functions-reference#_addroleaccount-srt1)
* [SignatureRoleTimelock.\_removeRoleAccount()](https://docs.cryptolegacy.app/documentation/functions-reference#_removeroleaccount-srt1)
* [SignatureRoleTimelock.getRoleAccounts()](https://docs.cryptolegacy.app/documentation/functions-reference#getroleaccounts-srt1)

### signatureRoles (SRT1-D7)

**Data Type:** `mapping(address => mapping(bytes4 => SignatureAttr))` **Visibility / Mutability:** public, none **Storage Location:** direct storage **Description:** Maps a target and selector to the required role and timelock.

**Modified by:**

* [SignatureRoleTimelock.\_addSignatureRole()](https://docs.cryptolegacy.app/documentation/functions-reference#_addsignaturerole-srt1)
* [SignatureRoleTimelock.\_removeSignatureRole()](https://docs.cryptolegacy.app/documentation/functions-reference#_removesignaturerole-srt1)

**Read by:**

* [SignatureRoleTimelock.\_addSignatureRole()](https://docs.cryptolegacy.app/documentation/functions-reference#_addsignaturerole-srt1)
* [SignatureRoleTimelock.\_removeSignatureRole()](https://docs.cryptolegacy.app/documentation/functions-reference#_removesignaturerole-srt1)
* [SignatureRoleTimelock.\_scheduleCall()](https://docs.cryptolegacy.app/documentation/functions-reference#_schedulecall-srt1)
* [SignatureRoleTimelock.getTargetSigs()](https://docs.cryptolegacy.app/documentation/functions-reference#gettargetsigs-srt1)

### targetSigs (SRT1-D8)

**Data Type:** `mapping(address => bytes4[])` **Visibility / Mutability:** public, none **Storage Location:** direct storage **Description:** Maps a target to the list of selectors that have signature roles.

**Modified by:**

* [SignatureRoleTimelock.\_addSignatureRole()](https://docs.cryptolegacy.app/documentation/functions-reference#_addsignaturerole-srt1)
* [SignatureRoleTimelock.\_removeSignatureRole()](https://docs.cryptolegacy.app/documentation/functions-reference#_removesignaturerole-srt1)

**Read by:**

* [SignatureRoleTimelock.\_addSignatureRole()](https://docs.cryptolegacy.app/documentation/functions-reference#_addsignaturerole-srt1)
* [SignatureRoleTimelock.\_removeSignatureRole()](https://docs.cryptolegacy.app/documentation/functions-reference#_removesignaturerole-srt1)
* [SignatureRoleTimelock.getTargetSigs()](https://docs.cryptolegacy.app/documentation/functions-reference#gettargetsigs-srt1)

### targets (SRT1-D9)

**Data Type:** `address[]` **Visibility / Mutability:** public, none **Storage Location:** direct storage **Description:** List of targets that have at least one signature role.

**Modified by:**

* [SignatureRoleTimelock.\_addSignatureRole()](https://docs.cryptolegacy.app/documentation/functions-reference#_addsignaturerole-srt1)
* [SignatureRoleTimelock.\_removeSignatureRole()](https://docs.cryptolegacy.app/documentation/functions-reference#_removesignaturerole-srt1)

**Read by:**

* [SignatureRoleTimelock.\_addSignatureRole()](https://docs.cryptolegacy.app/documentation/functions-reference#_addsignaturerole-srt1)
* [SignatureRoleTimelock.\_removeSignatureRole()](https://docs.cryptolegacy.app/documentation/functions-reference#_removesignaturerole-srt1)
* [SignatureRoleTimelock.getTargets()](https://docs.cryptolegacy.app/documentation/functions-reference#gettargets-srt1)

### pendingCalls (SRT1-D10)

**Data Type:** `mapping(bytes32 => CallRequest)` **Visibility / Mutability:** public, none **Storage Location:** direct storage **Description:** Stores scheduled call requests keyed by call id.

**Modified by:**

* [SignatureRoleTimelock.\_scheduleCall()](https://docs.cryptolegacy.app/documentation/functions-reference#_schedulecall-srt1)
* [SignatureRoleTimelock.\_executeCall()](https://docs.cryptolegacy.app/documentation/functions-reference#_executecall-srt1)
* [SignatureRoleTimelock.\_cancelCall()](https://docs.cryptolegacy.app/documentation/functions-reference#_cancelcall-srt1)

**Read by:**

* [SignatureRoleTimelock.\_scheduleCall()](https://docs.cryptolegacy.app/documentation/functions-reference#_schedulecall-srt1)
* [SignatureRoleTimelock.\_executeCall()](https://docs.cryptolegacy.app/documentation/functions-reference#_executecall-srt1)
* [SignatureRoleTimelock.\_cancelCall()](https://docs.cryptolegacy.app/documentation/functions-reference#_cancelcall-srt1)
* [SignatureRoleTimelock.getCall()](https://docs.cryptolegacy.app/documentation/functions-reference#getcall-srt1)
* [SignatureRoleTimelock.getCallsList()](https://docs.cryptolegacy.app/documentation/functions-reference#getcallslist-srt1)

### callsIds (SRT1-D11)

**Data Type:** `bytes32[]` **Visibility / Mutability:** public, none **Storage Location:** direct storage **Description:** List of scheduled call ids.

**Modified by:**

* [SignatureRoleTimelock.\_scheduleCall()](https://docs.cryptolegacy.app/documentation/functions-reference#_schedulecall-srt1)

**Read by:**

* [SignatureRoleTimelock.\_scheduleCall()](https://docs.cryptolegacy.app/documentation/functions-reference#_schedulecall-srt1)
* [SignatureRoleTimelock.getCallIds()](https://docs.cryptolegacy.app/documentation/functions-reference#getcallids-srt1)
* [SignatureRoleTimelock.getCallsList()](https://docs.cryptolegacy.app/documentation/functions-reference#getcallslist-srt1)
* [SignatureRoleTimelock.getCallsLength()](https://docs.cryptolegacy.app/documentation/functions-reference#getcallslength-srt1)

## ArbSys (AS1)

**No tracked data items in this contract/library.**

## Flags (FLG1)

### UNWRAP\_ETH (FLG1-D1)

**Data Type:** `uint256` **Visibility / Mutability:** public, constant **Storage Location:** inlined constant **Description:** Flag index used to indicate unwrap ETH behavior.

**Modified by:** None

**Read by:** None

### REVERT\_IF\_EXTERNAL\_FAIL (FLG1-D2)

**Data Type:** `uint256` **Visibility / Mutability:** public, constant **Storage Location:** inlined constant **Description:** Flag index used to revert if an external call fails.

**Modified by:** None

**Read by:**

* [LockChainGate.\_send()](https://docs.cryptolegacy.app/documentation/functions-reference#_send-lcg1)

### PROXY\_WITH\_SENDER (FLG1-D3)

**Data Type:** `uint256` **Visibility / Mutability:** public, constant **Storage Location:** inlined constant **Description:** Flag index used to proxy calls with sender context.

**Modified by:** None

**Read by:**

* [LockChainGate.\_send()](https://docs.cryptolegacy.app/documentation/functions-reference#_send-lcg1)

### SEND\_HASHED\_DATA (FLG1-D4)

**Data Type:** `uint256` **Visibility / Mutability:** public, constant **Storage Location:** inlined constant **Description:** Flag index used to indicate hashed data sending mode.

**Modified by:** None

**Read by:** None

### SEND\_EXTERNAL\_CALL\_GAS\_LIMIT (FLG1-D5)

**Data Type:** `uint256` **Visibility / Mutability:** public, constant **Storage Location:** inlined constant **Description:** Flag index used to set external call gas limit behavior.

**Modified by:** None

**Read by:** None

### MULTI\_SEND (FLG1-D6)

**Data Type:** `uint256` **Visibility / Mutability:** public, constant **Storage Location:** inlined constant **Description:** Flag index used to enable multi-send behavior.

**Modified by:** None

**Read by:** None

## IAaveV3Pool (IAV3P1)

**No tracked data items in this contract/library.**

## IAaveV3PoolDataProvider (IAV3PDP1)

**No tracked data items in this contract/library.**

## WethUnwrap (WU1)

### WETH (WU1-D1)

**Data Type:** `address` **Visibility / Mutability:** public, immutable **Storage Location:** inlined immutable **Description:** WETH token address pulled from callers and unwrapped to native ETH during `unwrap_weth`.

**Modified by:**

* [WethUnwrap.constructor()](https://docs.cryptolegacy.app/documentation/functions-reference#constructor-wu1)

**Read by:**

* [WethUnwrap.unwrap\_weth()](https://docs.cryptolegacy.app/documentation/functions-reference#unwrap_weth-wu1)

## IBeneficiaryRegistry (IBR1)

### EntityType (IBR1-E1)

**Type:** `enum` **Members:**

* `NONE`
* `OWNER`
* `BENEFICIARY`
* `GUARDIAN`
* `RECOVERY`

**Used by:**

* [LibCryptoLegacy.\_setCryptoLegacyToBeneficiaryRegistry()](https://docs.cryptolegacy.app/documentation/functions-reference#_setcryptolegacytobeneficiaryregistry-lcl1)
* [LibCryptoLegacy.\_setCryptoLegacyListToBeneficiaryRegistry()](https://docs.cryptolegacy.app/documentation/functions-reference#_setcryptolegacylisttobeneficiaryregistry-lcl1)

## IBuildManagerOwnable (IBMO1)

**No tracked data items in this contract/library.**

## ICallProxy (ICP1)

**No tracked data items in this contract/library.**

## ICryptoLegacy (ICL1)

### BeneficiaryConfig (ICL1-S1)

**Type:** `struct` **Fields:**

* `claimDelay (uint64)`: Delay before claims become available.
* `vestingPeriod (uint64)`: Duration over which claims vest.
* `shareBps (uint64)`: Beneficiary share in basis points.

**Used by:**

* [LibCryptoLegacy.\_getStartAndEndDate()](https://docs.cryptolegacy.app/documentation/functions-reference#_getstartandenddate-lcl1)
* [LibCryptoLegacy.\_getVestedAndClaimedAmount()](https://docs.cryptolegacy.app/documentation/functions-reference#_getvestedandclaimedamount-lcl1)
* [LibCryptoLegacy.\_getBeneficiaryConfigAndVesting()](https://docs.cryptolegacy.app/documentation/functions-reference#_getbeneficiaryconfigandvesting-lcl1)

**Notes / Edge cases:** None

### BeneficiaryVesting (ICL1-S2)

**Type:** `struct` **Fields:**

* `tokenAmountClaimed (mapping(address => uint256))`: Amount claimed per token.

**Used by:**

* [LibCryptoLegacy.\_getVestedAndClaimedAmount()](https://docs.cryptolegacy.app/documentation/functions-reference#_getvestedandclaimedamount-lcl1)
* [LibCryptoLegacy.\_getBeneficiaryConfigAndVesting()](https://docs.cryptolegacy.app/documentation/functions-reference#_getbeneficiaryconfigandvesting-lcl1)

**Notes / Edge cases:** None

### TokenDistribution (ICL1-S3)

**Type:** `struct` **Fields:**

* `amountToDistribute (uint256)`: Total amount allocated for distribution.
* `lastBalance (uint256)`: Last recorded token balance.

**Used by:**

* [LibCryptoLegacy.\_tokenPrepareToDistribute()](https://docs.cryptolegacy.app/documentation/functions-reference#_tokenpreparetodistribute-lcl1)
* [LibCryptoLegacy.\_getVestedAndClaimedAmount()](https://docs.cryptolegacy.app/documentation/functions-reference#_getvestedandclaimedamount-lcl1)

**Notes / Edge cases:** None

### CryptoLegacyStorage (ICL1-S4)

**Type:** `struct` **Fields:**

* `isPaused (bool)`: Pause flag for the protocol.
* `initialFeeToPay (uint128)`: Initial fee amount required.
* `updateFee (uint128)`: Current update fee amount.
* `updateInterval (uint64)`: Interval between required updates.
* `challengeTimeout (uint64)`: Challenge period timeout.
* `lastFeePaidAt (uint64)`: Timestamp of the last fee payment.
* `lastUpdateAt (uint64)`: Timestamp of the last update.
* `distributionStartAt (uint64)`: Timestamp when distribution starts.
* `pendingOwner (address)`: Pending owner address for ownership transfer.
* `invitedByRefCode (bytes8)`: Referral code used at build time.
* `defaultFuncDisabled (uint8)`: Bitmask of disabled default functions.
* `gasLimitMultiplier (uint8)`: Multiplier applied to gas estimates.
* `buildManager (ICryptoLegacyBuildManager)`: Build manager contract reference.
* `beneficiaries (EnumerableSet.Bytes32Set)`: Set of beneficiary hashes.
* `beneficiaryConfig (mapping(bytes32 => BeneficiaryConfig))`: Configuration per beneficiary hash.
* `originalBeneficiaryHash (mapping(bytes32 => bytes32))`: Mapping from beneficiary hash to original hash.
* `beneficiarySwitchTimelock (mapping(bytes32 => uint64))`: Timelock for beneficiary switch.
* `beneficiaryVesting (mapping(bytes32 => BeneficiaryVesting))`: Vesting data per beneficiary hash.
* `tokenDistribution (mapping(address => TokenDistribution))`: Distribution data per token.
* `beneficiaryMessagesGotByBlockNumber (mapping(bytes32 => uint64[]))`: Message block history per beneficiary.
* `transfersGotByBlockNumber (uint64[])`: Block numbers for transfers from the legacy.

**Used by:**

* [LibCryptoLegacy.getCryptoLegacyStorage()](https://docs.cryptolegacy.app/documentation/functions-reference#getcryptolegacystorage-lcl1)
* [LibCryptoLegacy.\_checkPause()](https://docs.cryptolegacy.app/documentation/functions-reference#_checkpause-lcl1)
* [LibCryptoLegacy.\_setPause()](https://docs.cryptolegacy.app/documentation/functions-reference#_setpause-lcl1)

**Notes / Edge cases:** None

### TokenTransferTo (ICL1-S5)

**Type:** `struct` **Fields:**

* `token (address)`: Token address.
* `recipient (address)`: Recipient address.
* `amount (uint256)`: Amount to transfer.

**Used by:**

* [LibCryptoLegacy.\_transferTokensFromLegacy()](https://docs.cryptolegacy.app/documentation/functions-reference#_transfertokensfromlegacy-lcl1)
* [LegacyRecoveryPlugin.lrWithdrawTokensFromLegacy()](https://docs.cryptolegacy.app/documentation/functions-reference#lrwithdrawtokensfromlegacy-lrp1)

**Notes / Edge cases:** None

## ICryptoLegacyBuildManager (ICLBM1)

### BuildArgs (ICLBM1-S1)

**Type:** `struct` **Fields:**

* `invitedByRefCode (bytes8)`: Referral code used for build.
* `beneficiaryHashes (bytes32[])`: Beneficiary hashes.
* `beneficiaryConfig (ICryptoLegacy.BeneficiaryConfig[])`: Beneficiary configurations.
* `plugins (address[])`: Plugin addresses to install.
* `updateInterval (uint64)`: Update interval for the legacy.
* `challengeTimeout (uint64)`: Challenge timeout for the legacy.

**Used by:**

* [CryptoLegacyBuildManager.\_createRefAndPayForBuild()](https://docs.cryptolegacy.app/documentation/functions-reference#_createrefandpayforbuild-clbm1)
* [CryptoLegacyBuildManager.buildCryptoLegacy()](https://docs.cryptolegacy.app/documentation/functions-reference#buildcryptolegacy-clbm1)
* [CryptoLegacyBuildManager.\_checkBuildArgs()](https://docs.cryptolegacy.app/documentation/functions-reference#_checkbuildargs-clbm1)

**Notes / Edge cases:** None

### RefArgs (ICLBM1-S2)

**Type:** `struct` **Fields:**

* `createRefRecipient (address)`: Recipient for created referral code.
* `createRefCustomCode (bytes8)`: Custom referral code, if provided.
* `createRefChains (uint256[])`: Chain ids for referral creation.
* `crossChainFees (uint256[])`: Cross-chain fees per chain id.

**Used by:**

* [CryptoLegacyBuildManager.\_createRefAndPayForBuild()](https://docs.cryptolegacy.app/documentation/functions-reference#_createrefandpayforbuild-clbm1)

**Notes / Edge cases:** None

### LifetimeNftMint (ICLBM1-S3)

**Type:** `struct` **Fields:**

* `toHolder (address)`: NFT recipient address.
* `amount (uint256)`: Amount of NFTs to mint.

**Used by:**

* [CryptoLegacyBuildManager.payForMultipleLifetimeNft()](https://docs.cryptolegacy.app/documentation/functions-reference#payformultiplelifetimenft-clbm1)

**Notes / Edge cases:** None

## ICryptoLegacyDiamondBase (ICLDB1)

**No tracked data items in this contract/library.**

## ICryptoLegacyFactory (ICLF1)

### Create2Args (ICLF1-S1)

**Type:** `struct` **Fields:**

* `create2Address (address)`: Expected CREATE2 address.
* `create2Salt (bytes32)`: CREATE2 salt.

**Used by:**

* [CryptoLegacyBuildManager.buildCryptoLegacy()](https://docs.cryptolegacy.app/documentation/functions-reference#buildcryptolegacy-clbm1)
* [ICryptoLegacyFactory.createCryptoLegacy()](https://docs.cryptolegacy.app/documentation/functions-reference#createcryptolegacy-iclf1)

**Notes / Edge cases:** None

## ICryptoLegacyLens (ICLL1)

### BeneficiaryTokenData (ICLL1-S1)

**Type:** `struct` **Fields:**

* `claimableAmount (uint256)`: Amount currently claimable.
* `claimedAmount (uint256)`: Amount already claimed.
* `totalAmount (uint256)`: Total amount allocated.

**Used by:**

* [LensPlugin.getVestedAndClaimedData()](https://docs.cryptolegacy.app/documentation/functions-reference#getvestedandclaimeddata-lp1)
* [ICryptoLegacyLens.getVestedAndClaimedData()](https://docs.cryptolegacy.app/documentation/functions-reference#getvestedandclaimeddata-icll1)

**Notes / Edge cases:** None

### PluginInfo (ICLL1-S2)

**Type:** `struct` **Fields:**

* `plugin (address)`: Plugin contract address.
* `name (string)`: Plugin name.
* `version (uint16)`: Plugin version.
* `descriptionBlockNumbers (uint64[])`: Block numbers when descriptions were added.

**Used by:**

* [LensPlugin.\_getPluginInfoList()](https://docs.cryptolegacy.app/documentation/functions-reference#_getplugininfolist-lp1)
* [LensPlugin.getPluginInfoList()](https://docs.cryptolegacy.app/documentation/functions-reference#getplugininfolist-lp1)

**Notes / Edge cases:** None

### CryptoLegacyBaseData (ICLL1-S3)

**Type:** `struct` **Fields:**

* `initialFeeToPay (uint128)`: Initial fee amount.
* `updateFee (uint128)`: Update fee amount.
* `updateInterval (uint64)`: Update interval.
* `challengeTimeout (uint64)`: Challenge timeout.
* `lastFeePaidAt (uint64)`: Timestamp of last fee payment.
* `lastUpdateAt (uint64)`: Timestamp of last update.
* `distributionStartAt (uint64)`: Timestamp of distribution start.
* `invitedByRefCode (bytes8)`: Referral code used at build time.
* `defaultFuncDisabled (uint8)`: Bitmask of disabled default functions.
* `buildManager (address)`: Build manager address.

**Used by:**

* [LensPlugin.getCryptoLegacyBaseData()](https://docs.cryptolegacy.app/documentation/functions-reference#getcryptolegacybasedata-lp1)
* [ICryptoLegacyLens.getCryptoLegacyBaseData()](https://docs.cryptolegacy.app/documentation/functions-reference#getcryptolegacybasedata-icll1)

**Notes / Edge cases:** None

### LensTokenDistribution (ICLL1-S4)

**Type:** `struct` **Fields:**

* `amountToDistribute (uint256)`: Amount to distribute.
* `lastBalance (uint256)`: Last recorded balance.
* `totalClaimed (uint256)`: Total claimed amount.

**Used by:**

* [LensPlugin.\_getTokensDistribution()](https://docs.cryptolegacy.app/documentation/functions-reference#_gettokensdistribution-lp1)
* [LensPlugin.getTokensDistribution()](https://docs.cryptolegacy.app/documentation/functions-reference#gettokensdistribution-lp1)

**Notes / Edge cases:** None

### CryptoLegacyListData (ICLL1-S5)

**Type:** `struct` **Fields:**

* `beneficiaries (bytes32[])`: Beneficiary hashes.
* `beneficiariesOriginalHashes (bytes32[])`: Original beneficiary hashes.
* `transfersGotByBlockNumber (uint64[])`: Block numbers for transfers.
* `beneficiaryConfigArr (ICryptoLegacy.BeneficiaryConfig[])`: Beneficiary configuration array.
* `plugins (PluginInfo[])`: Plugin metadata list.
* `tokenDistributions (LensTokenDistribution[])`: Token distribution data per token.

**Used by:**

* [LensPlugin.getCryptoLegacyListData()](https://docs.cryptolegacy.app/documentation/functions-reference#getcryptolegacylistdata-lp1)
* [ICryptoLegacyLens.getCryptoLegacyListData()](https://docs.cryptolegacy.app/documentation/functions-reference#getcryptolegacylistdata-icll1)

**Notes / Edge cases:** None

## ICryptoLegacyOwnable (ICLO1)

**No tracked data items in this contract/library.**

## ICryptoLegacyPlugin (ICLP1)

**No tracked data items in this contract/library.**

## ICryptoLegacyUpdaterPlugin (ICLUP1)

**No tracked data items in this contract/library.**

## IDeBridgeGate (IDBG1)

### TokenInfo (IDBG1-S1)

**Type:** `struct` **Fields:**

* `nativeChainId (uint256)`: Native chain identifier.
* `nativeAddress (bytes)`: Native token address bytes.

**Used by:** None

**Notes / Edge cases:** None

### DebridgeInfo (IDBG1-S2)

**Type:** `struct` **Fields:**

* `chainId (uint256)`: Chain identifier.
* `maxAmount (uint256)`: Maximum transferable amount.
* `balance (uint256)`: Total locked balance.
* `lockedInStrategies (uint256)`: Amount locked in strategies.
* `tokenAddress (address)`: Token address on the current chain.
* `minReservesBps (uint16)`: Minimum reserves in basis points.
* `exist (bool)`: Whether the debridge exists.

**Used by:** None

**Notes / Edge cases:** None

### DebridgeFeeInfo (IDBG1-S3)

**Type:** `struct` **Fields:**

* `collectedFees (uint256)`: Total collected fees.
* `withdrawnFees (uint256)`: Total withdrawn fees.
* `getChainFee (mapping(uint256 => uint256))`: Fee per chain id.

**Used by:** None

**Notes / Edge cases:** None

### ChainSupportInfo (IDBG1-S4)

**Type:** `struct` **Fields:**

* `fixedNativeFee (uint256)`: Fixed native fee amount.
* `isSupported (bool)`: Whether the chain is supported.
* `transferFeeBps (uint16)`: Transfer fee in basis points.

**Used by:**

* [ChainsSupportUpdated](https://docs.cryptolegacy.app/documentation/events-reference#chainssupportupdated-idbg1)

**Notes / Edge cases:** None

### DiscountInfo (IDBG1-S5)

**Type:** `struct` **Fields:**

* `discountFixBps (uint16)`: Fixed fee discount in basis points.
* `discountTransferBps (uint16)`: Transfer fee discount in basis points.

**Used by:** None

**Notes / Edge cases:** None

### SubmissionAutoParamsTo (IDBG1-S6)

**Type:** `struct` **Fields:**

* `executionFee (uint256)`: Execution fee amount.
* `flags (uint256)`: Packed flag set.
* `fallbackAddress (bytes)`: Fallback address bytes.
* `data (bytes)`: Call data.

**Used by:** None

**Notes / Edge cases:** None

### SubmissionAutoParamsFrom (IDBG1-S7)

**Type:** `struct` **Fields:**

* `executionFee (uint256)`: Execution fee amount.
* `flags (uint256)`: Packed flag set.
* `fallbackAddress (address)`: Fallback address.
* `data (bytes)`: Call data.
* `nativeSender (bytes)`: Native sender address bytes.

**Used by:** None

**Notes / Edge cases:** None

### FeeParams (IDBG1-S8)

**Type:** `struct` **Fields:**

* `receivedAmount (uint256)`: Received amount.
* `fixFee (uint256)`: Fixed fee amount.
* `transferFee (uint256)`: Transfer fee amount.
* `useAssetFee (bool)`: Whether asset fee is used.
* `isNativeToken (bool)`: Whether the token is native.

**Used by:**

* [Sent](https://docs.cryptolegacy.app/documentation/events-reference#sent-idbg1)

**Notes / Edge cases:** None

## IDiamondCut (IDC1)

### FacetCutAction (IDC1-E1)

**Type:** `enum` **Members:**

* `Add`
* `Replace`
* `Remove`

**Used by:**

* [LibDiamond.diamondCut()](https://docs.cryptolegacy.app/documentation/functions-reference#diamondcut-ld1)
* [IDiamondCut.diamondCut()](https://docs.cryptolegacy.app/documentation/functions-reference#diamondcut-idc1)

### FacetCut (IDC1-S1)

**Type:** `struct` **Fields:**

* `facetAddress (address)`: Facet address.
* `action (FacetCutAction)`: Cut action to apply.
* `functionSelectors (bytes4[])`: Selectors affected by the cut.

**Used by:**

* [LibDiamond.diamondCut()](https://docs.cryptolegacy.app/documentation/functions-reference#diamondcut-ld1)
* [IDiamondCut.diamondCut()](https://docs.cryptolegacy.app/documentation/functions-reference#diamondcut-idc1)

**Notes / Edge cases:** None

## IDiamondLoupe (IDL1)

### Facet (IDL1-S1)

**Type:** `struct` **Fields:**

* `facetAddress (address)`: Facet address.
* `functionSelectors (bytes4[])`: Function selectors provided by the facet.

**Used by:**

* [DiamondLoupeFacet.facets()](https://docs.cryptolegacy.app/documentation/functions-reference#facets-dlf1)
* [IDiamondLoupe.facets()](https://docs.cryptolegacy.app/documentation/functions-reference#facets-idl1)

**Notes / Edge cases:** None

## IFeeRegistry (IFR1)

### FRStorage (IFR1-S1)

**Type:** `struct` **Fields:**

* `defaultDiscountPct (uint32)`: Default discount percentage.
* `defaultSharePct (uint32)`: Default share percentage.
* `accumulatedFee (uint128)`: Accumulated fee amount.
* `supportedRefInChains (EnumerableSet.UintSet)`: Supported referral chains.
* `refererByCode (mapping(bytes8 => Referrer))`: Referrer data by code.
* `codeByReferrer (mapping(address => bytes8))`: Code by referrer address.
* `codeOperators (EnumerableSet.AddressSet)`: Authorized code operators.
* `feeByContractCase (mapping(address => mapping(uint8 => uint128)))`: Fee by contract and case.
* `feeBeneficiaries (FeeBeneficiary[])`: Fee beneficiary list.

**Used by:**

* [FeeRegistry.lockFeeRegistryStorage()](https://docs.cryptolegacy.app/documentation/functions-reference#lockfeeregistrystorage-fr1)
* [FeeRegistry.getFeeBeneficiaries()](https://docs.cryptolegacy.app/documentation/functions-reference#getfeebeneficiaries-fr1)
* [IFeeRegistry.accumulatedFee()](https://docs.cryptolegacy.app/documentation/functions-reference#accumulatedfee-ifr1)

**Notes / Edge cases:** None

### Referrer (IFR1-S2)

**Type:** `struct` **Fields:**

* `owner (address)`: Referrer owner address.
* `recipient (address)`: Fee recipient address.
* `discountPct (uint32)`: Discount percentage.
* `sharePct (uint32)`: Share percentage.
* `accumulatedFee (uint128)`: Accumulated fee for the referrer.

**Used by:**

* [FeeRegistry.createCustomCode()](https://docs.cryptolegacy.app/documentation/functions-reference#createcustomcode-fr1)
* [FeeRegistry.createCode()](https://docs.cryptolegacy.app/documentation/functions-reference#createcode-fr1)
* [IFeeRegistry.accumulatedFee()](https://docs.cryptolegacy.app/documentation/functions-reference#accumulatedfee-ifr1)

**Notes / Edge cases:** None

### FeeBeneficiary (IFR1-S3)

**Type:** `struct` **Fields:**

* `recipient (address)`: Fee recipient address.
* `sharePct (uint32)`: Share percentage.

**Used by:**

* [FeeRegistry.setFeeBeneficiaries()](https://docs.cryptolegacy.app/documentation/functions-reference#setfeebeneficiaries-fr1)
* [FeeRegistry.getFeeBeneficiaries()](https://docs.cryptolegacy.app/documentation/functions-reference#getfeebeneficiaries-fr1)
* [FeeRegistry.withdrawAccumulatedFee()](https://docs.cryptolegacy.app/documentation/functions-reference#withdrawaccumulatedfee-fr1)

**Notes / Edge cases:** None

## ILockChainGate (ILCG1)

### LCGStorage (ILCG1-S1)

**Type:** `struct` **Fields:**

* `deBridgeGate (IDeBridgeGate)`: DeBridgeGate contract reference.
* `deBridgeNativeFee (mapping(uint256 => uint256))`: Native fee by chain id.
* `destinationChainContracts (mapping(uint256 => address))`: Destination chain contract by chain id.
* `sourceChainsContracts (mapping(uint256 => address))`: Source chain contract by chain id.
* `lockOperators (EnumerableSet.AddressSet)`: Set of lock operators.
* `lifetimeNft (ILifetimeNft)`: Lifetime NFT contract reference.
* `lockPeriod (uint64)`: Lock period duration.
* `transferTimeout (uint64)`: Transfer timeout duration.
* `referralCode (uint32)`: Referral code value.
* `customChainId (uint256)`: Custom chain id override.
* `lockedNft (mapping(address => LockedNft))`: Locked NFT data by holder.
* `ownerOfTokenId (mapping(uint256 => address))`: Owner by token id.
* `lockedToChainsIds (mapping(uint256 => EnumerableSet.UintSet))`: Locked chain ids per token id.
* `lockedNftFromChainId (mapping(uint256 => uint256))`: Source chain id per token id.
* `lockedNftApprovedTo (mapping(uint256 => address))`: Approved address per token id.

**Used by:**

* [LockChainGate.lockChainGateStorage()](https://docs.cryptolegacy.app/documentation/functions-reference#lockchaingatestorage-lcg1)
* [ILockChainGate.lockLifetimeNft()](https://docs.cryptolegacy.app/documentation/functions-reference#locklifetimenft-ilcg1)
* [ILockChainGate.isNftLocked()](https://docs.cryptolegacy.app/documentation/functions-reference#isnftlocked-ilcg1)
* [ILockChainGate.isNftLockedAndUpdate()](https://docs.cryptolegacy.app/documentation/functions-reference#isnftlockedandupdate-ilcg1)

**Notes / Edge cases:** None

### LockedNft (ILCG1-S2)

**Type:** `struct` **Fields:**

* `lockedAt (uint256)`: Timestamp when the NFT was locked.
* `tokenId (uint256)`: Locked token id.

**Used by:**

* [ILockChainGate.lockLifetimeNft()](https://docs.cryptolegacy.app/documentation/functions-reference#locklifetimenft-ilcg1)
* [ILockChainGate.isNftLocked()](https://docs.cryptolegacy.app/documentation/functions-reference#isnftlocked-ilcg1)
* [ILockChainGate.isNftLockedAndUpdate()](https://docs.cryptolegacy.app/documentation/functions-reference#isnftlockedandupdate-ilcg1)

**Notes / Edge cases:** None

## ILegacyMessenger (ILM1)

**No tracked data items in this contract/library.**

## ILido (ILD1)

**No tracked data items in this contract/library.**

## ILidoWithdrawalQueue (ILWQ1)

**No tracked data items in this contract/library.**

## ILifetimeNft (ILN1)

### Tier (ILN1-E1)

**Type:** `enum` **Members:**

* `None`
* `Silicon`
* `Gallium`
* `Indium`
* `Based`
* `Tantalum`

**Used by:**

* [ILifetimeNft.mint()](https://docs.cryptolegacy.app/documentation/functions-reference#mint-iln1)

## IPermit2 (IPM21)

**No tracked data items in this contract/library.**

## IPluginsRegistry (IPR1)

### PluginInfo (IPR1-S1)

**Type:** `struct` **Fields:**

* `plugin (address)`: Plugin address.
* `name (string)`: Plugin name.
* `version (uint16)`: Plugin version.
* `descriptionBlockNumbers (uint64[])`: Block numbers for description updates.

**Used by:**

* [PluginsRegistry.getPluginInfoList()](https://docs.cryptolegacy.app/documentation/functions-reference#getplugininfolist-pr1)

**Notes / Edge cases:** None

## ISafeMinimalMultisig (ISM1)

### Storage (ISM1-S1)

**Type:** `struct` **Fields:**

* `requiredConfirmations (uint128)`: Required confirmations count.
* `voters (bytes32[])`: Voter identifiers.
* `proposals (Proposal[])`: Proposal list.
* `confirmedBy (mapping(uint256 => mapping(bytes32 => bool)))`: Confirmation tracking by proposal and voter.
* `heldEth (mapping(bytes32 => uint256))`: ETH held per voter hash.

**Used by:**

* [LibSafeMinimalMultisig.\_initializationStatus()](https://docs.cryptolegacy.app/documentation/functions-reference#_initializationstatus-lsm1)
* [LibSafeMinimalMultisig.\_propose()](https://docs.cryptolegacy.app/documentation/functions-reference#_propose-lsm1)
* [LibSafeMinimalMultisig.\_confirm()](https://docs.cryptolegacy.app/documentation/functions-reference#_confirm-lsm1)

**Notes / Edge cases:** None

### ProposalStatus (ISM1-E1)

**Type:** `enum` **Members:**

* `NOT\_EXIST`
* `PENDING`
* `CANCELED`
* `EXECUTED`

**Used by:**

* [LibSafeMinimalMultisig.\_propose()](https://docs.cryptolegacy.app/documentation/functions-reference#_propose-lsm1)
* [LibSafeMinimalMultisig.\_cancel()](https://docs.cryptolegacy.app/documentation/functions-reference#_cancel-lsm1)
* [LibSafeMinimalMultisig.\_execute()](https://docs.cryptolegacy.app/documentation/functions-reference#_execute-lsm1)

### Proposal (ISM1-S2)

**Type:** `struct` **Fields:**

* `params (bytes)`: Proposal parameters.
* `confirms (uint128)`: Confirmation count.
* `selector (bytes4)`: Target function selector.
* `status (ProposalStatus)`: Proposal status.

**Used by:**

* [LibSafeMinimalMultisig.\_propose()](https://docs.cryptolegacy.app/documentation/functions-reference#_propose-lsm1)
* [LibSafeMinimalMultisig.\_getProposalWithStatus()](https://docs.cryptolegacy.app/documentation/functions-reference#_getproposalwithstatus-lsm1)

**Notes / Edge cases:** None

### ProposalWithStatus (ISM1-S3)

**Type:** `struct` **Fields:**

* `proposal (Proposal)`: Proposal data.
* `confirmedBy (bool[])`: Confirmation flags by voter index.

**Used by:**

* [LibSafeMinimalMultisig.\_getProposalWithStatus()](https://docs.cryptolegacy.app/documentation/functions-reference#_getproposalwithstatus-lsm1)
* [LibSafeMinimalMultisig.\_getProposalListWithStatusesAndStorageVoters()](https://docs.cryptolegacy.app/documentation/functions-reference#_getproposallistwithstatusesandstoragevoters-lsm1)
* [LibSafeMinimalBeneficiaryMultisig.\_getProposalWithStatus()](https://docs.cryptolegacy.app/documentation/functions-reference#_getproposalwithstatus-lsmb1)

**Notes / Edge cases:** None

### InitializationStatus (ISM1-E2)

**Type:** `enum` **Members:**

* `UNKNOWN`
* `INITIALIZED`
* `NOT\_INITIALIZED\_NO\_NEED`
* `NOT\_INITIALIZED\_BUT\_NEED`

**Used by:**

* [LibSafeMinimalMultisig.\_initializationStatus()](https://docs.cryptolegacy.app/documentation/functions-reference#_initializationstatus-lsm1)
* [LibSafeMinimalBeneficiaryMultisig.\_initializationStatus()](https://docs.cryptolegacy.app/documentation/functions-reference#_initializationstatus-lsmb1)

## ISignatureRoleTimelock (ISRT1)

### CallRequest (ISRT1-S1)

**Type:** `struct` **Fields:**

* `caller (address)`: Caller who scheduled the call.
* `target (address)`: Target contract address.
* `data (bytes)`: Encoded call data.
* `executeAfter (uint128)`: Earliest execution timestamp.
* `executeBefore (uint128)`: Latest execution timestamp.
* `pending (bool)`: Whether the call is still pending.

**Used by:**

* [SignatureRoleTimelock.\_scheduleCall()](https://docs.cryptolegacy.app/documentation/functions-reference#_schedulecall-srt1)
* [SignatureRoleTimelock.getCall()](https://docs.cryptolegacy.app/documentation/functions-reference#getcall-srt1)
* [SignatureRoleTimelock.getCallsList()](https://docs.cryptolegacy.app/documentation/functions-reference#getcallslist-srt1)

**Notes / Edge cases:** None

### AddressRoleInput (ISRT1-S2)

**Type:** `struct` **Fields:**

* `role (bytes32)`: Role identifier.
* `newAccount (address)`: New account to add.
* `prevAccount (address)`: Previous account to remove or replace.

**Used by:**

* [SignatureRoleTimelock.setRoleAccounts()](https://docs.cryptolegacy.app/documentation/functions-reference#setroleaccounts-srt1)

**Notes / Edge cases:** None

### SignatureAttr (ISRT1-S3)

**Type:** `struct` **Fields:**

* `role (bytes32)`: Role identifier.
* `timelock (uint128)`: Timelock duration.

**Used by:**

* [SignatureRoleTimelock.\_addSignatureRole()](https://docs.cryptolegacy.app/documentation/functions-reference#_addsignaturerole-srt1)
* [SignatureRoleTimelock.\_scheduleCall()](https://docs.cryptolegacy.app/documentation/functions-reference#_schedulecall-srt1)
* [SignatureRoleTimelock.getTargetSigs()](https://docs.cryptolegacy.app/documentation/functions-reference#gettargetsigs-srt1)

**Notes / Edge cases:** None

### SignatureToAdd (ISRT1-S4)

**Type:** `struct` **Fields:**

* `target (address)`: Target contract address.
* `signature (bytes4)`: Function selector.
* `role (bytes32)`: Role identifier.
* `timelock (uint128)`: Timelock duration.

**Used by:**

* [SignatureRoleTimelock.constructor()](https://docs.cryptolegacy.app/documentation/functions-reference#constructor-srt1)
* [SignatureRoleTimelock.addSignatureRoleList()](https://docs.cryptolegacy.app/documentation/functions-reference#addsignaturerolelist-srt1)

**Notes / Edge cases:** None

### SignatureToRemove (ISRT1-S5)

**Type:** `struct` **Fields:**

* `target (address)`: Target contract address.
* `signature (bytes4)`: Function selector.

**Used by:**

* [SignatureRoleTimelock.removeSignatureRoleList()](https://docs.cryptolegacy.app/documentation/functions-reference#removesignaturerolelist-srt1)

**Notes / Edge cases:** None

### CallToAdd (ISRT1-S6)

**Type:** `struct` **Fields:**

* `target (address)`: Target contract address.
* `data (bytes)`: Encoded call data.

**Used by:**

* [SignatureRoleTimelock.scheduleCallList()](https://docs.cryptolegacy.app/documentation/functions-reference#schedulecalllist-srt1)

**Notes / Edge cases:** None

### TargetSigRes (ISRT1-S7)

**Type:** `struct` **Fields:**

* `signature (bytes4)`: Function selector.
* `role (bytes32)`: Required role identifier.
* `timelock (uint256)`: Timelock duration.

**Used by:**

* [SignatureRoleTimelock.getTargetSigs()](https://docs.cryptolegacy.app/documentation/functions-reference#gettargetsigs-srt1)

**Notes / Edge cases:** None

## IStataToken (ISTA1)

**No tracked data items in this contract/library.**

## IStataTokenFactory (ISTF1)

**No tracked data items in this contract/library.**

## ITrustedGuardiansPlugin (ITGP1)

### PluginStorage (ITGP1-S1)

**Type:** `struct` **Fields:**

* `guardians (EnumerableSet.Bytes32Set)`: Set of guardian hashes.
* `guardiansVoted (bytes32[])`: Guardians that have voted.
* `guardiansThreshold (uint128)`: Required guardian threshold.
* `guardiansChallengeTimeout (uint64)`: Guardians challenge timeout.

**Used by:**

* [LibTrustedGuardiansPlugin.getPluginStorage()](https://docs.cryptolegacy.app/documentation/functions-reference#getpluginstorage-ltgp1)
* [TrustedGuardiansPlugin.getGuardiansData()](https://docs.cryptolegacy.app/documentation/functions-reference#getguardiansdata-tgp1)
* [TrustedGuardiansPlugin.checkGuardiansVotedAndGetGuardiansData()](https://docs.cryptolegacy.app/documentation/functions-reference#checkguardiansvotedandgetguardiansdata-tgp1)

**Notes / Edge cases:** None

### GuardianToChange (ITGP1-S2)

**Type:** `struct` **Fields:**

* `hash (bytes32)`: Guardian hash.
* `isAdd (bool)`: True to add, false to remove.

**Used by:**

* [TrustedGuardiansPlugin.initializeGuardians()](https://docs.cryptolegacy.app/documentation/functions-reference#initializeguardians-tgp1)
* [TrustedGuardiansPlugin.setGuardians()](https://docs.cryptolegacy.app/documentation/functions-reference#setguardians-tgp1)
* [TrustedGuardiansPlugin.\_setGuardians()](https://docs.cryptolegacy.app/documentation/functions-reference#_setguardians-tgp1)

**Notes / Edge cases:** None

## DiamondLoupeFacet (DLF1)

**No tracked data items in this contract/library.**

## IUniversalRouter (IUR1)

**No tracked data items in this contract/library.**

## IWETH (IWETH1)

**No tracked data items in this contract/library.**

## IWstETH (IWSTETH1)

**No tracked data items in this contract/library.**

## WethUnwrapIWETH (WUI1)

**No tracked data items in this contract/library.**

## LibCLUtils (LCLU1)

**No tracked data items in this contract/library.**

## LibClaimMigrationCore (LCMC1)

### MIGRATION\_SCALE (LCMC1-D1)

**Data Type:** `uint256` **Visibility / Mutability:** internal, constant **Storage Location:** inlined constant **Description:** Fixed 1e18 scaling factor used by claim-migration math to keep fractions and ratios in 18-decimal fixed-point precision.

**Modified by:** None

**Read by:**

* [LibClaimMigrationCore.calculateFractionAndRatio()](https://docs.cryptolegacy.app/documentation/functions-reference#calculatefractionandratio-lcmc1)
* [LibClaimMigrationCore.applyMigrationFormula()](https://docs.cryptolegacy.app/documentation/functions-reference#applymigrationformula-lcmc1)

## LibOneStepClaimMigration (LOSCM1)

**No tracked data items in this contract/library.**

## LibTwoStepClaimMigration (LTSCM1)

### CLAIM\_LOCK\_AMOUNT (LTSCM1-D1)

**Data Type:** `uint256` **Visibility / Mutability:** internal, constant **Storage Location:** inlined constant **Description:** `type(uint256).max` sentinel written into beneficiary claim slots while a delayed migration is pending.

**Modified by:** None

**Read by:**

* [LibTwoStepClaimMigration.start()](https://docs.cryptolegacy.app/documentation/functions-reference#start-ltscm1)

### CachedClaims (LTSCM1-S1)

**Type:** `struct` **Fields:**

* `claimedOut (uint256)`: Cached claimed amount for the source token.
* `claimedIn (uint256)`: Cached claimed amount for the destination token.

**Used by:**

* [LibTwoStepClaimMigration.start()](https://docs.cryptolegacy.app/documentation/functions-reference#start-ltscm1)
* [LibTwoStepClaimMigration.abandon()](https://docs.cryptolegacy.app/documentation/functions-reference#abandon-ltscm1)
* [LibTwoStepClaimMigration.\_applyPendingMigration()](https://docs.cryptolegacy.app/documentation/functions-reference#_applypendingmigration-ltscm1)

**Notes / Edge cases:** Stores beneficiary snapshots only while a delayed migration is active; entries are deleted during `complete` and `abandon`.

### PendingMigration (LTSCM1-S2)

**Type:** `struct` **Fields:**

* `active (bool)`: Whether a delayed migration is currently active.
* `tokenOut (address)`: Source token that left the contract first.
* `tokenIn (address)`: Destination token expected to arrive later.
* `amountOut (uint256)`: Source-token amount removed when the migration started.
* `outBalanceBefore (uint256)`: Source-token balance snapshot captured before the delayed flow began.

**Used by:**

* [LibTwoStepClaimMigration.isActive()](https://docs.cryptolegacy.app/documentation/functions-reference#isactive-ltscm1)
* [LibTwoStepClaimMigration.getPendingTokens()](https://docs.cryptolegacy.app/documentation/functions-reference#getpendingtokens-ltscm1)
* [LibTwoStepClaimMigration.start()](https://docs.cryptolegacy.app/documentation/functions-reference#start-ltscm1)
* [LibTwoStepClaimMigration.complete()](https://docs.cryptolegacy.app/documentation/functions-reference#complete-ltscm1)
* [LibTwoStepClaimMigration.abandon()](https://docs.cryptolegacy.app/documentation/functions-reference#abandon-ltscm1)
* [LibTwoStepClaimMigration.\_applyPendingMigration()](https://docs.cryptolegacy.app/documentation/functions-reference#_applypendingmigration-ltscm1)

**Notes / Edge cases:** Holds only one pending migration at a time; callers must keep any protocol-specific identifiers elsewhere.

### PendingMigrationStorage (LTSCM1-S3)

**Type:** `struct` **Fields:**

* `pending (PendingMigration)`: Active pending-migration record.
* `cachedClaimsByBeneficiary (mapping (bytes32 => CachedClaims))`: Cached claim snapshots keyed by beneficiary hash.
* `cachedBeneficiaryHashes (bytes32[])`: Beneficiary order preserved for completion/abandon sweeps.

**Used by:**

* [LibTwoStepClaimMigration.isActive()](https://docs.cryptolegacy.app/documentation/functions-reference#isactive-ltscm1)
* [LibTwoStepClaimMigration.getPendingTokens()](https://docs.cryptolegacy.app/documentation/functions-reference#getpendingtokens-ltscm1)
* [LibTwoStepClaimMigration.start()](https://docs.cryptolegacy.app/documentation/functions-reference#start-ltscm1)
* [LibTwoStepClaimMigration.complete()](https://docs.cryptolegacy.app/documentation/functions-reference#complete-ltscm1)
* [LibTwoStepClaimMigration.abandon()](https://docs.cryptolegacy.app/documentation/functions-reference#abandon-ltscm1)
* [LibTwoStepClaimMigration.\_applyPendingMigration()](https://docs.cryptolegacy.app/documentation/functions-reference#_applypendingmigration-ltscm1)

**Notes / Edge cases:** Encapsulates both the active migration header and the beneficiary-level cached snapshots required to restore or finalize delayed migrations.

## LibCreate3 (LC31)

### PROXY\_CHILD\_BYTECODE (LC31-D1)

**Data Type:** `bytes` **Visibility / Mutability:** internal, constant **Storage Location:** inlined constant **Description:** Bytecode for the CREATE3 proxy child contract.

**Modified by:** None

**Read by:**

* [LibCreate3.create3()](https://docs.cryptolegacy.app/documentation/functions-reference#create3bytes32bytes-lc31)
* [LibCreate3.create3()](https://docs.cryptolegacy.app/documentation/functions-reference#create3bytes32bytesuint256-lc31)

### KECCAK256\_PROXY\_CHILD\_BYTECODE (LC31-D2)

**Data Type:** `bytes32` **Visibility / Mutability:** internal, constant **Storage Location:** inlined constant **Description:** Keccak256 hash of the CREATE3 proxy child bytecode.

**Modified by:** None

**Read by:**

* [LibCreate3.addressOf()](https://docs.cryptolegacy.app/documentation/functions-reference#addressof-lc31)

## LibCryptoLegacy (LCL1)

### SHARE\_BASE (LCL1-D1)

**Data Type:** `uint256` **Visibility / Mutability:** internal, constant **Storage Location:** inlined constant **Description:** Fixed 10,000 denominator for beneficiary-share and vesting-percentage calculations.

**Modified by:** None

**Read by:**

* [LibCryptoLegacy.\_transferFee()](https://docs.cryptolegacy.app/documentation/functions-reference#_transferfee-lcl1)
* [LibCryptoLegacy.\_getVestedAndClaimedAmount()](https://docs.cryptolegacy.app/documentation/functions-reference#_getvestedandclaimedamount-lcl1)

### MAX\_CHAINS\_ARRAY\_LENGTH (LCL1-D2)

**Data Type:** `uint256` **Visibility / Mutability:** internal, constant **Storage Location:** inlined constant **Description:** Maximum length for chain id arrays.

**Modified by:** None

**Read by:**

* [LibCryptoLegacy.\_checkFee()](https://docs.cryptolegacy.app/documentation/functions-reference#_checkfee-lcl1)

### BENEFICIARY\_SWITCH\_TIMELOCK\_DURATION (LCL1-D3)

**Data Type:** `uint64` **Visibility / Mutability:** internal, constant **Storage Location:** inlined constant **Description:** Timelock duration for beneficiary switching.

**Modified by:** None

**Read by:**

* [CryptoLegacyBasePlugin.beneficiarySwitch()](https://docs.cryptolegacy.app/documentation/functions-reference#beneficiaryswitch-clbp1)

### CLAIM\_FUNC\_FLAG (LCL1-D4)

**Data Type:** `uint8` **Visibility / Mutability:** internal, constant **Storage Location:** inlined constant **Description:** Flag value used for claim function disablement.

**Modified by:** None

**Read by:**

* [LibCryptoLegacy.\_checkDisabledFunc()](https://docs.cryptolegacy.app/documentation/functions-reference#_checkdisabledfunc-lcl1)
* [CryptoLegacyBasePlugin.beneficiaryClaim()](https://docs.cryptolegacy.app/documentation/functions-reference#beneficiaryclaim-clbp1)

### MAX\_GAS\_MULTIPLIER (LCL1-D5)

**Data Type:** `uint8` **Visibility / Mutability:** internal, constant **Storage Location:** inlined constant **Description:** Maximum gas multiplier allowed for selector-based gas estimates.

**Modified by:** None

**Read by:**

* [CryptoLegacyBasePlugin.setGasLimitMultiplier()](https://docs.cryptolegacy.app/documentation/functions-reference#setgaslimitmultiplier-clbp1)

### CRYPTO\_LEGACY\_STORAGE\_POSITION (LCL1-D6)

**Data Type:** `bytes32` **Visibility / Mutability:** internal, constant **Storage Location:** diamond storage slot **Description:** Storage slot identifier for CryptoLegacyStorage.

**Modified by:** None

**Read by:**

* [LibCryptoLegacy.getCryptoLegacyStorage()](https://docs.cryptolegacy.app/documentation/functions-reference#getcryptolegacystorage-lcl1)

### transferValueSelector (LCL1-D7)

**Data Type:** `bytes4` **Visibility / Mutability:** internal, constant **Storage Location:** inlined constant **Description:** Selector used for transfer value call gas estimation.

**Modified by:** None

**Read by:**

* [LibCryptoLegacy.\_sendFeeByTransfer()](https://docs.cryptolegacy.app/documentation/functions-reference#_sendfeebytransfer-lcl1)
* [LibCryptoLegacy.\_gasBySelector()](https://docs.cryptolegacy.app/documentation/functions-reference#_gasbyselector-lcl1)

### lockNftSelector (LCL1-D8)

**Data Type:** `bytes4` **Visibility / Mutability:** internal, constant **Storage Location:** inlined constant **Description:** Selector used for lifetime NFT lock call gas estimation.

**Modified by:** None

**Read by:**

* [LibCryptoLegacy.\_checkFee()](https://docs.cryptolegacy.app/documentation/functions-reference#_checkfee-lcl1)
* [LibCryptoLegacy.\_gasBySelector()](https://docs.cryptolegacy.app/documentation/functions-reference#_gasbyselector-lcl1)

## LibCryptoLegacyDeploy (LCLD1)

**No tracked data items in this contract/library.**

## LibCryptoLegacyPlugins (LCLP1)

**No tracked data items in this contract/library.**

## LibDiamond (LD1)

### DIAMOND\_STORAGE\_POSITION (LD1-D1)

**Data Type:** `bytes32` **Visibility / Mutability:** none, constant **Storage Location:** diamond storage slot **Description:** Storage slot identifier for DiamondStorage.

**Modified by:** None

**Read by:**

* [LibDiamond.diamondStorage()](https://docs.cryptolegacy.app/documentation/functions-reference#diamondstorage-ld1)

### FacetAddressAndPosition (LD1-S1)

**Type:** `struct` **Fields:**

* `facetAddress (address)`: Facet address.
* `functionSelectorPosition (uint96)`: Selector position within the facet selector array.

**Used by:**

* [LibDiamond.diamondStorage()](https://docs.cryptolegacy.app/documentation/functions-reference#diamondstorage-ld1)
* [DiamondLoupeFacet.facets()](https://docs.cryptolegacy.app/documentation/functions-reference#facets-dlf1)

**Notes / Edge cases:** None

### FacetFunctionSelectors (LD1-S2)

**Type:** `struct` **Fields:**

* `functionSelectors (bytes4[])`: Selector list for the facet.
* `facetAddressPosition (uint256)`: Position of the facet address in the facet list.

**Used by:**

* [LibDiamond.diamondStorage()](https://docs.cryptolegacy.app/documentation/functions-reference#diamondstorage-ld1)
* [DiamondLoupeFacet.facetFunctionSelectors()](https://docs.cryptolegacy.app/documentation/functions-reference#facetfunctionselectors-dlf1)

**Notes / Edge cases:** None

### DiamondStorage (LD1-S3)

**Type:** `struct` **Fields:**

* `selectorToFacetAndPosition (mapping(bytes4 => FacetAddressAndPosition))`: Selector to facet mapping.
* `facetFunctionSelectors (mapping(address => FacetFunctionSelectors))`: Facet to selectors mapping.
* `facetAddresses (address[])`: List of facet addresses.
* `supportedInterfaces (mapping(bytes4 => bool))`: ERC165 interface support mapping.
* `contractOwner (address)`: Diamond owner address.

**Used by:**

* [LibDiamond.diamondStorage()](https://docs.cryptolegacy.app/documentation/functions-reference#diamondstorage-ld1)
* [DiamondLoupeFacet.facets()](https://docs.cryptolegacy.app/documentation/functions-reference#facets-dlf1)
* [DiamondLoupeFacet.facetAddresses()](https://docs.cryptolegacy.app/documentation/functions-reference#facetaddresses-dlf1)
* [DiamondLoupeFacet.facetAddress()](https://docs.cryptolegacy.app/documentation/functions-reference#facetaddress-dlf1)

**Notes / Edge cases:** None

## LibSafeMinimalBeneficiaryMultisig (LSMB1)

**No tracked data items in this contract/library.**

## LibSafeMinimalMultisig (LSM1)

**No tracked data items in this contract/library.**

## LibTrustedGuardiansPlugin (LTGP1)

### PLUGIN\_POSITION (LTGP1-D1)

**Data Type:** `bytes32` **Visibility / Mutability:** internal, constant **Storage Location:** diamond storage slot **Description:** Storage slot identifier for TrustedGuardians plugin storage.

**Modified by:** None

**Read by:**

* [LibTrustedGuardiansPlugin.getPluginStorage()](https://docs.cryptolegacy.app/documentation/functions-reference#getpluginstorage-ltgp1)

## BeneficiaryAaveV3SupplyPlugin (BALP1)

### PLUGIN\_MULTISIG\_POSITION (BALP1-D1)

**Data Type:** `bytes32` **Visibility / Mutability:** public, constant **Storage Location:** diamond storage slot **Description:** Storage slot identifier for the Aave beneficiary-plugin multisig storage.

**Modified by:** None

**Read by:**

* [BeneficiaryAaveV3SupplyPlugin.getPluginMultisigStorage()](https://docs.cryptolegacy.app/documentation/functions-reference#getpluginmultisigstorage-balp1)

### POOL (BALP1-D2)

**Data Type:** `address` **Visibility / Mutability:** public, immutable **Storage Location:** inlined immutable **Description:** Aave V3 Pool address used for supply and withdrawal operations.

**Modified by:**

* [BeneficiaryAaveV3SupplyPlugin.constructor()](https://docs.cryptolegacy.app/documentation/functions-reference#constructor-balp1)

**Read by:**

* [BeneficiaryAaveV3SupplyPlugin.baavesSupply()](https://docs.cryptolegacy.app/documentation/functions-reference#baavessupply-balp1)
* [BeneficiaryAaveV3SupplyPlugin.baavesWithdraw()](https://docs.cryptolegacy.app/documentation/functions-reference#baaveswithdraw-balp1)

### POOL\_DATA\_PROVIDER (BALP1-D3)

**Data Type:** `address` **Visibility / Mutability:** public, immutable **Storage Location:** inlined immutable **Description:** PoolDataProvider address used to resolve the reserve's aToken address.

**Modified by:**

* [BeneficiaryAaveV3SupplyPlugin.constructor()](https://docs.cryptolegacy.app/documentation/functions-reference#constructor-balp1)

**Read by:**

* [BeneficiaryAaveV3SupplyPlugin.\_getAToken()](https://docs.cryptolegacy.app/documentation/functions-reference#_getatoken-balp1)

### STATA\_TOKEN\_FACTORY (BALP1-D4)

**Data Type:** `address` **Visibility / Mutability:** public, immutable **Storage Location:** inlined immutable **Description:** StataToken factory used to resolve the wrapper for a given reserve asset.

**Modified by:**

* [BeneficiaryAaveV3SupplyPlugin.constructor()](https://docs.cryptolegacy.app/documentation/functions-reference#constructor-balp1)

**Read by:**

* [BeneficiaryAaveV3SupplyPlugin.\_getStataToken()](https://docs.cryptolegacy.app/documentation/functions-reference#_getstatatoken-balp1)

### DEFAULT\_REFERRAL\_CODE (BALP1-D5)

**Data Type:** `uint16` **Visibility / Mutability:** public, immutable **Storage Location:** inlined immutable **Description:** Default Aave referral code used when `baavesSupply()` receives `0` as the requested referral code.

**Modified by:**

* [BeneficiaryAaveV3SupplyPlugin.constructor()](https://docs.cryptolegacy.app/documentation/functions-reference#constructor-balp1)

**Read by:**

* [BeneficiaryAaveV3SupplyPlugin.baavesSupply()](https://docs.cryptolegacy.app/documentation/functions-reference#baavessupply-balp1)

## BeneficiaryLidoStakingPlugin (BLSP1)

### LidoWithdrawalStorage (BLSP1-S1)

**Type:** `struct` **Fields:**

* `pendingRequestIds (uint256[])`: Withdrawal-queue request IDs waiting to be claimed or abandoned.

**Used by:**

* [BeneficiaryLidoStakingPlugin.getLidoWithdrawalStorage()](https://docs.cryptolegacy.app/documentation/functions-reference#getlidowithdrawalstorage-blsp1)
* [BeneficiaryLidoStakingPlugin.blsLidoGetPendingRequestIds()](https://docs.cryptolegacy.app/documentation/functions-reference#blslidogetpendingrequestids-blsp1)
* [BeneficiaryLidoStakingPlugin.blsLidoClaimWithdrawals()](https://docs.cryptolegacy.app/documentation/functions-reference#blslidoclaimwithdrawals-blsp1)
* [BeneficiaryLidoStakingPlugin.\_storeLidoRequestIds()](https://docs.cryptolegacy.app/documentation/functions-reference#_storelidorequestids-blsp1)

**Notes / Edge cases:** Cleared after successful claims and when `blsLidoAbandonMigration()` abandons the pending migration.

### BeneficiarySwitchGuardStorage (BLSP1-S2)

**Type:** `struct` **Fields:**

* `active (bool)`: Whether beneficiary switching is currently frozen.
* `snapshotOriginalHashes (bytes32[])`: Original beneficiary hashes captured before the guard was activated.
* `timelockBeforeByOriginal (mapping (bytes32 => uint64))`: Timelocks that must be restored after the pending migration completes or is abandoned.

**Used by:**

* [BeneficiaryLidoStakingPlugin.getBeneficiarySwitchGuardStorage()](https://docs.cryptolegacy.app/documentation/functions-reference#getbeneficiaryswitchguardstorage-blsp1)
* [BeneficiaryLidoStakingPlugin.\_activateBeneficiarySwitchGuard()](https://docs.cryptolegacy.app/documentation/functions-reference#_activatebeneficiaryswitchguard-blsp1)
* [BeneficiaryLidoStakingPlugin.\_releaseBeneficiarySwitchGuard()](https://docs.cryptolegacy.app/documentation/functions-reference#_releasebeneficiaryswitchguard-blsp1)

**Notes / Edge cases:** While active, beneficiary-switch timelocks are temporarily set to `type(uint64).max` to block switching during pending migrations.

### PLUGIN\_MULTISIG\_POSITION (BLSP1-D1)

**Data Type:** `bytes32` **Visibility / Mutability:** public, constant **Storage Location:** diamond storage slot **Description:** Storage slot identifier for the Lido beneficiary-plugin multisig storage.

**Modified by:** None

**Read by:**

* [BeneficiaryLidoStakingPlugin.getPluginMultisigStorage()](https://docs.cryptolegacy.app/documentation/functions-reference#getpluginmultisigstorage-blsp1)

### PLUGIN\_PENDING\_MIGRATION\_POSITION (BLSP1-D2)

**Data Type:** `bytes32` **Visibility / Mutability:** public, constant **Storage Location:** diamond storage slot **Description:** Storage slot identifier for the plugin-local pending-migration storage.

**Modified by:** None

**Read by:**

* [BeneficiaryLidoStakingPlugin.getPendingMigrationStorage()](https://docs.cryptolegacy.app/documentation/functions-reference#getpendingmigrationstorage-blsp1)

### PLUGIN\_LIDO\_WITHDRAWAL\_POSITION (BLSP1-D3)

**Data Type:** `bytes32` **Visibility / Mutability:** public, constant **Storage Location:** diamond storage slot **Description:** Storage slot identifier for pending Lido withdrawal request IDs.

**Modified by:** None

**Read by:**

* [BeneficiaryLidoStakingPlugin.getLidoWithdrawalStorage()](https://docs.cryptolegacy.app/documentation/functions-reference#getlidowithdrawalstorage-blsp1)

### PLUGIN\_BENEFICIARY\_SWITCH\_GUARD\_POSITION (BLSP1-D4)

**Data Type:** `bytes32` **Visibility / Mutability:** public, constant **Storage Location:** diamond storage slot **Description:** Storage slot identifier for the temporary beneficiary-switch guard used during two-step migrations.

**Modified by:** None

**Read by:**

* [BeneficiaryLidoStakingPlugin.getBeneficiarySwitchGuardStorage()](https://docs.cryptolegacy.app/documentation/functions-reference#getbeneficiaryswitchguardstorage-blsp1)

### WETH (BLSP1-D5)

**Data Type:** `address` **Visibility / Mutability:** public, constant **Storage Location:** inlined constant **Description:** Canonical WETH token address used before unwrapping and after successful claim wrapping.

**Modified by:** None

**Read by:**

* [BeneficiaryLidoStakingPlugin.blsLidoStakeWethToStEth()](https://docs.cryptolegacy.app/documentation/functions-reference#blslidostakewethtosteth-blsp1)
* [BeneficiaryLidoStakingPlugin.blsLidoWrapWethToWstEth()](https://docs.cryptolegacy.app/documentation/functions-reference#blslidowrapwethtowsteth-blsp1)
* [BeneficiaryLidoStakingPlugin.blsLidoRequestStEthWithdrawal()](https://docs.cryptolegacy.app/documentation/functions-reference#blslidorequeststethwithdrawal-blsp1)
* [BeneficiaryLidoStakingPlugin.blsLidoRequestWstEthWithdrawal()](https://docs.cryptolegacy.app/documentation/functions-reference#blslidorequestwstethwithdrawal-blsp1)
* [BeneficiaryLidoStakingPlugin.blsLidoClaimWithdrawals()](https://docs.cryptolegacy.app/documentation/functions-reference#blslidoclaimwithdrawals-blsp1)
* [BeneficiaryLidoStakingPlugin.blsLidoUnsafeClaimWithdrawals()](https://docs.cryptolegacy.app/documentation/functions-reference#blslidounsafeclaimwithdrawals-blsp1)

### stETH (BLSP1-D6)

**Data Type:** `address` **Visibility / Mutability:** public, constant **Storage Location:** inlined constant **Description:** Canonical stETH token address used for staking, withdrawal requests, and Lido-side claim migration.

**Modified by:** None

**Read by:**

* [BeneficiaryLidoStakingPlugin.blsLidoStakeWethToStEth()](https://docs.cryptolegacy.app/documentation/functions-reference#blslidostakewethtosteth-blsp1)
* [BeneficiaryLidoStakingPlugin.blsLidoRequestStEthWithdrawal()](https://docs.cryptolegacy.app/documentation/functions-reference#blslidorequeststethwithdrawal-blsp1)
* [BeneficiaryLidoStakingPlugin.blsLidoWrapStEthToWstEth()](https://docs.cryptolegacy.app/documentation/functions-reference#blslidowrapstethtowsteth-blsp1)
* [BeneficiaryLidoStakingPlugin.blsLidoUnwrapWstEthToStEth()](https://docs.cryptolegacy.app/documentation/functions-reference#blslidounwrapwstethtosteth-blsp1)

### wstETH (BLSP1-D7)

**Data Type:** `address` **Visibility / Mutability:** public, constant **Storage Location:** inlined constant **Description:** Canonical wrapped-stETH token address used for direct wrapping, unwrapping, and withdrawal requests.

**Modified by:** None

**Read by:**

* [BeneficiaryLidoStakingPlugin.blsLidoWrapWethToWstEth()](https://docs.cryptolegacy.app/documentation/functions-reference#blslidowrapwethtowsteth-blsp1)
* [BeneficiaryLidoStakingPlugin.blsLidoRequestWstEthWithdrawal()](https://docs.cryptolegacy.app/documentation/functions-reference#blslidorequestwstethwithdrawal-blsp1)
* [BeneficiaryLidoStakingPlugin.blsLidoWrapStEthToWstEth()](https://docs.cryptolegacy.app/documentation/functions-reference#blslidowrapstethtowsteth-blsp1)
* [BeneficiaryLidoStakingPlugin.blsLidoUnwrapWstEthToStEth()](https://docs.cryptolegacy.app/documentation/functions-reference#blslidounwrapwstethtosteth-blsp1)

### LIDO\_WITHDRAWAL\_QUEUE (BLSP1-D8)

**Data Type:** `address` **Visibility / Mutability:** public, constant **Storage Location:** inlined constant **Description:** Lido withdrawal-queue address used to request and claim finalized withdrawals.

**Modified by:** None

**Read by:**

* [BeneficiaryLidoStakingPlugin.blsLidoRequestStEthWithdrawal()](https://docs.cryptolegacy.app/documentation/functions-reference#blslidorequeststethwithdrawal-blsp1)
* [BeneficiaryLidoStakingPlugin.blsLidoRequestWstEthWithdrawal()](https://docs.cryptolegacy.app/documentation/functions-reference#blslidorequestwstethwithdrawal-blsp1)
* [BeneficiaryLidoStakingPlugin.blsLidoClaimWithdrawals()](https://docs.cryptolegacy.app/documentation/functions-reference#blslidoclaimwithdrawals-blsp1)
* [BeneficiaryLidoStakingPlugin.blsLidoUnsafeClaimWithdrawals()](https://docs.cryptolegacy.app/documentation/functions-reference#blslidounsafeclaimwithdrawals-blsp1)

### WETH\_UNWRAP (BLSP1-D9)

**Data Type:** `address` **Visibility / Mutability:** public, immutable **Storage Location:** inlined immutable **Description:** Helper contract address used to unwrap WETH into native ETH before Lido-side operations.

**Modified by:**

* [BeneficiaryLidoStakingPlugin.constructor()](https://docs.cryptolegacy.app/documentation/functions-reference#constructor-blsp1)

**Read by:**

* [BeneficiaryLidoStakingPlugin.blsLidoStakeWethToStEth()](https://docs.cryptolegacy.app/documentation/functions-reference#blslidostakewethtosteth-blsp1)
* [BeneficiaryLidoStakingPlugin.blsLidoWrapWethToWstEth()](https://docs.cryptolegacy.app/documentation/functions-reference#blslidowrapwethtowsteth-blsp1)

### LIDO\_REFERRAL (BLSP1-D10)

**Data Type:** `address` **Visibility / Mutability:** private, constant **Storage Location:** inlined constant **Description:** Default zero-address referral used when the staking caller does not provide a custom Lido referral.

**Modified by:** None

**Read by:**

* [BeneficiaryLidoStakingPlugin.blsLidoStakeWethToStEth()](https://docs.cryptolegacy.app/documentation/functions-reference#blslidostakewethtosteth-blsp1)

## BeneficiaryPluginAddRights (BPAR1)

### PLUGIN\_MULTISIG\_POSITION (BPAR1-D1)

**Data Type:** `bytes32` **Visibility / Mutability:** public, constant **Storage Location:** diamond storage slot **Description:** Storage slot identifier for beneficiary add-rights multisig storage.

**Modified by:** None

**Read by:**

* [BeneficiaryPluginAddRights.getPluginMultisigStorage()](https://docs.cryptolegacy.app/documentation/functions-reference#getpluginmultisigstorage-bpar1)

## BeneficiaryUniswapV4SwapPlugin (BU4SP1)

### PoolKey (BU4SP1-S1)

**Type:** `struct` **Fields:**

* `currency0 (address)`: First currency address in the selected Uniswap V4 pool.
* `currency1 (address)`: Second currency address in the selected Uniswap V4 pool.
* `fee (uint24)`: Pool fee tier.
* `tickSpacing (int24)`: Tick spacing configured for the pool.
* `hooks (address)`: Hook contract address for the pool.

**Used by:**

* [BeneficiaryUniswapV4SwapPlugin.bunisSwapExactInputSingle()](https://docs.cryptolegacy.app/documentation/functions-reference#bunisswapexactinputsingle-bu4sp1)
* [BeneficiaryUniswapV4SwapPlugin.\_executeExactInputSingleRouter()](https://docs.cryptolegacy.app/documentation/functions-reference#_executeexactinputsinglerouter-bu4sp1)

**Notes / Edge cases:** None

### PathKey (BU4SP1-S2)

**Type:** `struct` **Fields:**

* `intermediateCurrency (address)`: Currency received after this hop.
* `fee (uint24)`: Fee tier for this hop.
* `tickSpacing (int24)`: Tick spacing configured for this hop's pool.
* `hooks (address)`: Hook contract address for this hop.
* `hookData (bytes)`: Hook payload forwarded to the Universal Router.

**Used by:**

* [BeneficiaryUniswapV4SwapPlugin.bunisSwapExactInput()](https://docs.cryptolegacy.app/documentation/functions-reference#bunisswapexactinput-bu4sp1)
* [BeneficiaryUniswapV4SwapPlugin.\_executeExactInputRouter()](https://docs.cryptolegacy.app/documentation/functions-reference#_executeexactinputrouter-bu4sp1)

**Notes / Edge cases:** None

### ExactInputSingleParams (BU4SP1-S3)

**Type:** `struct` **Fields:**

* `poolKey (PoolKey)`: Single-hop pool definition.
* `zeroForOne (bool)`: Swap direction flag.
* `amountIn (uint128)`: Exact input amount.
* `amountOutMinimum (uint128)`: Minimum output expected from the swap.
* `hookData (bytes)`: Arbitrary hook payload passed to the router.

**Used by:**

* [BeneficiaryUniswapV4SwapPlugin.\_executeExactInputSingleRouter()](https://docs.cryptolegacy.app/documentation/functions-reference#_executeexactinputsinglerouter-bu4sp1)

**Notes / Edge cases:** None

### ExactInputParams (BU4SP1-S4)

**Type:** `struct` **Fields:**

* `currencyIn (address)`: Input currency for the first hop.
* `path (PathKey[])`: Hop-by-hop route description.
* `maxHopSlippage (uint256[])`: Optional hop-level slippage caps.
* `amountIn (uint128)`: Exact input amount.
* `amountOutMinimum (uint128)`: Minimum output expected after the full route.

**Used by:**

* [BeneficiaryUniswapV4SwapPlugin.\_executeExactInputRouter()](https://docs.cryptolegacy.app/documentation/functions-reference#_executeexactinputrouter-bu4sp1)

**Notes / Edge cases:** The live implementation currently initializes `maxHopSlippage` as an empty array.

### PLUGIN\_MULTISIG\_POSITION (BU4SP1-D1)

**Data Type:** `bytes32` **Visibility / Mutability:** public, constant **Storage Location:** diamond storage slot **Description:** Storage slot identifier for the Uniswap V4 beneficiary-plugin multisig storage.

**Modified by:** None

**Read by:**

* [BeneficiaryUniswapV4SwapPlugin.getPluginMultisigStorage()](https://docs.cryptolegacy.app/documentation/functions-reference#getpluginmultisigstorage-bu4sp1)

### V4\_SWAP (BU4SP1-D2)

**Data Type:** `uint8` **Visibility / Mutability:** private, constant **Storage Location:** inlined constant **Description:** Universal Router command byte that enters the Uniswap V4 action dispatcher.

**Modified by:** None

**Read by:**

* [BeneficiaryUniswapV4SwapPlugin.\_executeExactInputSingleRouter()](https://docs.cryptolegacy.app/documentation/functions-reference#_executeexactinputsinglerouter-bu4sp1)
* [BeneficiaryUniswapV4SwapPlugin.\_executeExactInputRouter()](https://docs.cryptolegacy.app/documentation/functions-reference#_executeexactinputrouter-bu4sp1)

### SWAP\_EXACT\_IN\_SINGLE (BU4SP1-D3)

**Data Type:** `uint8` **Visibility / Mutability:** private, constant **Storage Location:** inlined constant **Description:** Universal Router action byte for the single-hop exact-input swap flow.

**Modified by:** None

**Read by:**

* [BeneficiaryUniswapV4SwapPlugin.\_executeExactInputSingleRouter()](https://docs.cryptolegacy.app/documentation/functions-reference#_executeexactinputsinglerouter-bu4sp1)

### SWAP\_EXACT\_IN (BU4SP1-D4)

**Data Type:** `uint8` **Visibility / Mutability:** private, constant **Storage Location:** inlined constant **Description:** Universal Router action byte for the multi-hop exact-input swap flow.

**Modified by:** None

**Read by:**

* [BeneficiaryUniswapV4SwapPlugin.\_executeExactInputRouter()](https://docs.cryptolegacy.app/documentation/functions-reference#_executeexactinputrouter-bu4sp1)

### SETTLE\_ALL (BU4SP1-D5)

**Data Type:** `uint8` **Visibility / Mutability:** private, constant **Storage Location:** inlined constant **Description:** Universal Router action byte that settles all inputs before taking swap outputs.

**Modified by:** None

**Read by:**

* [BeneficiaryUniswapV4SwapPlugin.\_executeExactInputSingleRouter()](https://docs.cryptolegacy.app/documentation/functions-reference#_executeexactinputsinglerouter-bu4sp1)
* [BeneficiaryUniswapV4SwapPlugin.\_executeExactInputRouter()](https://docs.cryptolegacy.app/documentation/functions-reference#_executeexactinputrouter-bu4sp1)

### TAKE\_ALL (BU4SP1-D6)

**Data Type:** `uint8` **Visibility / Mutability:** private, constant **Storage Location:** inlined constant **Description:** Universal Router action byte that withdraws the full swap proceeds after execution.

**Modified by:** None

**Read by:**

* [BeneficiaryUniswapV4SwapPlugin.\_executeExactInputSingleRouter()](https://docs.cryptolegacy.app/documentation/functions-reference#_executeexactinputsinglerouter-bu4sp1)
* [BeneficiaryUniswapV4SwapPlugin.\_executeExactInputRouter()](https://docs.cryptolegacy.app/documentation/functions-reference#_executeexactinputrouter-bu4sp1)

### UNIVERSAL\_ROUTER (BU4SP1-D7)

**Data Type:** `address` **Visibility / Mutability:** public, immutable **Storage Location:** inlined immutable **Description:** Universal Router address used to execute encoded Uniswap V4 swap command sequences.

**Modified by:**

* [BeneficiaryUniswapV4SwapPlugin.constructor()](https://docs.cryptolegacy.app/documentation/functions-reference#constructor-bu4sp1)

**Read by:**

* [BeneficiaryUniswapV4SwapPlugin.bunisSwapExactInputSingle()](https://docs.cryptolegacy.app/documentation/functions-reference#bunisswapexactinputsingle-bu4sp1)
* [BeneficiaryUniswapV4SwapPlugin.bunisSwapExactInput()](https://docs.cryptolegacy.app/documentation/functions-reference#bunisswapexactinput-bu4sp1)
* [BeneficiaryUniswapV4SwapPlugin.\_executeExactInputSingleRouter()](https://docs.cryptolegacy.app/documentation/functions-reference#_executeexactinputsinglerouter-bu4sp1)
* [BeneficiaryUniswapV4SwapPlugin.\_executeExactInputRouter()](https://docs.cryptolegacy.app/documentation/functions-reference#_executeexactinputrouter-bu4sp1)

### PERMIT2 (BU4SP1-D8)

**Data Type:** `address` **Visibility / Mutability:** public, immutable **Storage Location:** inlined immutable **Description:** Permit2 contract address used to authorize the Universal Router to spend the plugin's tokens.

**Modified by:**

* [BeneficiaryUniswapV4SwapPlugin.constructor()](https://docs.cryptolegacy.app/documentation/functions-reference#constructor-bu4sp1)

**Read by:**

* [BeneficiaryUniswapV4SwapPlugin.bunisSwapExactInputSingle()](https://docs.cryptolegacy.app/documentation/functions-reference#bunisswapexactinputsingle-bu4sp1)
* [BeneficiaryUniswapV4SwapPlugin.bunisSwapExactInput()](https://docs.cryptolegacy.app/documentation/functions-reference#bunisswapexactinput-bu4sp1)

## CryptoLegacyBasePlugin (CLBP1)

**No tracked data items in this contract/library.**

## LegacyRecoveryPlugin (LRP1)

### PLUGIN\_MULTISIG\_POSITION (LRP1-D1)

**Data Type:** `bytes32` **Visibility / Mutability:** public, constant **Storage Location:** diamond storage slot **Description:** Storage slot identifier for legacy recovery multisig storage.

**Modified by:** None

**Read by:**

* [LegacyRecoveryPlugin.getPluginMultisigStorage()](https://docs.cryptolegacy.app/documentation/functions-reference#getpluginmultisigstorage-lrp1)

## LensPlugin (LP1)

**No tracked data items in this contract/library.**

## NftLegacyPlugin (NLP1)

### PLUGIN\_POSITION (NLP1-D1)

**Data Type:** `bytes32` **Visibility / Mutability:** public, constant **Storage Location:** diamond storage slot **Description:** Storage slot identifier for NFT legacy plugin storage.

**Modified by:** None

**Read by:**

* [NftLegacyPlugin.getPluginStorage()](https://docs.cryptolegacy.app/documentation/functions-reference#getpluginstorage-nlp1)

### NftBeneficiary (NLP1-S1)

**Type:** `struct` **Fields:**

* `addressHash (bytes32)`: Beneficiary address hash.
* `claimDelay (uint64)`: Claim delay duration.

**Used by:**

* [NftLegacyPlugin.setNftBeneficiary()](https://docs.cryptolegacy.app/documentation/functions-reference#setnftbeneficiary-nlp1)
* [NftLegacyPlugin.beneficiaryClaimNft()](https://docs.cryptolegacy.app/documentation/functions-reference#beneficiaryclaimnft-nlp1)

**Notes / Edge cases:** None

### PluginStorage (NLP1-S2)

**Type:** `struct` **Fields:**

* `nftBeneficiary (mapping (address => mapping (uint256 => NftBeneficiary)))`: NFT beneficiary data by owner and token id.

**Used by:**

* [NftLegacyPlugin.getPluginStorage()](https://docs.cryptolegacy.app/documentation/functions-reference#getpluginstorage-nlp1)
* [NftLegacyPlugin.setNftBeneficiary()](https://docs.cryptolegacy.app/documentation/functions-reference#setnftbeneficiary-nlp1)
* [NftLegacyPlugin.beneficiaryClaimNft()](https://docs.cryptolegacy.app/documentation/functions-reference#beneficiaryclaimnft-nlp1)

**Notes / Edge cases:** None

## ReceiveEthPlugin (REP1)

### WETH (REP1-D1)

**Data Type:** `address` **Visibility / Mutability:** public, immutable **Storage Location:** inlined immutable **Description:** WETH contract address used when wrapping received ETH into the ERC-20 form.

**Modified by:**

* [ReceiveEthPlugin.constructor()](https://docs.cryptolegacy.app/documentation/functions-reference#constructor-rep1)

**Read by:**

* [ReceiveEthPlugin.wrapEthToWeth()](https://docs.cryptolegacy.app/documentation/functions-reference#wrapethtoweth-rep1)

## TrustedGuardiansPlugin (TGP1)

### DEFAULT\_GUARDIANS\_CHALLENGE\_TIMEOUT (TGP1-D1)

**Data Type:** `uint64` **Visibility / Mutability:** public, constant **Storage Location:** inlined constant **Description:** Default 30-day guardians challenge timeout returned when no custom timeout is configured.

**Modified by:** None

**Read by:**

* [TrustedGuardiansPlugin.\_getGuardiansChallengeTimeout()](https://docs.cryptolegacy.app/documentation/functions-reference#_getguardianschallengetimeout-tgp1)

### MAX\_GUARDIANS\_CHALLENGE\_TIMEOUT (TGP1-D2)

**Data Type:** `uint64` **Visibility / Mutability:** public, constant **Storage Location:** inlined constant **Description:** 30-day upper bound for configured guardians challenge timeouts.

**Modified by:** None

**Read by:**

* [TrustedGuardiansPlugin.\_setGuardiansConfig()](https://docs.cryptolegacy.app/documentation/functions-reference#_setguardiansconfig-tgp1)

## UpdateRolePlugin (URP1)

### PLUGIN\_POSITION (URP1-D1)

**Data Type:** `bytes32` **Visibility / Mutability:** public, constant **Storage Location:** diamond storage slot **Description:** Storage slot identifier for update role plugin storage.

**Modified by:** None

**Read by:**

* [UpdateRolePlugin.getPluginStorage()](https://docs.cryptolegacy.app/documentation/functions-reference#getpluginstorage-urp1)

### PluginStorage (URP1-S1)

**Type:** `struct` **Fields:**

* `updaters (EnumerableSet.AddressSet)`: Set of updater addresses.

**Used by:**

* [UpdateRolePlugin.getPluginStorage()](https://docs.cryptolegacy.app/documentation/functions-reference#getpluginstorage-urp1)
* [UpdateRolePlugin.getUpdaterList()](https://docs.cryptolegacy.app/documentation/functions-reference#getupdaterlist-urp1)
* [UpdateRolePlugin.isUpdater()](https://docs.cryptolegacy.app/documentation/functions-reference#isupdater-urp1)
* [UpdateRolePlugin.setUpdater()](https://docs.cryptolegacy.app/documentation/functions-reference#setupdater-urp1)
* [UpdateRolePlugin.updateByUpdater()](https://docs.cryptolegacy.app/documentation/functions-reference#updatebyupdater-urp1)

**Notes / Edge cases:** None

## Data Types Used

* `struct`
* `enum`
* `mapping`
* `EnumerableSet.AddressSet`
* `EnumerableSet.Bytes32Set`
* `EnumerableSet.UintSet`
* `address`
* `bool`
* `bytes`
* `bytes4`
* `bytes8`
* `bytes32`
* `string`
* `uint8`
* `uint16`
* `uint32`
* `uint64`
* `uint96`
* `uint128`
* `uint256`
* `address[]`
* `bytes32[]`
* `bytes4[]`
* `uint64[]`
* `uint256[]`


# Contracts Events

This document consolidates all known events from the primary CryptoLegacy contracts, along with their parameters and descriptions.

## Table of Contents

1. [BeneficiaryRegistry (BR1)](#beneficiaryregistry-br1)
2. [BuildManagerOwnable (BMO1)](#buildmanagerownable-bmo1)
3. [Create3Factory (C3F1)](#create3factory-c3f1)
   * [Create3Contract (C3F1)](#create3contract-c3f1)
4. [CryptoLegacy (CL1)](#cryptolegacy-cl1)
5. [CryptoLegacyBuildManager (CLBM1)](#cryptolegacybuildmanager-clbm1)
6. [CryptoLegacyDiamondBase (CLDB1)](#cryptolegacydiamondbase-cldb1)
7. [CryptoLegacyExternalLens (CLEXL1)](#cryptolegacyexternallens-clexl1)
8. [CryptoLegacyFactory (CLF1)](#cryptolegacyfactory-clf1)
9. [CryptoLegacyOwnable (CLO1)](#cryptolegacyownable-clo1)
10. [FeeRegistry (FR1)](#feeregistry-fr1)
11. [LegacyMessenger (LM1)](#legacymessenger-lm1)
12. [LifetimeNft (LN1)](#lifetimenft-ln1)
    * [SetBaseURI (LN1)](#setbaseuri-ln1)
    * [SetMinterOperator (LN1)](#setminteroperator-ln1)
13. [LockChainGate (LCG1)](#lockchaingate-lcg1)
14. [MultiPermit (MP1)](#multipermit-mp1)
15. [PluginsRegistry (PR1)](#pluginsregistry-pr1)
16. [ProxyBuilder (PB1)](#proxybuilder-pb1)
    * [Build (PB1)](#build-pb1)
    * [SetProxyAdmin (PB1)](#setproxyadmin-pb1)
17. [ProxyBuilderAdmin (PBA1)](#proxybuilderadmin-pba1)
18. [SignatureRoleTimelock (SRT1)](#signatureroletimelock-srt1)
19. [ArbSys (AS1)](#arbsys-as1)
20. [Flags (FLG1)](#flags-flg1)
21. [IAaveV3Pool (IAV3P1)](#iaavev3pool-iav3p1)
22. [IAaveV3PoolDataProvider (IAV3PDP1)](#iaavev3pooldataprovider-iav3pdp1)
23. [WethUnwrap (WU1)](#wethunwrap-wu1)
24. [IBeneficiaryRegistry (IBR1)](#ibeneficiaryregistry-ibr1)
    * [AddCryptoLegacyForBeneficiary (IBR1)](#addcryptolegacyforbeneficiary-ibr1)
    * [RemoveCryptoLegacyForBeneficiary (IBR1)](#removecryptolegacyforbeneficiary-ibr1)
    * [AddCryptoLegacyForGuardian (IBR1)](#addcryptolegacyforguardian-ibr1)
    * [RemoveCryptoLegacyForGuardian (IBR1)](#removecryptolegacyforguardian-ibr1)
    * [AddCryptoLegacyForRecovery (IBR1)](#addcryptolegacyforrecovery-ibr1)
    * [RemoveCryptoLegacyForRecovery (IBR1)](#removecryptolegacyforrecovery-ibr1)
    * [AddCryptoLegacyForOwner (IBR1)](#addcryptolegacyforowner-ibr1)
    * [RemoveCryptoLegacyForOwner (IBR1)](#removecryptolegacyforowner-ibr1)
25. [IBuildManagerOwnable (IBMO1)](#ibuildmanagerownable-ibmo1)
    * [AddBuildManager (IBMO1)](#addbuildmanager-ibmo1)
    * [RemoveBuildManager (IBMO1)](#removebuildmanager-ibmo1)
26. [ICallProxy (ICP1)](#icallproxy-icp1)
27. [ICryptoLegacy (ICL1)](#icryptolegacy-icl1)
    * [PauseSet (ICL1)](#pauseset-icl1)
    * [Update (ICL1)](#update-icl1)
    * [FeePaidByLifetime (ICL1)](#feepaidbylifetime-icl1)
    * [FeePaidByDefault (ICL1)](#feepaidbydefault-icl1)
    * [FeePaidByTransfer (ICL1)](#feepaidbytransfer-icl1)
    * [FeeSentToRefByTransfer (ICL1)](#feesenttorefbytransfer-icl1)
    * [BeneficiaryClaim (ICL1)](#beneficiaryclaim-icl1)
    * [BeneficiaryClaimAmountDecrease (ICL1)](#beneficiaryclaimamountdecrease-icl1)
    * [TransferTreasuryTokensToLegacy (ICL1)](#transfertreasurytokenstolegacy-icl1)
    * [TransferTokensFromLegacy (ICL1)](#transfertokensfromlegacy-icl1)
    * [SetGasLimitMultiplier (ICL1)](#setgaslimitmultiplier-icl1)
    * [AddFunctions (ICL1)](#addfunctions-icl1)
    * [RemoveFunctions (ICL1)](#removefunctions-icl1)
    * [SkipSendFeeByTransfer (ICL1)](#skipsendfeebytransfer-icl1)
    * [IsLifetimeNftLockedAndUpdateCatch (ICL1)](#islifetimenftlockedandupdatecatch-icl1)
    * [GetUpdateFeeCatch (ICL1)](#getupdatefeecatch-icl1)
    * [PayFeeCatch (ICL1)](#payfeecatch-icl1)
    * [SetCryptoLegacyOwnerCatch (ICL1)](#setcryptolegacyownercatch-icl1)
    * [SetCryptoLegacyBeneficiaryCatch (ICL1)](#setcryptolegacybeneficiarycatch-icl1)
    * [SetCryptoLegacyGuardianCatch (ICL1)](#setcryptolegacyguardiancatch-icl1)
    * [SetCryptoLegacyRecoveryAddressesCatch (ICL1)](#setcryptolegacyrecoveryaddressescatch-icl1)
    * [BeneficiaryRegistryCatch (ICL1)](#beneficiaryregistrycatch-icl1)
    * [BeneficiaryRegistryNotDefined (ICL1)](#beneficiaryregistrynotdefined-icl1)
28. [ICryptoLegacyBuildManager (ICLBM1)](#icryptolegacybuildmanager-iclbm1)
    * [CreateRef (ICLBM1)](#createref-iclbm1)
    * [CreateCustomRef (ICLBM1)](#createcustomref-iclbm1)
    * [SetCrossChainsRef (ICLBM1)](#setcrosschainsref-iclbm1)
    * [WithdrawFee (ICLBM1)](#withdrawfee-iclbm1)
    * [SetRegistries (ICLBM1)](#setregistries-iclbm1)
    * [SetFactory (ICLBM1)](#setfactory-iclbm1)
    * [SetSupplyLimit (ICLBM1)](#setsupplylimit-iclbm1)
    * [SetExternalLens (ICLBM1)](#setexternallens-iclbm1)
    * [PaidForMint (ICLBM1)](#paidformint-iclbm1)
    * [PaidForMultipleNft (ICLBM1)](#paidformultiplenft-iclbm1)
    * [Build (ICLBM1)](#build-iclbm1)
29. [ICryptoLegacyDiamondBase (ICLDB1)](#icryptolegacydiamondbase-icldb1)
    * [StaticCallCheck (ICLDB1)](#staticcallcheck-icldb1)
30. [ICryptoLegacyFactory (ICLF1)](#icryptolegacyfactory-iclf1)
    * [AddBuildOperator (ICLF1)](#addbuildoperator-iclf1)
    * [RemoveBuildOperator (ICLF1)](#removebuildoperator-iclf1)
31. [ICryptoLegacyLens (ICLL1)](#icryptolegacylens-icll1)
32. [ICryptoLegacyOwnable (ICLO1)](#icryptolegacyownable-iclo1)
    * [OwnershipTransferStarted (ICLO1)](#ownershiptransferstarted-iclo1)
    * [OwnershipTransferred (ICLO1)](#ownershiptransferred-iclo1)
33. [ICryptoLegacyPlugin (ICLP1)](#icryptolegacyplugin-iclp1)
34. [ICryptoLegacyUpdaterPlugin (ICLUP1)](#icryptolegacyupdaterplugin-iclup1)
    * [AddUpdater (ICLUP1)](#addupdater-iclup1)
    * [RemoveUpdater (ICLUP1)](#removeupdater-iclup1)
35. [IDeBridgeGate (IDBG1)](#idebridgegate-idbg1)
    * [Sent (IDBG1)](#sent-idbg1)
    * [Claimed (IDBG1)](#claimed-idbg1)
    * [PairAdded (IDBG1)](#pairadded-idbg1)
    * [MonitoringSendEvent (IDBG1)](#monitoringsendevent-idbg1)
    * [MonitoringClaimEvent (IDBG1)](#monitoringclaimevent-idbg1)
    * [ChainSupportUpdated (IDBG1)](#chainsupportupdated-idbg1)
    * [ChainsSupportUpdated (IDBG1)](#chainssupportupdated-idbg1)
    * [CallProxyUpdated (IDBG1)](#callproxyupdated-idbg1)
    * [AutoRequestExecuted (IDBG1)](#autorequestexecuted-idbg1)
    * [Blocked (IDBG1)](#blocked-idbg1)
    * [Unblocked (IDBG1)](#unblocked-idbg1)
    * [WithdrawnFee (IDBG1)](#withdrawnfee-idbg1)
    * [FixedNativeFeeUpdated (IDBG1)](#fixednativefeeupdated-idbg1)
    * [FixedNativeFeeAutoUpdated (IDBG1)](#fixednativefeeautoupdated-idbg1)
36. [IDiamondCut (IDC1)](#idiamondcut-idc1)
    * [DiamondCut (IDC1)](#diamondcut-idc1)
37. [IDiamondLoupe (IDL1)](#idiamondloupe-idl1)
38. [IFeeRegistry (IFR1)](#ifeeregistry-ifr1)
    * [AddCodeOperator (IFR1)](#addcodeoperator-ifr1)
    * [RemoveCodeOperator (IFR1)](#removecodeoperator-ifr1)
    * [SetDefaultPct (IFR1)](#setdefaultpct-ifr1)
    * [SetRefererSpecificPct (IFR1)](#setrefererspecificpct-ifr1)
    * [SetContractCaseFee (IFR1)](#setcontractcasefee-ifr1)
    * [TakeFee (IFR1)](#takefee-ifr1)
    * [SentFee (IFR1)](#sentfee-ifr1)
    * [AccumulateFee (IFR1)](#accumulatefee-ifr1)
    * [CreateCode (IFR1)](#createcode-ifr1)
    * [UpdateCode (IFR1)](#updatecode-ifr1)
    * [ChangeCode (IFR1)](#changecode-ifr1)
    * [ChangeRecipient (IFR1)](#changerecipient-ifr1)
    * [SetCrossChainsRef (IFR1)](#setcrosschainsref-ifr1)
    * [SetFeeBeneficiaries (IFR1)](#setfeebeneficiaries-ifr1)
    * [AddSupportedRefCodeInChain (IFR1)](#addsupportedrefcodeinchain-ifr1)
    * [RemoveSupportedRefCodeInChain (IFR1)](#removesupportedrefcodeinchain-ifr1)
    * [WithdrawFee (IFR1)](#withdrawfee-ifr1)
    * [WithdrawRefFee (IFR1)](#withdrawreffee-ifr1)
39. [ILockChainGate (ILCG1)](#ilockchaingate-ilcg1)
    * [AddLockOperator (ILCG1)](#addlockoperator-ilcg1)
    * [RemoveLockOperator (ILCG1)](#removelockoperator-ilcg1)
    * [SetDestinationChainContract (ILCG1)](#setdestinationchaincontract-ilcg1)
    * [SetSourceChainContract (ILCG1)](#setsourcechaincontract-ilcg1)
    * [SetDeBridgeGate (ILCG1)](#setdebridgegate-ilcg1)
    * [SetDeBridgeNativeFee (ILCG1)](#setdebridgenativefee-ilcg1)
    * [SetLockPeriodConfig (ILCG1)](#setlockperiodconfig-ilcg1)
    * [SendToChain (ILCG1)](#sendtochain-ilcg1)
    * [LockNft (ILCG1)](#locknft-ilcg1)
    * [UnlockNft (ILCG1)](#unlocknft-ilcg1)
    * [ApproveNft (ILCG1)](#approvenft-ilcg1)
    * [TransferNft (ILCG1)](#transfernft-ilcg1)
    * [LockToChain (ILCG1)](#locktochain-ilcg1)
    * [UpdateLockToChain (ILCG1)](#updatelocktochain-ilcg1)
    * [Update (ILCG1)](#update-ilcg1)
    * [UnlockFromChain (ILCG1)](#unlockfromchain-ilcg1)
    * [CrossLockNft (ILCG1)](#crosslocknft-ilcg1)
    * [CrossUnlockNft (ILCG1)](#crossunlocknft-ilcg1)
    * [CrossUpdateNftOwner (ILCG1)](#crossupdatenftowner-ilcg1)
    * [SetReferralCode (ILCG1)](#setreferralcode-ilcg1)
    * [SetCustomChainId (ILCG1)](#setcustomchainid-ilcg1)
40. [ILegacyMessenger (ILM1)](#ilegacymessenger-ilm1)
    * [LegacyMessage (ILM1)](#legacymessage-ilm1)
    * [LegacyMessageCheck (ILM1)](#legacymessagecheck-ilm1)
41. [ILido (ILD1)](#ilido-ild1)
42. [ILidoWithdrawalQueue (ILWQ1)](#ilidowithdrawalqueue-ilwq1)
43. [ILifetimeNft (ILN1)](#ilifetimenft-iln1)
44. [IPermit2 (IPM21)](#ipermit2-ipm21)
45. [IPluginsRegistry (IPR1)](#ipluginsregistry-ipr1)
    * [AddPlugin (IPR1)](#addplugin-ipr1)
    * [AddPluginDescription (IPR1)](#addplugindescription-ipr1)
    * [RemovePlugin (IPR1)](#removeplugin-ipr1)
46. [ISafeMinimalMultisig (ISM1)](#isafeminimalmultisig-ism1)
    * [CreateSafeMinimalMultisigProposal (ISM1)](#createsafeminimalmultisigproposal-ism1)
    * [CancelSafeMinimalMultisigProposal (ISM1)](#cancelsafeminimalmultisigproposal-ism1)
    * [ConfirmSafeMinimalMultisigProposal (ISM1)](#confirmsafeminimalmultisigproposal-ism1)
    * [ExecuteSafeMinimalMultisigProposal (ISM1)](#executesafeminimalmultisigproposal-ism1)
    * [SetVotersAndConfirmations (ISM1)](#setvotersandconfirmations-ism1)
    * [SetConfirmations (ISM1)](#setconfirmations-ism1)
    * [AddHeldEth (ISM1)](#addheldeth-ism1)
    * [WithdrawHeldEth (ISM1)](#withdrawheldeth-ism1)
47. [ISignatureRoleTimelock (ISRT1)](#isignatureroletimelock-isrt1)
    * [SetMaxExecutionPeriod (ISRT1)](#setmaxexecutionperiod-isrt1)
    * [AddRoleAccount (ISRT1)](#addroleaccount-isrt1)
    * [RemoveRoleAccount (ISRT1)](#removeroleaccount-isrt1)
    * [AddSignatureRole (ISRT1)](#addsignaturerole-isrt1)
    * [RemoveSignatureRole (ISRT1)](#removesignaturerole-isrt1)
    * [AddTarget (ISRT1)](#addtarget-isrt1)
    * [RemoveTarget (ISRT1)](#removetarget-isrt1)
    * [CallScheduled (ISRT1)](#callscheduled-isrt1)
    * [CallExecuted (ISRT1)](#callexecuted-isrt1)
    * [CallCanceled (ISRT1)](#callcanceled-isrt1)
48. [IStataToken (ISTA1)](#istatatoken-ista1)
49. [IStataTokenFactory (ISTF1)](#istatatokenfactory-istf1)
50. [ITrustedGuardiansPlugin (ITGP1)](#itrustedguardiansplugin-itgp1)
    * [SetGuardian (ITGP1)](#setguardian-itgp1)
    * [GuardiansVoteForDistribution (ITGP1)](#guardiansvotefordistribution-itgp1)
    * [GuardiansDistributionStartSet (ITGP1)](#guardiansdistributionstartset-itgp1)
    * [SetGuardiansConfig (ITGP1)](#setguardiansconfig-itgp1)
    * [ResetGuardiansVoting (ITGP1)](#resetguardiansvoting-itgp1)
    * [ClearGuardiansVoted (ITGP1)](#clearguardiansvoted-itgp1)
51. [DiamondLoupeFacet (DLF1)](#diamondloupefacet-dlf1)
52. [IUniversalRouter (IUR1)](#iuniversalrouter-iur1)
53. [IWETH (IWETH1)](#iweth-iweth1)
54. [IWstETH (IWSTETH1)](#iwsteth-iwsteth1)
55. [WethUnwrapIWETH (WUI1)](#wethunwrapiweth-wui1)
56. [LibCLUtils (LCLU1)](#libclutils-lclu1)
57. [LibClaimMigrationCore (LCMC1)](#libclaimmigrationcore-lcmc1)
58. [LibOneStepClaimMigration (LOSCM1)](#libonestepclaimmigration-loscm1)
59. [LibTwoStepClaimMigration (LTSCM1)](#libtwostepclaimmigration-ltscm1)
60. [LibCreate3 (LC31)](#libcreate3-lc31)
61. [LibCryptoLegacy (LCL1)](#libcryptolegacy-lcl1)
62. [LibCryptoLegacyDeploy (LCLD1)](#libcryptolegacydeploy-lcld1)
    * [CryptoLegacyCreation (LCLD1)](#cryptolegacycreation-lcld1)
63. [LibCryptoLegacyPlugins (LCLP1)](#libcryptolegacyplugins-lclp1)
64. [LibDiamond (LD1)](#libdiamond-ld1)
    * [OwnershipTransferred (LD1)](#ownershiptransferred-ld1)
    * [DiamondCut (LD1)](#diamondcut-ld1)
65. [LibSafeMinimalBeneficiaryMultisig (LSMB1)](#libsafeminimalbeneficiarymultisig-lsmb1)
66. [LibSafeMinimalMultisig (LSM1)](#libsafeminimalmultisig-lsm1)
67. [LibTrustedGuardiansPlugin (LTGP1)](#libtrustedguardiansplugin-ltgp1)
68. [BeneficiaryAaveV3SupplyPlugin (BALP1)](#beneficiaryaavev3supplyplugin-balp1)
    * [AaveSupply (BALP1)](#aavesupply-balp1)
    * [AaveWithdraw (BALP1)](#aavewithdraw-balp1)
    * [WrapATokenToStataToken (BALP1)](#wrapatokentostatatoken-balp1)
    * [UnwrapStataTokenToAToken (BALP1)](#unwrapstatatokentoatoken-balp1)
    * [DepositToStataToken (BALP1)](#deposittostatatoken-balp1)
    * [RedeemFromStataToken (BALP1)](#redeemfromstatatoken-balp1)
69. [BeneficiaryLidoStakingPlugin (BLSP1)](#beneficiarylidostakingplugin-blsp1)
    * [StakeWethToStEth (BLSP1)](#stakewethtosteth-blsp1)
    * [WrapWethToWstEth (BLSP1)](#wrapwethtowsteth-blsp1)
    * [RequestStEthWithdrawal (BLSP1)](#requeststethwithdrawal-blsp1)
    * [RequestWstEthWithdrawal (BLSP1)](#requestwstethwithdrawal-blsp1)
    * [ClaimWithdrawals (BLSP1)](#claimwithdrawals-blsp1)
    * [UnsafeClaimWithdrawals (BLSP1)](#unsafeclaimwithdrawals-blsp1)
    * [AbandonMigration (BLSP1)](#abandonmigration-blsp1)
70. [BeneficiaryPluginAddRights (BPAR1)](#beneficiarypluginaddrights-bpar1)
71. [BeneficiaryUniswapV4SwapPlugin (BU4SP1)](#beneficiaryuniswapv4swapplugin-bu4sp1)
    * [UniswapV4SwapExactInputSingle (BU4SP1)](#uniswapv4swapexactinputsingle-bu4sp1)
    * [UniswapV4SwapExactInput (BU4SP1)](#uniswapv4swapexactinput-bu4sp1)
72. [CryptoLegacyBasePlugin (CLBP1)](#cryptolegacybaseplugin-clbp1)
    * [SetBeneficiary (CLBP1)](#setbeneficiary-clbp1)
    * [SwitchBeneficiary (CLBP1)](#switchbeneficiary-clbp1)
    * [ChallengeInitiate (CLBP1)](#challengeinitiate-clbp1)
    * [BeneficiaryMessage (CLBP1)](#beneficiarymessage-clbp1)
    * [BeneficiaryMessageCheck (CLBP1)](#beneficiarymessagecheck-clbp1)
73. [LegacyRecoveryPlugin (LRP1)](#legacyrecoveryplugin-lrp1)
74. [LensPlugin (LP1)](#lensplugin-lp1)
75. [NftLegacyPlugin (NLP1)](#nftlegacyplugin-nlp1)
    * [SetNftBeneficiary (NLP1)](#setnftbeneficiary-nlp1)
    * [BeneficiaryClaimNft (NLP1)](#beneficiaryclaimnft-nlp1)
    * [TransferNftToCryptoLegacy (NLP1)](#transfernfttocryptolegacy-nlp1)
76. [ReceiveEthPlugin (REP1)](#receiveethplugin-rep1)
    * [WrapEthToWeth (REP1)](#wrapethtoweth-rep1)
77. [TrustedGuardiansPlugin (TGP1)](#trustedguardiansplugin-tgp1)
78. [UpdateRolePlugin (URP1)](#updateroleplugin-urp1)
79. [Parameter Types](#parameter-types)

## BeneficiaryRegistry (BR1)

**No events in this contract/library.**

## BuildManagerOwnable (BMO1)

**No events in this contract/library.**

## Create3Factory (C3F1)

### Create3Contract (C3F1)

**Parameters:**

* `contractAddress (address)`: Address of the contract deployed via CREATE3.

**Description:** Emitted after a successful CREATE3 deployment in `build`, providing the deployed contract address.

**Event Signature:** `Create3Contract(address contractAddress)`

**Emitted by:**

* [Create3Factory.build()](https://docs.cryptolegacy.app/documentation/functions-reference#build-c3f1)

**Notes / Edge cases:** None

## CryptoLegacy (CL1)

**No events in this contract/library.**

## CryptoLegacyBuildManager (CLBM1)

**No events in this contract/library.**

## CryptoLegacyDiamondBase (CLDB1)

**No events in this contract/library.**

## CryptoLegacyExternalLens (CLEXL1)

**No events in this contract/library.**

## CryptoLegacyFactory (CLF1)

**No events in this contract/library.**

## CryptoLegacyOwnable (CLO1)

**No events in this contract/library.**

## FeeRegistry (FR1)

**No events in this contract/library.**

## LegacyMessenger (LM1)

**No events in this contract/library.**

## LifetimeNft (LN1)

### SetBaseURI (LN1)

**Parameters:**

* `baseURI (string)`: New base URI prefix used by `tokenURI` for all LifetimeNft tokens.

**Description:** Emitted when the LifetimeNft base URI prefix is set or updated (during deployment or via the owner), signaling indexers to refresh token metadata URLs.

**Event Signature:** `SetBaseURI(string baseURI)`

**Emitted by:**

* [LifetimeNft.\_setBaseUri()](https://docs.cryptolegacy.app/documentation/functions-reference#_setbaseuri-ln1)

**Notes / Edge cases:** None

### SetMinterOperator (LN1)

**Parameters:**

* `minter (address, indexed)`: Address whose minting permission is being updated.
* `isActive (bool, indexed)`: `true` to grant minting rights, `false` to revoke them.

**Description:** Emitted when the owner grants or revokes an address’s ability to mint LifetimeNft tokens via the `minterOperator` mapping.

**Event Signature:** `SetMinterOperator(address indexed minter, bool indexed isActive)`

**Emitted by:**

* [LifetimeNft.setMinterOperator()](https://docs.cryptolegacy.app/documentation/functions-reference#setminteroperator-ln1)

**Notes / Edge cases:** None

## LockChainGate (LCG1)

**No events in this contract/library.**

## MultiPermit (MP1)

**No events in this contract/library.**

## PluginsRegistry (PR1)

**No events in this contract/library.**

## ProxyBuilder (PB1)

### Build (PB1)

**Parameters:**

* `proxy (address)`: Address of the newly deployed proxy contract.
* `implementation (address)`: Implementation address set in the new proxy.

**Description:** Emitted after `build` deploys a new `TransparentUpgradeableProxy` via CREATE3 and the address check succeeds.

**Event Signature:** `Build(address proxy, address implementation)`

**Emitted by:**

* [ProxyBuilder.build()](https://docs.cryptolegacy.app/documentation/functions-reference#build-pb1)

**Notes / Edge cases:** None

### SetProxyAdmin (PB1)

**Parameters:**

* `proxyAdmin (address)`: New ProxyAdmin address to manage newly created proxies.

**Description:** Emitted when the owner updates the `proxyAdmin` controller used by ProxyBuilder.

**Event Signature:** `SetProxyAdmin(address proxyAdmin)`

**Emitted by:**

* [ProxyBuilder.setProxyAdmin()](https://docs.cryptolegacy.app/documentation/functions-reference#setproxyadmin-pb1)

**Notes / Edge cases:** None

## ProxyBuilderAdmin (PBA1)

**No events in this contract/library.**

## SignatureRoleTimelock (SRT1)

**No events in this contract/library.**

## ArbSys (AS1)

**No events in this contract/library.**

## Flags (FLG1)

**No events in this contract/library.**

## IAaveV3Pool (IAV3P1)

**No events in this contract/library.**

## IAaveV3PoolDataProvider (IAV3PDP1)

**No events in this contract/library.**

## WethUnwrap (WU1)

**No events in this contract/library.**

## IBeneficiaryRegistry (IBR1)

### AddCryptoLegacyForBeneficiary (IBR1)

**Parameters:**

* `beneficiary (bytes32, indexed)`: Hash of the beneficiary identifier being linked.
* `cryptoLegacy (address, indexed)`: CryptoLegacy contract address added to the registry for this beneficiary.

**Description:** Emitted when the beneficiary registry adds a CryptoLegacy contract under a beneficiary hash via `IBeneficiaryRegistry`.

**Event Signature:** `AddCryptoLegacyForBeneficiary(bytes32 indexed beneficiary, address indexed cryptoLegacy)`

**Emitted by:**

* [BeneficiaryRegistry.setCryptoLegacyBeneficiary()](https://docs.cryptolegacy.app/documentation/functions-reference#setcryptolegacybeneficiary-br1)

**Notes / Edge cases:** Emitted even if `cryptoLegacy` was already linked to the hash, because `EnumerableSet.add` is idempotent and its return value is ignored.

### RemoveCryptoLegacyForBeneficiary (IBR1)

**Parameters:**

* `beneficiary (bytes32, indexed)`: Hash of the beneficiary identifier being unlinked.
* `cryptoLegacy (address, indexed)`: CryptoLegacy contract address removed from the registry for this beneficiary.

**Description:** Emitted when the beneficiary registry removes a CryptoLegacy contract from a beneficiary hash via `IBeneficiaryRegistry`.

**Event Signature:** `RemoveCryptoLegacyForBeneficiary(bytes32 indexed beneficiary, address indexed cryptoLegacy)`

**Emitted by:**

* [BeneficiaryRegistry.setCryptoLegacyBeneficiary()](https://docs.cryptolegacy.app/documentation/functions-reference#setcryptolegacybeneficiary-br1)

**Notes / Edge cases:** Emitted even if `cryptoLegacy` was not linked to the hash, because `EnumerableSet.remove` return value is ignored.

### AddCryptoLegacyForGuardian (IBR1)

**Parameters:**

* `guardian (bytes32, indexed)`: Hash of the guardian identifier being linked.
* `cryptoLegacy (address, indexed)`: CryptoLegacy contract address added to the registry for this guardian.

**Description:** Emitted when the beneficiary registry adds a CryptoLegacy contract under a guardian hash via `IBeneficiaryRegistry`.

**Event Signature:** `AddCryptoLegacyForGuardian(bytes32 indexed guardian, address indexed cryptoLegacy)`

**Emitted by:**

* [BeneficiaryRegistry.setCryptoLegacyGuardian()](https://docs.cryptolegacy.app/documentation/functions-reference#setcryptolegacyguardian-br1)

**Notes / Edge cases:** Emitted even if `cryptoLegacy` was already linked to the hash, because `EnumerableSet.add` is idempotent and its return value is ignored.

### RemoveCryptoLegacyForGuardian (IBR1)

**Parameters:**

* `guardian (bytes32, indexed)`: Hash of the guardian identifier being unlinked.
* `cryptoLegacy (address, indexed)`: CryptoLegacy contract address removed from the registry for this guardian.

**Description:** Emitted when the beneficiary registry removes a CryptoLegacy contract from a guardian hash via `IBeneficiaryRegistry`.

**Event Signature:** `RemoveCryptoLegacyForGuardian(bytes32 indexed guardian, address indexed cryptoLegacy)`

**Emitted by:**

* [BeneficiaryRegistry.setCryptoLegacyGuardian()](https://docs.cryptolegacy.app/documentation/functions-reference#setcryptolegacyguardian-br1)

**Notes / Edge cases:** Emitted even if `cryptoLegacy` was not linked to the hash, because `EnumerableSet.remove` return value is ignored.

### AddCryptoLegacyForRecovery (IBR1)

**Parameters:**

* `recovery (bytes32, indexed)`: Hash of the recovery identifier being linked.
* `cryptoLegacy (address, indexed)`: CryptoLegacy contract address added to the registry for this recovery.

**Description:** Emitted when the beneficiary registry adds a CryptoLegacy contract under a recovery hash via `IBeneficiaryRegistry`.

**Event Signature:** `AddCryptoLegacyForRecovery(bytes32 indexed recovery, address indexed cryptoLegacy)`

**Emitted by:**

* [BeneficiaryRegistry.setCryptoLegacyRecoveryAddresses()](https://docs.cryptolegacy.app/documentation/functions-reference#setcryptolegacyrecoveryaddresses-br1)

**Notes / Edge cases:** Emitted even if `cryptoLegacy` was already linked to the hash, because `EnumerableSet.add` is idempotent and its return value is ignored.

### RemoveCryptoLegacyForRecovery (IBR1)

**Parameters:**

* `recovery (bytes32, indexed)`: Hash of the recovery identifier being unlinked.
* `cryptoLegacy (address, indexed)`: CryptoLegacy contract address removed from the registry for this recovery.

**Description:** Emitted when the beneficiary registry removes a CryptoLegacy contract from a recovery hash via `IBeneficiaryRegistry`.

**Event Signature:** `RemoveCryptoLegacyForRecovery(bytes32 indexed recovery, address indexed cryptoLegacy)`

**Emitted by:**

* [BeneficiaryRegistry.setCryptoLegacyRecoveryAddresses()](https://docs.cryptolegacy.app/documentation/functions-reference#setcryptolegacyrecoveryaddresses-br1)

**Notes / Edge cases:** Emitted even if `cryptoLegacy` was not linked to the hash, because `EnumerableSet.remove` return value is ignored.

### AddCryptoLegacyForOwner (IBR1)

**Parameters:**

* `owner (bytes32, indexed)`: Hash of the owner identifier being linked.
* `cryptoLegacy (address, indexed)`: CryptoLegacy contract address added to the registry for this owner.

**Description:** Emitted when the beneficiary registry adds a CryptoLegacy contract under an owner hash via `IBeneficiaryRegistry`.

**Event Signature:** `AddCryptoLegacyForOwner(bytes32 indexed owner, address indexed cryptoLegacy)`

**Emitted by:**

* [BeneficiaryRegistry.setCryptoLegacyOwner()](https://docs.cryptolegacy.app/documentation/functions-reference#setcryptolegacyowner-br1)

**Notes / Edge cases:** Emitted even if `cryptoLegacy` was already linked to the hash, because `EnumerableSet.add` is idempotent and its return value is ignored.

### RemoveCryptoLegacyForOwner (IBR1)

**Parameters:**

* `owner (bytes32, indexed)`: Hash of the owner identifier being unlinked.
* `cryptoLegacy (address, indexed)`: CryptoLegacy contract address removed from the registry for this owner.

**Description:** Emitted when the beneficiary registry removes a CryptoLegacy contract from an owner hash via `IBeneficiaryRegistry`.

**Event Signature:** `RemoveCryptoLegacyForOwner(bytes32 indexed owner, address indexed cryptoLegacy)`

**Emitted by:**

* [BeneficiaryRegistry.setCryptoLegacyOwner()](https://docs.cryptolegacy.app/documentation/functions-reference#setcryptolegacyowner-br1)

**Notes / Edge cases:** Emitted even if `cryptoLegacy` was not linked to the hash, because `EnumerableSet.remove` return value is ignored.

## IBuildManagerOwnable (IBMO1)

### AddBuildManager (IBMO1)

**Parameters:**

* `buildManager (address, indexed)`: Address being added to the allowed build manager set.

**Description:** Emitted when the owner adds a build manager via `setBuildManager` with the add flag set to `true`, updating the allowed build manager set.

**Event Signature:** `AddBuildManager(address indexed buildManager)`

**Emitted by:**

* [BuildManagerOwnable.setBuildManager()](https://docs.cryptolegacy.app/documentation/functions-reference#setbuildmanager-bmo1)

**Notes / Edge cases:** Emitted even if the address was already in the set, because `EnumerableSet.add` is idempotent and the return value is not checked before emitting.

### RemoveBuildManager (IBMO1)

**Parameters:**

* `buildManager (address, indexed)`: Address being removed from the allowed build manager set.

**Description:** Emitted when the owner removes a build manager via `setBuildManager` with the add flag set to `false`, updating the allowed build manager set.

**Event Signature:** `RemoveBuildManager(address indexed buildManager)`

**Emitted by:**

* [BuildManagerOwnable.setBuildManager()](https://docs.cryptolegacy.app/documentation/functions-reference#setbuildmanager-bmo1)

**Notes / Edge cases:** Emitted even if the address was not in the set, because `EnumerableSet.remove` is a no-op and its return value is not checked before emitting.

## ICallProxy (ICP1)

**No events in this contract/library.**

## ICryptoLegacy (ICL1)

### PauseSet (ICL1)

**Parameters:**

* `isPaused (bool, indexed)`: New paused state for the CryptoLegacy instance.

**Description:** Emitted when the pause flag is toggled for a CryptoLegacy instance (paused or unpaused).

**Event Signature:** `PauseSet(bool indexed isPaused)`

**Emitted by:**

* [CryptoLegacyOwnable.setPause()](https://docs.cryptolegacy.app/documentation/functions-reference#setpause-clo1)
* [CryptoLegacyBasePlugin.initializeByBuildManager()](https://docs.cryptolegacy.app/documentation/functions-reference#initializebybuildmanager-clbp1)
* [CryptoLegacyBasePlugin.payInitialFee()](https://docs.cryptolegacy.app/documentation/functions-reference#payinitialfee-clbp1)
* [LibCryptoLegacy.\_setPause()](https://docs.cryptolegacy.app/documentation/functions-reference#_setpause-lcl1)

**Notes / Edge cases:** None

### Update (ICL1)

**Parameters:**

* `updateFee (uint256)`: Fee amount recorded for the update.
* `byPlugin (bytes32, indexed)`: Plugin identifier that initiated the update.

**Description:** Emitted after an update operation, recording the fee and the plugin that triggered it.

**Event Signature:** `Update(uint256 updateFee, bytes32 indexed byPlugin)`

**Emitted by:**

* [CryptoLegacyBasePlugin.update()](https://docs.cryptolegacy.app/documentation/functions-reference#update-clbp1)

**Notes / Edge cases:** None

### FeePaidByLifetime (ICL1)

**Parameters:**

* `refCode (bytes8, indexed)`: Referral code applied to the payment.
* `initial (bool, indexed)`: True if this is the initial fee payment; false for an update/recurring payment.
* `factory (address)`: Build manager/factory address that receives the fee.
* `lastFeePaidAt (uint64)`: Updated last-fee-payment timestamp (seconds).

**Description:** Emitted when the fee is satisfied via the lifetime NFT path.

**Event Signature:** `FeePaidByLifetime(bytes8 indexed refCode, bool indexed initial, address factory, uint64 lastFeePaidAt)`

**Emitted by:**

* [CryptoLegacyBasePlugin.payInitialFee()](https://docs.cryptolegacy.app/documentation/functions-reference#payinitialfee-clbp1)

**Notes / Edge cases:** None

### FeePaidByDefault (ICL1)

**Parameters:**

* `refCode (bytes8, indexed)`: Referral code applied to the payment.
* `initial (bool, indexed)`: True if this is the initial fee payment; false for an update/recurring payment.
* `value (uint256)`: Amount paid as the fee.
* `returnedValue (uint256)`: Amount refunded to the payer (excess over required fee).
* `factory (address)`: Build manager/factory address that receives the fee.
* `lastFeePaidAt (uint64)`: Updated last-fee-payment timestamp (seconds).

**Description:** Emitted when the standard (non-transfer) fee payment succeeds, including any refund.

**Event Signature:** `FeePaidByDefault(bytes8 indexed refCode, bool indexed initial, uint256 value, uint256 returnedValue, address factory, uint64 lastFeePaidAt)`

**Emitted by:**

* [CryptoLegacyBasePlugin.payInitialFee()](https://docs.cryptolegacy.app/documentation/functions-reference#payinitialfee-clbp1)

**Notes / Edge cases:** None

### FeePaidByTransfer (ICL1)

**Parameters:**

* `refCode (bytes8, indexed)`: Referral code applied to the payment.
* `initial (bool, indexed)`: True if this is the initial fee payment; false for an update/recurring payment.
* `value (uint256)`: Amount transferred as the fee to the build manager (after any referral share).
* `factory (address)`: Build manager/factory address that receives the fee.
* `lastFeePaidAt (uint64)`: Updated last-fee-payment timestamp (seconds).

**Description:** Emitted when the fee is paid via the direct transfer path.

**Event Signature:** `FeePaidByTransfer(bytes8 indexed refCode, bool indexed initial, uint256 value, address factory, uint64 lastFeePaidAt)`

**Emitted by:**

* [CryptoLegacyBasePlugin.payInitialFee()](https://docs.cryptolegacy.app/documentation/functions-reference#payinitialfee-clbp1)

**Notes / Edge cases:** None

### FeeSentToRefByTransfer (ICL1)

**Parameters:**

* `refCode (bytes8, indexed)`: Referral code tied to the fee payment.
* `value (uint256)`: Portion of the fee forwarded to the referral.
* `referral (address)`: Address receiving the referral share.

**Description:** Emitted when a fee paid via the transfer path includes a referral share, recording the referral code, amount sent, and recipient.

**Event Signature:** `FeeSentToRefByTransfer(bytes8 indexed refCode, uint256 value, address referral)`

**Emitted by:**

* [CryptoLegacyBasePlugin.beneficiaryClaim()](https://docs.cryptolegacy.app/documentation/functions-reference#beneficiaryclaim-clbp1)
* [LibCryptoLegacy.\_sendFeeByTransfer()](https://docs.cryptolegacy.app/documentation/functions-reference#_sendfeebytransfer-lcl1)

**Notes / Edge cases:** None

### BeneficiaryClaim (ICL1)

**Parameters:**

* `token (address, indexed)`: Token address being claimed.
* `amount (uint256)`: Amount claimed by the beneficiary.
* `beneficiary (bytes32, indexed)`: Beneficiary hash receiving the claim.

**Description:** Emitted when a beneficiary claim is executed for a token.

**Event Signature:** `BeneficiaryClaim(address indexed token, uint256 amount, bytes32 indexed beneficiary)`

**Emitted by:**

* [CryptoLegacyBasePlugin.\_claimTokenWithVesting()](https://docs.cryptolegacy.app/documentation/functions-reference#_claimtokenwithvesting-clbp1)

**Notes / Edge cases:** None

### BeneficiaryClaimAmountDecrease (ICL1)

**Parameters:**

* `token (address, indexed)`: Token whose claimable amount was reduced.
* `beneficiary (bytes32, indexed)`: Beneficiary hash whose claimable balance changed.
* `prevAmount (uint256)`: Claimable amount before the decrease.
* `newAmount (uint256)`: Claimable amount after the decrease.

**Description:** Emitted when a beneficiary's claimable amount for a token is reduced (e.g., after vesting/claim calculation).

**Event Signature:** `BeneficiaryClaimAmountDecrease(address indexed token, bytes32 indexed beneficiary, uint256 prevAmount, uint256 newAmount)`

**Emitted by:**

* [CryptoLegacyBasePlugin.\_claimTokenWithVesting()](https://docs.cryptolegacy.app/documentation/functions-reference#_claimtokenwithvesting-clbp1)

**Notes / Edge cases:** None

### TransferTreasuryTokensToLegacy (ICL1)

**Parameters:**

* `holders (address[])`: Treasury holder addresses whose balances are moved.
* `tokens (address[])`: Token addresses being moved from the treasury into the legacy contract.

**Description:** Emitted when treasury-held tokens are transferred into the legacy contract, listing holders and token set.

**Event Signature:** `TransferTreasuryTokensToLegacy(address[] holders, address[] tokens)`

**Emitted by:**

* [CryptoLegacyBasePlugin.transferTreasuryTokensToLegacy()](https://docs.cryptolegacy.app/documentation/functions-reference#transfertreasurytokenstolegacy-clbp1)
* [LegacyRecoveryPlugin.lrTransferTreasuryTokensToLegacy()](https://docs.cryptolegacy.app/documentation/functions-reference#lrtransfertreasurytokenstolegacy-lrp1)
* [TrustedGuardiansPlugin.guardiansTransferTreasuryTokensToLegacy()](https://docs.cryptolegacy.app/documentation/functions-reference#guardianstransfertreasurytokenstolegacy-tgp1)
* [LibCryptoLegacy.\_transferTreasuryTokensToLegacy()](https://docs.cryptolegacy.app/documentation/functions-reference#_transfertreasurytokenstolegacy-lcl1)

**Notes / Edge cases:** None

### TransferTokensFromLegacy (ICL1)

**Parameters:**

* `transfers (ICryptoLegacy.TokenTransferTo[])`: Batch of token transfers executed from the legacy contract (token, recipient, amount).

**Description:** Emitted after executing a batch transfer of tokens from the legacy contract to recipients, capturing the full transfer list.

**Event Signature:** `TransferTokensFromLegacy(ICryptoLegacy.TokenTransferTo[] transfers)`

**Emitted by:**

* [LegacyRecoveryPlugin.lrWithdrawTokensFromLegacy()](https://docs.cryptolegacy.app/documentation/functions-reference#lrwithdrawtokensfromlegacy-lrp1)
* [LibCryptoLegacy.\_transferTokensFromLegacy()](https://docs.cryptolegacy.app/documentation/functions-reference#_transfertokensfromlegacy-lcl1)

**Notes / Edge cases:** None

### SetGasLimitMultiplier (ICL1)

**Parameters:**

* `gasLimitMultiplier (uint)`: New multiplier applied to gas limits for external calls.

**Description:** Emitted when the gas limit multiplier used for external calls is updated.

**Event Signature:** `SetGasLimitMultiplier(uint gasLimitMultiplier)`

**Emitted by:**

* [CryptoLegacyBasePlugin.setGasLimitMultiplier()](https://docs.cryptolegacy.app/documentation/functions-reference#setgaslimitmultiplier-clbp1)

**Notes / Edge cases:** None

### AddFunctions (ICL1)

**Parameters:**

* `\_facetAddress (address)`: Facet address that provides the new selectors.
* `\_functionSelectors (bytes4[])`: Function selectors being added to the diamond.
* `selectorPosition (uint16)`: Starting selector position/index assigned to this facet.

**Description:** Emitted when function selectors are added to a facet during a diamond update.

**Event Signature:** `AddFunctions(address \_facetAddress, bytes4[] \_functionSelectors, uint16 selectorPosition)`

**Emitted by:**

* [CryptoLegacy.constructor()](https://docs.cryptolegacy.app/documentation/functions-reference#constructor-cl1)
* [CryptoLegacy.replacePlugin()](https://docs.cryptolegacy.app/documentation/functions-reference#replaceplugin-cl1)
* [CryptoLegacy.addPluginList()](https://docs.cryptolegacy.app/documentation/functions-reference#addpluginlist-cl1)
* [BeneficiaryPluginAddRights.barAddPluginList()](https://docs.cryptolegacy.app/documentation/functions-reference#baraddpluginlist-bpar1)
* [LibCryptoLegacyPlugins.\_addPluginList()](https://docs.cryptolegacy.app/documentation/functions-reference#_addpluginlist-lclp1)
* [LibCryptoLegacyPlugins.addFunctions()](https://docs.cryptolegacy.app/documentation/functions-reference#addfunctions-lclp1)

**Notes / Edge cases:** None

### RemoveFunctions (ICL1)

**Parameters:**

* `\_facetAddress (address)`: Facet address from which selectors are removed.
* `\_functionSelectors (bytes4[])`: Function selectors being removed from the diamond.

**Description:** Emitted when function selectors are removed from a facet during a diamond update.

**Event Signature:** `RemoveFunctions(address \_facetAddress, bytes4[] \_functionSelectors)`

**Emitted by:**

* [CryptoLegacy.replacePlugin()](https://docs.cryptolegacy.app/documentation/functions-reference#replaceplugin-cl1)
* [CryptoLegacy.removePluginList()](https://docs.cryptolegacy.app/documentation/functions-reference#removepluginlist-cl1)
* [LibCryptoLegacyPlugins.\_removePlugin()](https://docs.cryptolegacy.app/documentation/functions-reference#_removeplugin-lclp1)
* [LibCryptoLegacyPlugins.removeFunctions()](https://docs.cryptolegacy.app/documentation/functions-reference#removefunctions-lclp1)

**Notes / Edge cases:** None

### SkipSendFeeByTransfer (ICL1)

**Parameters:**

* `buildManagerAddress (address)`: Build manager address that would have received the fee transfer.
* `value (uint256)`: ETH amount provided (zero when skipped).

**Description:** Emitted when the transfer-based fee path is skipped because `msg.value` is zero.

**Event Signature:** `SkipSendFeeByTransfer(address buildManagerAddress, uint256 value)`

**Emitted by:**

* [CryptoLegacyBasePlugin.update()](https://docs.cryptolegacy.app/documentation/functions-reference#update-clbp1)
* [CryptoLegacyBasePlugin.beneficiaryClaim()](https://docs.cryptolegacy.app/documentation/functions-reference#beneficiaryclaim-clbp1)
* [LegacyRecoveryPlugin.lrResetGuardianVoting()](https://docs.cryptolegacy.app/documentation/functions-reference#lrresetguardianvoting-lrp1)
* [TrustedGuardiansPlugin.resetGuardianVoting()](https://docs.cryptolegacy.app/documentation/functions-reference#resetguardianvoting-tgp1)
* [LibCryptoLegacy.\_sendFeeByTransfer()](https://docs.cryptolegacy.app/documentation/functions-reference#_sendfeebytransfer-lcl1)

**Notes / Edge cases:** None

### IsLifetimeNftLockedAndUpdateCatch (ICL1)

**Parameters:**

* `reason (bytes)`: Revert data returned by the failed `isLifetimeNftLockedAndUpdate` call.

**Description:** Emitted when the lifetime-NFT status check on the build manager reverts and the error is captured.

**Event Signature:** `IsLifetimeNftLockedAndUpdateCatch(bytes reason)`

**Emitted by:**

* [CryptoLegacyBasePlugin.payInitialFee()](https://docs.cryptolegacy.app/documentation/functions-reference#payinitialfee-clbp1)
* [LegacyRecoveryPlugin.lrResetGuardianVoting()](https://docs.cryptolegacy.app/documentation/functions-reference#lrresetguardianvoting-lrp1)
* [TrustedGuardiansPlugin.resetGuardianVoting()](https://docs.cryptolegacy.app/documentation/functions-reference#resetguardianvoting-tgp1)
* [LibCryptoLegacy.\_isLifetimeActiveAndUpdate()](https://docs.cryptolegacy.app/documentation/functions-reference#_islifetimeactiveandupdate-lcl1)

**Notes / Edge cases:** None

### GetUpdateFeeCatch (ICL1)

**Parameters:**

* `reason (bytes)`: Revert data from the failed build manager `getUpdateFee` call.

**Description:** Emitted when fetching the update fee from the build manager reverts.

**Event Signature:** `GetUpdateFeeCatch(bytes reason)`

**Emitted by:**

* [CryptoLegacyBasePlugin.update()](https://docs.cryptolegacy.app/documentation/functions-reference#update-clbp1)
* [CryptoLegacyBasePlugin.beneficiaryClaim()](https://docs.cryptolegacy.app/documentation/functions-reference#beneficiaryclaim-clbp1)
* [LegacyRecoveryPlugin.lrResetGuardianVoting()](https://docs.cryptolegacy.app/documentation/functions-reference#lrresetguardianvoting-lrp1)
* [TrustedGuardiansPlugin.resetGuardianVoting()](https://docs.cryptolegacy.app/documentation/functions-reference#resetguardianvoting-tgp1)
* [LibCryptoLegacy.\_takeFee()](https://docs.cryptolegacy.app/documentation/functions-reference#_takefee-lcl1)

**Notes / Edge cases:** None

### PayFeeCatch (ICL1)

**Parameters:**

* `reason (bytes)`: Revert data from the failed build manager `payFee` call.

**Description:** Emitted when the build manager fee payment call reverts and the flow falls back to transfer-based handling.

**Event Signature:** `PayFeeCatch(bytes reason)`

**Emitted by:**

* [CryptoLegacyBasePlugin.update()](https://docs.cryptolegacy.app/documentation/functions-reference#update-clbp1)
* [CryptoLegacyBasePlugin.beneficiaryClaim()](https://docs.cryptolegacy.app/documentation/functions-reference#beneficiaryclaim-clbp1)
* [LegacyRecoveryPlugin.lrResetGuardianVoting()](https://docs.cryptolegacy.app/documentation/functions-reference#lrresetguardianvoting-lrp1)
* [TrustedGuardiansPlugin.resetGuardianVoting()](https://docs.cryptolegacy.app/documentation/functions-reference#resetguardianvoting-tgp1)
* [LibCryptoLegacy.\_takeFee()](https://docs.cryptolegacy.app/documentation/functions-reference#_takefee-lcl1)

**Notes / Edge cases:** None

### SetCryptoLegacyOwnerCatch (ICL1)

**Parameters:**

* `reason (bytes)`: Revert data from the failed `setCryptoLegacyOwner` call to the beneficiary registry.

**Description:** Emitted when updating the owner entry in the beneficiary registry reverts.

**Event Signature:** `SetCryptoLegacyOwnerCatch(bytes reason)`

**Emitted by:**

* [CryptoLegacyOwnable.acceptOwnership()](https://docs.cryptolegacy.app/documentation/functions-reference#acceptownership-clo1)
* [CryptoLegacyBasePlugin.initializeByBuildManager()](https://docs.cryptolegacy.app/documentation/functions-reference#initializebybuildmanager-clbp1)
* [LibCryptoLegacy.\_setCryptoLegacyToBeneficiaryRegistry()](https://docs.cryptolegacy.app/documentation/functions-reference#_setcryptolegacytobeneficiaryregistry-lcl1)

**Notes / Edge cases:** None

### SetCryptoLegacyBeneficiaryCatch (ICL1)

**Parameters:**

* `reason (bytes)`: Revert data from the failed `setCryptoLegacyBeneficiary` call to the beneficiary registry.

**Description:** Emitted when updating the beneficiary entry in the registry reverts.

**Event Signature:** `SetCryptoLegacyBeneficiaryCatch(bytes reason)`

**Emitted by:**

* [CryptoLegacyBasePlugin.initializeByBuildManager()](https://docs.cryptolegacy.app/documentation/functions-reference#initializebybuildmanager-clbp1)
* [CryptoLegacyBasePlugin.setBeneficiaries()](https://docs.cryptolegacy.app/documentation/functions-reference#setbeneficiaries-clbp1)
* [LibCryptoLegacy.\_setCryptoLegacyToBeneficiaryRegistry()](https://docs.cryptolegacy.app/documentation/functions-reference#_setcryptolegacytobeneficiaryregistry-lcl1)

**Notes / Edge cases:** None

### SetCryptoLegacyGuardianCatch (ICL1)

**Parameters:**

* `reason (bytes)`: Revert data from the failed `setCryptoLegacyGuardian` call to the beneficiary registry.

**Description:** Emitted when updating the guardian entry in the registry reverts.

**Event Signature:** `SetCryptoLegacyGuardianCatch(bytes reason)`

**Emitted by:**

* [TrustedGuardiansPlugin.initializeGuardians()](https://docs.cryptolegacy.app/documentation/functions-reference#initializeguardians-tgp1)
* [TrustedGuardiansPlugin.setGuardians()](https://docs.cryptolegacy.app/documentation/functions-reference#setguardians-tgp1)
* [LibCryptoLegacy.\_setCryptoLegacyToBeneficiaryRegistry()](https://docs.cryptolegacy.app/documentation/functions-reference#_setcryptolegacytobeneficiaryregistry-lcl1)

**Notes / Edge cases:** None

### SetCryptoLegacyRecoveryAddressesCatch (ICL1)

**Parameters:**

* `reason (bytes)`: Revert data from the failed `setCryptoLegacyRecoveryAddresses` call.

**Description:** Emitted when updating recovery addresses in the registry reverts.

**Event Signature:** `SetCryptoLegacyRecoveryAddressesCatch(bytes reason)`

**Emitted by:**

* [LegacyRecoveryPlugin.lrSetMultisigConfig()](https://docs.cryptolegacy.app/documentation/functions-reference#lrsetmultisigconfig-lrp1)
* [LibCryptoLegacy.\_setCryptoLegacyListToBeneficiaryRegistry()](https://docs.cryptolegacy.app/documentation/functions-reference#_setcryptolegacylisttobeneficiaryregistry-lcl1)

**Notes / Edge cases:** None

### BeneficiaryRegistryCatch (ICL1)

**Parameters:**

* `reason (bytes)`: Revert data from the failed `beneficiaryRegistry()` lookup on the build manager.

**Description:** Emitted when fetching the beneficiary registry from the build manager reverts.

**Event Signature:** `BeneficiaryRegistryCatch(bytes reason)`

**Emitted by:**

* [CryptoLegacyOwnable.acceptOwnership()](https://docs.cryptolegacy.app/documentation/functions-reference#acceptownership-clo1)
* [LegacyRecoveryPlugin.lrSetMultisigConfig()](https://docs.cryptolegacy.app/documentation/functions-reference#lrsetmultisigconfig-lrp1)
* [LibCryptoLegacy.\_getBeneficiaryRegistry()](https://docs.cryptolegacy.app/documentation/functions-reference#_getbeneficiaryregistry-lcl1)

**Notes / Edge cases:** None

### BeneficiaryRegistryNotDefined (ICL1)

**Parameters:** None

**Description:** Emitted when the beneficiary registry address is not configured (zero address), so registry updates are skipped.

**Event Signature:** `BeneficiaryRegistryNotDefined()`

**Emitted by:**

* [CryptoLegacyOwnable.acceptOwnership()](https://docs.cryptolegacy.app/documentation/functions-reference#acceptownership-clo1)
* [CryptoLegacyBasePlugin.initializeByBuildManager()](https://docs.cryptolegacy.app/documentation/functions-reference#initializebybuildmanager-clbp1)
* [CryptoLegacyBasePlugin.setBeneficiaries()](https://docs.cryptolegacy.app/documentation/functions-reference#setbeneficiaries-clbp1)
* [LegacyRecoveryPlugin.lrSetMultisigConfig()](https://docs.cryptolegacy.app/documentation/functions-reference#lrsetmultisigconfig-lrp1)
* [TrustedGuardiansPlugin.initializeGuardians()](https://docs.cryptolegacy.app/documentation/functions-reference#initializeguardians-tgp1)
* [TrustedGuardiansPlugin.setGuardians()](https://docs.cryptolegacy.app/documentation/functions-reference#setguardians-tgp1)
* [LibCryptoLegacy.\_setCryptoLegacyToBeneficiaryRegistry()](https://docs.cryptolegacy.app/documentation/functions-reference#_setcryptolegacytobeneficiaryregistry-lcl1)
* [LibCryptoLegacy.\_setCryptoLegacyListToBeneficiaryRegistry()](https://docs.cryptolegacy.app/documentation/functions-reference#_setcryptolegacylisttobeneficiaryregistry-lcl1)

**Notes / Edge cases:** None

## ICryptoLegacyBuildManager (ICLBM1)

### CreateRef (ICLBM1)

**Parameters:**

* `sender (address, indexed)`: Address that initiated the referral creation.
* `refCode (bytes8, indexed)`: Generated referral code.
* `recipient (address, indexed)`: Address that receives referral benefits for this code.
* `chainIds (uint256[])`: Destination chain IDs included for cross-chain usage.

**Description:** Emitted when a new referral code is created via `createRef`/`\_createRef` (including via `\_createRefAndPayForBuild`).

**Event Signature:** `CreateRef(address indexed sender, bytes8 indexed refCode, address indexed recipient, uint256[] chainIds)`

**Emitted by:**

* [CryptoLegacyBuildManager.\_createRef()](https://docs.cryptolegacy.app/documentation/functions-reference#_createref-clbm1)

**Notes / Edge cases:** None

### CreateCustomRef (ICLBM1)

**Parameters:**

* `sender (address, indexed)`: Address that initiated the custom referral creation.
* `refCode (bytes8, indexed)`: Custom referral code created (or assigned) for the recipient.
* `recipient (address, indexed)`: Address that receives referral benefits for this code.
* `chainIds (uint256[])`: Destination chain IDs included for cross-chain usage.

**Description:** Emitted when a custom referral code is created via `createCustomRef`/`\_createCustomRef` (including via `\_createRefAndPayForBuild`).

**Event Signature:** `CreateCustomRef(address indexed sender, bytes8 indexed refCode, address indexed recipient, uint256[] chainIds)`

**Emitted by:**

* [CryptoLegacyBuildManager.\_createCustomRef()](https://docs.cryptolegacy.app/documentation/functions-reference#_createcustomref-clbm1)

**Notes / Edge cases:** None

### SetCrossChainsRef (ICLBM1)

**Parameters:**

* `sender (address, indexed)`: Address that updated the cross-chain referral settings.
* `chainIds (uint256[])`: Destination chain IDs enabled for cross-chain referral usage.

**Description:** Emitted when a caller updates the cross-chain referral configuration for their referral code.

**Event Signature:** `SetCrossChainsRef(address indexed sender, uint256[] chainIds)`

**Emitted by:**

* [CryptoLegacyBuildManager.updateCrossChainsRef()](https://docs.cryptolegacy.app/documentation/functions-reference#updatecrosschainsref-clbm1)

**Notes / Edge cases:** None

### WithdrawFee (ICLBM1)

**Parameters:**

* `recipient (address, indexed)`: Address receiving the withdrawn fees.
* `amount (uint256, indexed)`: Amount of fees withdrawn.

**Description:** Emitted when accumulated fees are withdrawn to a recipient address.

**Event Signature:** `WithdrawFee(address indexed recipient, uint256 indexed amount)`

**Emitted by:**

* [CryptoLegacyBuildManager.withdrawFee()](https://docs.cryptolegacy.app/documentation/functions-reference#withdrawfee-clbm1)

**Notes / Edge cases:** None

### SetRegistries (ICLBM1)

**Parameters:**

* `feeRegistry (address, indexed)`: Address of the fee registry contract.
* `pluginsRegistry (address, indexed)`: Address of the plugins registry contract.
* `beneficiaryRegistry (address, indexed)`: Address of the beneficiary registry contract.

**Description:** Emitted when registry contract addresses are set or updated.

**Event Signature:** `SetRegistries(address indexed feeRegistry, address indexed pluginsRegistry, address indexed beneficiaryRegistry)`

**Emitted by:**

* [CryptoLegacyBuildManager.\_setRegistries()](https://docs.cryptolegacy.app/documentation/functions-reference#_setregistries-clbm1)

**Notes / Edge cases:** None

### SetFactory (ICLBM1)

**Parameters:**

* `factory (address, indexed)`: Address of the CryptoLegacy factory contract.

**Description:** Emitted when the factory address used to deploy CryptoLegacy contracts is set or updated.

**Event Signature:** `SetFactory(address indexed factory)`

**Emitted by:**

* [CryptoLegacyBuildManager.\_setFactory()](https://docs.cryptolegacy.app/documentation/functions-reference#_setfactory-clbm1)

**Notes / Edge cases:** None

### SetSupplyLimit (ICLBM1)

**Parameters:**

* `supplyLimit (uint256)`: New lifetime NFT supply limit used by the build manager.

**Description:** Emitted when the lifetime NFT supply limit is updated.

**Event Signature:** `SetSupplyLimit(uint256 supplyLimit)`

**Emitted by:**

* [CryptoLegacyBuildManager.setSupplyLimit()](https://docs.cryptolegacy.app/documentation/functions-reference#setsupplylimit-clbm1)

**Notes / Edge cases:** None

### SetExternalLens (ICLBM1)

**Parameters:**

* `externalLens (address, indexed)`: Address of the external lens contract.

**Description:** Emitted when the external lens address is set or updated.

**Event Signature:** `SetExternalLens(address indexed externalLens)`

**Emitted by:**

* [CryptoLegacyBuildManager.setExternalLens()](https://docs.cryptolegacy.app/documentation/functions-reference#setexternallens-clbm1)

**Notes / Edge cases:** None

### PaidForMint (ICLBM1)

**Parameters:**

* `sender (address, indexed)`: Address that paid for the mint.
* `tokenId (uint256, indexed)`: Token ID of the newly minted lifetime NFT.
* `toHolder (address, indexed)`: Address receiving the minted lifetime NFT.

**Description:** Emitted for each lifetime NFT minted during a paid mint flow.

**Event Signature:** `PaidForMint(address indexed sender, uint256 indexed tokenId, address indexed toHolder)`

**Emitted by:**

* [CryptoLegacyBuildManager.payForMultipleLifetimeNft()](https://docs.cryptolegacy.app/documentation/functions-reference#payformultiplelifetimenft-clbm1)

**Notes / Edge cases:** None

### PaidForMultipleNft (ICLBM1)

**Parameters:**

* `sender (address, indexed)`: Address that paid for the batch mint.
* `code (bytes8, indexed)`: Referral code applied to the payment.
* `value (uint256)`: Total fee amount paid.
* `totalAmount (uint256)`: Total number of NFTs minted in the batch.

**Description:** Emitted after a successful batch lifetime NFT purchase and minting.

**Event Signature:** `PaidForMultipleNft(address indexed sender, bytes8 indexed code, uint256 value, uint256 totalAmount)`

**Emitted by:**

* [CryptoLegacyBuildManager.payForMultipleLifetimeNft()](https://docs.cryptolegacy.app/documentation/functions-reference#payformultiplelifetimenft-clbm1)

**Notes / Edge cases:** None

### Build (ICLBM1)

**Parameters:**

* `sender (address, indexed)`: Address that initiated the build.
* `cryptoLegacy (address, indexed)`: Newly deployed CryptoLegacy contract address.
* `plugins (address[])`: Plugin addresses configured on deployment.
* `beneficiaryHashes (bytes32[])`: Beneficiary hashes configured for the legacy.
* `beneficiaryConfig (ICryptoLegacy.BeneficiaryConfig[])`: Beneficiary configuration entries.
* `isPaid (bool)`: True if the initial fee was already paid (no initial fee due).
* `updateInterval (uint64)`: Update interval configured for the legacy.
* `challengeTimeout (uint64)`: Challenge timeout configured for the legacy.

**Description:** Emitted when a new CryptoLegacy contract is deployed and initialized with plugins and beneficiary settings.

**Event Signature:** `Build(address indexed sender, address indexed cryptoLegacy, address[] plugins, bytes32[] beneficiaryHashes, ICryptoLegacy.BeneficiaryConfig[] beneficiaryConfig, bool isPaid, uint64 updateInterval, uint64 challengeTimeout)`

**Emitted by:**

* [CryptoLegacyBuildManager.buildCryptoLegacy()](https://docs.cryptolegacy.app/documentation/functions-reference#buildcryptolegacy-clbm1)

**Notes / Edge cases:** None

## ICryptoLegacyDiamondBase (ICLDB1)

### StaticCallCheck (ICLDB1)

**Parameters:** None

**Description:** Emitted by the self-call probe when `staticCallChecker()` succeeds in a non-static context, allowing the diamond fallback to detect that the current call is not static.

**Event Signature:** `StaticCallCheck()`

**Emitted by:**

* [CryptoLegacyDiamondBase.staticCallChecker()](https://docs.cryptolegacy.app/documentation/functions-reference#staticcallchecker-cldb1)

**Notes / Edge cases:** None

## ICryptoLegacyFactory (ICLF1)

### AddBuildOperator (ICLF1)

**Parameters:**

* `buildOperator (address, indexed)`: Address granted the build-operator role.

**Description:** Emitted when a build operator is added to the allowed set.

**Event Signature:** `AddBuildOperator(address indexed buildOperator)`

**Emitted by:**

* [CryptoLegacyFactory.setBuildOperator()](https://docs.cryptolegacy.app/documentation/functions-reference#setbuildoperator-clf1)

**Notes / Edge cases:** None

### RemoveBuildOperator (ICLF1)

**Parameters:**

* `buildOperator (address, indexed)`: Address removed from the build-operator role.

**Description:** Emitted when a build operator is removed from the allowed set.

**Event Signature:** `RemoveBuildOperator(address indexed buildOperator)`

**Emitted by:**

* [CryptoLegacyFactory.setBuildOperator()](https://docs.cryptolegacy.app/documentation/functions-reference#setbuildoperator-clf1)

**Notes / Edge cases:** None

## ICryptoLegacyLens (ICLL1)

**No events in this contract/library.**

## ICryptoLegacyOwnable (ICLO1)

### OwnershipTransferStarted (ICLO1)

**Parameters:**

* `previousOwner (address, indexed)`: Current owner before transfer is initiated.
* `newOwner (address, indexed)`: Pending owner set during initiation.

**Description:** Emitted when a two-step ownership transfer is initiated and a pending owner is set.

**Event Signature:** `OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner)`

**Emitted by:**

* [CryptoLegacyOwnable.\_transferOwnership()](https://docs.cryptolegacy.app/documentation/functions-reference#_transferownership-clo1)

**Notes / Edge cases:** None

### OwnershipTransferred (ICLO1)

**Parameters:**

* `previousOwner (address, indexed)`: Owner address before the transfer completes.
* `newOwner (address, indexed)`: Owner address after the transfer completes.

**Description:** Emitted when ownership is transferred to a new owner.

**Event Signature:** `OwnershipTransferred(address indexed previousOwner, address indexed newOwner)`

**Emitted by:** None

**Notes / Edge cases:** None

## ICryptoLegacyPlugin (ICLP1)

**No events in this contract/library.**

## ICryptoLegacyUpdaterPlugin (ICLUP1)

### AddUpdater (ICLUP1)

**Parameters:**

* `owner (address, indexed)`: Owner address that added the updater.
* `updater (address, indexed)`: Updater address added to the allowlist.

**Description:** Emitted when the owner adds an updater account.

**Event Signature:** `AddUpdater(address indexed owner, address indexed updater)`

**Emitted by:**

* [UpdateRolePlugin.setUpdater()](https://docs.cryptolegacy.app/documentation/functions-reference#setupdater-urp1)

**Notes / Edge cases:** None

### RemoveUpdater (ICLUP1)

**Parameters:**

* `owner (address, indexed)`: Owner address that removed the updater.
* `updater (address, indexed)`: Updater address removed from the allowlist.

**Description:** Emitted when the owner removes an updater account.

**Event Signature:** `RemoveUpdater(address indexed owner, address indexed updater)`

**Emitted by:**

* [UpdateRolePlugin.setUpdater()](https://docs.cryptolegacy.app/documentation/functions-reference#setupdater-urp1)

**Notes / Edge cases:** None

## IDeBridgeGate (IDBG1)

### Sent (IDBG1)

**Parameters:**

* `submissionId (bytes32)`: Unique submission ID for the transfer.
* `debridgeId (bytes32, indexed)`: Asset identifier within deBridge.
* `amount (uint256)`: Amount sent/locked on the source chain.
* `receiver (bytes)`: Encoded receiver address on the destination chain.
* `nonce (uint256)`: Nonce associated with this submission.
* `chainIdTo (uint256, indexed)`: Destination chain ID.
* `referralCode (uint32)`: Referral code associated with the submission.
* `feeParams (FeeParams)`: Fee parameters applied to the transfer.
* `autoParams (bytes)`: Auto-execution parameters for the target call.
* `nativeSender (address)`: Native sender address on the source chain.

**Description:** Emitted when assets are sent from the native chain to another chain, creating a transfer submission.

**Event Signature:** `Sent(bytes32 submissionId, bytes32 indexed debridgeId, uint256 amount, bytes receiver, uint256 nonce, uint256 indexed chainIdTo, uint32 referralCode, FeeParams feeParams, bytes autoParams, address nativeSender)`

**Emitted by:** None

**Notes / Edge cases:** None

### Claimed (IDBG1)

**Parameters:**

* `submissionId (bytes32)`: Submission ID being claimed on the target chain.
* `debridgeId (bytes32, indexed)`: Asset identifier within deBridge.
* `amount (uint256)`: Amount claimed/withdrawn.
* `receiver (address, indexed)`: Receiver address on the target chain.
* `nonce (uint256)`: Nonce associated with the submission.
* `chainIdFrom (uint256, indexed)`: Source chain ID.
* `autoParams (bytes)`: Auto-execution parameters used during claim.
* `isNativeToken (bool)`: True if the asset is the native token.

**Description:** Emitted when a transfer is claimed and withdrawn on the target chain.

**Event Signature:** `Claimed(bytes32 submissionId, bytes32 indexed debridgeId, uint256 amount, address indexed receiver, uint256 nonce, uint256 indexed chainIdFrom, bytes autoParams, bool isNativeToken)`

**Emitted by:** None

**Notes / Edge cases:** None

### PairAdded (IDBG1)

**Parameters:**

* `debridgeId (bytes32)`: Asset identifier within deBridge.
* `tokenAddress (address)`: Asset address on the current chain.
* `nativeAddress (bytes)`: Asset address on the native chain (encoded).
* `nativeChainId (uint256, indexed)`: Native chain ID for the asset.
* `maxAmount (uint256)`: Maximum transferable amount for the asset.
* `minReservesBps (uint16)`: Minimum reserves in basis points for the asset.

**Description:** Emitted when support for a new asset pair is added.

**Event Signature:** `PairAdded(bytes32 debridgeId, address tokenAddress, bytes nativeAddress, uint256 indexed nativeChainId, uint256 maxAmount, uint16 minReservesBps)`

**Emitted by:** None

**Notes / Edge cases:** None

### MonitoringSendEvent (IDBG1)

**Parameters:**

* `submissionId (bytes32)`: Submission ID being monitored.
* `nonce (uint256)`: Nonce associated with the submission.
* `lockedOrMintedAmount (uint256)`: Amount locked or minted for the send.
* `totalSupply (uint256)`: Total supply after the send.

**Description:** Emitted for monitoring when a send locks or mints assets and updates total supply.

**Event Signature:** `MonitoringSendEvent(bytes32 submissionId, uint256 nonce, uint256 lockedOrMintedAmount, uint256 totalSupply)`

**Emitted by:** None

**Notes / Edge cases:** None

### MonitoringClaimEvent (IDBG1)

**Parameters:**

* `submissionId (bytes32)`: Submission ID being monitored.
* `lockedOrMintedAmount (uint256)`: Amount unlocked or burned for the claim.
* `totalSupply (uint256)`: Total supply after the claim.

**Description:** Emitted for monitoring when a claim is processed and total supply is updated.

**Event Signature:** `MonitoringClaimEvent(bytes32 submissionId, uint256 lockedOrMintedAmount, uint256 totalSupply)`

**Emitted by:** None

**Notes / Edge cases:** None

### ChainSupportUpdated (IDBG1)

**Parameters:**

* `chainId (uint256)`: Chain ID whose support flag changed.
* `isSupported (bool)`: Whether the chain is supported.
* `isChainFrom (bool)`: True if the update applies to the source-chain side.

**Description:** Emitted when support for a single chain is enabled or disabled.

**Event Signature:** `ChainSupportUpdated(uint256 chainId, bool isSupported, bool isChainFrom)`

**Emitted by:** None

**Notes / Edge cases:** None

### ChainsSupportUpdated (IDBG1)

**Parameters:**

* `chainIds (uint256)`: Chain ID being updated.
* `chainSupportInfo (ChainSupportInfo)`: Support settings for the chain (fees and support flag).
* `isChainFrom (bool)`: True if the update applies to the source-chain side.

**Description:** Emitted when chain support settings are updated.

**Event Signature:** `ChainsSupportUpdated(uint256 chainIds, ChainSupportInfo chainSupportInfo, bool isChainFrom)`

**Emitted by:** None

**Notes / Edge cases:** None

### CallProxyUpdated (IDBG1)

**Parameters:**

* `callProxy (address)`: Address of the new call proxy contract.

**Description:** Emitted when the call proxy address is updated.

**Event Signature:** `CallProxyUpdated(address callProxy)`

**Emitted by:** None

**Notes / Edge cases:** None

### AutoRequestExecuted (IDBG1)

**Parameters:**

* `submissionId (bytes32)`: Submission ID whose auto-request executed.
* `success (bool, indexed)`: Whether the auto-execution succeeded.
* `callProxy (address)`: Call proxy used for the execution.

**Description:** Emitted when an auto-execution request is executed via the call proxy.

**Event Signature:** `AutoRequestExecuted(bytes32 submissionId, bool indexed success, address callProxy)`

**Emitted by:** None

**Notes / Edge cases:** None

### Blocked (IDBG1)

**Parameters:**

* `submissionId (bytes32)`: Submission ID that was blocked.

**Description:** Emitted when a submission is blocked.

**Event Signature:** `Blocked(bytes32 submissionId)`

**Emitted by:** None

**Notes / Edge cases:** None

### Unblocked (IDBG1)

**Parameters:**

* `submissionId (bytes32)`: Submission ID that was unblocked.

**Description:** Emitted when a submission is unblocked.

**Event Signature:** `Unblocked(bytes32 submissionId)`

**Emitted by:** None

**Notes / Edge cases:** None

### WithdrawnFee (IDBG1)

**Parameters:**

* `debridgeId (bytes32)`: Asset identifier whose fees were withdrawn.
* `fee (uint256)`: Fee amount withdrawn.

**Description:** Emitted when accumulated fees are withdrawn for an asset.

**Event Signature:** `WithdrawnFee(bytes32 debridgeId, uint256 fee)`

**Emitted by:** None

**Notes / Edge cases:** None

### FixedNativeFeeUpdated (IDBG1)

**Parameters:**

* `globalFixedNativeFee (uint256)`: Updated global fixed native fee.
* `globalTransferFeeBps (uint256)`: Updated global transfer fee in basis points.

**Description:** Emitted when global fixed native fee and transfer fee parameters are updated.

**Event Signature:** `FixedNativeFeeUpdated(uint256 globalFixedNativeFee, uint256 globalTransferFeeBps)`

**Emitted by:** None

**Notes / Edge cases:** None

### FixedNativeFeeAutoUpdated (IDBG1)

**Parameters:**

* `globalFixedNativeFee (uint256)`: New global fixed native fee set by the updater.

**Description:** Emitted when the global fixed native fee is auto-updated by the fee updater.

**Event Signature:** `FixedNativeFeeAutoUpdated(uint256 globalFixedNativeFee)`

**Emitted by:** None

**Notes / Edge cases:** None

## IDiamondCut (IDC1)

### DiamondCut (IDC1)

**Parameters:**

* `\_diamondCut (FacetCut[])`: Facet cut operations (add/replace/remove) applied to the diamond.
* `\_init (address)`: Optional initialization target for delegatecall.
* `\_calldata (bytes)`: Initialization calldata passed to the delegatecall.

**Description:** Emitted after applying a diamond cut to record the facet changes and optional initialization.

**Event Signature:** `DiamondCut(FacetCut[] \_diamondCut, address \_init, bytes \_calldata)`

**Emitted by:** None

**Notes / Edge cases:** None

## IDiamondLoupe (IDL1)

**No events in this contract/library.**

## IFeeRegistry (IFR1)

### AddCodeOperator (IFR1)

**Parameters:**

* `codeOperator (address, indexed)`: Address targeted to be added as an authorized code operator.

**Description:** Emitted when the owner calls `setCodeOperator` with `\_isAdd = true` (even if the operator is already present).

**Event Signature:** `AddCodeOperator(address indexed codeOperator)`

**Emitted by:**

* [FeeRegistry.setCodeOperator()](https://docs.cryptolegacy.app/documentation/functions-reference#setcodeoperator-fr1)

**Notes / Edge cases:** None

### RemoveCodeOperator (IFR1)

**Parameters:**

* `codeOperator (address, indexed)`: Address targeted to be removed from the set of authorized code operators.

**Description:** Emitted when the owner calls `setCodeOperator` with `\_isAdd = false` (even if the operator is not present).

**Event Signature:** `RemoveCodeOperator(address indexed codeOperator)`

**Emitted by:**

* [FeeRegistry.setCodeOperator()](https://docs.cryptolegacy.app/documentation/functions-reference#setcodeoperator-fr1)

**Notes / Edge cases:** None

### SetDefaultPct (IFR1)

**Parameters:**

* `defaultDiscountPct (uint32)`: New default discount percentage (basis points, denominator 10,000).
* `defaultSharePct (uint32)`: New default referrer share percentage (basis points, denominator 10,000).

**Description:** Emitted after the default discount/share percentages are written to storage during initialization or an owner update.

**Event Signature:** `SetDefaultPct(uint32 defaultDiscountPct, uint32 defaultSharePct)`

**Emitted by:**

* [FeeRegistry.\_setDefaultPct()](https://docs.cryptolegacy.app/documentation/functions-reference#_setdefaultpct-fr1)

**Notes / Edge cases:** None

### SetRefererSpecificPct (IFR1)

**Parameters:**

* `referrer (address, indexed)`: Referrer whose custom percentages are updated.
* `code (bytes8, indexed)`: Referral code associated with the referrer.
* `discountPct (uint32)`: New discount percentage (basis points).
* `sharePct (uint32)`: New referrer share percentage (basis points).

**Description:** Emitted when the owner updates a referrer’s custom discount/share percentages in `setRefererSpecificPct`.

**Event Signature:** `SetRefererSpecificPct(address indexed referrer, bytes8 indexed code, uint32 discountPct, uint32 sharePct)`

**Emitted by:**

* [FeeRegistry.setRefererSpecificPct()](https://docs.cryptolegacy.app/documentation/functions-reference#setrefererspecificpct-fr1)

**Notes / Edge cases:** None

### SetContractCaseFee (IFR1)

**Parameters:**

* `sourceContract (address, indexed)`: Source contract for which the fee is configured.
* `contractCase (uint8, indexed)`: Case identifier within the source contract.
* `fee (uint256)`: New fee value set for the contract-case combination.

**Description:** Emitted when the owner sets or updates the fee for a specific pair `sourceContract` + `contractCase`.

**Event Signature:** `SetContractCaseFee(address indexed sourceContract, uint8 indexed contractCase, uint256 fee)`

**Emitted by:**

* [FeeRegistry.setContractCaseFee()](https://docs.cryptolegacy.app/documentation/functions-reference#setcontractcasefee-fr1)

**Notes / Edge cases:** None

### TakeFee (IFR1)

**Parameters:**

* `sourceContract (address, indexed)`: Source contract for which the fee is charged.
* `contractCase (uint8, indexed)`: Case identifier within the source contract.
* `code (bytes8, indexed)`: Referral code used for fee calculation.
* `discount (uint256)`: Discount amount applied to the base fee.
* `share (uint256)`: Referral share amount (either sent or accumulated).
* `fee (uint256)`: Final fee required from the caller after discount.
* `value (uint256)`: `msg.value` supplied with the call.

**Description:** Emitted after `takeFee` calculates the fee and processes the referral share; captures the final fee math and the actual ETH value provided.

**Event Signature:** `TakeFee(address indexed sourceContract, uint8 indexed contractCase, bytes8 indexed code, uint256 discount, uint256 share, uint256 fee, uint256 value)`

**Emitted by:**

* [FeeRegistry.takeFee()](https://docs.cryptolegacy.app/documentation/functions-reference#takefee-fr1)

**Notes / Edge cases:** None

### SentFee (IFR1)

**Parameters:**

* `referrer (address, indexed)`: Referrer (owner of the referral code).
* `code (bytes8, indexed)`: Referral code used for the fee calculation.
* `recipient (address, indexed)`: Recipient that successfully received the referral share.
* `value (uint256)`: Amount of the referral share transferred to `recipient`.

**Description:** Emitted when `takeFee` successfully transfers the referral share to the configured recipient (transfer succeeds, and the share is not accumulated).

**Event Signature:** `SentFee(address indexed referrer, bytes8 indexed code, address indexed recipient, uint256 value)`

**Emitted by:**

* [FeeRegistry.takeFee()](https://docs.cryptolegacy.app/documentation/functions-reference#takefee-fr1)

**Notes / Edge cases:** None

### AccumulateFee (IFR1)

**Parameters:**

* `referrer (address, indexed)`: Referrer (owner of the referral code).
* `code (bytes8, indexed)`: Referral code used for the fee calculation.
* `recipient (address, indexed)`: Intended recipient of the referral share.
* `value (uint256)`: Amount of the referral share that was accumulated.
* `transferResponse (bytes)`: Low-level call return data from the failed transfer attempt.

**Description:** Emitted when the referral share transfer in `takeFee` fails, and the share is added to the referrer’s accumulated balance for later withdrawal.

**Event Signature:** `AccumulateFee(address indexed referrer, bytes8 indexed code, address indexed recipient, uint256 value, bytes transferResponse)`

**Emitted by:**

* [FeeRegistry.takeFee()](https://docs.cryptolegacy.app/documentation/functions-reference#takefee-fr1)

**Notes / Edge cases:** None

### CreateCode (IFR1)

**Parameters:**

* `codeOperator (address, indexed)`: Operator that initiates code creation.
* `referrer (address, indexed)`: Referrer that owns the code.
* `code (bytes8, indexed)`: Newly created referral code.
* `recipient (address)`: Recipient of referral rewards.
* `fromChain (uint256)`: Source chain ID for cross-chain creation (0 for local).
* `discountPct (uint32)`: Discount percentage assigned to the code.
* `sharePct (uint32)`: Referrer share percentage assigned to the code.

**Description:** Emitted when a new referral code is created in `\_createCustomCode`, including cross-chain creation.

**Event Signature:** `CreateCode(address indexed codeOperator, address indexed referrer, bytes8 indexed code, address recipient, uint256 fromChain, uint32 discountPct, uint32 sharePct)`

**Emitted by:**

* [FeeRegistry.\_createCustomCode()](https://docs.cryptolegacy.app/documentation/functions-reference#_createcustomcode-fr1)

**Notes / Edge cases:** None

### UpdateCode (IFR1)

**Parameters:**

* `codeOperator (address, indexed)`: Sender of the cross-chain message that triggered the update.
* `referrer (address, indexed)`: Referrer that owns the updated code.
* `code (bytes8, indexed)`: Referral code being updated.
* `recipient (address)`: New recipient for referral rewards.
* `fromChain (uint256)`: Source chain ID that sent the update.
* `discountPct (uint32)`: Updated discount percentage (basis points).
* `sharePct (uint32)`: Updated referrer share percentage (basis points).

**Description:** Emitted after `crossUpdateCustomCode` applies a cross-chain update to a referral code, updating referrer/recipient and discount/share percentages.

**Event Signature:** `UpdateCode(address indexed codeOperator, address indexed referrer, bytes8 indexed code, address recipient, uint256 fromChain, uint32 discountPct, uint32 sharePct)`

**Emitted by:**

* [FeeRegistry.crossUpdateCustomCode()](https://docs.cryptolegacy.app/documentation/functions-reference#crossupdatecustomcode-fr1)

**Notes / Edge cases:** None

### ChangeCode (IFR1)

**Parameters:**

* `oldReferrer (address, indexed)`: Previous referrer (current owner) of the code.
* `newReferrer (address, indexed)`: New referrer set for the code.
* `code (bytes8, indexed)`: Referral code whose referrer changes.

**Description:** Emitted when a referrer transfers ownership of a referral code to a new referrer in `changeCodeReferrer`.

**Event Signature:** `ChangeCode(address indexed oldReferrer, address indexed newReferrer, bytes8 indexed code)`

**Emitted by:**

* [FeeRegistry.changeCodeReferrer()](https://docs.cryptolegacy.app/documentation/functions-reference#changecodereferrer-fr1)

**Notes / Edge cases:** None

### ChangeRecipient (IFR1)

**Parameters:**

* `referrer (address, indexed)`: Referrer that owns the code.
* `newRecipient (address, indexed)`: New recipient address for referral rewards.
* `code (bytes8, indexed)`: Referral code whose recipient changes.

**Description:** Emitted when the referrer updates the recipient address for a referral code in `changeRecipientReferrer`.

**Event Signature:** `ChangeRecipient(address indexed referrer, address indexed newRecipient, bytes8 indexed code)`

**Emitted by:**

* [FeeRegistry.changeRecipientReferrer()](https://docs.cryptolegacy.app/documentation/functions-reference#changerecipientreferrer-fr1)

**Notes / Edge cases:** None

### SetCrossChainsRef (IFR1)

**Parameters:**

* `shortCode (bytes8, indexed)`: Referral code being created or updated across chains.
* `isCreate (bool, indexed)`: Whether the cross-chain operation is a create (`true`) or update (`false`).
* `toChainIDs (uint256[])`: Destination chain IDs targeted by the cross-chain update.
* `crossChainFees (uint256[])`: Fees used for each destination chain send.

**Description:** Emitted after `\_setCrossChainsRef` prepares and sends cross-chain create/update commands for the referral code.

**Event Signature:** `SetCrossChainsRef(bytes8 indexed shortCode, bool indexed isCreate, uint256[] toChainIDs, uint256[] crossChainFees)`

**Emitted by:**

* [FeeRegistry.\_setCrossChainsRef()](https://docs.cryptolegacy.app/documentation/functions-reference#_setcrosschainsref-fr1)

**Notes / Edge cases:** None

### SetFeeBeneficiaries (IFR1)

**Parameters:**

* `beneficiaries (FeeBeneficiary[])`: New list of fee beneficiaries and their share percentages.

**Description:** Emitted after the fee beneficiary list is replaced and validated in `setFeeBeneficiaries`.

**Event Signature:** `SetFeeBeneficiaries(FeeBeneficiary[] beneficiaries)`

**Emitted by:**

* [FeeRegistry.setFeeBeneficiaries()](https://docs.cryptolegacy.app/documentation/functions-reference#setfeebeneficiaries-fr1)

**Notes / Edge cases:** None

### AddSupportedRefCodeInChain (IFR1)

**Parameters:**

* `chainId (uint256, indexed)`: Chain ID added to the supported referral-code chains list.

**Description:** Emitted for each chain ID added to `supportedRefInChains` via `setSupportedRefCodeInChains`.

**Event Signature:** `AddSupportedRefCodeInChain(uint256 indexed chainId)`

**Emitted by:**

* [FeeRegistry.setSupportedRefCodeInChains()](https://docs.cryptolegacy.app/documentation/functions-reference#setsupportedrefcodeinchains-fr1)

**Notes / Edge cases:** None

### RemoveSupportedRefCodeInChain (IFR1)

**Parameters:**

* `chainId (uint256, indexed)`: Chain ID removed from the supported referral-code chains list.

**Description:** Emitted for each chain ID removed from `supportedRefInChains` via `setSupportedRefCodeInChains`.

**Event Signature:** `RemoveSupportedRefCodeInChain(uint256 indexed chainId)`

**Emitted by:**

* [FeeRegistry.setSupportedRefCodeInChains()](https://docs.cryptolegacy.app/documentation/functions-reference#setsupportedrefcodeinchains-fr1)

**Notes / Edge cases:** None

### WithdrawFee (IFR1)

**Parameters:**

* `beneficiary (address, indexed)`: Fee beneficiary that receives the payout.
* `value (uint256)`: Amount of fee share transferred to the beneficiary.

**Description:** Emitted for each beneficiary when `withdrawAccumulatedFee` distributes the accumulated fee share to that beneficiary.

**Event Signature:** `WithdrawFee(address indexed beneficiary, uint256 value)`

**Emitted by:**

* [FeeRegistry.withdrawAccumulatedFee()](https://docs.cryptolegacy.app/documentation/functions-reference#withdrawaccumulatedfee-fr1)

**Notes / Edge cases:** None

### WithdrawRefFee (IFR1)

**Parameters:**

* `recipient (address, indexed)`: Referral fee recipient address.
* `value (uint256)`: Amount of accumulated referral fee transferred.

**Description:** Emitted when `withdrawReferralAccumulatedFee` transfers the accumulated referral fee to the recipient for the given code.

**Event Signature:** `WithdrawRefFee(address indexed recipient, uint256 value)`

**Emitted by:**

* [FeeRegistry.withdrawReferralAccumulatedFee()](https://docs.cryptolegacy.app/documentation/functions-reference#withdrawreferralaccumulatedfee-fr1)

**Notes / Edge cases:** None

## ILockChainGate (ILCG1)

### AddLockOperator (ILCG1)

**Parameters:**

* `lockOperator (address, indexed)`: Address granted the lock-operator role.

**Description:** Emitted when a lock operator is added to the allowlist.

**Event Signature:** `AddLockOperator(address indexed lockOperator)`

**Emitted by:**

* [LockChainGate.setLockOperator()](https://docs.cryptolegacy.app/documentation/functions-reference#setlockoperator-lcg1)

**Notes / Edge cases:** None

### RemoveLockOperator (ILCG1)

**Parameters:**

* `lockOperator (address, indexed)`: Address removed from the lock-operator role.

**Description:** Emitted when a lock operator is removed from the allowlist.

**Event Signature:** `RemoveLockOperator(address indexed lockOperator)`

**Emitted by:**

* [LockChainGate.setLockOperator()](https://docs.cryptolegacy.app/documentation/functions-reference#setlockoperator-lcg1)

**Notes / Edge cases:** None

### SetDestinationChainContract (ILCG1)

**Parameters:**

* `chainId (uint256, indexed)`: Destination chain ID being configured.
* `chainContract (address, indexed)`: Contract address on the destination chain.

**Description:** Emitted when the destination-chain contract mapping is set or updated.

**Event Signature:** `SetDestinationChainContract(uint256 indexed chainId, address indexed chainContract)`

**Emitted by:**

* [LockChainGate.\_setDestinationChainContract()](https://docs.cryptolegacy.app/documentation/functions-reference#_setdestinationchaincontract-lcg1)

**Notes / Edge cases:** None

### SetSourceChainContract (ILCG1)

**Parameters:**

* `chainId (uint256, indexed)`: Source chain ID being configured.
* `chainContract (address, indexed)`: Contract address on the source chain.

**Description:** Emitted when the source-chain contract mapping is set or updated.

**Event Signature:** `SetSourceChainContract(uint256 indexed chainId, address indexed chainContract)`

**Emitted by:**

* [LockChainGate.\_setSourceChainContract()](https://docs.cryptolegacy.app/documentation/functions-reference#_setsourcechaincontract-lcg1)

**Notes / Edge cases:** None

### SetDeBridgeGate (ILCG1)

**Parameters:**

* `deBridgeGate (address, indexed)`: Address of the deBridgeGate contract.

**Description:** Emitted when the deBridgeGate address is set or updated.

**Event Signature:** `SetDeBridgeGate(address indexed deBridgeGate)`

**Emitted by:**

* [LockChainGate.setDebridgeGate()](https://docs.cryptolegacy.app/documentation/functions-reference#setdebridgegate-lcg1)

**Notes / Edge cases:** None

### SetDeBridgeNativeFee (ILCG1)

**Parameters:**

* `chainId (uint256, indexed)`: Chain ID whose native fee is set.
* `nativeFee (uint256)`: Native fee amount configured for the chain.

**Description:** Emitted when the native fee for a chain is set or updated.

**Event Signature:** `SetDeBridgeNativeFee(uint256 indexed chainId, uint256 nativeFee)`

**Emitted by:**

* [LockChainGate.setDebridgeNativeFee()](https://docs.cryptolegacy.app/documentation/functions-reference#setdebridgenativefee-lcg1)

**Notes / Edge cases:** None

### SetLockPeriodConfig (ILCG1)

**Parameters:**

* `lockPeriod (uint256)`: Required lock period for a lifetime NFT.
* `transferTimeout (uint256)`: Timeout after which transfers are permitted.

**Description:** Emitted when the lock period and transfer timeout configuration is updated.

**Event Signature:** `SetLockPeriodConfig(uint256 lockPeriod, uint256 transferTimeout)`

**Emitted by:**

* [LockChainGate.\_initializeLockChainGate()](https://docs.cryptolegacy.app/documentation/functions-reference#_initializelockchaingate-lcg1)
* [LockChainGate.setLockPeriod()](https://docs.cryptolegacy.app/documentation/functions-reference#setlockperiod-lcg1)

**Notes / Edge cases:** None

### SendToChain (ILCG1)

**Parameters:**

* `toChainId (uint256, indexed)`: Destination chain ID.
* `submissionId (bytes32, indexed)`: deBridge submission ID.
* `value (uint256)`: Native fee value sent with the submission.
* `dstTransactionCall (bytes)`: Encoded destination-chain call payload.

**Description:** Emitted when a cross-chain call/transfer is submitted to deBridge.

**Event Signature:** `SendToChain(uint256 indexed toChainId, bytes32 indexed submissionId, uint256 value, bytes dstTransactionCall)`

**Emitted by:**

* [LockChainGate.\_send()](https://docs.cryptolegacy.app/documentation/functions-reference#_send-lcg1)

**Notes / Edge cases:** None

### LockNft (ILCG1)

**Parameters:**

* `lockedAt (uint256)`: Timestamp when the NFT was locked.
* `tokenId (uint256, indexed)`: Token ID that was locked.
* `holder (address, indexed)`: Address that locked the NFT.

**Description:** Emitted when a lifetime NFT is locked for a holder.

**Event Signature:** `LockNft(uint256 lockedAt, uint256 indexed tokenId, address indexed holder)`

**Emitted by:**

* [LockChainGate.lockLifetimeNft()](https://docs.cryptolegacy.app/documentation/functions-reference#locklifetimenft-lcg1)

**Notes / Edge cases:** None

### UnlockNft (ILCG1)

**Parameters:**

* `lockedAt (uint256)`: Timestamp when the NFT was locked.
* `tokenId (uint256, indexed)`: Token ID that was unlocked.
* `holder (address, indexed)`: Address that previously held the lock.
* `recipient (address, indexed)`: Address receiving the unlocked NFT.

**Description:** Emitted when a lifetime NFT is unlocked and transferred to a recipient.

**Event Signature:** `UnlockNft(uint256 lockedAt, uint256 indexed tokenId, address indexed holder, address indexed recipient)`

**Emitted by:**

* [LockChainGate.unlockLifetimeNft()](https://docs.cryptolegacy.app/documentation/functions-reference#unlocklifetimenft-lcg1)

**Notes / Edge cases:** None

### ApproveNft (ILCG1)

**Parameters:**

* `tokenId (uint256, indexed)`: Token ID being approved.
* `holder (address, indexed)`: Current holder granting the approval.
* `approveTo (address, indexed)`: Address approved to manage the NFT.

**Description:** Emitted when a holder approves another address to manage a locked NFT.

**Event Signature:** `ApproveNft(uint256 indexed tokenId, address indexed holder, address indexed approveTo)`

**Emitted by:**

* [LockChainGate.approveLifetimeNftTo()](https://docs.cryptolegacy.app/documentation/functions-reference#approvelifetimenftto-lcg1)

**Notes / Edge cases:** None

### TransferNft (ILCG1)

**Parameters:**

* `tokenId (uint256, indexed)`: Token ID being transferred.
* `holder (address, indexed)`: Previous owner of the NFT.
* `transferTo (address, indexed)`: New owner of the NFT.
* `fromChainID (uint256)`: Origin chain ID for the transfer (0 for same-chain).

**Description:** Emitted when NFT ownership is transferred locally or via a cross-chain update.

**Event Signature:** `TransferNft(uint256 indexed tokenId, address indexed holder, address indexed transferTo, uint256 fromChainID)`

**Emitted by:**

* [LockChainGate.\_transferLifetimeNftTo()](https://docs.cryptolegacy.app/documentation/functions-reference#_transferlifetimenftto-lcg1)

**Notes / Edge cases:** None

### LockToChain (ILCG1)

**Parameters:**

* `sender (address, indexed)`: Address that initiated the lock-to-chain action.
* `tokenId (uint256, indexed)`: Token ID being locked to the chain.
* `toChainID (uint256, indexed)`: Destination chain ID.
* `submissionId (bytes32)`: deBridge submission ID.

**Description:** Emitted when a lock command is sent to a destination chain.

**Event Signature:** `LockToChain(address indexed sender, uint256 indexed tokenId, uint256 indexed toChainID, bytes32 submissionId)`

**Emitted by:**

* [LockChainGate.\_lockLifetimeNftToChain()](https://docs.cryptolegacy.app/documentation/functions-reference#_locklifetimenfttochain-lcg1)

**Notes / Edge cases:** None

### UpdateLockToChain (ILCG1)

**Parameters:**

* `sender (address, indexed)`: Address that initiated the update.
* `tokenId (uint256, indexed)`: Token ID whose owner is being updated.
* `toChainID (uint256, indexed)`: Destination chain ID.
* `submissionId (bytes32)`: deBridge submission ID.

**Description:** Emitted when an ownership update is sent to a destination chain.

**Event Signature:** `UpdateLockToChain(address indexed sender, uint256 indexed tokenId, uint256 indexed toChainID, bytes32 submissionId)`

**Emitted by:**

* [LockChainGate.\_updateLifetimeNftOwnerOnChain()](https://docs.cryptolegacy.app/documentation/functions-reference#_updatelifetimenftowneronchain-lcg1)

**Notes / Edge cases:** None

### Update (ILCG1)

**Parameters:**

* `sender (address, indexed)`: Address that initiated the update.
* `tokenId (uint256, indexed)`: Token ID being updated.
* `toChainID (uint256, indexed)`: Destination chain ID.
* `submissionId (bytes32)`: deBridge submission ID.

**Description:** Emitted when a lock-chain update submission is created.

**Event Signature:** `Update(address indexed sender, uint256 indexed tokenId, uint256 indexed toChainID, bytes32 submissionId)`

**Emitted by:** None

**Notes / Edge cases:** None

### UnlockFromChain (ILCG1)

**Parameters:**

* `sender (address, indexed)`: Address that initiated the unlock.
* `tokenId (uint256, indexed)`: Token ID being unlocked.
* `toChainID (uint256, indexed)`: Destination chain ID for the unlock.
* `submissionId (bytes32)`: deBridge submission ID.

**Description:** Emitted when an unlock command is sent to a destination chain.

**Event Signature:** `UnlockFromChain(address indexed sender, uint256 indexed tokenId, uint256 indexed toChainID, bytes32 submissionId)`

**Emitted by:**

* [LockChainGate.unlockLifetimeNftFromChain()](https://docs.cryptolegacy.app/documentation/functions-reference#unlocklifetimenftfromchain-lcg1)

**Notes / Edge cases:** None

### CrossLockNft (ILCG1)

**Parameters:**

* `lockedAt (uint256)`: Timestamp when the NFT was locked on the source chain.
* `tokenId (uint256, indexed)`: Token ID locked across chains.
* `holder (address, indexed)`: Holder address on the destination chain.
* `fromChainID (uint256, indexed)`: Source chain ID.

**Description:** Emitted when a cross-chain lock is received from another chain.

**Event Signature:** `CrossLockNft(uint256 lockedAt, uint256 indexed tokenId, address indexed holder, uint256 indexed fromChainID)`

**Emitted by:**

* [LockChainGate.crossLockLifetimeNft()](https://docs.cryptolegacy.app/documentation/functions-reference#crosslocklifetimenft-lcg1)

**Notes / Edge cases:** None

### CrossUnlockNft (ILCG1)

**Parameters:**

* `lockedAt (uint256)`: Timestamp when the NFT was locked on the source chain.
* `tokenId (uint256, indexed)`: Token ID being unlocked across chains.
* `holder (address, indexed)`: Holder address on the destination chain.
* `fromChainID (uint256, indexed)`: Source chain ID.

**Description:** Emitted when a cross-chain unlock is received from another chain.

**Event Signature:** `CrossUnlockNft(uint256 lockedAt, uint256 indexed tokenId, address indexed holder, uint256 indexed fromChainID)`

**Emitted by:**

* [LockChainGate.crossUnlockLifetimeNft()](https://docs.cryptolegacy.app/documentation/functions-reference#crossunlocklifetimenft-lcg1)

**Notes / Edge cases:** None

### CrossUpdateNftOwner (ILCG1)

**Parameters:**

* `fromChainID (uint256, indexed)`: Source chain ID.
* `tokenId (uint256, indexed)`: Token ID whose owner is updated.
* `transferTo (address, indexed)`: New owner address on the destination chain.

**Description:** Emitted when a cross-chain owner update is received from another chain.

**Event Signature:** `CrossUpdateNftOwner(uint256 indexed fromChainID, uint256 indexed tokenId, address indexed transferTo)`

**Emitted by:**

* [LockChainGate.crossUpdateNftOwner()](https://docs.cryptolegacy.app/documentation/functions-reference#crossupdatenftowner-lcg1)

**Notes / Edge cases:** None

### SetReferralCode (ILCG1)

**Parameters:**

* `referralCode (uint32, indexed)`: Referral code applied to cross-chain submissions.

**Description:** Emitted when the referral code used for submissions is set or updated.

**Event Signature:** `SetReferralCode(uint32 indexed referralCode)`

**Emitted by:**

* [LockChainGate.setReferralCode()](https://docs.cryptolegacy.app/documentation/functions-reference#setreferralcode-lcg1)

**Notes / Edge cases:** None

### SetCustomChainId (ILCG1)

**Parameters:**

* `customChainId (uint256, indexed)`: Custom chain ID override used for cross-chain messages.

**Description:** Emitted when the custom chain ID override is set or updated.

**Event Signature:** `SetCustomChainId(uint256 indexed customChainId)`

**Emitted by:**

* [LockChainGate.setCustomChainId()](https://docs.cryptolegacy.app/documentation/functions-reference#setcustomchainid-lcg1)

**Notes / Edge cases:** None

## ILegacyMessenger (ILM1)

### LegacyMessage (ILM1)

**Parameters:**

* `legacy (address, indexed)`: CryptoLegacy contract address sending the message.
* `toRecipient (bytes32, indexed)`: Recipient hash the message is addressed to.
* `messageHash (bytes32)`: Hash of the message payload.
* `message (bytes)`: Raw message payload.
* `messageType (uint256, indexed)`: Message type identifier.

**Description:** Emitted when a legacy message is sent to a recipient.

**Event Signature:** `LegacyMessage(address indexed legacy, bytes32 indexed toRecipient, bytes32 messageHash, bytes message, uint256 indexed messageType)`

**Emitted by:**

* [LegacyMessenger.sendMessagesTo()](https://docs.cryptolegacy.app/documentation/functions-reference#sendmessagesto-lm1)

**Notes / Edge cases:** None

### LegacyMessageCheck (ILM1)

**Parameters:**

* `legacy (address, indexed)`: CryptoLegacy contract address sending the message.
* `toBeneficiary (bytes32, indexed)`: Beneficiary hash the message targets for verification.
* `messageHash (bytes32)`: Hash of the message payload.
* `message (bytes)`: Raw message payload.
* `messageType (uint256, indexed)`: Message type identifier.

**Description:** Emitted when a message is sent for beneficiary verification/check.

**Event Signature:** `LegacyMessageCheck(address indexed legacy, bytes32 indexed toBeneficiary, bytes32 messageHash, bytes message, uint256 indexed messageType)`

**Emitted by:**

* [LegacyMessenger.sendMessagesTo()](https://docs.cryptolegacy.app/documentation/functions-reference#sendmessagesto-lm1)

**Notes / Edge cases:** None

## ILido (ILD1)

**No events in this contract/library.**

## ILidoWithdrawalQueue (ILWQ1)

**No events in this contract/library.**

## ILifetimeNft (ILN1)

**No events in this contract/library.**

## IPermit2 (IPM21)

**No events in this contract/library.**

## IPluginsRegistry (IPR1)

### AddPlugin (IPR1)

**Parameters:**

* `plugin (address, indexed)`: Plugin contract address being registered.
* `description (string)`: Human-readable plugin description.

**Description:** Emitted when a plugin is added to the registry with its description.

**Event Signature:** `AddPlugin(address indexed plugin, string description)`

**Emitted by:**

* [PluginsRegistry.addPlugin()](https://docs.cryptolegacy.app/documentation/functions-reference#addplugin-pr1)

**Notes / Edge cases:** None

### AddPluginDescription (IPR1)

**Parameters:**

* `plugin (address, indexed)`: Plugin contract address being updated.
* `description (string)`: Updated human-readable plugin description.

**Description:** Emitted when a plugin description is set or updated.

**Event Signature:** `AddPluginDescription(address indexed plugin, string description)`

**Emitted by:**

* [PluginsRegistry.addPluginDescription()](https://docs.cryptolegacy.app/documentation/functions-reference#addplugindescription-pr1)

**Notes / Edge cases:** None

### RemovePlugin (IPR1)

**Parameters:**

* `plugin (address, indexed)`: Plugin contract address removed from the registry.

**Description:** Emitted when a plugin is removed from the registry.

**Event Signature:** `RemovePlugin(address indexed plugin)`

**Emitted by:**

* [PluginsRegistry.removePlugin()](https://docs.cryptolegacy.app/documentation/functions-reference#removeplugin-pr1)

**Notes / Edge cases:** None

## ISafeMinimalMultisig (ISM1)

### CreateSafeMinimalMultisigProposal (ISM1)

**Parameters:**

* `proposalId (uint256)`: Identifier of the newly created proposal.
* `voter (bytes32)`: Voter identifier that created the proposal.
* `reqConfirmations (uint128)`: Required confirmations for this proposal.

**Description:** Emitted when a multisig proposal is created.

**Event Signature:** `CreateSafeMinimalMultisigProposal(uint256 proposalId, bytes32 voter, uint128 reqConfirmations)`

**Emitted by:**

* [BeneficiaryPluginAddRights.barPropose()](https://docs.cryptolegacy.app/documentation/functions-reference#barpropose-bpar1)
* [LegacyRecoveryPlugin.lrPropose()](https://docs.cryptolegacy.app/documentation/functions-reference#lrpropose-lrp1)
* [LibSafeMinimalBeneficiaryMultisig.\_propose()](https://docs.cryptolegacy.app/documentation/functions-reference#_propose-lsmb1)
* [LibSafeMinimalMultisig.\_propose()](https://docs.cryptolegacy.app/documentation/functions-reference#_propose-lsm1)

**Notes / Edge cases:** None

### CancelSafeMinimalMultisigProposal (ISM1)

**Parameters:**

* `proposalId (uint256)`: Identifier of the canceled proposal.
* `voter (bytes32)`: Voter identifier that canceled the proposal.
* `reqConfirmations (uint128)`: Required confirmations for this proposal.
* `status (ProposalStatus)`: Proposal status after cancellation.

**Description:** Emitted when a multisig proposal is canceled.

**Event Signature:** `CancelSafeMinimalMultisigProposal(uint256 proposalId, bytes32 voter, uint128 reqConfirmations, ProposalStatus status)`

**Emitted by:**

* [BeneficiaryPluginAddRights.barCancel()](https://docs.cryptolegacy.app/documentation/functions-reference#barcancel-bpar1)
* [LegacyRecoveryPlugin.lrCancel()](https://docs.cryptolegacy.app/documentation/functions-reference#lrcancel-lrp1)
* [LibSafeMinimalBeneficiaryMultisig.\_cancel()](https://docs.cryptolegacy.app/documentation/functions-reference#_cancel-lsmb1)
* [LibSafeMinimalMultisig.\_cancel()](https://docs.cryptolegacy.app/documentation/functions-reference#_cancel-lsm1)

**Notes / Edge cases:** None

### ConfirmSafeMinimalMultisigProposal (ISM1)

**Parameters:**

* `proposalId (uint256)`: Identifier of the confirmed proposal.
* `voter (bytes32)`: Voter identifier that confirmed the proposal.
* `reqConfirmations (uint128)`: Required confirmations for this proposal.
* `confirms (uint256)`: Current number of confirmations after this vote.

**Description:** Emitted when a voter confirms a multisig proposal.

**Event Signature:** `ConfirmSafeMinimalMultisigProposal(uint256 proposalId, bytes32 voter, uint128 reqConfirmations, uint256 confirms)`

**Emitted by:**

* [BeneficiaryPluginAddRights.barConfirm()](https://docs.cryptolegacy.app/documentation/functions-reference#barconfirm-bpar1)
* [LegacyRecoveryPlugin.lrConfirm()](https://docs.cryptolegacy.app/documentation/functions-reference#lrconfirm-lrp1)
* [LibSafeMinimalBeneficiaryMultisig.\_confirm()](https://docs.cryptolegacy.app/documentation/functions-reference#_confirm-lsmb1)
* [LibSafeMinimalMultisig.\_confirm()](https://docs.cryptolegacy.app/documentation/functions-reference#_confirm-lsm1)

**Notes / Edge cases:** None

### ExecuteSafeMinimalMultisigProposal (ISM1)

**Parameters:**

* `proposalId (uint256)`: Identifier of the executed proposal.
* `voter (bytes32)`: Voter identifier that executed the proposal.
* `executed (bool)`: Whether the execution succeeded.
* `returnData (bytes)`: Return data from the executed call.

**Description:** Emitted when a multisig proposal is executed (or execution is attempted).

**Event Signature:** `ExecuteSafeMinimalMultisigProposal(uint256 proposalId, bytes32 voter, bool executed, bytes returnData)`

**Emitted by:**

* [BeneficiaryPluginAddRights.barPropose()](https://docs.cryptolegacy.app/documentation/functions-reference#barpropose-bpar1)
* [BeneficiaryPluginAddRights.barConfirm()](https://docs.cryptolegacy.app/documentation/functions-reference#barconfirm-bpar1)
* [LegacyRecoveryPlugin.lrPropose()](https://docs.cryptolegacy.app/documentation/functions-reference#lrpropose-lrp1)
* [LegacyRecoveryPlugin.lrConfirm()](https://docs.cryptolegacy.app/documentation/functions-reference#lrconfirm-lrp1)
* [LibSafeMinimalMultisig.\_execute()](https://docs.cryptolegacy.app/documentation/functions-reference#_execute-lsm1)

**Notes / Edge cases:** None

### SetVotersAndConfirmations (ISM1)

**Parameters:**

* `voters (bytes32[])`: New list of voter identifiers.
* `requiredConfirmations (uint128)`: New required confirmations threshold.

**Description:** Emitted when the voter set and confirmation threshold are updated.

**Event Signature:** `SetVotersAndConfirmations(bytes32[] voters, uint128 requiredConfirmations)`

**Emitted by:**

* [LegacyRecoveryPlugin.lrSetMultisigConfig()](https://docs.cryptolegacy.app/documentation/functions-reference#lrsetmultisigconfig-lrp1)
* [LibSafeMinimalMultisig.\_setVotersAndConfirmations()](https://docs.cryptolegacy.app/documentation/functions-reference#_setvotersandconfirmations-lsm1)

**Notes / Edge cases:** None

### SetConfirmations (ISM1)

**Parameters:**

* `requiredConfirmations (uint128)`: New required confirmations threshold.

**Description:** Emitted when the required confirmations threshold is updated.

**Event Signature:** `SetConfirmations(uint128 requiredConfirmations)`

**Emitted by:**

* [BeneficiaryPluginAddRights.barSetMultisigConfig()](https://docs.cryptolegacy.app/documentation/functions-reference#barsetmultisigconfig-bpar1)
* [BeneficiaryPluginAddRights.barPropose()](https://docs.cryptolegacy.app/documentation/functions-reference#barpropose-bpar1)
* [BeneficiaryPluginAddRights.barConfirm()](https://docs.cryptolegacy.app/documentation/functions-reference#barconfirm-bpar1)
* [LibSafeMinimalBeneficiaryMultisig.\_setConfirmations()](https://docs.cryptolegacy.app/documentation/functions-reference#_setconfirmations-lsmb1)

**Notes / Edge cases:** None

### AddHeldEth (ISM1)

**Parameters:**

* `voter (bytes32)`: Voter identifier whose held ETH balance increased.
* `value (uint256)`: Amount of ETH credited.

**Description:** Emitted when ETH is credited to a voter's held balance.

**Event Signature:** `AddHeldEth(bytes32 voter, uint256 value)`

**Emitted by:**

* [BeneficiaryPluginAddRights.barPropose()](https://docs.cryptolegacy.app/documentation/functions-reference#barpropose-bpar1)
* [BeneficiaryPluginAddRights.barConfirm()](https://docs.cryptolegacy.app/documentation/functions-reference#barconfirm-bpar1)
* [LegacyRecoveryPlugin.lrPropose()](https://docs.cryptolegacy.app/documentation/functions-reference#lrpropose-lrp1)
* [LegacyRecoveryPlugin.lrConfirm()](https://docs.cryptolegacy.app/documentation/functions-reference#lrconfirm-lrp1)
* [LibSafeMinimalMultisig.\_updateHeldEth()](https://docs.cryptolegacy.app/documentation/functions-reference#_updateheldeth-lsm1)

**Notes / Edge cases:** None

### WithdrawHeldEth (ISM1)

**Parameters:**

* `voter (bytes32)`: Voter identifier whose held ETH balance decreased.
* `value (uint256)`: Amount of ETH withdrawn.

**Description:** Emitted when ETH is withdrawn from a voter's held balance.

**Event Signature:** `WithdrawHeldEth(bytes32 voter, uint256 value)`

**Emitted by:**

* [BeneficiaryPluginAddRights.barWithdrawHeldEth()](https://docs.cryptolegacy.app/documentation/functions-reference#barwithdrawheldeth-bpar1)
* [LegacyRecoveryPlugin.lrWithdrawHeldEth()](https://docs.cryptolegacy.app/documentation/functions-reference#lrwithdrawheldeth-lrp1)
* [LibSafeMinimalBeneficiaryMultisig.\_withdrawHeldEth()](https://docs.cryptolegacy.app/documentation/functions-reference#_withdrawheldeth-lsmb1)
* [LibSafeMinimalMultisig.\_withdrawHeldEth()](https://docs.cryptolegacy.app/documentation/functions-reference#_withdrawheldeth-lsm1)

**Notes / Edge cases:** None

## ISignatureRoleTimelock (ISRT1)

### SetMaxExecutionPeriod (ISRT1)

**Parameters:**

* `maxExecutionPeriod (uint128, indexed)`: Maximum execution window for scheduled calls (seconds).

**Description:** Emitted when the maximum execution period is set or updated.

**Event Signature:** `SetMaxExecutionPeriod(uint128 indexed maxExecutionPeriod)`

**Emitted by:**

* [SignatureRoleTimelock.setMaxExecutionPeriod()](https://docs.cryptolegacy.app/documentation/functions-reference#setmaxexecutionperiod-srt1)

**Notes / Edge cases:** None

### AddRoleAccount (ISRT1)

**Parameters:**

* `role (bytes32, indexed)`: Role identifier being granted.
* `account (address, indexed)`: Account address granted the role.

**Description:** Emitted when an account is granted a role.

**Event Signature:** `AddRoleAccount(bytes32 indexed role, address indexed account)`

**Emitted by:**

* [SignatureRoleTimelock.\_addRoleAccount()](https://docs.cryptolegacy.app/documentation/functions-reference#_addroleaccount-srt1)

**Notes / Edge cases:** None

### RemoveRoleAccount (ISRT1)

**Parameters:**

* `role (bytes32, indexed)`: Role identifier being revoked.
* `account (address, indexed)`: Account address removed from the role.

**Description:** Emitted when an account is removed from a role.

**Event Signature:** `RemoveRoleAccount(bytes32 indexed role, address indexed account)`

**Emitted by:**

* [SignatureRoleTimelock.\_removeRoleAccount()](https://docs.cryptolegacy.app/documentation/functions-reference#_removeroleaccount-srt1)

**Notes / Edge cases:** None

### AddSignatureRole (ISRT1)

**Parameters:**

* `target (address, indexed)`: Target contract address.
* `signature (bytes4, indexed)`: Function selector being restricted.
* `role (bytes32, indexed)`: Role required to schedule/execute the call.
* `timelock (uint256)`: Timelock delay (seconds) for the signature.

**Description:** Emitted when a role requirement and timelock are assigned to a target function.

**Event Signature:** `AddSignatureRole(address indexed target, bytes4 indexed signature, bytes32 indexed role, uint256 timelock)`

**Emitted by:**

* [SignatureRoleTimelock.\_addSignatureRole()](https://docs.cryptolegacy.app/documentation/functions-reference#_addsignaturerole-srt1)

**Notes / Edge cases:** None

### RemoveSignatureRole (ISRT1)

**Parameters:**

* `target (address, indexed)`: Target contract address.
* `signature (bytes4, indexed)`: Function selector being unassigned.

**Description:** Emitted when a role requirement for a target function is removed.

**Event Signature:** `RemoveSignatureRole(address indexed target, bytes4 indexed signature)`

**Emitted by:**

* [SignatureRoleTimelock.\_removeSignatureRole()](https://docs.cryptolegacy.app/documentation/functions-reference#_removesignaturerole-srt1)

**Notes / Edge cases:** None

### AddTarget (ISRT1)

**Parameters:**

* `target (address, indexed)`: Target contract address added to the allowlist.

**Description:** Emitted when a target contract is added to the allowlist.

**Event Signature:** `AddTarget(address indexed target)`

**Emitted by:**

* [SignatureRoleTimelock.\_addSignatureRole()](https://docs.cryptolegacy.app/documentation/functions-reference#_addsignaturerole-srt1)

**Notes / Edge cases:** None

### RemoveTarget (ISRT1)

**Parameters:**

* `target (address, indexed)`: Target contract address removed from the allowlist.

**Description:** Emitted when a target contract is removed from the allowlist.

**Event Signature:** `RemoveTarget(address indexed target)`

**Emitted by:**

* [SignatureRoleTimelock.\_removeSignatureRole()](https://docs.cryptolegacy.app/documentation/functions-reference#_removesignaturerole-srt1)

**Notes / Edge cases:** None

### CallScheduled (ISRT1)

**Parameters:**

* `callId (bytes32, indexed)`: Unique identifier of the scheduled call.
* `caller (address, indexed)`: Address that scheduled the call.
* `target (address, indexed)`: Target contract address.
* `signature (bytes4)`: Function selector to be executed.
* `executeAfter (uint256)`: Earliest timestamp when the call can be executed.

**Description:** Emitted when a call is scheduled with a timelock.

**Event Signature:** `CallScheduled(bytes32 indexed callId, address indexed caller, address indexed target, bytes4 signature, uint256 executeAfter)`

**Emitted by:**

* [SignatureRoleTimelock.\_scheduleCall()](https://docs.cryptolegacy.app/documentation/functions-reference#_schedulecall-srt1)

**Notes / Edge cases:** None

### CallExecuted (ISRT1)

**Parameters:**

* `callId (bytes32, indexed)`: Identifier of the executed call.
* `msgSender (address, indexed)`: Executor address.
* `returnData (bytes)`: Return data from the executed call.

**Description:** Emitted when a scheduled call is executed.

**Event Signature:** `CallExecuted(bytes32 indexed callId, address indexed msgSender, bytes returnData)`

**Emitted by:**

* [SignatureRoleTimelock.\_executeCall()](https://docs.cryptolegacy.app/documentation/functions-reference#_executecall-srt1)

**Notes / Edge cases:** None

### CallCanceled (ISRT1)

**Parameters:**

* `callId (bytes32, indexed)`: Identifier of the canceled call.
* `msgSender (address, indexed)`: Address that canceled the call.

**Description:** Emitted when a scheduled call is canceled.

**Event Signature:** `CallCanceled(bytes32 indexed callId, address indexed msgSender)`

**Emitted by:**

* [SignatureRoleTimelock.\_cancelCall()](https://docs.cryptolegacy.app/documentation/functions-reference#_cancelcall-srt1)

**Notes / Edge cases:** None

## IStataToken (ISTA1)

**No events in this contract/library.**

## IStataTokenFactory (ISTF1)

**No events in this contract/library.**

## ITrustedGuardiansPlugin (ITGP1)

### SetGuardian (ITGP1)

**Parameters:**

* `guardian (bytes32, indexed)`: Guardian identifier hash that was added to or removed from the guardians set.
* `\_isAdd (bool, indexed)`: True if the guardian was added; false if removed.

**Description:** Emitted when a guardian is added to or removed from the guardians set during initialization or updates.

**Event Signature:** `SetGuardian(bytes32 indexed guardian, bool indexed \_isAdd)`

**Emitted by:**

* [TrustedGuardiansPlugin.\_setGuardians()](https://docs.cryptolegacy.app/documentation/functions-reference#_setguardians-tgp1)

**Notes / Edge cases:** None

### GuardiansVoteForDistribution (ITGP1)

**Parameters:**

* `guardian (bytes32, indexed)`: Guardian identifier hash that submitted the vote.
* `votedCount (uint256)`: Current number of recorded guardian votes after this vote (may be reset to 0 if the threshold is reached).

**Description:** Emitted when a guardian successfully votes for distribution and the vote count is updated.

**Event Signature:** `GuardiansVoteForDistribution(bytes32 indexed guardian, uint256 votedCount)`

**Emitted by:**

* [TrustedGuardiansPlugin.guardiansVoteForDistribution()](https://docs.cryptolegacy.app/documentation/functions-reference#guardiansvotefordistribution-tgp1)

**Notes / Edge cases:** None

### GuardiansDistributionStartSet (ITGP1)

**Parameters:**

* `guardian (bytes32, indexed)`: Guardian identifier hash whose vote triggered or updated the distribution start time.
* `distributionStartAt (uint256)`: Timestamp when distribution becomes available after the guardians challenge timeout.

**Description:** Emitted when the voting threshold is met and the distribution start time is set or updated.

**Event Signature:** `GuardiansDistributionStartSet(bytes32 indexed guardian, uint256 distributionStartAt)`

**Emitted by:**

* [TrustedGuardiansPlugin.guardiansVoteForDistribution()](https://docs.cryptolegacy.app/documentation/functions-reference#guardiansvotefordistribution-tgp1)

**Notes / Edge cases:** None

### SetGuardiansConfig (ITGP1)

**Parameters:**

* `guardiansThreshold (uint128)`: Required number of guardian votes to trigger distribution.
* `guardiansChallengeTimeout (uint64)`: Challenge timeout in seconds applied once the threshold is met.

**Description:** Emitted when the guardians threshold and challenge timeout configuration is set or updated.

**Event Signature:** `SetGuardiansConfig(uint128 guardiansThreshold, uint64 guardiansChallengeTimeout)`

**Emitted by:**

* [TrustedGuardiansPlugin.\_setGuardiansConfig()](https://docs.cryptolegacy.app/documentation/functions-reference#_setguardiansconfig-tgp1)

**Notes / Edge cases:** None

### ResetGuardiansVoting (ITGP1)

**Parameters:** None

**Description:** Emitted when guardian voting state is reset, clearing recorded guardian votes and resetting the distribution start time.

**Event Signature:** `ResetGuardiansVoting()`

**Emitted by:**

* [LegacyRecoveryPlugin.lrResetGuardianVoting()](https://docs.cryptolegacy.app/documentation/functions-reference#lrresetguardianvoting-lrp1)
* [TrustedGuardiansPlugin.resetGuardianVoting()](https://docs.cryptolegacy.app/documentation/functions-reference#resetguardianvoting-tgp1)
* [LibTrustedGuardiansPlugin.\_resetGuardianVoting()](https://docs.cryptolegacy.app/documentation/functions-reference#_resetguardianvoting-ltgp1)

**Notes / Edge cases:** None

### ClearGuardiansVoted (ITGP1)

**Parameters:** None

**Description:** Emitted when the guardian votes list is cleared after guardians configuration changes.

**Event Signature:** `ClearGuardiansVoted()`

**Emitted by:**

* [TrustedGuardiansPlugin.\_afterGuardiansSet()](https://docs.cryptolegacy.app/documentation/functions-reference#_afterguardiansset-tgp1)

**Notes / Edge cases:** None

## DiamondLoupeFacet (DLF1)

**No events in this contract/library.**

## IUniversalRouter (IUR1)

**No events in this contract/library.**

## IWETH (IWETH1)

**No events in this contract/library.**

## IWstETH (IWSTETH1)

**No events in this contract/library.**

## WethUnwrapIWETH (WUI1)

**No events in this contract/library.**

## LibCLUtils (LCLU1)

**No events in this contract/library.**

## LibClaimMigrationCore (LCMC1)

**No events in this contract/library.**

## LibOneStepClaimMigration (LOSCM1)

**No events in this contract/library.**

## LibTwoStepClaimMigration (LTSCM1)

**No events in this contract/library.**

## LibCreate3 (LC31)

**No events in this contract/library.**

## LibCryptoLegacy (LCL1)

**No events in this contract/library.**

## LibCryptoLegacyDeploy (LCLD1)

### CryptoLegacyCreation (LCLD1)

**Parameters:**

* `addr (address)`: Address of the newly deployed CryptoLegacy contract.
* `salt (bytes32)`: The final CREATE3 salt derived from the owner and factory/user salt used for deployment.
* `userSalt (bytes32)`: The factory/user-provided salt that seeds the final CREATE3 salt (or its fallback value).

**Description:** Emitted after a successful CREATE3 deployment to record the deployed address and salts used.

**Event Signature:** `CryptoLegacyCreation(address addr, bytes32 salt, bytes32 userSalt)`

**Emitted by:**

* [LibCryptoLegacyDeploy.\_deployByCreate3()](https://docs.cryptolegacy.app/documentation/functions-reference#_deploybycreate3-lcld1)

**Notes / Edge cases:** None

## LibCryptoLegacyPlugins (LCLP1)

**No events in this contract/library.**

## LibDiamond (LD1)

### OwnershipTransferred (LD1)

**Parameters:**

* `previousOwner (address, indexed)`: Address that previously owned the diamond.
* `newOwner (address, indexed)`: Address that becomes the new diamond owner.

**Description:** Emitted when the diamond owner is updated via `LibDiamond.setContractOwner`.

**Event Signature:** `OwnershipTransferred(address indexed previousOwner, address indexed newOwner)`

**Emitted by:**

* [LibDiamond.setContractOwner()](https://docs.cryptolegacy.app/documentation/functions-reference#setcontractowner-ld1)

**Notes / Edge cases:** None

### DiamondCut (LD1)

**Parameters:**

* `\_diamondCut (IDiamondCut.FacetCut[])`: The list of facet add/replace/remove operations applied to the diamond.
* `\_init (address)`: Optional initialization target that will receive the delegatecall.
* `\_calldata (bytes)`: Initialization calldata passed to the delegatecall (empty if no init).

**Description:** Emitted after applying a facet cut to record the changes and the optional initialization call.

**Event Signature:** `DiamondCut(IDiamondCut.FacetCut[] \_diamondCut, address \_init, bytes \_calldata)`

**Emitted by:**

* [LibDiamond.diamondCut()](https://docs.cryptolegacy.app/documentation/functions-reference#diamondcut-ld1)

**Notes / Edge cases:** None

## LibSafeMinimalBeneficiaryMultisig (LSMB1)

**No events in this contract/library.**

## LibSafeMinimalMultisig (LSM1)

**No events in this contract/library.**

## LibTrustedGuardiansPlugin (LTGP1)

**No events in this contract/library.**

## BeneficiaryAaveV3SupplyPlugin (BALP1)

### AaveSupply (BALP1)

**Parameters:**

* `asset (address, indexed)`: Reserve asset supplied into Aave.
* `aToken (address, indexed)`: Yield-bearing aToken received for the reserve.
* `amount (uint256)`: Asset amount that was supplied.

**Description:** Emitted after the plugin supplies an asset into Aave V3 and migrates beneficiary claims from the reserve asset into its aToken.

**Event Signature:** `AaveSupply(address indexed asset, address indexed aToken, uint256 amount)`

**Emitted by:**

* [BeneficiaryAaveV3SupplyPlugin.baavesSupply()](https://docs.cryptolegacy.app/documentation/functions-reference#baavessupply-balp1)

**Notes / Edge cases:** None

### AaveWithdraw (BALP1)

**Parameters:**

* `asset (address, indexed)`: Reserve asset withdrawn from Aave.
* `aToken (address, indexed)`: aToken burned during the withdrawal.
* `amount (uint256)`: Asset amount requested from the pool.

**Description:** Emitted after the plugin withdraws an asset from Aave V3 and migrates beneficiary claims from the aToken back into the reserve asset.

**Event Signature:** `AaveWithdraw(address indexed asset, address indexed aToken, uint256 amount)`

**Emitted by:**

* [BeneficiaryAaveV3SupplyPlugin.baavesWithdraw()](https://docs.cryptolegacy.app/documentation/functions-reference#baaveswithdraw-balp1)

**Notes / Edge cases:** None

### WrapATokenToStataToken (BALP1)

**Parameters:**

* `aToken (address, indexed)`: aToken that was wrapped.
* `stataToken (address, indexed)`: StataToken received by the plugin.
* `aTokenAmount (uint256)`: aToken amount sent into the wrapper.
* `stataTokenReceived (uint256)`: StataToken shares minted to the plugin.

**Description:** Emitted after the plugin converts rebasing aTokens into non-rebasing StataToken shares.

**Event Signature:** `WrapATokenToStataToken(address indexed aToken, address indexed stataToken, uint256 aTokenAmount, uint256 stataTokenReceived)`

**Emitted by:**

* [BeneficiaryAaveV3SupplyPlugin.baavesWrapATokenToStataToken()](https://docs.cryptolegacy.app/documentation/functions-reference#baaveswrapatokentostatatoken-balp1)

**Notes / Edge cases:** When `aTokenAmount == type(uint256).max`, the plugin first expands it to the full aToken balance it currently holds.

### UnwrapStataTokenToAToken (BALP1)

**Parameters:**

* `stataToken (address, indexed)`: StataToken share contract being redeemed.
* `aToken (address, indexed)`: aToken returned by the redemption.
* `stataTokenShares (uint256)`: Share amount redeemed.
* `aTokenReceived (uint256)`: aToken amount received by the plugin.

**Description:** Emitted after the plugin redeems StataToken shares back into rebasing aTokens.

**Event Signature:** `UnwrapStataTokenToAToken(address indexed stataToken, address indexed aToken, uint256 stataTokenShares, uint256 aTokenReceived)`

**Emitted by:**

* [BeneficiaryAaveV3SupplyPlugin.baavesUnwrapStataTokenToAToken()](https://docs.cryptolegacy.app/documentation/functions-reference#baavesunwrapstatatokentoatoken-balp1)

**Notes / Edge cases:** The emitted `aTokenReceived` depends on the current ERC-4626 exchange rate.

### DepositToStataToken (BALP1)

**Parameters:**

* `asset (address, indexed)`: Reserve asset deposited into the StataToken wrapper.
* `stataToken (address, indexed)`: StataToken received by the plugin.
* `amount (uint256)`: Asset amount deposited.
* `stataTokenReceived (uint256)`: StataToken shares minted to the plugin.

**Description:** Emitted after the plugin deposits a reserve asset directly into its StataToken wrapper and migrates beneficiary claims in one step.

**Event Signature:** `DepositToStataToken(address indexed asset, address indexed stataToken, uint256 amount, uint256 stataTokenReceived)`

**Emitted by:**

* [BeneficiaryAaveV3SupplyPlugin.baavesDepositToStataToken()](https://docs.cryptolegacy.app/documentation/functions-reference#baavesdeposittostatatoken-balp1)

**Notes / Edge cases:** None

### RedeemFromStataToken (BALP1)

**Parameters:**

* `stataToken (address, indexed)`: StataToken share contract being redeemed.
* `asset (address, indexed)`: Reserve asset received by the plugin.
* `stataTokenShares (uint256)`: Share amount redeemed.
* `assetReceived (uint256)`: Reserve-asset amount returned by the redemption.

**Description:** Emitted after the plugin redeems StataToken shares directly into the reserve asset and migrates claims back into the underlying token.

**Event Signature:** `RedeemFromStataToken(address indexed stataToken, address indexed asset, uint256 stataTokenShares, uint256 assetReceived)`

**Emitted by:**

* [BeneficiaryAaveV3SupplyPlugin.baavesRedeemFromStataToken()](https://docs.cryptolegacy.app/documentation/functions-reference#baavesredeemfromstatatoken-balp1)

**Notes / Edge cases:** None

## BeneficiaryLidoStakingPlugin (BLSP1)

### StakeWethToStEth (BLSP1)

**Parameters:**

* `wethAmount (uint256)`: WETH amount unwrapped and staked.
* `sharesMinted (uint256)`: Lido share amount minted from the stake.

**Description:** Emitted after the plugin unwraps WETH into ETH and submits that ETH to Lido for rebasing stETH shares.

**Event Signature:** `StakeWethToStEth(uint256 wethAmount, uint256 sharesMinted)`

**Emitted by:**

* [BeneficiaryLidoStakingPlugin.blsLidoStakeWethToStEth()](https://docs.cryptolegacy.app/documentation/functions-reference#blslidostakewethtosteth-blsp1)

**Notes / Edge cases:** The stETH balance may differ by 1-2 wei from the input ETH because Lido internally accounts in shares.

### WrapWethToWstEth (BLSP1)

**Parameters:**

* `wethAmount (uint256)`: WETH amount unwrapped and forwarded into wstETH wrapping.
* `wstEthMinted (uint256)`: wstETH amount minted to the plugin.

**Description:** Emitted after the plugin unwraps WETH into ETH and atomically wraps the resulting ETH into non-rebasing wstETH.

**Event Signature:** `WrapWethToWstEth(uint256 wethAmount, uint256 wstEthMinted)`

**Emitted by:**

* [BeneficiaryLidoStakingPlugin.blsLidoWrapWethToWstEth()](https://docs.cryptolegacy.app/documentation/functions-reference#blslidowrapwethtowsteth-blsp1)

**Notes / Edge cases:** The emitted `wstEthMinted` reflects the current stETH:wstETH exchange rate, not a 1:1 relationship with ETH.

### RequestStEthWithdrawal (BLSP1)

**Parameters:**

* `requestIds (uint256[])`: Withdrawal-request IDs returned by the Lido queue.
* `stEthAmounts (uint256[])`: stETH amounts requested for withdrawal.

**Description:** Emitted after the plugin submits stETH withdrawal requests and starts a pending two-step migration from stETH into WETH.

**Event Signature:** `RequestStEthWithdrawal(uint256[] requestIds, uint256[] stEthAmounts)`

**Emitted by:**

* [BeneficiaryLidoStakingPlugin.blsLidoRequestStEthWithdrawal()](https://docs.cryptolegacy.app/documentation/functions-reference#blslidorequeststethwithdrawal-blsp1)

**Notes / Edge cases:** None

### RequestWstEthWithdrawal (BLSP1)

**Parameters:**

* `requestIds (uint256[])`: Withdrawal-request IDs returned by the Lido queue.
* `wstEthAmounts (uint256[])`: wstETH amounts requested for withdrawal.

**Description:** Emitted after the plugin submits wstETH withdrawal requests and starts a pending two-step migration from wstETH into WETH.

**Event Signature:** `RequestWstEthWithdrawal(uint256[] requestIds, uint256[] wstEthAmounts)`

**Emitted by:**

* [BeneficiaryLidoStakingPlugin.blsLidoRequestWstEthWithdrawal()](https://docs.cryptolegacy.app/documentation/functions-reference#blslidorequestwstethwithdrawal-blsp1)

**Notes / Edge cases:** None

### ClaimWithdrawals (BLSP1)

**Parameters:**

* `requestIds (uint256[])`: Withdrawal-request IDs claimed in the queue.
* `ethClaimedAmount (uint256)`: ETH amount claimed and then wrapped into WETH.

**Description:** Emitted after a beneficiary claims finalized Lido withdrawals and the plugin completes the pending two-step migration into WETH.

**Event Signature:** `ClaimWithdrawals(uint256[] requestIds, uint256 ethClaimedAmount)`

**Emitted by:**

* [BeneficiaryLidoStakingPlugin.blsLidoClaimWithdrawals()](https://docs.cryptolegacy.app/documentation/functions-reference#blslidoclaimwithdrawals-blsp1)

**Notes / Edge cases:** Emits even when the claimed ETH amount is zero.

### UnsafeClaimWithdrawals (BLSP1)

**Parameters:**

* `requestIds (uint256[])`: Withdrawal-request IDs claimed in the queue.
* `ethClaimedAmount (uint256)`: ETH amount claimed and then wrapped into WETH.

**Description:** Emitted after the emergency unsafe-claim path settles finalized Lido withdrawals without replaying the original fair migration state.

**Event Signature:** `UnsafeClaimWithdrawals(uint256[] requestIds, uint256 ethClaimedAmount)`

**Emitted by:**

* [BeneficiaryLidoStakingPlugin.blsLidoUnsafeClaimWithdrawals()](https://docs.cryptolegacy.app/documentation/functions-reference#blslidounsafeclaimwithdrawals-blsp1)

**Notes / Edge cases:** This path is intentionally unfair relative to historical claims and exists only for emergency recovery scenarios.

### AbandonMigration (BLSP1)

**Parameters:**

* `tokenOut (address, indexed)`: Token being abandoned as the migration source.
* `tokenIn (address, indexed)`: Token that would have been credited by the pending migration.
* `tokenOutBalance (uint256)`: Source-token balance remaining after the abandonment path completes.

**Description:** Emitted after the plugin abandons an active Lido pending migration and restores the source-token distribution state.

**Event Signature:** `AbandonMigration(address indexed tokenOut, address indexed tokenIn, uint256 tokenOutBalance)`

**Emitted by:**

* [BeneficiaryLidoStakingPlugin.blsLidoAbandonMigration()](https://docs.cryptolegacy.app/documentation/functions-reference#blslidoabandonmigration-blsp1)

**Notes / Edge cases:** When `tokenOutBalance == 0`, the plugin also zeroes the cached beneficiary claims for that token before emitting the event.

## BeneficiaryPluginAddRights (BPAR1)

**No events in this contract/library.**

## BeneficiaryUniswapV4SwapPlugin (BU4SP1)

### UniswapV4SwapExactInputSingle (BU4SP1)

**Parameters:**

* `tokenIn (address, indexed)`: Input token sold into the swap.
* `tokenOut (address, indexed)`: Output token received from the swap.
* `amountIn (uint256)`: Exact input amount sent into the router.
* `amountOut (uint256)`: Output amount received by the plugin.

**Description:** Emitted after the plugin executes a single-hop exact-input swap through the Universal Router and migrates claims from the sold token into the received token.

**Event Signature:** `UniswapV4SwapExactInputSingle(address indexed tokenIn, address indexed tokenOut, uint256 amountIn, uint256 amountOut)`

**Emitted by:**

* [BeneficiaryUniswapV4SwapPlugin.bunisSwapExactInputSingle()](https://docs.cryptolegacy.app/documentation/functions-reference#bunisswapexactinputsingle-bu4sp1)

**Notes / Edge cases:** None

### UniswapV4SwapExactInput (BU4SP1)

**Parameters:**

* `tokenIn (address, indexed)`: Input token sold into the multi-hop route.
* `tokenOut (address, indexed)`: Final output token received from the route.
* `amountIn (uint256)`: Exact input amount sent into the router.
* `amountOut (uint256)`: Final output amount received by the plugin.

**Description:** Emitted after the plugin executes a multi-hop exact-input swap through the Universal Router and migrates claims into the route's final output token.

**Event Signature:** `UniswapV4SwapExactInput(address indexed tokenIn, address indexed tokenOut, uint256 amountIn, uint256 amountOut)`

**Emitted by:**

* [BeneficiaryUniswapV4SwapPlugin.bunisSwapExactInput()](https://docs.cryptolegacy.app/documentation/functions-reference#bunisswapexactinput-bu4sp1)

**Notes / Edge cases:** None

## CryptoLegacyBasePlugin (CLBP1)

### SetBeneficiary (CLBP1)

**Parameters:**

* `beneficiary (bytes32, indexed)`: Beneficiary hash being configured.
* `vestingPeriod (uint64, indexed)`: Vesting period (seconds) for the beneficiary.
* `shareBps (uint64)`: Share in basis points assigned to the beneficiary.
* `claimDelay (uint64)`: Delay (seconds) before the beneficiary can claim.

**Description:** Emitted when a beneficiary configuration is set or updated.

**Event Signature:** `SetBeneficiary(bytes32 indexed beneficiary, uint64 indexed vestingPeriod, uint64 shareBps, uint64 claimDelay)`

**Emitted by:**

* [CryptoLegacyBasePlugin.\_setBeneficiaries()](https://docs.cryptolegacy.app/documentation/functions-reference#_setbeneficiaries-clbp1)

**Notes / Edge cases:** None

### SwitchBeneficiary (CLBP1)

**Parameters:**

* `oldBeneficiary (bytes32, indexed)`: Previous beneficiary hash.
* `newBeneficiary (bytes32, indexed)`: New beneficiary hash.

**Description:** Emitted when the beneficiary is switched from one hash to another.

**Event Signature:** `SwitchBeneficiary(bytes32 indexed oldBeneficiary, bytes32 indexed newBeneficiary)`

**Emitted by:**

* [CryptoLegacyBasePlugin.beneficiarySwitch()](https://docs.cryptolegacy.app/documentation/functions-reference#beneficiaryswitch-clbp1)

**Notes / Edge cases:** None

### ChallengeInitiate (CLBP1)

**Parameters:**

* `beneficiary (bytes32, indexed)`: Beneficiary hash being challenged.

**Description:** Emitted when a beneficiary challenge process is initiated.

**Event Signature:** `ChallengeInitiate(bytes32 indexed beneficiary)`

**Emitted by:**

* [CryptoLegacyBasePlugin.initiateChallenge()](https://docs.cryptolegacy.app/documentation/functions-reference#initiatechallenge-clbp1)

**Notes / Edge cases:** None

### BeneficiaryMessage (CLBP1)

**Parameters:**

* `toBeneficiary (bytes32, indexed)`: Beneficiary hash receiving the message.
* `messageHash (bytes32)`: Hash of the message payload.
* `message (bytes)`: Raw message payload.
* `messageType (uint256, indexed)`: Message type identifier.

**Description:** Emitted when a message is sent to a beneficiary.

**Event Signature:** `BeneficiaryMessage(bytes32 indexed toBeneficiary, bytes32 messageHash, bytes message, uint256 indexed messageType)`

**Emitted by:**

* [CryptoLegacyBasePlugin.sendMessagesToBeneficiary()](https://docs.cryptolegacy.app/documentation/functions-reference#sendmessagestobeneficiary-clbp1)

**Notes / Edge cases:** None

### BeneficiaryMessageCheck (CLBP1)

**Parameters:**

* `toBeneficiary (bytes32, indexed)`: Beneficiary hash receiving the message check.
* `messageHash (bytes32)`: Hash of the message payload.
* `message (bytes)`: Raw message payload.
* `messageType (uint256, indexed)`: Message type identifier.

**Description:** Emitted when a message is sent for beneficiary verification/check.

**Event Signature:** `BeneficiaryMessageCheck(bytes32 indexed toBeneficiary, bytes32 messageHash, bytes message, uint256 indexed messageType)`

**Emitted by:**

* [CryptoLegacyBasePlugin.sendMessagesToBeneficiary()](https://docs.cryptolegacy.app/documentation/functions-reference#sendmessagestobeneficiary-clbp1)

**Notes / Edge cases:** None

## LegacyRecoveryPlugin (LRP1)

**No events in this contract/library.**

## LensPlugin (LP1)

**No events in this contract/library.**

## NftLegacyPlugin (NLP1)

### SetNftBeneficiary (NLP1)

**Parameters:**

* `nftContract (address, indexed)`: Address of the NFT contract for which the beneficiary is being set.
* `tokenId (uint256, indexed)`: ID of the NFT for which the beneficiary is being set.
* `beneficiaryHash (bytes32, indexed)`: Beneficiary hash (typically keccak256 of the address) assigned rights to this NFT.

**Description:** Emitted when a beneficiary is set or updated for a specific NFT in `setNftBeneficiary` (one event per `tokenId`).

**Event Signature:** `SetNftBeneficiary(address indexed nftContract, uint256 indexed tokenId, bytes32 indexed beneficiaryHash)`

**Emitted by:**

* [NftLegacyPlugin.setNftBeneficiary()](https://docs.cryptolegacy.app/documentation/functions-reference#setnftbeneficiary-nlp1)

**Notes / Edge cases:** None

### BeneficiaryClaimNft (NLP1)

**Parameters:**

* `nftContract (address, indexed)`: Address of the NFT contract whose token is being claimed.
* `tokenId (uint256, indexed)`: ID of the NFT claimed by the beneficiary.
* `beneficiaryHash (bytes32, indexed)`: Beneficiary hash authorized to claim the NFT.
* `beneficiaryAddress (address)`: Beneficiary address that received the NFT.

**Description:** Emitted after a beneficiary successfully claims an NFT in `beneficiaryClaimNft` (eligibility and delay already verified).

**Event Signature:** `BeneficiaryClaimNft(address indexed nftContract, uint256 indexed tokenId, bytes32 indexed beneficiaryHash, address beneficiaryAddress)`

**Emitted by:**

* [NftLegacyPlugin.beneficiaryClaimNft()](https://docs.cryptolegacy.app/documentation/functions-reference#beneficiaryclaimnft-nlp1)

**Notes / Edge cases:** None

### TransferNftToCryptoLegacy (NLP1)

**Parameters:**

* `nftContract (address, indexed)`: Address of the NFT contract whose token is transferred to CryptoLegacy.
* `tokenId (uint256, indexed)`: ID of the NFT transferred to the CryptoLegacy contract.

**Description:** Emitted when an NFT is transferred to CryptoLegacy during `transferNftTokensToLegacy` (one event per `tokenId`).

**Event Signature:** `TransferNftToCryptoLegacy(address indexed nftContract, uint256 indexed tokenId)`

**Emitted by:**

* [NftLegacyPlugin.transferNftTokensToLegacy()](https://docs.cryptolegacy.app/documentation/functions-reference#transfernfttokenstolegacy-nlp1)

**Notes / Edge cases:** None

## ReceiveEthPlugin (REP1)

### WrapEthToWeth (REP1)

**Parameters:**

* `amount (uint256)`: Amount of ETH that was wrapped into WETH.

**Description:** Emitted when `wrapEthToWeth()` converts the contract's ETH balance into WETH and updates CryptoLegacy distribution state.

**Event Signature:** `WrapEthToWeth(uint256 amount)`

**Emitted by:**

* [ReceiveEthPlugin.wrapEthToWeth()](https://docs.cryptolegacy.app/documentation/functions-reference#wrapethtoweth-rep1)

**Notes / Edge cases:** The emitted amount equals the full ETH balance held by the plugin context at execution time.

## TrustedGuardiansPlugin (TGP1)

**No events in this contract/library.**

## UpdateRolePlugin (URP1)

**No events in this contract/library.**

## Parameter Types

| Type                                | Description                                        |
| ----------------------------------- | -------------------------------------------------- |
| `address`                           | EOA or contract address.                           |
| `string`                            | UTF-8 string.                                      |
| `bool`                              | Boolean flag.                                      |
| `bytes32`                           | Fixed-length byte array.                           |
| `uint256`                           | Unsigned 256-bit integer.                          |
| `bytes8`                            | Fixed-length 8-byte array.                         |
| `uint64`                            | Unsigned 64-bit integer.                           |
| `address[]`                         | Array of `address` values.                         |
| `ICryptoLegacy.TokenTransferTo[]`   | Array of `ICryptoLegacy.TokenTransferTo` values.   |
| `uint`                              | Unsigned integer (alias of uint256).               |
| `bytes4[]`                          | Array of `bytes4` values.                          |
| `uint16`                            | Unsigned 16-bit integer.                           |
| `bytes`                             | Dynamic byte array.                                |
| `uint256[]`                         | Array of `uint256` values.                         |
| `bytes32[]`                         | Array of `bytes32` values.                         |
| `ICryptoLegacy.BeneficiaryConfig[]` | Array of `ICryptoLegacy.BeneficiaryConfig` values. |
| `uint32`                            | Unsigned 32-bit integer.                           |
| `FeeParams`                         | Type defined in the source contracts.              |
| `ChainSupportInfo`                  | Type defined in the source contracts.              |
| `FacetCut[]`                        | Array of `FacetCut` values.                        |
| `uint8`                             | Unsigned 8-bit integer.                            |
| `FeeBeneficiary[]`                  | Array of `FeeBeneficiary` values.                  |
| `uint128`                           | Unsigned 128-bit integer.                          |
| `ProposalStatus`                    | Type defined in the source contracts.              |
| `bytes4`                            | Fixed-length 4-byte array.                         |
| `IDiamondCut.FacetCut[]`            | Array of `IDiamondCut.FacetCut` values.            |


# Contracts Errors

This document consolidates all known errors from the CryptoLegacy contracts and libraries, as well as any relevant supporting contracts and libraries.

## Table of Contents

1. [BeneficiaryRegistry (BR1)](#beneficiaryregistry-br1)
2. [BuildManagerOwnable (BMO1)](#buildmanagerownable-bmo1)
3. [Create3Factory (C3F1)](#create3factory-c3f1)
4. [CryptoLegacy (CL1)](#cryptolegacy-cl1)
5. [CryptoLegacyBuildManager (CLBM1)](#cryptolegacybuildmanager-clbm1)
6. [CryptoLegacyDiamondBase (CLDB1)](#cryptolegacydiamondbase-cldb1)
7. [CryptoLegacyExternalLens (CLEXL1)](#cryptolegacyexternallens-clexl1)
8. [CryptoLegacyFactory (CLF1)](#cryptolegacyfactory-clf1)
9. [CryptoLegacyOwnable (CLO1)](#cryptolegacyownable-clo1)
10. [FeeRegistry (FR1)](#feeregistry-fr1)
11. [LegacyMessenger (LM1)](#legacymessenger-lm1)
12. [LifetimeNft (LN1)](#lifetimenft-ln1)
13. [LockChainGate (LCG1)](#lockchaingate-lcg1)
14. [MultiPermit (MP1)](#multipermit-mp1)
15. [PluginsRegistry (PR1)](#pluginsregistry-pr1)
16. [ProxyBuilder (PB1)](#proxybuilder-pb1)

* [AdminAlreadyCreated (PB1)](#adminalreadycreated-pb1)
* [AddressMismatch (PB1)](#addressmismatch-pb1)

17. [ProxyBuilderAdmin (PBA1)](#proxybuilderadmin-pba1)
18. [SignatureRoleTimelock (SRT1)](#signatureroletimelock-srt1)
19. [ArbSys (AS1)](#arbsys-as1)
20. [Flags (FLG1)](#flags-flg1)
21. [IAaveV3Pool (IAV3P1)](#iaavev3pool-iav3p1)
22. [IAaveV3PoolDataProvider (IAV3PDP1)](#iaavev3pooldataprovider-iav3pdp1)
23. [WethUnwrap (WU1)](#wethunwrap-wu1)

* [CallbackCallFailed (WU1)](#callbackcallfailed-wu1)

24. [IBeneficiaryRegistry (IBR1)](#ibeneficiaryregistry-ibr1)
25. [IBuildManagerOwnable (IBMO1)](#ibuildmanagerownable-ibmo1)

* [NotTheOwnerOfCryptoLegacy (IBMO1)](#nottheownerofcryptolegacy-ibmo1)
* [CryptoLegacyNotRegistered (IBMO1)](#cryptolegacynotregistered-ibmo1)
* [BuildManagerNotAdded (IBMO1)](#buildmanagernotadded-ibmo1)

26. [ICallProxy (ICP1)](#icallproxy-icp1)
27. [ICryptoLegacy (ICL1)](#icryptolegacy-icl1)

* [BeneficiarySwitchTimelock (ICL1)](#beneficiaryswitchtimelock-icl1)
* [ArrayLengthMismatch (ICL1)](#arraylengthmismatch-icl1)
* [DisabledFunc (ICL1)](#disabledfunc-icl1)
* [NotTheOwner (ICL1)](#nottheowner-icl1)
* [NotTheBeneficiary (ICL1)](#notthebeneficiary-icl1)
* [BeneficiaryNotExist (ICL1)](#beneficiarynotexist-icl1)
* [TooEarly (ICL1)](#tooearly-icl1)
* [IncorrectRefShare (ICL1)](#incorrectrefshare-icl1)
* [NoValueAllowed (ICL1)](#novalueallowed-icl1)
* [TooLongArray (ICL1)](#toolongarray-icl1)
* [IncorrectFee (ICL1)](#incorrectfee-icl1)
* [ZeroAddress (ICL1)](#zeroaddress-icl1)
* [ZeroTokens (ICL1)](#zerotokens-icl1)
* [InitialFeeNotPaid (ICL1)](#initialfeenotpaid-icl1)
* [InitialFeeAlreadyPaid (ICL1)](#initialfeealreadypaid-icl1)
* [NotBuildManager (ICL1)](#notbuildmanager-icl1)
* [LengthMismatch (ICL1)](#lengthmismatch-icl1)
* [ShareSumDoesntMatchBase (ICL1)](#sharesumdoesntmatchbase-icl1)
* [OriginalHashDuplicate (ICL1)](#originalhashduplicate-icl1)
* [DistributionStarted (ICL1)](#distributionstarted-icl1)
* [DistributionStartAlreadySet (ICL1)](#distributionstartalreadyset-icl1)
* [DistributionDelay (ICL1)](#distributiondelay-icl1)
* [ChallengePeriodStarted (ICL1)](#challengeperiodstarted-icl1)
* [AlreadySet (ICL1)](#alreadyset-icl1)
* [BeneficiaryNotSet (ICL1)](#beneficiarynotset-icl1)
* [Pause (ICL1)](#pause-icl1)
* [IncorrectFacetCutAction (ICL1)](#incorrectfacetcutaction-icl1)
* [NotContractOwner (ICL1)](#notcontractowner-icl1)
* [FacetNotFound (ICL1)](#facetnotfound-icl1)
* [FacetHasNoCode (ICL1)](#facethasnocode-icl1)
* [NoSelectorsInFacetToCut (ICL1)](#noselectorsinfacettocut-icl1)
* [FacetCantBeZero (ICL1)](#facetcantbezero-icl1)
* [CantRemoveImmutableFunctions (ICL1)](#cantremoveimmutablefunctions-icl1)
* [CantAddFunctionThatAlreadyExists (ICL1)](#cantaddfunctionthatalreadyexists-icl1)
* [CantReplaceFunctionWithSameFunction (ICL1)](#cantreplacefunctionwithsamefunction-icl1)
* [InitFunctionReverted (ICL1)](#initfunctionreverted-icl1)
* [InitAddressZeroButCalldataIsNot (ICL1)](#initaddresszerobutcalldataisnot-icl1)
* [InitCalldataZeroButAddressIsNot (ICL1)](#initcalldatazerobutaddressisnot-icl1)
* [PluginNotRegistered (ICL1)](#pluginnotregistered-icl1)
* [TransferFeeFailed (ICL1)](#transferfeefailed-icl1)
* [TooBigMultiplier (ICL1)](#toobigmultiplier-icl1)

28. [ICryptoLegacyBuildManager (ICLBM1)](#icryptolegacybuildmanager-iclbm1)

* [AlreadyLifetime (ICLBM1)](#alreadylifetime-iclbm1)
* [WithdrawFeeFailed (ICLBM1)](#withdrawfeefailed-iclbm1)
* [NotValidTimeout (ICLBM1)](#notvalidtimeout-iclbm1)
* [IncorrectFee (ICLBM1)](#incorrectfee-iclbm1)
* [BelowMinimumSupply (ICLBM1)](#belowminimumsupply-iclbm1)
* [NotRegisteredCryptoLegacy (ICLBM1)](#notregisteredcryptolegacy-iclbm1)
* [NotOwnerOfCryptoLegacy (ICLBM1)](#notownerofcryptolegacy-iclbm1)
* [TransferFeeFailed (ICLBM1)](#transferfeefailed-iclbm1)

29. [ICryptoLegacyDiamondBase (ICLDB1)](#icryptolegacydiamondbase-icldb1)

* [FunctionNotExists (ICLDB1)](#functionnotexists-icldb1)
* [NotSelfCall (ICLDB1)](#notselfcall-icldb1)

30. [ICryptoLegacyFactory (ICLF1)](#icryptolegacyfactory-iclf1)

* [NotBuildOperator (ICLF1)](#notbuildoperator-iclf1)

31. [ICryptoLegacyLens (ICLL1)](#icryptolegacylens-icll1)
32. [ICryptoLegacyOwnable (ICLO1)](#icryptolegacyownable-iclo1)

* [OwnableUnauthorizedAccount (ICLO1)](#ownableunauthorizedaccount-iclo1)

33. [ICryptoLegacyPlugin (ICLP1)](#icryptolegacyplugin-iclp1)
34. [ICryptoLegacyUpdaterPlugin (ICLUP1)](#icryptolegacyupdaterplugin-iclup1)

* [NotTheUpdater (ICLUP1)](#nottheupdater-iclup1)

35. [IDeBridgeGate (IDBG1)](#idebridgegate-idbg1)
36. [IDiamondCut (IDC1)](#idiamondcut-idc1)
37. [IDiamondLoupe (IDL1)](#idiamondloupe-idl1)
38. [IFeeRegistry (IFR1)](#ifeeregistry-ifr1)

* [WithdrawAccumulatedFeeFailed (IFR1)](#withdrawaccumulatedfeefailed-ifr1)
* [PctSumDoesntMatchBase (IFR1)](#pctsumdoesntmatchbase-ifr1)
* [TooBigPct (IFR1)](#toobigpct-ifr1)
* [RefAlreadyCreated (IFR1)](#refalreadycreated-ifr1)
* [ZeroCode (IFR1)](#zerocode-ifr1)
* [NotOperator (IFR1)](#notoperator-ifr1)
* [NotReferrer (IFR1)](#notreferrer-ifr1)
* [AlreadyReferrer (IFR1)](#alreadyreferrer-ifr1)
* [CodeNotCreated (IFR1)](#codenotcreated-ifr1)

39. [ILockChainGate (ILCG1)](#ilockchaingate-ilcg1)

* [ArrayLengthMismatch (ILCG1)](#arraylengthmismatch-ilcg1)
* [AlreadyLocked (ILCG1)](#alreadylocked-ilcg1)
* [LockedToChains (ILCG1)](#lockedtochains-ilcg1)
* [CrossChainLock (ILCG1)](#crosschainlock-ilcg1)
* [TooEarly (ILCG1)](#tooearly-ilcg1)
* [DestinationChainNotSpecified (ILCG1)](#destinationchainnotspecified-ilcg1)
* [TokenNotLocked (ILCG1)](#tokennotlocked-ilcg1)
* [TokenIdMismatch (ILCG1)](#tokenidmismatch-ilcg1)
* [AlreadyLockedToChain (ILCG1)](#alreadylockedtochain-ilcg1)
* [SourceNotSpecified (ILCG1)](#sourcenotspecified-ilcg1)
* [NotLockedByChain (ILCG1)](#notlockedbychain-ilcg1)
* [DestinationNotSpecified (ILCG1)](#destinationnotspecified-ilcg1)
* [NotAvailable (ILCG1)](#notavailable-ilcg1)
* [IncorrectFee (ILCG1)](#incorrectfee-ilcg1)
* [SameAddress (ILCG1)](#sameaddress-ilcg1)
* [RecipientLocked (ILCG1)](#recipientlocked-ilcg1)
* [TransferLockTimeout (ILCG1)](#transferlocktimeout-ilcg1)
* [NotCallProxy (ILCG1)](#notcallproxy-ilcg1)
* [ChainIdMismatch (ILCG1)](#chainidmismatch-ilcg1)
* [NotValidSender (ILCG1)](#notvalidsender-ilcg1)
* [NotAllowed (ILCG1)](#notallowed-ilcg1)
* [TransferFeeFailed (ILCG1)](#transferfeefailed-ilcg1)

40. [ILegacyMessenger (ILM1)](#ilegacymessenger-ilm1)
41. [ILido (ILD1)](#ilido-ild1)
42. [ILidoWithdrawalQueue (ILWQ1)](#ilidowithdrawalqueue-ilwq1)
43. [ILifetimeNft (ILN1)](#ilifetimenft-iln1)

* [NotTheMinter (ILN1)](#nottheminter-iln1)

44. [IPermit2 (IPM21)](#ipermit2-ipm21)
45. [IPluginsRegistry (IPR1)](#ipluginsregistry-ipr1)
46. [ISafeMinimalMultisig (ISM1)](#isafeminimalmultisig-ism1)

* [MultisigProposalNotPending (ISM1)](#multisigproposalnotpending-ism1)
* [MultisigNotConfirmed (ISM1)](#multisignotconfirmed-ism1)
* [MultisigExecutionFailed (ISM1)](#multisigexecutionfailed-ism1)
* [MultisigMethodNotAllowed (ISM1)](#multisigmethodnotallowed-ism1)
* [MultisigVoterNotAllowed (ISM1)](#multisigvoternotallowed-ism1)
* [MultisigOnlyExecutor (ISM1)](#multisigonlyexecutor-ism1)
* [MultisigIncorrectRequiredConfirmations (ISM1)](#multisigincorrectrequiredconfirmations-ism1)
* [MultisigNothingToWithdraw (ISM1)](#multisignothingtowithdraw-ism1)
* [TransferFeeFailed (ISM1)](#transferfeefailed-ism1)

47. [ISignatureRoleTimelock (ISRT1)](#isignatureroletimelock-isrt1)

* [DisabledFunction (ISRT1)](#disabledfunction-isrt1)
* [AlreadyHaveRole (ISRT1)](#alreadyhaverole-isrt1)
* [DoesntHaveRole (ISRT1)](#doesnthaverole-isrt1)
* [RoleDontExist (ISRT1)](#roledontexist-isrt1)
* [CallerNotCurrentAddress (ISRT1)](#callernotcurrentaddress-isrt1)
* [IncorrectSignatureIndex (ISRT1)](#incorrectsignatureindex-isrt1)
* [IncorrectRoleIndex (ISRT1)](#incorrectroleindex-isrt1)
* [CallFailed (ISRT1)](#callfailed-isrt1)
* [CallNotScheduled (ISRT1)](#callnotscheduled-isrt1)
* [NotPending (ISRT1)](#notpending-isrt1)
* [TimelockActive (ISRT1)](#timelockactive-isrt1)
* [TimelockExpired (ISRT1)](#timelockexpired-isrt1)
* [CallerHaveNoRequiredRole (ISRT1)](#callerhavenorequiredrole-isrt1)
* [CallAlreadyScheduled (ISRT1)](#callalreadyscheduled-isrt1)
* [SignatureAlreadyExists (ISRT1)](#signaturealreadyexists-isrt1)
* [SignatureTimeLockNotSet (ISRT1)](#signaturetimelocknotset-isrt1)
* [OutOfTimelockBounds (ISRT1)](#outoftimelockbounds-isrt1)
* [OutOfMaxExecutionPeriodBounds (ISRT1)](#outofmaxexecutionperiodbounds-isrt1)

48. [IStataToken (ISTA1)](#istatatoken-ista1)
49. [IStataTokenFactory (ISTF1)](#istatatokenfactory-istf1)
50. [ITrustedGuardiansPlugin (ITGP1)](#itrustedguardiansplugin-itgp1)

* [NotGuardian (ITGP1)](#notguardian-itgp1)
* [ZeroGuardian (ITGP1)](#zeroguardian-itgp1)
* [ThresholdDontMet (ITGP1)](#thresholddontmet-itgp1)
* [ThresholdTooBig (ITGP1)](#thresholdtoobig-itgp1)
* [GuardianAlreadyVoted (ITGP1)](#guardianalreadyvoted-itgp1)
* [GuardiansTimeoutCantBeZero (ITGP1)](#guardianstimeoutcantbezero-itgp1)
* [MaxGuardiansTimeout (ITGP1)](#maxguardianstimeout-itgp1)

51. [DiamondLoupeFacet (DLF1)](#diamondloupefacet-dlf1)
52. [IUniversalRouter (IUR1)](#iuniversalrouter-iur1)
53. [IWETH (IWETH1)](#iweth-iweth1)
54. [IWstETH (IWSTETH1)](#iwsteth-iwsteth1)
55. [WethUnwrapIWETH (WUI1)](#wethunwrapiweth-wui1)
56. [LibCLUtils (LCLU1)](#libclutils-lclu1)

* [ApprovalFailed (LCLU1)](#approvalfailed-lclu1)

57. [LibClaimMigrationCore (LCMC1)](#libclaimmigrationcore-lcmc1)

* [MigrationInvalidDelta (LCMC1)](#migrationinvaliddelta-lcmc1)
* [MigrationAmountTooSmall (LCMC1)](#migrationamounttoosmall-lcmc1)

58. [LibOneStepClaimMigration (LOSCM1)](#libonestepclaimmigration-loscm1)
59. [LibTwoStepClaimMigration (LTSCM1)](#libtwostepclaimmigration-ltscm1)

* [NoPendingMigration (LTSCM1)](#nopendingmigration-ltscm1)
* [PendingMigrationAlreadyExists (LTSCM1)](#pendingmigrationalreadyexists-ltscm1)
* [TokenAlreadyLocked (LTSCM1)](#tokenalreadylocked-ltscm1)

60. [LibCreate3 (LC31)](#libcreate3-lc31)

* [ErrorCreatingProxy (LC31)](#errorcreatingproxy-lc31)
* [ErrorCreatingContract (LC31)](#errorcreatingcontract-lc31)
* [TargetAlreadyExists (LC31)](#targetalreadyexists-lc31)

61. [LibCryptoLegacy (LCL1)](#libcryptolegacy-lcl1)
62. [LibCryptoLegacyDeploy (LCLD1)](#libcryptolegacydeploy-lcld1)

* [BytecodeEmpty (LCLD1)](#bytecodeempty-lcld1)
* [AddressMismatch (LCLD1)](#addressmismatch-lcld1)
* [Create3Failed (LCLD1)](#create3failed-lcld1)

63. [LibCryptoLegacyPlugins (LCLP1)](#libcryptolegacyplugins-lclp1)
64. [LibDiamond (LD1)](#libdiamond-ld1)

* [InitializationFunctionReverted (LD1)](#initializationfunctionreverted-ld1)

65. [LibSafeMinimalBeneficiaryMultisig (LSMB1)](#libsafeminimalbeneficiarymultisig-lsmb1)
66. [LibSafeMinimalMultisig (LSM1)](#libsafeminimalmultisig-lsm1)
67. [LibTrustedGuardiansPlugin (LTGP1)](#libtrustedguardiansplugin-ltgp1)
68. [BeneficiaryAaveV3SupplyPlugin (BALP1)](#beneficiaryaavev3supplyplugin-balp1)

* [ZeroAmount (BALP1)](#zeroamount-balp1)
* [ATokenNotFound (BALP1)](#atokennotfound-balp1)
* [StataTokenNotFound (BALP1)](#statatokennotfound-balp1)

69. [BeneficiaryLidoStakingPlugin (BLSP1)](#beneficiarylidostakingplugin-blsp1)

* [ZeroStEthAmount (BLSP1)](#zerostethamount-blsp1)
* [ZeroWethAmount (BLSP1)](#zerowethamount-blsp1)
* [ZeroWstEthAmount (BLSP1)](#zerowstethamount-blsp1)
* [InsufficientStEth (BLSP1)](#insufficientsteth-blsp1)
* [InsufficientWstEth (BLSP1)](#insufficientwsteth-blsp1)
* [LidoRequestIdsEmpty (BLSP1)](#lidorequestidsempty-blsp1)
* [WethUnwrapAmountMismatch (BLSP1)](#wethunwrapamountmismatch-blsp1)
* [WstEthWrapFailed (BLSP1)](#wstethwrapfailed-blsp1)
* [EmptyWithdrawalAmounts (BLSP1)](#emptywithdrawalamounts-blsp1)
* [PendingMigrationActive (BLSP1)](#pendingmigrationactive-blsp1)
* [BeneficiarySwitchGuardAlreadyActive (BLSP1)](#beneficiaryswitchguardalreadyactive-blsp1)

70. [BeneficiaryPluginAddRights (BPAR1)](#beneficiarypluginaddrights-bpar1)
71. [BeneficiaryUniswapV4SwapPlugin (BU4SP1)](#beneficiaryuniswapv4swapplugin-bu4sp1)

* [ZeroAmount (BU4SP1)](#zeroamount-bu4sp1)
* [EmptyPath (BU4SP1)](#emptypath-bu4sp1)

72. [CryptoLegacyBasePlugin (CLBP1)](#cryptolegacybaseplugin-clbp1)
73. [LegacyRecoveryPlugin (LRP1)](#legacyrecoveryplugin-lrp1)
74. [LensPlugin (LP1)](#lensplugin-lp1)
75. [NftLegacyPlugin (NLP1)](#nftlegacyplugin-nlp1)
76. [ReceiveEthPlugin (REP1)](#receiveethplugin-rep1)

* [NoEthToWrap (REP1)](#noethtowrap-rep1)

77. [TrustedGuardiansPlugin (TGP1)](#trustedguardiansplugin-tgp1)
78. [UpdateRolePlugin (URP1)](#updateroleplugin-urp1)
79. [Parameter Types](#parameter-types)

## BeneficiaryRegistry (BR1)

**No errors in this contract/library.**

## BuildManagerOwnable (BMO1)

**No errors in this contract/library.**

## Create3Factory (C3F1)

**No errors in this contract/library.**

## CryptoLegacy (CL1)

**No errors in this contract/library.**

## CryptoLegacyBuildManager (CLBM1)

**No errors in this contract/library.**

## CryptoLegacyDiamondBase (CLDB1)

**No errors in this contract/library.**

## CryptoLegacyExternalLens (CLEXL1)

**No errors in this contract/library.**

## CryptoLegacyFactory (CLF1)

**No errors in this contract/library.**

## CryptoLegacyOwnable (CLO1)

**No errors in this contract/library.**

## FeeRegistry (FR1)

**No errors in this contract/library.**

## LegacyMessenger (LM1)

**No errors in this contract/library.**

## LifetimeNft (LN1)

**No errors in this contract/library.**

## LockChainGate (LCG1)

**No errors in this contract/library.**

## MultiPermit (MP1)

**No errors in this contract/library.**

## PluginsRegistry (PR1)

**No errors in this contract/library.**

## ProxyBuilder (PB1)

### AdminAlreadyCreated (PB1)

**Parameters:** None

**Description:** Raised when trying to create a ProxyBuilderAdmin contract if one already exists under the same environment.

**Error Signature:** `AdminAlreadyCreated()`

**Raised by:** None

**Notes / Edge cases:** None

### AddressMismatch (PB1)

**Parameters:** None

**Description:** Raised when a computed deployment address does not match the expected address.

**Error Signature:** `AddressMismatch()`

**Raised by:**

* [ProxyBuilder.build()](https://docs.cryptolegacy.app/documentation/functions-reference#build-pb1)

**Notes / Edge cases:** None

## ProxyBuilderAdmin (PBA1)

**No errors in this contract/library.**

## SignatureRoleTimelock (SRT1)

**No errors in this contract/library.**

## ArbSys (AS1)

**No errors in this contract/library.**

## Flags (FLG1)

**No errors in this contract/library.**

## IAaveV3Pool (IAV3P1)

**No errors in this contract/library.**

## IAaveV3PoolDataProvider (IAV3PDP1)

**No errors in this contract/library.**

## WethUnwrap (WU1)

### CallbackCallFailed (WU1)

**Parameters:** None

**Description:** Raised when `WethUnwrap.unwrap_weth()` successfully unwraps WETH but the callback back into `msg.sender` returns `false`.

**Error Signature:** `CallbackCallFailed()`

**Raised by:**

* [WethUnwrap.unwrap\_weth()](https://docs.cryptolegacy.app/documentation/functions-reference#unwrap_weth-wu1)

**Notes / Edge cases:** Guards the final low-level callback only; upstream WETH transfer/withdraw failures bubble directly from the WETH implementation instead of using this custom error.

## IBeneficiaryRegistry (IBR1)

**No errors in this contract/library.**

## IBuildManagerOwnable (IBMO1)

### NotTheOwnerOfCryptoLegacy (IBMO1)

**Parameters:** None

**Description:** Raised when a check determines that the caller is not the actual owner of the referenced CryptoLegacy contract.

**Error Signature:** `NotTheOwnerOfCryptoLegacy()`

**Raised by:**

* [BuildManagerOwnable.\_checkBuildManagerValid()](https://docs.cryptolegacy.app/documentation/functions-reference#_checkbuildmanagervalid-bmo1)

**Notes / Edge cases:** None

### CryptoLegacyNotRegistered (IBMO1)

**Parameters:** None

**Description:** Raised when a CryptoLegacy contract has not been registered by a valid build manager or is otherwise unknown.

**Error Signature:** `CryptoLegacyNotRegistered()`

**Raised by:**

* [BuildManagerOwnable.\_checkBuildManagerValid()](https://docs.cryptolegacy.app/documentation/functions-reference#_checkbuildmanagervalid-bmo1)

**Notes / Edge cases:** None

### BuildManagerNotAdded (IBMO1)

**Parameters:** None

**Description:** Raised when an operation requires a build manager that is not recognized in the added build managers list.

**Error Signature:** `BuildManagerNotAdded()`

**Raised by:**

* [BuildManagerOwnable.\_checkBuildManagerValid()](https://docs.cryptolegacy.app/documentation/functions-reference#_checkbuildmanagervalid-bmo1)

**Notes / Edge cases:** None

## ICallProxy (ICP1)

**No errors in this contract/library.**

## ICryptoLegacy (ICL1)

### BeneficiarySwitchTimelock (ICL1)

**Parameters:** None

**Description:** Raised when attempting to switch a beneficiary before the switch timelock expires.

**Error Signature:** `BeneficiarySwitchTimelock()`

**Raised by:**

* [CryptoLegacyBasePlugin.beneficiarySwitch()](https://docs.cryptolegacy.app/documentation/functions-reference#beneficiaryswitch-clbp1)

**Notes / Edge cases:** None

### ArrayLengthMismatch (ICL1)

**Parameters:** None

**Description:** Raised when related arrays are expected to be the same length but are not.

**Error Signature:** `ArrayLengthMismatch()`

**Raised by:**

* [CryptoLegacyBasePlugin.payInitialFee()](https://docs.cryptolegacy.app/documentation/functions-reference#payinitialfee-clbp1)
* [CryptoLegacyBasePlugin.update()](https://docs.cryptolegacy.app/documentation/functions-reference#update-clbp1)

**Notes / Edge cases:** None

### DisabledFunc (ICL1)

**Parameters:** None

**Description:** Raised when a function call is disabled by the contract's internal configuration.

**Error Signature:** `DisabledFunc()`

**Raised by:**

* [LibCryptoLegacy.\_checkDisabledFunc()](https://docs.cryptolegacy.app/documentation/functions-reference#_checkdisabledfunc-lcl1)

**Notes / Edge cases:** None

### NotTheOwner (ICL1)

**Parameters:** None

**Description:** Raised when the caller attempts an owner-only action but is not recognized as the contract owner.

**Error Signature:** `NotTheOwner()`

**Raised by:**

* [LibCryptoLegacy.\_checkSenderOwner()](https://docs.cryptolegacy.app/documentation/functions-reference#_checksenderowner-lcl1)

**Notes / Edge cases:** None

### NotTheBeneficiary (ICL1)

**Parameters:** None

**Description:** Raised when an address that is not a valid beneficiary tries to perform a beneficiary-only action.

**Error Signature:** `NotTheBeneficiary()`

**Raised by:**

* [LibCryptoLegacy.\_checkAddressIsBeneficiary()](https://docs.cryptolegacy.app/documentation/functions-reference#_checkaddressisbeneficiary-lcl1)
* [NftLegacyPlugin.transferNftTokensToLegacy()](https://docs.cryptolegacy.app/documentation/functions-reference#transfernfttokenstolegacy-nlp1)
* [NftLegacyPlugin.beneficiaryClaimNft()](https://docs.cryptolegacy.app/documentation/functions-reference#beneficiaryclaimnft-nlp1)

**Notes / Edge cases:** None

### BeneficiaryNotExist (ICL1)

**Parameters:** None

**Description:** Raised when a beneficiary hash is not present or has no configuration in storage.

**Error Signature:** `BeneficiaryNotExist()`

**Raised by:**

* [LibCryptoLegacy.\_getBeneficiaryConfigAndVesting()](https://docs.cryptolegacy.app/documentation/functions-reference#_getbeneficiaryconfigandvesting-lcl1)

**Notes / Edge cases:** None

### TooEarly (ICL1)

**Parameters:** None

**Description:** Raised when an unlocking or transfer is attempted before the lock period has elapsed.

**Error Signature:** `TooEarly()`

**Raised by:**

* [LibCryptoLegacy.\_checkDistributionReady()](https://docs.cryptolegacy.app/documentation/functions-reference#_checkdistributionready-lcl1)
* [CryptoLegacyBasePlugin.initiateChallenge()](https://docs.cryptolegacy.app/documentation/functions-reference#initiatechallenge-clbp1)
* [CryptoLegacyBasePlugin.beneficiaryClaim()](https://docs.cryptolegacy.app/documentation/functions-reference#beneficiaryclaim-clbp1)

**Notes / Edge cases:** None

### IncorrectRefShare (ICL1)

**Parameters:** None

**Description:** Raised when a referrer or beneficiary share is invalid or outside allowed bounds.

**Error Signature:** `IncorrectRefShare()`

**Raised by:**

* [LibCryptoLegacy.\_sendFeeByTransfer()](https://docs.cryptolegacy.app/documentation/functions-reference#_sendfeebytransfer-lcl1)

**Notes / Edge cases:** None

### NoValueAllowed (ICL1)

**Parameters:** None

**Description:** Raised when a function that requires zero `msg.value` is called with a nonzero value.

**Error Signature:** `NoValueAllowed()`

**Raised by:**

* [LibCryptoLegacy.\_checkNoFee()](https://docs.cryptolegacy.app/documentation/functions-reference#_checknofee-lcl1)

**Notes / Edge cases:** None

### TooLongArray (ICL1)

**Parameters:**

* `maxLength (uint256)`: Maximum allowed length for the array.

**Description:** Raised when an array exceeds the maximum allowed length.

**Error Signature:** `TooLongArray(uint256 maxLength)`

**Raised by:**

* [LibCryptoLegacy.\_takeFee()](https://docs.cryptolegacy.app/documentation/functions-reference#_takefee-lcl1)

**Notes / Edge cases:** None

### IncorrectFee (ICL1)

**Parameters:**

* `requiredFee (uint256)`: Exact fee amount required by the operation.

**Description:** Raised if the fee passed into a function is less than the required amount or otherwise mismatched.

**Error Signature:** `IncorrectFee(uint256 requiredFee)`

**Raised by:**

* [LibCryptoLegacy.\_checkFee()](https://docs.cryptolegacy.app/documentation/functions-reference#_checkfee-lcl1)

**Notes / Edge cases:** None

### ZeroAddress (ICL1)

**Parameters:** None

**Description:** Raised when a provided address argument is the zero address (i.e., `0x0000000000000000000000000000000000000000`).

**Error Signature:** `ZeroAddress()`

**Raised by:**

* [CryptoLegacyOwnable.\_transferOwnership()](https://docs.cryptolegacy.app/documentation/functions-reference#_transferownership-clo1)

**Notes / Edge cases:** None

### ZeroTokens (ICL1)

**Parameters:** None

**Description:** Raised when an operation that expects one or more tokens is called with zero tokens or an empty list.

**Error Signature:** `ZeroTokens()`

**Raised by:**

* [NftLegacyPlugin.beneficiaryClaimNft()](https://docs.cryptolegacy.app/documentation/functions-reference#beneficiaryclaimnft-nlp1)

**Notes / Edge cases:** None

### InitialFeeNotPaid (ICL1)

**Parameters:** None

**Description:** Raised when certain actions require that the initial deployment fee has already been paid, but it has not.

**Error Signature:** `InitialFeeNotPaid()`

**Raised by:**

* [LibCryptoLegacy.\_checkOwner()](https://docs.cryptolegacy.app/documentation/functions-reference#_checkowner-lcl1)
* [TrustedGuardiansPlugin.\_checkGuardian()](https://docs.cryptolegacy.app/documentation/functions-reference#_checkguardian-tgp1)

**Notes / Edge cases:** None

### InitialFeeAlreadyPaid (ICL1)

**Parameters:** None

**Description:** Raised if an attempt is made to pay the initial fee again after it has already been settled.

**Error Signature:** `InitialFeeAlreadyPaid()`

**Raised by:**

* [CryptoLegacyBasePlugin.payInitialFee()](https://docs.cryptolegacy.app/documentation/functions-reference#payinitialfee-clbp1)

**Notes / Edge cases:** None

### NotBuildManager (ICL1)

**Parameters:** None

**Description:** Raised when a restricted action is attempted by an entity that is not recognized as the Build Manager.

**Error Signature:** `NotBuildManager()`

**Raised by:**

* [CryptoLegacyBasePlugin.initializeByBuildManager()](https://docs.cryptolegacy.app/documentation/functions-reference#initializebybuildmanager-clbp1)

**Notes / Edge cases:** None

### LengthMismatch (ICL1)

**Parameters:** None

**Description:** Raised when two or more arrays passed to a function have mismatched lengths, preventing proper correlation of elements.

**Error Signature:** `LengthMismatch()`

**Raised by:**

* [CryptoLegacyBasePlugin.\_setBeneficiaries()](https://docs.cryptolegacy.app/documentation/functions-reference#_setbeneficiaries-clbp1)

**Notes / Edge cases:** None

### ShareSumDoesntMatchBase (ICL1)

**Parameters:** None

**Description:** Raised when beneficiary share percentages do not sum to the required base (e.g., 10000 basis points).

**Error Signature:** `ShareSumDoesntMatchBase()`

**Raised by:**

* [CryptoLegacyBasePlugin.\_setBeneficiaries()](https://docs.cryptolegacy.app/documentation/functions-reference#_setbeneficiaries-clbp1)

**Notes / Edge cases:** None

### OriginalHashDuplicate (ICL1)

**Parameters:** None

**Description:** Raised when an original beneficiary hash is already linked and cannot be duplicated.

**Error Signature:** `OriginalHashDuplicate()`

**Raised by:**

* [CryptoLegacyBasePlugin.\_setBeneficiaries()](https://docs.cryptolegacy.app/documentation/functions-reference#_setbeneficiaries-clbp1)

**Notes / Edge cases:** None

### DistributionStarted (ICL1)

**Parameters:** None

**Description:** Raised when an operation that must occur before distribution cannot proceed because distribution has already begun.

**Error Signature:** `DistributionStarted()`

**Raised by:**

* [LibCryptoLegacy.\_checkDistributionStart()](https://docs.cryptolegacy.app/documentation/functions-reference#_checkdistributionstart-lcl1)

**Notes / Edge cases:** None

### DistributionStartAlreadySet (ICL1)

**Parameters:** None

**Description:** Raised if distributionStartAt was already set, yet an attempt is made to set or re-initiate it again.

**Error Signature:** `DistributionStartAlreadySet()`

**Raised by:**

* [CryptoLegacyBasePlugin.initiateChallenge()](https://docs.cryptolegacy.app/documentation/functions-reference#initiatechallenge-clbp1)

**Notes / Edge cases:** None

### DistributionDelay (ICL1)

**Parameters:** None

**Description:** Raised if a beneficiary tries to claim an asset or operation before the required distribution delay.

**Error Signature:** `DistributionDelay()`

**Raised by:**

* [NftLegacyPlugin.beneficiaryClaimNft()](https://docs.cryptolegacy.app/documentation/functions-reference#beneficiaryclaimnft-nlp1)

**Notes / Edge cases:** None

### ChallengePeriodStarted (ICL1)

**Parameters:** None

**Description:** Raised when an action that must occur before the challenge period is attempted after it has started.

**Error Signature:** `ChallengePeriodStarted()`

**Raised by:**

* [LibCryptoLegacy.\_setPause()](https://docs.cryptolegacy.app/documentation/functions-reference#_setpause-lcl1)

**Notes / Edge cases:** None

### AlreadySet (ICL1)

**Parameters:** None

**Description:** Raised when a switch or assignment is made but the target was already assigned or set to the same value.

**Error Signature:** `AlreadySet()`

**Raised by:**

* [CryptoLegacyBasePlugin.beneficiarySwitch()](https://docs.cryptolegacy.app/documentation/functions-reference#beneficiaryswitch-clbp1)

**Notes / Edge cases:** None

### BeneficiaryNotSet (ICL1)

**Parameters:** None

**Description:** Raised when a beneficiary is assumed to exist but none is configured.

**Error Signature:** `BeneficiaryNotSet()`

**Raised by:**

* [NftLegacyPlugin.transferNftTokensToLegacy()](https://docs.cryptolegacy.app/documentation/functions-reference#transfernfttokenstolegacy-nlp1)

**Notes / Edge cases:** None

### Pause (ICL1)

**Parameters:** None

**Description:** Raised if a call is attempted while the contract is in a paused state, blocking the requested action.

**Error Signature:** `Pause()`

**Raised by:**

* [LibCryptoLegacy.\_checkPause()](https://docs.cryptolegacy.app/documentation/functions-reference#_checkpause-lcl1)

**Notes / Edge cases:** None

### IncorrectFacetCutAction (ICL1)

**Parameters:** None

**Description:** Raised if the diamond cut (facet management) action is not recognized (not Add, Replace, or Remove).

**Error Signature:** `IncorrectFacetCutAction()`

**Raised by:** None

**Notes / Edge cases:** None

### NotContractOwner (ICL1)

**Parameters:** None

**Description:** Raised if a diamond operation expects the diamond's internal owner but is called by someone else.

**Error Signature:** `NotContractOwner()`

**Raised by:** None

**Notes / Edge cases:** None

### FacetNotFound (ICL1)

**Parameters:** None

**Description:** Raised when an attempt is made to manage or reference a facet address that cannot be located in storage.

**Error Signature:** `FacetNotFound()`

**Raised by:**

* [LibCryptoLegacyPlugins.\_getFacetAddressPosition()](https://docs.cryptolegacy.app/documentation/functions-reference#_getfacetaddressposition-lclp1)

**Notes / Edge cases:** None

### FacetHasNoCode (ICL1)

**Parameters:** None

**Description:** Raised if a facet address is found to contain no contract code upon an Add or Replace operation.

**Error Signature:** `FacetHasNoCode()`

**Raised by:** None

**Notes / Edge cases:** None

### NoSelectorsInFacetToCut (ICL1)

**Parameters:** None

**Description:** Raised if a facet cut is requested with zero function selectors.

**Error Signature:** `NoSelectorsInFacetToCut()`

**Raised by:** None

**Notes / Edge cases:** None

### FacetCantBeZero (ICL1)

**Parameters:** None

**Description:** Raised if an Add, Replace, or Remove action references a zero address for the facet.

**Error Signature:** `FacetCantBeZero()`

**Raised by:**

* [LibCryptoLegacyPlugins.addFunctions()](https://docs.cryptolegacy.app/documentation/functions-reference#addfunctions-lclp1)
* [LibCryptoLegacyPlugins.removeFunctions()](https://docs.cryptolegacy.app/documentation/functions-reference#removefunctions-lclp1)

**Notes / Edge cases:** None

### CantRemoveImmutableFunctions (ICL1)

**Parameters:** None

**Description:** Raised if a removal is attempted on a function that is immutable (defined directly in the diamond).

**Error Signature:** `CantRemoveImmutableFunctions()`

**Raised by:**

* [LibCryptoLegacyPlugins.removeFunctions()](https://docs.cryptolegacy.app/documentation/functions-reference#removefunctions-lclp1)

**Notes / Edge cases:** None

### CantAddFunctionThatAlreadyExists (ICL1)

**Parameters:** None

**Description:** Raised if a new facet or plugin tries to add a function selector that already exists in the contract.

**Error Signature:** `CantAddFunctionThatAlreadyExists()`

**Raised by:**

* [LibCryptoLegacyPlugins.addFunctions()](https://docs.cryptolegacy.app/documentation/functions-reference#addfunctions-lclp1)

**Notes / Edge cases:** None

### CantReplaceFunctionWithSameFunction (ICL1)

**Parameters:** None

**Description:** Raised if a Replace operation attempts to replace a function selector with a facet that already provides it.

**Error Signature:** `CantReplaceFunctionWithSameFunction()`

**Raised by:** None

**Notes / Edge cases:** None

### InitFunctionReverted (ICL1)

**Parameters:** None

**Description:** Raised if the init function (delegatecall) reverts during a diamond cut.

**Error Signature:** `InitFunctionReverted()`

**Raised by:** None

**Notes / Edge cases:** None

### InitAddressZeroButCalldataIsNot (ICL1)

**Parameters:** None

**Description:** Raised if an address is zero but non-empty calldata was provided for the init function, leading to a mismatch.

**Error Signature:** `InitAddressZeroButCalldataIsNot()`

**Raised by:** None

**Notes / Edge cases:** None

### InitCalldataZeroButAddressIsNot (ICL1)

**Parameters:** None

**Description:** Raised if an init address is non-zero but the calldata is empty, which is invalid for a diamond cut initialization.

**Error Signature:** `InitCalldataZeroButAddressIsNot()`

**Raised by:** None

**Notes / Edge cases:** None

### PluginNotRegistered (ICL1)

**Parameters:** None

**Description:** Raised if a plugin is used that is not recognized in the plugins registry.

**Error Signature:** `PluginNotRegistered()`

**Raised by:**

* [LibCryptoLegacyPlugins.\_validatePlugin()](https://docs.cryptolegacy.app/documentation/functions-reference#_validateplugin-lclp1)

**Notes / Edge cases:** None

### TransferFeeFailed (ICL1)

**Parameters:**

* `response (bytes)`: Raw response bytes from the failed fee transfer.

**Description:** Raised when transferring or refunding a fee fails and returns error data.

**Error Signature:** `TransferFeeFailed(bytes response)`

**Raised by:**

* [LibCryptoLegacy.\_transferFee()](https://docs.cryptolegacy.app/documentation/functions-reference#_transferfee-lcl1)

**Notes / Edge cases:** None

### TooBigMultiplier (ICL1)

**Parameters:**

* `maxMultiplier (uint8)`: Maximum permitted gas limit multiplier.

**Description:** Raised when a gas limit multiplier exceeds the permitted maximum.

**Error Signature:** `TooBigMultiplier(uint8 maxMultiplier)`

**Raised by:**

* [CryptoLegacyBasePlugin.setGasLimitMultiplier()](https://docs.cryptolegacy.app/documentation/functions-reference#setgaslimitmultiplier-clbp1)

**Notes / Edge cases:** None

## ICryptoLegacyBuildManager (ICLBM1)

### AlreadyLifetime (ICLBM1)

**Parameters:** None

**Description:** Raised if an operation tries to pay a lifetime fee or set a lifetime NFT, but the user already has lifetime status.

**Error Signature:** `AlreadyLifetime()`

**Raised by:** None

**Notes / Edge cases:** None

### WithdrawFeeFailed (ICLBM1)

**Parameters:**

* `reason (bytes)`: Raw revert data returned by the failed withdrawal.

**Description:** Raised when a fee withdrawal fails and returns revert data.

**Error Signature:** `WithdrawFeeFailed(bytes reason)`

**Raised by:**

* [CryptoLegacyBuildManager.withdrawFee()](https://docs.cryptolegacy.app/documentation/functions-reference#withdrawfee-clbm1)

**Notes / Edge cases:** None

### NotValidTimeout (ICLBM1)

**Parameters:** None

**Description:** Raised if the provided interval or timeout is not valid for the expected usage (e.g., not matching required durations).

**Error Signature:** `NotValidTimeout()`

**Raised by:**

* [CryptoLegacyBuildManager.\_checkBuildArgs()](https://docs.cryptolegacy.app/documentation/functions-reference#_checkbuildargs-clbm1)

**Notes / Edge cases:** None

### IncorrectFee (ICLBM1)

**Parameters:**

* `feeToTake (uint256)`: Fee amount the build manager expected to collect.

**Description:** Raised if the fee passed into a function is less than the required amount or otherwise mismatched.

**Error Signature:** `IncorrectFee(uint256 feeToTake)`

**Raised by:**

* [CryptoLegacyBuildManager.\_checkFee()](https://docs.cryptolegacy.app/documentation/functions-reference#_checkfee-clbm1)
* [CryptoLegacyBuildManager.payForMultipleLifetimeNft()](https://docs.cryptolegacy.app/documentation/functions-reference#payformultiplelifetimenft-clbm1)

**Notes / Edge cases:** None

### BelowMinimumSupply (ICLBM1)

**Parameters:**

* `supplyLimit (uint256)`: Minimum supply threshold required for the operation.

**Description:** Raised when an operation requires a minimum supply but the current supply is below the configured limit.

**Error Signature:** `BelowMinimumSupply(uint256 supplyLimit)`

**Raised by:**

* [CryptoLegacyBuildManager.payForMultipleLifetimeNft()](https://docs.cryptolegacy.app/documentation/functions-reference#payformultiplelifetimenft-clbm1)

**Notes / Edge cases:** None

### NotRegisteredCryptoLegacy (ICLBM1)

**Parameters:** None

**Description:** Raised when a CryptoLegacy contract is not registered in the build manager.

**Error Signature:** `NotRegisteredCryptoLegacy()`

**Raised by:**

* [CryptoLegacyBuildManager.isLifetimeNftLockedAndUpdate()](https://docs.cryptolegacy.app/documentation/functions-reference#islifetimenftlockedandupdate-clbm1)
* [LibCryptoLegacy.\_isLifetimeActiveAndUpdate()](https://docs.cryptolegacy.app/documentation/functions-reference#_islifetimeactiveandupdate-lcl1)

**Notes / Edge cases:** None

### NotOwnerOfCryptoLegacy (ICLBM1)

**Parameters:** None

**Description:** Raised when the caller is not the owner of the specified CryptoLegacy contract.

**Error Signature:** `NotOwnerOfCryptoLegacy()`

**Raised by:**

* [CryptoLegacyBuildManager.isLifetimeNftLockedAndUpdate()](https://docs.cryptolegacy.app/documentation/functions-reference#islifetimenftlockedandupdate-clbm1)
* [LibCryptoLegacy.\_isLifetimeActiveAndUpdate()](https://docs.cryptolegacy.app/documentation/functions-reference#_islifetimeactiveandupdate-lcl1)

**Notes / Edge cases:** None

### TransferFeeFailed (ICLBM1)

**Parameters:**

* `response (bytes)`: Raw response bytes from the failed fee transfer.

**Description:** Raised when transferring or refunding a fee fails and returns error data.

**Error Signature:** `TransferFeeFailed(bytes response)`

**Raised by:**

* [CryptoLegacyBuildManager.\_returnFee()](https://docs.cryptolegacy.app/documentation/functions-reference#_returnfee-clbm1)

**Notes / Edge cases:** None

## ICryptoLegacyDiamondBase (ICLDB1)

### FunctionNotExists (ICLDB1)

**Parameters:**

* `selector (bytes4)`: Function selector that was not found.

**Description:** Raised when a function call does not match any available facet or plugin, indicating that the function does not exist.

**Error Signature:** `FunctionNotExists(bytes4 selector)`

**Raised by:**

* [CryptoLegacyDiamondBase.fallback()](https://docs.cryptolegacy.app/documentation/functions-reference#fallback-cldb1)

**Notes / Edge cases:** None

### NotSelfCall (ICLDB1)

**Parameters:** None

**Description:** Raised when a static call checker detects that a call is not made from the contract to itself (self-call is required).

**Error Signature:** `NotSelfCall()`

**Raised by:**

* [CryptoLegacyDiamondBase.staticCallChecker()](https://docs.cryptolegacy.app/documentation/functions-reference#staticcallchecker-cldb1)

**Notes / Edge cases:** None

## ICryptoLegacyFactory (ICLF1)

### NotBuildOperator (ICLF1)

**Parameters:** None

**Description:** Raised when an action is attempted by an address that is not registered as an allowed build operator.

**Error Signature:** `NotBuildOperator()`

**Raised by:**

* [CryptoLegacyFactory.createCryptoLegacy()](https://docs.cryptolegacy.app/documentation/functions-reference#createcryptolegacy-clf1)

**Notes / Edge cases:** None

## ICryptoLegacyLens (ICLL1)

**No errors in this contract/library.**

## ICryptoLegacyOwnable (ICLO1)

### OwnableUnauthorizedAccount (ICLO1)

**Parameters:**

* `account (address)`: Account that failed an authorization check.

**Description:** Raised when an account that is not the owner attempts an owner-restricted action.

**Error Signature:** `OwnableUnauthorizedAccount(address account)`

**Raised by:**

* [CryptoLegacyOwnable.acceptOwnership()](https://docs.cryptolegacy.app/documentation/functions-reference#acceptownership-clo1)

**Notes / Edge cases:** None

## ICryptoLegacyPlugin (ICLP1)

**No errors in this contract/library.**

## ICryptoLegacyUpdaterPlugin (ICLUP1)

### NotTheUpdater (ICLUP1)

**Parameters:** None

**Description:** Raised when a function that only an approved updater may call is attempted by an address that is not recognized as an updater.

**Error Signature:** `NotTheUpdater()`

**Raised by:**

* [UpdateRolePlugin.updateByUpdater()](https://docs.cryptolegacy.app/documentation/functions-reference#updatebyupdater-urp1)

**Notes / Edge cases:** None

## IDeBridgeGate (IDBG1)

**No errors in this contract/library.**

## IDiamondCut (IDC1)

**No errors in this contract/library.**

## IDiamondLoupe (IDL1)

**No errors in this contract/library.**

## IFeeRegistry (IFR1)

### WithdrawAccumulatedFeeFailed (IFR1)

**Parameters:**

* `reason (bytes)`: Raw revert data returned by the failed withdrawal.

**Description:** Raised when withdrawing accumulated fees fails and returns revert data.

**Error Signature:** `WithdrawAccumulatedFeeFailed(bytes reason)`

**Raised by:**

* [FeeRegistry.withdrawAccumulatedFee()](https://docs.cryptolegacy.app/documentation/functions-reference#withdrawaccumulatedfee-fr1)
* [FeeRegistry.withdrawReferralAccumulatedFee()](https://docs.cryptolegacy.app/documentation/functions-reference#withdrawreferralaccumulatedfee-fr1)

**Notes / Edge cases:** None

### PctSumDoesntMatchBase (IFR1)

**Parameters:** None

**Description:** Raised when fee beneficiary shares do not sum to the required base (10000).

**Error Signature:** `PctSumDoesntMatchBase()`

**Raised by:**

* [FeeRegistry.setFeeBeneficiaries()](https://docs.cryptolegacy.app/documentation/functions-reference#setfeebeneficiaries-fr1)

**Notes / Edge cases:** None

### TooBigPct (IFR1)

**Parameters:** None

**Description:** Raised when a discount or share percentage is greater than the permissible maximum (10000 bps).

**Error Signature:** `TooBigPct()`

**Raised by:**

* [FeeRegistry.setRefererSpecificPct()](https://docs.cryptolegacy.app/documentation/functions-reference#setrefererspecificpct-fr1)
* [FeeRegistry.\_calculateFee()](https://docs.cryptolegacy.app/documentation/functions-reference#_calculatefee-fr1)

**Notes / Edge cases:** None

### RefAlreadyCreated (IFR1)

**Parameters:** None

**Description:** Raised if a referral code is being created but it already exists in the registry.

**Error Signature:** `RefAlreadyCreated()`

**Raised by:**

* [FeeRegistry.\_createCustomCode()](https://docs.cryptolegacy.app/documentation/functions-reference#_createcustomcode-fr1)

**Notes / Edge cases:** None

### ZeroCode (IFR1)

**Parameters:** None

**Description:** Raised if an attempt is made to create or use a referral code that is `bytes8(0)`, which is disallowed.

**Error Signature:** `ZeroCode()`

**Raised by:**

* [FeeRegistry.\_checkCodeNotZero()](https://docs.cryptolegacy.app/documentation/functions-reference#_checkcodenotzero-fr1)

**Notes / Edge cases:** None

### NotOperator (IFR1)

**Parameters:** None

**Description:** Raised if a function limited to code operators is called by an address not in that set.

**Error Signature:** `NotOperator()`

**Raised by:**

* [FeeRegistry.\_checkSenderIsOperator()](https://docs.cryptolegacy.app/documentation/functions-reference#_checksenderisoperator-fr1)

**Notes / Edge cases:** None

### NotReferrer (IFR1)

**Parameters:** None

**Description:** Raised if a call referencing a referral code is made by someone other than the recognized code owner (referrer).

**Error Signature:** `NotReferrer()`

**Raised by:**

* [FeeRegistry.\_checkSenderIsReferrer()](https://docs.cryptolegacy.app/documentation/functions-reference#_checksenderisreferrer-fr1)

**Notes / Edge cases:** None

### AlreadyReferrer (IFR1)

**Parameters:** None

**Description:** Raised if a new owner address is designated for a referral code but already has a code assigned.

**Error Signature:** `AlreadyReferrer()`

**Raised by:**

* [FeeRegistry.\_checkNewOwnerIsNotReferrer()](https://docs.cryptolegacy.app/documentation/functions-reference#_checknewownerisnotreferrer-fr1)

**Notes / Edge cases:** None

### CodeNotCreated (IFR1)

**Parameters:** None

**Description:** Raised if an update or cross-chain referral action references a code that does not exist in storage.

**Error Signature:** `CodeNotCreated()`

**Raised by:**

* [FeeRegistry.updateCrossChainsRef()](https://docs.cryptolegacy.app/documentation/functions-reference#updatecrosschainsref-fr1)

**Notes / Edge cases:** None

## ILockChainGate (ILCG1)

### ArrayLengthMismatch (ILCG1)

**Parameters:** None

**Description:** Raised when related arrays are expected to be the same length but are not.

**Error Signature:** `ArrayLengthMismatch()`

**Raised by:**

* [FeeRegistry.\_setCrossChainsRef()](https://docs.cryptolegacy.app/documentation/functions-reference#_setcrosschainsref-fr1)
* [LockChainGate.\_lockLifetimeNftToChains()](https://docs.cryptolegacy.app/documentation/functions-reference#_locklifetimenfttochains-lcg1)
* [LockChainGate.\_updateNftOwnerOnChainList()](https://docs.cryptolegacy.app/documentation/functions-reference#_updatenftowneronchainlist-lcg1)

**Notes / Edge cases:** None

### AlreadyLocked (ILCG1)

**Parameters:** None

**Description:** Raised when an NFT is already locked for a holder and a new lock attempt is made without unlocking first.

**Error Signature:** `AlreadyLocked()`

**Raised by:**

* [LockChainGate.\_writeLockLifetimeNft()](https://docs.cryptolegacy.app/documentation/functions-reference#_writelocklifetimenft-lcg1)

**Notes / Edge cases:** None

### LockedToChains (ILCG1)

**Parameters:** None

**Description:** Raised when an action (e.g., unlocking) is attempted but the NFT is still locked to multiple chains.

**Error Signature:** `LockedToChains()`

**Raised by:**

* [LockChainGate.unlockLifetimeNft()](https://docs.cryptolegacy.app/documentation/functions-reference#unlocklifetimenft-lcg1)

**Notes / Edge cases:** None

### CrossChainLock (ILCG1)

**Parameters:** None

**Description:** Raised when an action cannot proceed because the NFT is currently locked under a cross-chain process.

**Error Signature:** `CrossChainLock()`

**Raised by:**

* [LockChainGate.\_checkCrossChainLock()](https://docs.cryptolegacy.app/documentation/functions-reference#_checkcrosschainlock-lcg1)

**Notes / Edge cases:** None

### TooEarly (ILCG1)

**Parameters:** None

**Description:** Raised when an unlocking or transfer is attempted before the lock period has elapsed.

**Error Signature:** `TooEarly()`

**Raised by:**

* [LockChainGate.\_checkTooEarly()](https://docs.cryptolegacy.app/documentation/functions-reference#_checktooearly-lcg1)

**Notes / Edge cases:** None

### DestinationChainNotSpecified (ILCG1)

**Parameters:** None

**Description:** Raised when a cross-chain locking action references a chain ID for which no destination contract is specified.

**Error Signature:** `DestinationChainNotSpecified()`

**Raised by:**

* [LockChainGate.\_checkDestinationLockedChain()](https://docs.cryptolegacy.app/documentation/functions-reference#_checkdestinationlockedchain-lcg1)

**Notes / Edge cases:** None

### TokenNotLocked (ILCG1)

**Parameters:** None

**Description:** Raised when an NFT-based action is attempted for a token that is not currently locked.

**Error Signature:** `TokenNotLocked()`

**Raised by:**

* [LockChainGate.\_checkTokenLocked()](https://docs.cryptolegacy.app/documentation/functions-reference#_checktokenlocked-lcg1)
* [LockChainGate.\_checkHolderTokenLock()](https://docs.cryptolegacy.app/documentation/functions-reference#_checkholdertokenlock-lcg1)

**Notes / Edge cases:** None

### TokenIdMismatch (ILCG1)

**Parameters:**

* `checkTokenId (uint256)`: Token ID that was expected for the operation.

**Description:** Raised when the token ID being updated or transferred does not match the token ID that was locked or recognized for the operation.

**Error Signature:** `TokenIdMismatch(uint256 checkTokenId)`

**Raised by:**

* [LockChainGate.\_updateLifetimeNftOwnerOnChain()](https://docs.cryptolegacy.app/documentation/functions-reference#_updatelifetimenftowneronchain-lcg1)

**Notes / Edge cases:** None

### AlreadyLockedToChain (ILCG1)

**Parameters:** None

**Description:** Raised when attempting to lock an NFT to a chain to which it is already locked.

**Error Signature:** `AlreadyLockedToChain()`

**Raised by:**

* [LockChainGate.\_lockLifetimeNftToChain()](https://docs.cryptolegacy.app/documentation/functions-reference#_locklifetimenfttochain-lcg1)

**Notes / Edge cases:** None

### SourceNotSpecified (ILCG1)

**Parameters:** None

**Description:** Raised if a cross-chain message originates from a chain ID for which no source contract is set in the gate configuration.

**Error Signature:** `SourceNotSpecified()`

**Raised by:**

* [LockChainGate.\_checkSource()](https://docs.cryptolegacy.app/documentation/functions-reference#_checksource-lcg1)

**Notes / Edge cases:** None

### NotLockedByChain (ILCG1)

**Parameters:** None

**Description:** Raised when an unlock-from-chain operation is attempted but the NFT is not locked by that chain.

**Error Signature:** `NotLockedByChain()`

**Raised by:**

* [LockChainGate.unlockLifetimeNftFromChain()](https://docs.cryptolegacy.app/documentation/functions-reference#unlocklifetimenftfromchain-lcg1)

**Notes / Edge cases:** None

### DestinationNotSpecified (ILCG1)

**Parameters:** None

**Description:** Raised when no destination chain contract is configured for the specified chain.

**Error Signature:** `DestinationNotSpecified()`

**Raised by:** None

**Notes / Edge cases:** None

### NotAvailable (ILCG1)

**Parameters:** None

**Description:** Raised when an operation on a locked NFT is not available to the caller or is blocked by conditions.

**Error Signature:** `NotAvailable()`

**Raised by:**

* [LockChainGate.unlockLifetimeNft()](https://docs.cryptolegacy.app/documentation/functions-reference#unlocklifetimenft-lcg1)
* [LockChainGate.transferLifetimeNftTo()](https://docs.cryptolegacy.app/documentation/functions-reference#transferlifetimenftto-lcg1)
* [LockChainGate.updateNftOwnerOnChainList()](https://docs.cryptolegacy.app/documentation/functions-reference#updatenftowneronchainlist-lcg1)

**Notes / Edge cases:** None

### IncorrectFee (ILCG1)

**Parameters:**

* `requiredFee (uint256)`: Exact fee amount required by the operation.

**Description:** Raised if the fee passed into a function is less than the required amount or otherwise mismatched.

**Error Signature:** `IncorrectFee(uint256 requiredFee)`

**Raised by:**

* [LockChainGate.\_checkFee()](https://docs.cryptolegacy.app/documentation/functions-reference#_checkfee-lcg1)

**Notes / Edge cases:** None

### SameAddress (ILCG1)

**Parameters:** None

**Description:** Raised when a transfer is requested, but the source and destination addresses are the same.

**Error Signature:** `SameAddress()`

**Raised by:**

* [LockChainGate.\_transferLifetimeNftTo()](https://docs.cryptolegacy.app/documentation/functions-reference#_transferlifetimenftto-lcg1)

**Notes / Edge cases:** None

### RecipientLocked (ILCG1)

**Parameters:** None

**Description:** Raised when trying to transfer an NFT to a recipient who already has a locked NFT, and the system prohibits such a scenario.

**Error Signature:** `RecipientLocked()`

**Raised by:**

* [LockChainGate.\_transferLifetimeNftTo()](https://docs.cryptolegacy.app/documentation/functions-reference#_transferlifetimenftto-lcg1)

**Notes / Edge cases:** None

### TransferLockTimeout (ILCG1)

**Parameters:** None

**Description:** Raised when a transfer or unlock is attempted after the transfer timeout has elapsed.

**Error Signature:** `TransferLockTimeout()`

**Raised by:**

* [LockChainGate.\_transferLifetimeNftTo()](https://docs.cryptolegacy.app/documentation/functions-reference#_transferlifetimenftto-lcg1)

**Notes / Edge cases:** None

### NotCallProxy (ILCG1)

**Parameters:** None

**Description:** Raised when a cross-chain operation is not being relayed by the expected CallProxy contract.

**Error Signature:** `NotCallProxy()`

**Raised by:**

* [LockChainGate.\_onlyCrossChain()](https://docs.cryptolegacy.app/documentation/functions-reference#_onlycrosschain-lcg1)

**Notes / Edge cases:** None

### ChainIdMismatch (ILCG1)

**Parameters:** None

**Description:** Raised when a cross-chain message’s chain ID does not match the chain ID that the contract expects for the submission.

**Error Signature:** `ChainIdMismatch()`

**Raised by:**

* [LockChainGate.\_onlyCrossChain()](https://docs.cryptolegacy.app/documentation/functions-reference#_onlycrosschain-lcg1)

**Notes / Edge cases:** None

### NotValidSender (ILCG1)

**Parameters:** None

**Description:** Raised when a cross-chain message’s native sender does not match the recognized source contract.

**Error Signature:** `NotValidSender()`

**Raised by:**

* [LockChainGate.\_onlyCrossChain()](https://docs.cryptolegacy.app/documentation/functions-reference#_onlycrosschain-lcg1)

**Notes / Edge cases:** None

### NotAllowed (ILCG1)

**Parameters:** None

**Description:** Raised when an operation on a locked NFT is restricted to certain operators, but the caller is not allowed.

**Error Signature:** `NotAllowed()`

**Raised by:**

* [LockChainGate.isNftLockedAndUpdate()](https://docs.cryptolegacy.app/documentation/functions-reference#isnftlockedandupdate-lcg1)

**Notes / Edge cases:** None

### TransferFeeFailed (ILCG1)

**Parameters:**

* `response (bytes)`: Raw response bytes from the failed fee transfer.

**Description:** Raised when transferring or refunding a fee fails and returns error data.

**Error Signature:** `TransferFeeFailed(bytes response)`

**Raised by:**

* [LockChainGate.\_returnFee()](https://docs.cryptolegacy.app/documentation/functions-reference#_returnfee-lcg1)

**Notes / Edge cases:** None

## ILegacyMessenger (ILM1)

**No errors in this contract/library.**

## ILido (ILD1)

**No errors in this contract/library.**

## ILidoWithdrawalQueue (ILWQ1)

**No errors in this contract/library.**

## ILifetimeNft (ILN1)

### NotTheMinter (ILN1)

**Parameters:** None

**Description:** Raised when an address attempts to mint a LifetimeNft but is not designated as an active minter operator.

**Error Signature:** `NotTheMinter()`

**Raised by:**

* [LifetimeNft.mint()](https://docs.cryptolegacy.app/documentation/functions-reference#mint-ln1)

**Notes / Edge cases:** None

## IPermit2 (IPM21)

**No errors in this contract/library.**

## IPluginsRegistry (IPR1)

**No errors in this contract/library.**

## ISafeMinimalMultisig (ISM1)

### MultisigProposalNotPending (ISM1)

**Parameters:** None

**Description:** Raised when a proposal is expected to be pending but is not.

**Error Signature:** `MultisigProposalNotPending()`

**Raised by:**

* [LibSafeMinimalMultisig.\_getPendingProposalForVoter()](https://docs.cryptolegacy.app/documentation/functions-reference#_getpendingproposalforvoter-lsm1)

**Notes / Edge cases:** None

### MultisigNotConfirmed (ISM1)

**Parameters:** None

**Description:** Raised when a proposal lacks the required confirmations for execution.

**Error Signature:** `MultisigNotConfirmed()`

**Raised by:**

* [LibSafeMinimalMultisig.\_cancel()](https://docs.cryptolegacy.app/documentation/functions-reference#_cancel-lsm1)

**Notes / Edge cases:** None

### MultisigExecutionFailed (ISM1)

**Parameters:** None

**Description:** Raised if the low-level call (execution of a proposal) fails or reverts.

**Error Signature:** `MultisigExecutionFailed()`

**Raised by:**

* [LibSafeMinimalMultisig.\_execute()](https://docs.cryptolegacy.app/documentation/functions-reference#_execute-lsm1)

**Notes / Edge cases:** None

### MultisigMethodNotAllowed (ISM1)

**Parameters:** None

**Description:** Raised if a proposal references a function selector that is not permitted by the chosen multi-sig flow.

**Error Signature:** `MultisigMethodNotAllowed()`

**Raised by:**

* [LibSafeMinimalMultisig.\_propose()](https://docs.cryptolegacy.app/documentation/functions-reference#_propose-lsm1)

**Notes / Edge cases:** None

### MultisigVoterNotAllowed (ISM1)

**Parameters:** None

**Description:** Raised when an address that is not in the set of recognized voters attempts to create or confirm a proposal.

**Error Signature:** `MultisigVoterNotAllowed()`

**Raised by:**

* [LibSafeMinimalMultisig.\_checkIsSenderAllowed()](https://docs.cryptolegacy.app/documentation/functions-reference#_checkissenderallowed-lsm1)

**Notes / Edge cases:** None

### MultisigOnlyExecutor (ISM1)

**Parameters:** None

**Description:** Raised if a proposal is executed by an entity other than the contract itself (where the design requires internal execution).

**Error Signature:** `MultisigOnlyExecutor()`

**Raised by:**

* [LibSafeMinimalMultisig.\_checkIsMultisigExecutor()](https://docs.cryptolegacy.app/documentation/functions-reference#_checkismultisigexecutor-lsm1)

**Notes / Edge cases:** None

### MultisigIncorrectRequiredConfirmations (ISM1)

**Parameters:** None

**Description:** Raised if an attempt is made to set or initialize a multi-sig with a required confirmation count that is zero or exceeds the number of voters.

**Error Signature:** `MultisigIncorrectRequiredConfirmations()`

**Raised by:**

* [LibSafeMinimalBeneficiaryMultisig.\_setConfirmations()](https://docs.cryptolegacy.app/documentation/functions-reference#_setconfirmations-lsmb1)
* [LibSafeMinimalMultisig.\_setVotersAndConfirmations()](https://docs.cryptolegacy.app/documentation/functions-reference#_setvotersandconfirmations-lsm1)

**Notes / Edge cases:** None

### MultisigNothingToWithdraw (ISM1)

**Parameters:** None

**Description:** Raised when a withdrawal is attempted but there is no held ETH to withdraw.

**Error Signature:** `MultisigNothingToWithdraw()`

**Raised by:**

* [LibSafeMinimalMultisig.\_withdrawHeldEth()](https://docs.cryptolegacy.app/documentation/functions-reference#_withdrawheldeth-lsm1)

**Notes / Edge cases:** None

### TransferFeeFailed (ISM1)

**Parameters:**

* `response (bytes)`: Raw response bytes from the failed fee transfer.

**Description:** Raised when transferring or refunding a fee fails and returns error data.

**Error Signature:** `TransferFeeFailed(bytes response)`

**Raised by:**

* [LibSafeMinimalMultisig.\_withdrawHeldEth()](https://docs.cryptolegacy.app/documentation/functions-reference#_withdrawheldeth-lsm1)

**Notes / Edge cases:** None

## ISignatureRoleTimelock (ISRT1)

### DisabledFunction (ISRT1)

**Parameters:** None

**Description:** Raised when a function or signature is disabled in the timelock configuration.

**Error Signature:** `DisabledFunction()`

**Raised by:**

* [SignatureRoleTimelock.renounceRole()](https://docs.cryptolegacy.app/documentation/functions-reference#renouncerole-srt1)

**Notes / Edge cases:** None

### AlreadyHaveRole (ISRT1)

**Parameters:** None

**Description:** Raised when adding a role to an account that already holds it.

**Error Signature:** `AlreadyHaveRole()`

**Raised by:**

* [SignatureRoleTimelock.\_addRoleAccount()](https://docs.cryptolegacy.app/documentation/functions-reference#_addroleaccount-srt1)

**Notes / Edge cases:** None

### DoesntHaveRole (ISRT1)

**Parameters:** None

**Description:** Raised when removing or modifying a role for an account that does not hold the role.

**Error Signature:** `DoesntHaveRole()`

**Raised by:**

* [SignatureRoleTimelock.\_removeRoleAccount()](https://docs.cryptolegacy.app/documentation/functions-reference#_removeroleaccount-srt1)

**Notes / Edge cases:** None

### RoleDontExist (ISRT1)

**Parameters:** None

**Description:** Raised when assigning a signature role to a role identifier that does not exist.

**Error Signature:** `RoleDontExist()`

**Raised by:**

* [SignatureRoleTimelock.\_addSignatureRole()](https://docs.cryptolegacy.app/documentation/functions-reference#_addsignaturerole-srt1)

**Notes / Edge cases:** None

### CallerNotCurrentAddress (ISRT1)

**Parameters:** None

**Description:** Raised when a function marked for internal use is called by an external address instead of the contract itself.

**Error Signature:** `CallerNotCurrentAddress()`

**Raised by:**

* [SignatureRoleTimelock.setMaxExecutionPeriod()](https://docs.cryptolegacy.app/documentation/functions-reference#setmaxexecutionperiod-srt1)
* [SignatureRoleTimelock.setRoleAccounts()](https://docs.cryptolegacy.app/documentation/functions-reference#setroleaccounts-srt1)
* [SignatureRoleTimelock.addSignatureRoleList()](https://docs.cryptolegacy.app/documentation/functions-reference#addsignaturerolelist-srt1)
* [SignatureRoleTimelock.removeSignatureRoleList()](https://docs.cryptolegacy.app/documentation/functions-reference#removesignaturerolelist-srt1)

**Notes / Edge cases:** None

### IncorrectSignatureIndex (ISRT1)

**Parameters:** None

**Description:** Raised when an index for a signature array is incorrect or out-of-bounds during a removal or update action.

**Error Signature:** `IncorrectSignatureIndex()`

**Raised by:**

* [SignatureRoleTimelock.\_removeSignatureRole()](https://docs.cryptolegacy.app/documentation/functions-reference#_removesignaturerole-srt1)

**Notes / Edge cases:** None

### IncorrectRoleIndex (ISRT1)

**Parameters:** None

**Description:** Raised when an index for a role array is incorrect or out-of-bounds during role management.

**Error Signature:** `IncorrectRoleIndex()`

**Raised by:**

* [SignatureRoleTimelock.\_removeRoleAccount()](https://docs.cryptolegacy.app/documentation/functions-reference#_removeroleaccount-srt1)

**Notes / Edge cases:** None

### CallFailed (ISRT1)

**Parameters:**

* `errorMessage (bytes)`: Raw revert data returned by the failed call.

**Description:** Raised when an external call made by the timelock fails.

**Error Signature:** `CallFailed(bytes errorMessage)`

**Raised by:**

* [SignatureRoleTimelock.\_executeCall()](https://docs.cryptolegacy.app/documentation/functions-reference#_executecall-srt1)

**Notes / Edge cases:** None

### CallNotScheduled (ISRT1)

**Parameters:** None

**Description:** Raised when attempting to execute or cancel a call that is not in the pending schedule.

**Error Signature:** `CallNotScheduled()`

**Raised by:**

* [SignatureRoleTimelock.\_executeCall()](https://docs.cryptolegacy.app/documentation/functions-reference#_executecall-srt1)
* [SignatureRoleTimelock.\_cancelCall()](https://docs.cryptolegacy.app/documentation/functions-reference#_cancelcall-srt1)

**Notes / Edge cases:** None

### NotPending (ISRT1)

**Parameters:** None

**Description:** Raised when a scheduled call has already been executed or canceled, so it is no longer pending.

**Error Signature:** `NotPending()`

**Raised by:**

* [SignatureRoleTimelock.\_executeCall()](https://docs.cryptolegacy.app/documentation/functions-reference#_executecall-srt1)
* [SignatureRoleTimelock.\_cancelCall()](https://docs.cryptolegacy.app/documentation/functions-reference#_cancelcall-srt1)

**Notes / Edge cases:** None

### TimelockActive (ISRT1)

**Parameters:** None

**Description:** Raised when execution is attempted before the timelock period has elapsed.

**Error Signature:** `TimelockActive()`

**Raised by:**

* [SignatureRoleTimelock.\_executeCall()](https://docs.cryptolegacy.app/documentation/functions-reference#_executecall-srt1)

**Notes / Edge cases:** None

### TimelockExpired (ISRT1)

**Parameters:** None

**Description:** Raised when execution is attempted after the timelock’s valid execution window.

**Error Signature:** `TimelockExpired()`

**Raised by:**

* [SignatureRoleTimelock.\_executeCall()](https://docs.cryptolegacy.app/documentation/functions-reference#_executecall-srt1)

**Notes / Edge cases:** None

### CallerHaveNoRequiredRole (ISRT1)

**Parameters:**

* `requiredRole (bytes32)`: Role identifier the caller must have.

**Description:** Raised when a caller tries to schedule or execute an action requiring a role they do not possess.

**Error Signature:** `CallerHaveNoRequiredRole(bytes32 requiredRole)`

**Raised by:**

* [SignatureRoleTimelock.\_checkRole()](https://docs.cryptolegacy.app/documentation/functions-reference#_checkrole-srt1)

**Notes / Edge cases:** None

### CallAlreadyScheduled (ISRT1)

**Parameters:** None

**Description:** Raised when a call is scheduled more than once with the same combination of target, data, and execution time.

**Error Signature:** `CallAlreadyScheduled()`

**Raised by:**

* [SignatureRoleTimelock.\_scheduleCall()](https://docs.cryptolegacy.app/documentation/functions-reference#_schedulecall-srt1)

**Notes / Edge cases:** None

### SignatureAlreadyExists (ISRT1)

**Parameters:** None

**Description:** Raised when an attempt is made to add a signature role that already exists for a given target/function.

**Error Signature:** `SignatureAlreadyExists()`

**Raised by:**

* [SignatureRoleTimelock.\_addSignatureRole()](https://docs.cryptolegacy.app/documentation/functions-reference#_addsignaturerole-srt1)

**Notes / Edge cases:** None

### SignatureTimeLockNotSet (ISRT1)

**Parameters:**

* `signature (bytes4)`: Function selector whose timelock is missing.

**Description:** Raised if a signature-based action is processed but no timelock parameter is set.

**Error Signature:** `SignatureTimeLockNotSet(bytes4 signature)`

**Raised by:**

* [SignatureRoleTimelock.\_scheduleCall()](https://docs.cryptolegacy.app/documentation/functions-reference#_schedulecall-srt1)

**Notes / Edge cases:** None

### OutOfTimelockBounds (ISRT1)

**Parameters:**

* `maxTimelock (uint256)`: Maximum allowed timelock duration.

**Description:** Raised when a proposed timelock duration exceeds the allowed maximum limit.

**Error Signature:** `OutOfTimelockBounds(uint256 maxTimelock)`

**Raised by:**

* [SignatureRoleTimelock.\_addSignatureRole()](https://docs.cryptolegacy.app/documentation/functions-reference#_addsignaturerole-srt1)

**Notes / Edge cases:** None

### OutOfMaxExecutionPeriodBounds (ISRT1)

**Parameters:**

* `minPeriod (uint256)`: Minimum execution window length allowed.
* `maxPeriod (uint256)`: Maximum execution window length allowed.

**Description:** Raised if a proposed max execution period for scheduled calls is out of the contract’s acceptable range.

**Error Signature:** `OutOfMaxExecutionPeriodBounds(uint256 minPeriod, uint256 maxPeriod)`

**Raised by:**

* [SignatureRoleTimelock.setMaxExecutionPeriod()](https://docs.cryptolegacy.app/documentation/functions-reference#setmaxexecutionperiod-srt1)

**Notes / Edge cases:** None

## IStataToken (ISTA1)

**No errors in this contract/library.**

## IStataTokenFactory (ISTF1)

**No errors in this contract/library.**

## ITrustedGuardiansPlugin (ITGP1)

### NotGuardian (ITGP1)

**Parameters:** None

**Description:** Raised if a function restricted to guardians is attempted by an address that is not in the guardian set.

**Error Signature:** `NotGuardian()`

**Raised by:**

* [TrustedGuardiansPlugin.\_checkGuardian()](https://docs.cryptolegacy.app/documentation/functions-reference#_checkguardian-tgp1)

**Notes / Edge cases:** None

### ZeroGuardian (ITGP1)

**Parameters:** None

**Description:** Raised when a guardian identifier is zero or empty.

**Error Signature:** `ZeroGuardian()`

**Raised by:**

* [TrustedGuardiansPlugin.\_setGuardians()](https://docs.cryptolegacy.app/documentation/functions-reference#_setguardians-tgp1)

**Notes / Edge cases:** None

### ThresholdDontMet (ITGP1)

**Parameters:** None

**Description:** Raised if an operation expects a certain guardian threshold to be met but it has not been reached.

**Error Signature:** `ThresholdDontMet()`

**Raised by:** None

**Notes / Edge cases:** None

### ThresholdTooBig (ITGP1)

**Parameters:** None

**Description:** Raised when the guardians threshold exceeds the maximum allowed value.

**Error Signature:** `ThresholdTooBig()`

**Raised by:**

* [TrustedGuardiansPlugin.\_afterGuardiansSet()](https://docs.cryptolegacy.app/documentation/functions-reference#_afterguardiansset-tgp1)

**Notes / Edge cases:** None

### GuardianAlreadyVoted (ITGP1)

**Parameters:** None

**Description:** Raised if a guardian tries to vote or re-vote when their vote is already recorded.

**Error Signature:** `GuardianAlreadyVoted()`

**Raised by:**

* [TrustedGuardiansPlugin.\_checkGuardianNotVoted()](https://docs.cryptolegacy.app/documentation/functions-reference#_checkguardiannotvoted-tgp1)

**Notes / Edge cases:** None

### GuardiansTimeoutCantBeZero (ITGP1)

**Parameters:** None

**Description:** Raised when the guardians challenge timeout is set to zero.

**Error Signature:** `GuardiansTimeoutCantBeZero()`

**Raised by:**

* [TrustedGuardiansPlugin.\_setGuardiansConfig()](https://docs.cryptolegacy.app/documentation/functions-reference#_setguardiansconfig-tgp1)

**Notes / Edge cases:** None

### MaxGuardiansTimeout (ITGP1)

**Parameters:**

* `guardiansThreshold (uint64)`: Guardians threshold value that exceeds the allowed maximum.

**Description:** Raised if a proposed guardians challenge timeout exceeds the permitted maximum (e.g., 30 days).

**Error Signature:** `MaxGuardiansTimeout(uint64 guardiansThreshold)`

**Raised by:**

* [TrustedGuardiansPlugin.\_setGuardiansConfig()](https://docs.cryptolegacy.app/documentation/functions-reference#_setguardiansconfig-tgp1)

**Notes / Edge cases:** None

## DiamondLoupeFacet (DLF1)

**No errors in this contract/library.**

## IUniversalRouter (IUR1)

**No errors in this contract/library.**

## IWETH (IWETH1)

**No errors in this contract/library.**

## IWstETH (IWSTETH1)

**No errors in this contract/library.**

## WethUnwrapIWETH (WUI1)

**No errors in this contract/library.**

## LibCLUtils (LCLU1)

### ApprovalFailed (LCLU1)

**Parameters:** None

**Description:** Raised when `LibCLUtils.approveToken()` performs the low-level ERC-20 approval call and the call either reverts or returns an explicit `false`.

**Error Signature:** `ApprovalFailed()`

**Raised by:**

* [LibCLUtils.approveToken()](https://docs.cryptolegacy.app/documentation/functions-reference#approvetoken-lclu1)

**Notes / Edge cases:** Covers both non-standard ERC-20 approve reverts and tokens that return a boolean `false` instead of reverting.

## LibClaimMigrationCore (LCMC1)

### MigrationInvalidDelta (LCMC1)

**Parameters:**

* `outBalanceBefore (uint256)`: Source-token balance snapshot before the conversion.
* `amountOut (uint256)`: Amount of source token that left the contract.
* `amountIn (uint256)`: Amount of destination token that arrived.

**Description:** Raised when the conversion delta used for claim migration is invalid because one of the required balances/deltas is zero.

**Error Signature:** `MigrationInvalidDelta(uint256 outBalanceBefore, uint256 amountOut, uint256 amountIn)`

**Raised by:**

* [LibClaimMigrationCore.calculateFractionAndRatio()](https://docs.cryptolegacy.app/documentation/functions-reference#calculatefractionandratio-lcmc1)
* [LibTwoStepClaimMigration.start()](https://docs.cryptolegacy.app/documentation/functions-reference#start-ltscm1)

**Notes / Edge cases:** `start()` raises this error directly when the source-token delta is zero before any ratio can be computed. The same error also surfaces transitively through `migrate()` and `complete()` when they delegate into `calculateFractionAndRatio()` or `_applyPendingMigration()`.

### MigrationAmountTooSmall (LCMC1)

**Parameters:**

* `outBalanceBefore (uint256)`: Source-token balance snapshot before the conversion.
* `amountOut (uint256)`: Amount of source token that left the contract.
* `amountIn (uint256)`: Amount of destination token that arrived.
* `fraction (uint256)`: Computed migration fraction that rounded to zero.
* `ratio (uint256)`: Computed exchange ratio that rounded to zero.

**Description:** Raised when the conversion is so small relative to the tracked balances that the scaled migration fraction or ratio rounds to zero.

**Error Signature:** `MigrationAmountTooSmall(uint256 outBalanceBefore, uint256 amountOut, uint256 amountIn, uint256 fraction, uint256 ratio)`

**Raised by:**

* [LibClaimMigrationCore.calculateFractionAndRatio()](https://docs.cryptolegacy.app/documentation/functions-reference#calculatefractionandratio-lcmc1)

**Notes / Edge cases:** This error is raised directly by `calculateFractionAndRatio()` and then bubbles through `migrate()`, `complete()`, and `_applyPendingMigration()` when the computed fraction or ratio rounds to zero.

## LibOneStepClaimMigration (LOSCM1)

**No errors in this contract/library.**

## LibTwoStepClaimMigration (LTSCM1)

### NoPendingMigration (LTSCM1)

**Parameters:** None

**Description:** Raised when a two-step migration operation expects an active pending migration but none exists.

**Error Signature:** `NoPendingMigration()`

**Raised by:**

* [LibTwoStepClaimMigration.complete()](https://docs.cryptolegacy.app/documentation/functions-reference#complete-ltscm1)
* [LibTwoStepClaimMigration.abandon()](https://docs.cryptolegacy.app/documentation/functions-reference#abandon-ltscm1)

**Notes / Edge cases:** Protects both the completion path and the emergency-abandon path from running against cleared or never-initialized migration state.

### PendingMigrationAlreadyExists (LTSCM1)

**Parameters:**

* `tokenOut (address)`: Source token associated with the already active pending migration.

**Description:** Raised when `LibTwoStepClaimMigration.start()` is called while another pending migration is still active.

**Error Signature:** `PendingMigrationAlreadyExists(address tokenOut)`

**Raised by:**

* [LibTwoStepClaimMigration.start()](https://docs.cryptolegacy.app/documentation/functions-reference#start-ltscm1)

**Notes / Edge cases:** Enforces the library invariant that only one delayed migration may be active at a time.

### TokenAlreadyLocked (LTSCM1)

**Parameters:**

* `token (address)`: Token whose beneficiary claim slots are already locked.

**Description:** Raised when `start()` encounters a beneficiary claim slot already set to the migration lock sentinel.

**Error Signature:** `TokenAlreadyLocked(address token)`

**Raised by:**

* [LibTwoStepClaimMigration.start()](https://docs.cryptolegacy.app/documentation/functions-reference#start-ltscm1)

**Notes / Edge cases:** Prevents overlapping delayed migrations that would otherwise reuse claim slots already locked by another in-flight migration.

## LibCreate3 (LC31)

### ErrorCreatingProxy (LC31)

**Parameters:** None

**Description:** Raised when the CREATE3 proxy deployment fails.

**Error Signature:** `ErrorCreatingProxy()`

**Raised by:**

* [LibCreate3.create3()](https://docs.cryptolegacy.app/documentation/functions-reference#create3bytes32bytesuint256-lc31)

**Notes / Edge cases:** None

### ErrorCreatingContract (LC31)

**Parameters:** None

**Description:** Raised when CREATE3 proxy deployment succeeds but the final contract creation fails.

**Error Signature:** `ErrorCreatingContract()`

**Raised by:**

* [LibCreate3.create3()](https://docs.cryptolegacy.app/documentation/functions-reference#create3bytes32bytesuint256-lc31)

**Notes / Edge cases:** None

### TargetAlreadyExists (LC31)

**Parameters:** None

**Description:** Raised when the target deployment address already has code.

**Error Signature:** `TargetAlreadyExists()`

**Raised by:**

* [LibCreate3.create3()](https://docs.cryptolegacy.app/documentation/functions-reference#create3bytes32bytesuint256-lc31)

**Notes / Edge cases:** None

## LibCryptoLegacy (LCL1)

**No errors in this contract/library.**

## LibCryptoLegacyDeploy (LCLD1)

### BytecodeEmpty (LCLD1)

**Parameters:** None

**Description:** Raised when a CREATE2 deployment is requested but the supplied bytecode is empty.

**Error Signature:** `BytecodeEmpty()`

**Raised by:**

* [LibCryptoLegacyDeploy.\_deployByCreate3()](https://docs.cryptolegacy.app/documentation/functions-reference#_deploybycreate3-lcld1)

**Notes / Edge cases:** None

### AddressMismatch (LCLD1)

**Parameters:** None

**Description:** Raised when a computed deployment address does not match the expected address.

**Error Signature:** `AddressMismatch()`

**Raised by:**

* [LibCryptoLegacyDeploy.\_deployByCreate3()](https://docs.cryptolegacy.app/documentation/functions-reference#_deploybycreate3-lcld1)

**Notes / Edge cases:** None

### Create3Failed (LCLD1)

**Parameters:** None

**Description:** Raised when a CREATE3 deployment fails to produce a contract address.

**Error Signature:** `Create3Failed()`

**Raised by:** None

**Notes / Edge cases:** None

## LibCryptoLegacyPlugins (LCLP1)

**No errors in this contract/library.**

## LibDiamond (LD1)

### InitializationFunctionReverted (LD1)

**Parameters:**

* `_initializationContractAddress (address)`: Initialization target that received the delegatecall during the diamond cut.
* `_calldata (bytes)`: Initialization calldata forwarded to the delegatecall.

**Description:** Raised when the post-cut initialization delegatecall fails without bubbling a concrete revert reason.

**Error Signature:** `InitializationFunctionReverted(address _initializationContractAddress, bytes _calldata)`

**Raised by:**

* [LibDiamond.initializeDiamondCut()](https://docs.cryptolegacy.app/documentation/functions-reference#initializediamondcut-ld1)

**Notes / Edge cases:** Surfaced only when the low-level delegatecall returns `success == false` without a decodable custom error or string reason.

## LibSafeMinimalBeneficiaryMultisig (LSMB1)

**No errors in this contract/library.**

## LibSafeMinimalMultisig (LSM1)

**No errors in this contract/library.**

## LibTrustedGuardiansPlugin (LTGP1)

**No errors in this contract/library.**

## BeneficiaryAaveV3SupplyPlugin (BALP1)

### ZeroAmount (BALP1)

**Parameters:** None

**Description:** Raised when an Aave beneficiary-plugin action receives a zero input amount or zero share amount.

**Error Signature:** `ZeroAmount()`

**Raised by:**

* [BeneficiaryAaveV3SupplyPlugin.baavesSupply()](https://docs.cryptolegacy.app/documentation/functions-reference#baavessupply-balp1)
* [BeneficiaryAaveV3SupplyPlugin.baavesWithdraw()](https://docs.cryptolegacy.app/documentation/functions-reference#baaveswithdraw-balp1)
* [BeneficiaryAaveV3SupplyPlugin.baavesWrapATokenToStataToken()](https://docs.cryptolegacy.app/documentation/functions-reference#baaveswrapatokentostatatoken-balp1)
* [BeneficiaryAaveV3SupplyPlugin.baavesUnwrapStataTokenToAToken()](https://docs.cryptolegacy.app/documentation/functions-reference#baavesunwrapstatatokentoatoken-balp1)
* [BeneficiaryAaveV3SupplyPlugin.baavesDepositToStataToken()](https://docs.cryptolegacy.app/documentation/functions-reference#baavesdeposittostatatoken-balp1)
* [BeneficiaryAaveV3SupplyPlugin.baavesRedeemFromStataToken()](https://docs.cryptolegacy.app/documentation/functions-reference#baavesredeemfromstatatoken-balp1)

**Notes / Edge cases:** None

### ATokenNotFound (BALP1)

**Parameters:** None

**Description:** Raised when the configured PoolDataProvider returns the zero address instead of a valid aToken for the requested reserve asset.

**Error Signature:** `ATokenNotFound()`

**Raised by:**

* [BeneficiaryAaveV3SupplyPlugin.\_getAToken()](https://docs.cryptolegacy.app/documentation/functions-reference#_getatoken-balp1)

**Notes / Edge cases:** The error is raised directly inside `_getAToken(asset)` and then bubbles into `baavesSupply()`, `baavesWithdraw()`, `baavesWrapATokenToStataToken()`, and `baavesUnwrapStataTokenToAToken()`.

### StataTokenNotFound (BALP1)

**Parameters:** None

**Description:** Raised when the configured StataTokenFactory returns the zero address instead of a wrapper for the requested reserve asset.

**Error Signature:** `StataTokenNotFound()`

**Raised by:**

* [BeneficiaryAaveV3SupplyPlugin.\_getStataToken()](https://docs.cryptolegacy.app/documentation/functions-reference#_getstatatoken-balp1)

**Notes / Edge cases:** The error is raised directly inside `_getStataToken(asset)` and then bubbles into `baavesWrapATokenToStataToken()`, `baavesUnwrapStataTokenToAToken()`, `baavesDepositToStataToken()`, and `baavesRedeemFromStataToken()`.

## BeneficiaryLidoStakingPlugin (BLSP1)

### ZeroStEthAmount (BLSP1)

**Parameters:** None

**Description:** Raised when a stETH wrapping request is submitted with a zero stETH amount.

**Error Signature:** `ZeroStEthAmount()`

**Raised by:**

* [BeneficiaryLidoStakingPlugin.blsLidoWrapStEthToWstEth()](https://docs.cryptolegacy.app/documentation/functions-reference#blslidowrapstethtowsteth-blsp1)

**Notes / Edge cases:** None

### ZeroWethAmount (BLSP1)

**Parameters:** None

**Description:** Raised when a WETH-based Lido action is requested with a zero WETH amount.

**Error Signature:** `ZeroWethAmount()`

**Raised by:**

* [BeneficiaryLidoStakingPlugin.blsLidoStakeWethToStEth()](https://docs.cryptolegacy.app/documentation/functions-reference#blslidostakewethtosteth-blsp1)
* [BeneficiaryLidoStakingPlugin.blsLidoWrapWethToWstEth()](https://docs.cryptolegacy.app/documentation/functions-reference#blslidowrapwethtowsteth-blsp1)

**Notes / Edge cases:** None

### ZeroWstEthAmount (BLSP1)

**Parameters:** None

**Description:** Raised when an unwrap request is submitted with a zero wstETH amount.

**Error Signature:** `ZeroWstEthAmount()`

**Raised by:**

* [BeneficiaryLidoStakingPlugin.blsLidoUnwrapWstEthToStEth()](https://docs.cryptolegacy.app/documentation/functions-reference#blslidounwrapwstethtosteth-blsp1)

**Notes / Edge cases:** None

### InsufficientStEth (BLSP1)

**Parameters:** None

**Description:** Raised when the plugin is asked to wrap more stETH than it currently holds.

**Error Signature:** `InsufficientStEth()`

**Raised by:**

* [BeneficiaryLidoStakingPlugin.blsLidoWrapStEthToWstEth()](https://docs.cryptolegacy.app/documentation/functions-reference#blslidowrapstethtowsteth-blsp1)

**Notes / Edge cases:** None

### InsufficientWstEth (BLSP1)

**Parameters:** None

**Description:** Raised when the plugin is asked to unwrap more wstETH than it currently holds.

**Error Signature:** `InsufficientWstEth()`

**Raised by:**

* [BeneficiaryLidoStakingPlugin.blsLidoUnwrapWstEthToStEth()](https://docs.cryptolegacy.app/documentation/functions-reference#blslidounwrapwstethtosteth-blsp1)

**Notes / Edge cases:** None

### LidoRequestIdsEmpty (BLSP1)

**Parameters:** None

**Description:** Raised when the Lido plugin has no pending request IDs to claim or when the request list being stored is unexpectedly empty.

**Error Signature:** `LidoRequestIdsEmpty()`

**Raised by:**

* [BeneficiaryLidoStakingPlugin.blsLidoClaimWithdrawals()](https://docs.cryptolegacy.app/documentation/functions-reference#blslidoclaimwithdrawals-blsp1)
* [BeneficiaryLidoStakingPlugin.blsLidoUnsafeClaimWithdrawals()](https://docs.cryptolegacy.app/documentation/functions-reference#blslidounsafeclaimwithdrawals-blsp1)
* [BeneficiaryLidoStakingPlugin.\_storeLidoRequestIds()](https://docs.cryptolegacy.app/documentation/functions-reference#_storelidorequestids-blsp1)

**Notes / Edge cases:** `blsLidoClaimWithdrawals()` and `blsLidoUnsafeClaimWithdrawals()` raise this error directly when no cached request IDs exist. The two request functions surface the same error transitively via `_storeLidoRequestIds(requestIds)` when the withdrawal queue unexpectedly returns an empty list. `blsLidoAbandonMigration()` does not raise this error.

### WethUnwrapAmountMismatch (BLSP1)

**Parameters:** None

**Description:** Raised when the ETH balance delta after `WethUnwrap.unwrap_weth()` does not equal the requested WETH amount.

**Error Signature:** `WethUnwrapAmountMismatch()`

**Raised by:**

* [BeneficiaryLidoStakingPlugin.blsLidoStakeWethToStEth()](https://docs.cryptolegacy.app/documentation/functions-reference#blslidostakewethtosteth-blsp1)
* [BeneficiaryLidoStakingPlugin.blsLidoWrapWethToWstEth()](https://docs.cryptolegacy.app/documentation/functions-reference#blslidowrapwethtowsteth-blsp1)

**Notes / Edge cases:** None

### WstEthWrapFailed (BLSP1)

**Parameters:** None

**Description:** Raised when the low-level call that wraps ETH into wstETH returns `false`.

**Error Signature:** `WstEthWrapFailed()`

**Raised by:**

* [BeneficiaryLidoStakingPlugin.blsLidoWrapWethToWstEth()](https://docs.cryptolegacy.app/documentation/functions-reference#blslidowrapwethtowsteth-blsp1)

**Notes / Edge cases:** None

### EmptyWithdrawalAmounts (BLSP1)

**Parameters:** None

**Description:** Raised when a withdrawal-request action is submitted with an empty amounts array.

**Error Signature:** `EmptyWithdrawalAmounts()`

**Raised by:**

* [BeneficiaryLidoStakingPlugin.blsLidoRequestStEthWithdrawal()](https://docs.cryptolegacy.app/documentation/functions-reference#blslidorequeststethwithdrawal-blsp1)
* [BeneficiaryLidoStakingPlugin.blsLidoRequestWstEthWithdrawal()](https://docs.cryptolegacy.app/documentation/functions-reference#blslidorequestwstethwithdrawal-blsp1)

**Notes / Edge cases:** None

### PendingMigrationActive (BLSP1)

**Parameters:** None

**Description:** Raised when the emergency unsafe-claim path is attempted while the fair two-step migration is still active.

**Error Signature:** `PendingMigrationActive()`

**Raised by:**

* [BeneficiaryLidoStakingPlugin.blsLidoUnsafeClaimWithdrawals()](https://docs.cryptolegacy.app/documentation/functions-reference#blslidounsafeclaimwithdrawals-blsp1)

**Notes / Edge cases:** None

### BeneficiarySwitchGuardAlreadyActive (BLSP1)

**Parameters:** None

**Description:** Raised when the plugin tries to activate the beneficiary-switch guard while it is already active.

**Error Signature:** `BeneficiarySwitchGuardAlreadyActive()`

**Raised by:**

* [BeneficiaryLidoStakingPlugin.\_activateBeneficiarySwitchGuard()](https://docs.cryptolegacy.app/documentation/functions-reference#_activatebeneficiaryswitchguard-blsp1)

**Notes / Edge cases:** The error is raised directly by `_activateBeneficiarySwitchGuard(cls)` and bubbles into `blsLidoRequestStEthWithdrawal()` and `blsLidoRequestWstEthWithdrawal()`.

## BeneficiaryPluginAddRights (BPAR1)

**No errors in this contract/library.**

## BeneficiaryUniswapV4SwapPlugin (BU4SP1)

### ZeroAmount (BU4SP1)

**Parameters:** None

**Description:** Raised when a Uniswap V4 swap request is submitted with a zero input amount.

**Error Signature:** `ZeroAmount()`

**Raised by:**

* [BeneficiaryUniswapV4SwapPlugin.bunisSwapExactInputSingle()](https://docs.cryptolegacy.app/documentation/functions-reference#bunisswapexactinputsingle-bu4sp1)
* [BeneficiaryUniswapV4SwapPlugin.bunisSwapExactInput()](https://docs.cryptolegacy.app/documentation/functions-reference#bunisswapexactinput-bu4sp1)

**Notes / Edge cases:** None

### EmptyPath (BU4SP1)

**Parameters:** None

**Description:** Raised when the multi-hop exact-input swap is called with an empty route.

**Error Signature:** `EmptyPath()`

**Raised by:**

* [BeneficiaryUniswapV4SwapPlugin.bunisSwapExactInput()](https://docs.cryptolegacy.app/documentation/functions-reference#bunisswapexactinput-bu4sp1)

**Notes / Edge cases:** None

## CryptoLegacyBasePlugin (CLBP1)

**No errors in this contract/library.**

## LegacyRecoveryPlugin (LRP1)

**No errors in this contract/library.**

## LensPlugin (LP1)

**No errors in this contract/library.**

## NftLegacyPlugin (NLP1)

**No errors in this contract/library.**

## ReceiveEthPlugin (REP1)

### NoEthToWrap (REP1)

**Parameters:** None

**Description:** Raised when `wrapEthToWeth()` is called while the plugin holds no ETH balance to convert into WETH.

**Error Signature:** `NoEthToWrap()`

**Raised by:**

* [ReceiveEthPlugin.wrapEthToWeth()](https://docs.cryptolegacy.app/documentation/functions-reference#wrapethtoweth-rep1)

**Notes / Edge cases:** Triggered before any WETH deposit or distribution-state update is attempted.

## TrustedGuardiansPlugin (TGP1)

**No errors in this contract/library.**

## UpdateRolePlugin (URP1)

**No errors in this contract/library.**

## Parameter Types

| Type      | Description                |
| --------- | -------------------------- |
| `address` | EOA or contract address    |
| `bytes`   | Dynamic byte array         |
| `bytes4`  | 4-byte selector            |
| `bytes32` | Fixed-length 32-byte value |
| `uint8`   | Unsigned 8-bit integer     |
| `uint64`  | Unsigned 64-bit integer    |
| `uint256` | Unsigned 256-bit integer   |


# Hello World, Nous sommes CryptoCustoms 👋

CryptoLegacy est une app sécurisée multichaîne pour transmettre vos cryptos à vos proches après un délai ou en cas d’urgence.

Enchantés — on fera court.

Nous sommes des bâtisseurs du Web3 depuis les débuts : GPU en surchauffe, forks de Bitcoin, effondrement de Mt. Gox, ICO d’Ethereum… On a tout vécu. Des bulles ICO et des étés DeFi aux NFTs, Rollups, RWAs, DePin, et même aux meme coins — on a tout vu, et on a tout construit.

Depuis 2017, on a lancé des projets pour le fun, pour l’innovation… et oui, parfois pour le profit. Mais toujours avec des principes clairs, une vision centrée sur l’utilisateur, et des bases tech solides.

En 2024, on a voulu faire les choses autrement. Pas un énième DEX, protocole de prêt ou Rollup, mais quelque chose de vraiment utile : une solution pour protéger et transmettre les actifs crypto.

Dès le premier jour, on avait cette idée en tête : CryptoLegacy, une dApp multichaîne et sécurisée, conçue pour garder vos cryptos en sécurité — et transmissibles en cas de coup dur.

CryptoLegacy ne conserve pas vos fonds. Elle gère la distribution via des contrats personnels, qui déclenchent des transferts privés à vos bénéficiaires en cas d’urgence ou après un certain délai d’inactivité.

C’est minimaliste, sécurisé, facile à utiliser — avec en prime des options de récupération intégrées.

Parce que l’enjeu n’est pas seulement de gagner de la crypto, mais de la préserver — pour vous, et pour les générations à venir.

Restez connectés — de grandes choses arrivent.

Suivez-nous sur [X](https://x.com/0xCust) pour les mises à jour.

Visitez <https://cryptolegacy.app/>

Et si vous n’avez pas envie de tout lire, posez simplement vos questions à notre GPT [juste ici](https://chatgpt.com/g/g-68c9f2e3d5ec8191a86f75068462c886-cryptolegacy-ai).


# Notre vision

Nous construisons un produit Web3 sécurisé, simple et décentralisé, axé sur la valeur durable - pas la spéculation - avec les utilisateurs au cœur, et sans investisseurs.

On ne peut pas créer un produit exceptionnel sans une vision claire. La plupart des projets dans cet écosystème sont conçus pour des gains à court terme et des schémas spéculatifs autour de tokens.

Nous rejetons cette approche. Nous construisons de la valeur durable et de l’inspiration — parce que vos actifs numériques méritent la pérennité.

**Principes clés:**

* &#x4C;**’utilisateur avant tout:** Nous construisons ce produit pour nous-mêmes, pour les personnes qu’on aime, pour vous et pour ceux qui comptent pour vous.
* **La sécurité comme priorité absolue:** Nous visons les plus hauts standards de sécurité, en collaboration avec des experts de premier plan dans le domaine.
* **Les tokens peuvent tomber à zéro — les produits Web3 doivent durer pour toujours:** Dès le départ, nous avons éliminé les risques spéculatifs pour garantir la longévité. Notre effet réseau repose sur un programme de parrainage équitable, pas sur la spéculation.
* **La décentralisation est essentielle:** À terme, tout ce que nous construisons sera pleinement décentralisé.
* **Aucune pression d’investisseurs:** Nous ne voulons pas de pression extérieure, donc nous ne levons pas de fonds. Si vous souhaitez nous soutenir, utilisez simplement le produit s’il vous convient.
* **La valeur avant tout:** Notre objectif principal est d’apporter une réelle valeur à nos utilisateurs.
* **La simplicité:** Nous concevons le produit pour qu’il soit extrêmement simple, avec une interface intuitive et des tutoriels étape par étape que même vos parents pourraient suivre sans difficulté.


# État du projet

**Statut actuel du projet CryptoLegacy au 4 août 2025 :**

* Le code des smart contracts est finalisé et a été audité avec succès par [Mixbytes](https://github.com/mixbytes/audits_public/tree/master/CryptoLegacy/CryptoLegacy), [Decurity](https://github.com/Decurity/audits/blob/master/Cryptolegacy/cryptolegacy-audit-report-2025-1.1.pdf), [Pessimistic](https://github.com/pessimistic-io/audits/blob/main/CryptoLegacy%20Security%20Analysis%20by%20Pessimistic.pdf) et [Kamensec](https://github.com/kamensec/solo-audits-public/blob/main/crypto-legacy-report-1.pdf).
* Les contrats sont déployés sur Ethereum, Arbitrum, Base, Optimism et Linea.
* L'interface est entièrement lancée et disponible sur [my.cryptolegacy.app](https://my.cryptolegacy.app).
* La plateforme est totalement opérationnelle sur tous les réseaux pris en charge.


# Comment fonctionne CryptoLegacy

CryptoLegacy automatise en toute sécurité l’héritage et la récupération de cryptos grâce à des smart contracts, des calendriers prédéfinis, des approbations de gardiens et des adresses de récupération

## HÉRITAGE

### Étape 1 : Configuration

Vous déployez un smart contract personnel depuis une Factory, en payant de petits frais à la DAO. Vous définissez des bénéficiaires, leurs parts et leurs calendriers (y compris les délais et les périodes de distribution), puis vous approuvez les transferts de tokens depuis vos portefeuilles principaux vers le contrat et chiffrez les données d’actifs pour chaque bénéficiaire individuellement. Tous les six mois, vous mettez à jour le délai (timeout) en envoyant une transaction incluant les frais de la DAO.

### Étape 2 : Contestation (3 mois)

Si le délai arrive à expiration, n’importe quel bénéficiaire peut initier une période de contestation. Pendant cette période, vous conservez la possibilité d’annuler le processus. Une fois la période de contestation terminée, les bénéficiaires peuvent déchiffrer les données d’actifs (auxquelles ils n’avaient pas accès auparavant) et transférer ces actifs depuis vos portefeuilles principaux vers le contrat CryptoLegacy afin de procéder à la distribution.

### Étape 3 : Distribution

Ensuite, les bénéficiaires réclament leurs actifs en fonction de leurs parts et de leurs calendriers (délais et périodes de distribution). Ils peuvent mettre à jour leurs adresses à tout moment si celles-ci sont compromises. Les actifs restent dans le contrat CryptoLegacy pendant toute la période de distribution.

***

## RÉCUPÉRATION

### Étape 1 : Ajouter une fonctionnalité de récupération

Lorsque vous créez votre contrat, deux plugins sont automatiquement intégrés. Par défaut, vos bénéficiaires sont désignés comme Gardiens, avec un seuil d’approbation de 2-sur-3 et un délai de contestation de 30 jours pour les Gardiens. Vous pouvez modifier à tout moment les Gardiens, les seuils et les délais. De plus, vous pouvez définir des adresses de récupération et leurs seuils d’approbation (par ex. 1-sur-3, 2-sur-3, 3-sur-5). Les adresses de Gardien et de récupération sont toutes stockées sous forme de hachage, ce qui évite de les lier directement à votre contrat CryptoLegacy.

### Étape 2 : Retrait d’urgence

Chaque Gardien doit envoyer une transaction pour lancer la distribution avant que le délai principal de 6 mois n’expire. Une fois le seuil d’approbation atteint, un délai de contestation optionnel (de 0 à 30 jours) pour les Gardiens commence.\
Vous ou toute adresse de récupération pouvez annuler ce délai de contestation. Une fois ce délai terminé, les Gardiens peuvent déchiffrer les données d’actifs (jusqu’alors cachées) et transférer ces actifs vers votre contrat personnel pour la distribution. Les Gardiens n’ont jamais un accès direct à vos fonds.

### Étape 3 : Distribution et récupération

Les bénéficiaires réclament leurs actifs conformément à leurs parts et à leurs calendriers prédéfinis. Vous conservez un contrôle total, avec la possibilité de récupérer tous les actifs à tout moment grâce à vos adresses de récupération, sécurisées par hachage et totalement distinctes du contrat CryptoLegacy.

***

## GESTION

### Étape 1 : Ajouter des plugins pour la gestion des actifs

Vous pouvez intégrer des plugins permettant aux bénéficiaires de gérer les actifs pendant la distribution, comme échanger des tokens, staker de l’ETH sur Lido, déplacer des actifs en cross-chain ou gérer la liquidité sur Uniswap. La plupart de ces plugins exigent un nombre spécifique de confirmations de la part des bénéficiaires (similaire à un multisig), nombre que vous pouvez configurer.

### Étape 2 : Autoriser les bénéficiaires à ajouter des plugins

Vous pouvez permettre aux bénéficiaires d’ajouter des plugins une fois la distribution commencée, ce qui est particulièrement utile si des protocoles intégrés doivent être mis à jour. Cependant, pour des raisons de sécurité, les bénéficiaires ne peuvent pas supprimer les plugins existants.

### Étape 3 : Gérer les actifs pendant la distribution

Pendant la distribution, les bénéficiaires peuvent utiliser ces plugins pour gérer les actifs, qui restent en sécurité dans votre contrat CryptoLegacy personnel. Chaque action nécessite un certain nombre de confirmations. Les bénéficiaires continuent de réclamer leurs actifs selon les parts et les calendriers prédéfinis.

***

## PERSONNALISATION

### Étape 1 : Ajouter des plugins avec une logique personnalisée

Vous pouvez ajouter des plugins pour personnaliser la logique de votre CryptoLegacy : par exemple, transférer des NFTs, clôturer automatiquement des positions Uniswap NFT, distribuer des montants fixes (plutôt que des parts) aux bénéficiaires ou créer de nouvelles règles entièrement personnalisées.

### Étape 2 : Permettre aux bénéficiaires d’ajouter leur propre logique

Vous pouvez autoriser les bénéficiaires à ajouter eux-mêmes des plugins une fois la distribution lancée. Ces plugins peuvent inclure une logique personnalisée, comme transférer des parts, ajouter de nouveaux bénéficiaires ou définir d’autres règles spécifiques.

### Étape 3 : Vérification de la sécurité des plugins

Tous les plugins sont vérifiés via le Plugin Registry, un smart contract géré par l’équipe principale, les protocoles partenaires et des sociétés de sécurité renommées. Ainsi, seuls les plugins ayant fait l’objet d’audits approfondis sont autorisés, garantissant la sécurité de votre contrat.


# Transfert sécurisé des données d’actifs avec CryptoLegacy

CryptoLegacy gère les données d’actifs via chiffrement elliptique, stockant les sauvegardes chiffrées on-chain jusqu’à expiration des time-outs ou approbations des gardiens.

CryptoLegacy garantit une confidentialité totale en ne stockant jamais d’informations sensibles des détenteurs d’actifs — telles que les adresses de portefeuille ou de jeton — directement dans le smart contract. Au lieu de cela, il repose entièrement sur des approbations de jetons, avec des données d’actifs chiffrées et stockées de manière sécurisée dans votre navigateur et sur la blockchain, assurant un contrôle total à l’utilisateur.

***

### Archivage sécurisé directement sur la blockchain

CryptoLegacy exploite le chiffrement intégré à MetaMask (**eth-sig-util**, outil permettant la génération et la gestion simplifiée des clés cryptographiques), reposant sur une cryptographie robuste par courbe elliptique (**x25519-xsalsa20-poly1305**). Les propriétaires de contrats génèrent régulièrement des archives sécurisées comprenant notamment :

* Les adresses des détenteurs d’actifs ;
* Les adresses associées aux tokens ;
* Les adresses de bénéficiaire, de gardien et de récupération ;
* Les clés publiques de chiffrement correspondantes.

Ces sauvegardes sont intégrées de manière sécurisée aux événements des transactions du smart contract sur la blockchain. Bien qu'elles soient publiquement accessibles, elles demeurent entièrement chiffrées et confidentielles.

***

### Types de sauvegardes sécurisées

**Sauvegardes du propriétaire :**\
Chiffrées avec la clé publique du propriétaire et stockées dans des contrats dédiés spécifiquement aux sauvegardes sur toute blockchain compatible.

**Sauvegardes du bénéficiaire, du gardien et de récupération :**\
Chiffrées individuellement avec les clés publiques fournies par chaque partie concernée, puis directement archivées dans le contrat CryptoLegacy.

***

### Accès et disponibilité des données

Les bénéficiaires, gardiens et adresses de récupération peuvent uniquement accéder aux données chiffrées lorsque certaines conditions précises sont remplies :

* Lorsque le délai prédéfini arrive à échéance, déclenchant ainsi la distribution des actifs ; ou
* Lorsque les seuils d’approbation requis par les gardiens (par ex. **2-sur-3**) sont atteints et que la période de contestation est écoulée.

Pour assurer une fiabilité optimale, CryptoLegacy recommande de vérifier au préalable les mécanismes de chiffrement à l’aide de messages-tests.

***

### Développements à venir

CryptoLegacy prévoit prochainement d’offrir des solutions complémentaires de chiffrement sécurisé, particulièrement utiles aux utilisateurs de portefeuilles ne proposant pas nativement la prise en charge du chiffrement des seed phrases.

***

### Considérations de sécurité

Bien qu’il soit théoriquement possible pour des bénéficiaires ou gardiens disposant de ressources considérables, de compétences techniques poussées et d’un temps significatif de déchiffrer ces sauvegardes, le risque pratique reste extrêmement faible. En effet, ces personnes sont généralement choisies parmi vos contacts personnels les plus dignes de confiance, ce qui rend très improbable toute tentative d’attaque sophistiquée telle que l’indexation ciblée de la blockchain ou la rétro-ingénierie cryptographique.

CryptoLegacy associe ainsi de manière transparente confidentialité, simplicité d’utilisation et robustesse cryptographique, assurant une gestion sécurisée, pratique et confidentielle de votre héritage numérique.


# Comment fonctionnent les périodes de contrat CryptoLegacy et les contrôles de gardien

CryptoLegacy automatise l’héritage crypto grâce à des check-ins programmés, des transferts d’urgence approuvés par des gardiens et des mécanismes de récupération sécurisés.

## Statuts du contrat CryptoLegacy:

* **Période normale**
  * Le contrat est actif, déployé et ne détient actuellement aucun actif.
  * Tous les 6 mois, vous (le propriétaire) confirmez que vous êtes actif en envoyant une transaction on-chain.
  * Cet intervalle de check-in de 6 mois est permanent et ne peut pas être modifié, garantissant fiabilité et clarté pour tous les participants.
* **Période de contestation**
  * Si vous omettez le check-in requis après 6 mois, tout bénéficiaire peut déclencher une Période de contestation de 3 mois.
  * Pendant ces 3 mois, vous (le propriétaire) pouvez intervenir à tout moment, confirmer votre statut et annuler le processus de distribution.
  * Cette durée de 3 mois est fixe et inaltérable, garantissant prévisibilité et équité.
* **Période de distribution**
  * Si la Période de contestation s’achève sans intervention du propriétaire, les bénéficiaires déchiffrent les informations relatives aux actifs, stockées de manière sécurisée dans les événements de transaction du smart contract (sous forme de données chiffrées).
  * Les bénéficiaires transfèrent alors vos actifs approuvés de vos portefeuilles principaux vers le contrat CryptoLegacy, conformément aux autorisations que vous aviez accordées.
  * Les bénéficiaires réclament leurs parts en fonction de vos paramètres prédéfinis :
    * **Délai** : La période d’attente après le début de la distribution, avant qu’un bénéficiaire puisse commencer à réclamer.
    * **Durée** : La période pendant laquelle les actifs se déverrouillent progressivement afin que les bénéficiaires puissent les réclamer par paliers.

## Gardiens et contrôles de récupération

### Gardiens

* Les gardiens sont des personnes de confiance désignées pour les situations d’urgence.
* Vous sélectionnez des gardiens et définissez un seuil d’approbation (par ex. 1-sur-3, 2-sur-3, 3-sur-5).
* Par défaut, vos bénéficiaires deviennent gardiens avec un seuil de 2-sur-3. S’il y a moins de 2 bénéficiaires, le seuil équivaut au nombre de bénéficiaires.
* La période de contestation par défaut pour les gardiens est de 30 jours, mais vous pouvez la modifier.
* Les adresses des gardiens sont stockées en toute sécurité sous forme de hachages, empêchant tout lien direct avec votre contrat CryptoLegacy.
* Les gardiens ne peuvent déchiffrer les données chiffrées relatives aux actifs qu’une fois la condition de seuil remplie, ce qui autorise un transfert d’urgence des actifs vers votre contrat CryptoLegacy.
* Les gardiens ne contrôlent ni ne retirent jamais directement vos actifs ; ils déclenchent simplement le transfert et le début de la distribution selon vos paramètres prédéfinis.

### Adresses de récupération

* Les adresses de récupération agissent comme des mécanismes de secours cachés, stockées de manière sécurisée sous forme de hachages et jamais liées directement au contrat CryptoLegacy avant qu’une action de récupération ne soit déclenchée. Une fois utilisées, elles deviennent visibles — ce qui est attendu, car leur rôle est conçu pour un usage unique. L’essentiel est qu’elles restent privées jusqu’au moment de leur activation. Ensuite, le propriétaire reprend le contrôle et peut utiliser librement tout outil de confidentialité supplémentaire si nécessaire.
* Elles peuvent déchiffrer les données chiffrées des événements de transaction, transférer et retirer des actifs de manière autonome, en contournant le calendrier normal des bénéficiaires si nécessaire.
* Les adresses de récupération peuvent annuler la période de contestation des gardiens avant le lancement de la distribution.

### Informations de sécurité supplémentaires

* Les bénéficiaires et gardiens ne peuvent accéder aux détails chiffrés des actifs qu’après :
  * Le début de la Période de distribution, **ou**
  * L’atteinte du seuil de gardiens, l’expiration de leur délai de contestation et le démarrage de la distribution.
* Les processus de chiffrement doivent être validés au préalable via des messages de test.

CryptoLegacy combine des procédures transparentes, des méthodes de chiffrement sécurisées et des mécanismes de gardien et de récupération clairement définis, vous permettant de gérer en toute confiance vos actifs numériques et votre héritage.


# Intégration Cross-Chain pour des NFTs à Vie et un Programme de Parrainage

CryptoLegacy utilise deBridge pour proposer facilement des NFTs permanents et un parrainage cross-chain : mint unique, usage universel, synchro automatique sur toutes les chaînes.

Lors de la conception de **CryptoLegacy**, notre principal objectif était d’assurer une accessibilité fluide sur tous les réseaux blockchain, afin de maximiser les effets de réseau et d’accélérer la croissance de l’écosystème.

Pour simplifier l’expérience utilisateur, nous avons lancé l’**Unlimited NFT Pass**, permettant de créer et de mettre à jour des contrats sur n’importe quelle blockchain compatible — gratuitement et pour toujours. Toutefois, la mise en place d’une fonctionnalité cross-chain fluide a présenté d’importants défis techniques.

En parallèle, nous avons développé un **Programme de Parrainage** robuste, où les utilisateurs peuvent gagner des récompenses en invitant de nouveaux arrivants. Permettre à un seul code de parrainage de fonctionner universellement sur toutes les blockchains prises en charge constituait un autre défi technique.

Nous avons résolu ces deux problèmes en intégrant le protocole **deBridge**, offrant un système de messagerie cross-chain efficace et une interopérabilité avancée.

***

### **Cross-chain NFTs : Comment ça marche**

#### 1. Frappez et verrouillez sur Ethereum

* Frappez (mint) et verrouillez votre NFT sur Ethereum pour bénéficier d’un accès à vie.

#### 2. Verrouillage cross-chain

Transférez facilement les données verrouillées de votre NFT vers n’importe quelle blockchain EVM-compatible prise en charge :

* Envoyez une transaction sur Ethereum.
* Attendez la confirmation du bridge.
* Passez à la blockchain souhaitée.
* Confirmez la transaction de verrouillage.

Vous pouvez alors déployer et mettre à jour vos contrats sur cette nouvelle blockchain sans frais supplémentaires.

#### 3. Déverrouillage des NFTs

Pour déverrouiller votre NFT sur Ethereum, commencez par le déverrouiller sur toutes les autres blockchains :

* Envoyez une transaction de déverrouillage sur chaque blockchain où votre NFT est verrouillé.
* Attendez les confirmations du bridge.
* Repassez sur Ethereum.
* Confirmez le déverrouillage.

**Principaux avantages :**

* Verrouillez simultanément votre NFT sur plusieurs blockchains avec une seule transaction.
* Mettez facilement à jour la propriété de votre NFT sur plusieurs blockchains en une seule transaction.
* Notre interface intuitive offre une expérience fluide et sans tracas.

***

### **Programme de Parrainage Cross-Chain**

Voici comment fonctionne le programme de parrainage sur plusieurs blockchains :

#### 1. Générez votre code de parrainage

Créez un shortcode personnalisé ou généré automatiquement (initialement sur Arbitrum pour réduire les frais).

#### 2. Déployez le code de parrainage sur plusieurs blockchains

Les données de parrainage se propagent automatiquement sur toutes les blockchains prises en charge via deBridge :

* Attendez la confirmation du bridge.
* Changez de réseau et confirmez la création du code de parrainage sur chaque blockchain.

**Les codes de parrainage sont uniques et flexibles :**

* Mettez facilement à jour le propriétaire du code ou l’adresse de paiement sur plusieurs blockchains simultanément.

**Notes importantes :**

* Si CryptoLegacy s’étend à de nouvelles blockchains, il vous suffit de mettre à jour les informations de parrainage sur ces nouvelles chaînes.
* Actuellement, changer le propriétaire du code ou l’adresse de paiement exige des transactions distinctes sur chaque blockchain.

***

### **Transfert d’Actifs Cross-Chain**

À l’heure actuelle, CryptoLegacy ne prend pas en charge les transferts cross-chain pour les actifs verrouillés. Cependant, nous prévoyons de développer un plugin à l’avenir. Les propriétaires de contrats pourront l’ajouter, permettant ainsi aux bénéficiaires de transférer facilement des actifs verrouillés entre différentes blockchains.

***

### **Copie de Contrat Cross-Chain**

Pour simplifier la configuration, vous pouvez déployer rapidement vos contrats avec la même adresse et les mêmes informations de bénéficiaire sur plusieurs blockchains compatibles EVM.


# Les plugins CryptoLegacy étendent les fonctionnalités du contrat

CryptoLegacy utilise des plugins modulaires validés par la DAO pour gérer les fonctions de contrats en toute sécurité, assurant flexibilité, évolutivité et rentabilité accrues.

CryptoLegacy s’appuie sur le standard Diamond pour fournir des fonctionnalités essentielles, prendre en charge des cas d’utilisation avancés et s’intégrer sans difficulté à divers protocoles blockchain. Tous les contrats intelligents CryptoLegacy personnels partagent une logique de plugin commune, réduisant ainsi considérablement les coûts de déploiement.

***

### Ajout, suppression, remplacement ou mise à jour de plugins

Les propriétaires de contrat peuvent facilement ajouter de nouveaux plugins, supprimer ceux qui ne sont plus nécessaires ou remplacer et mettre à jour des plugins existants en envoyant simplement une transaction à leur contrat CryptoLegacy personnel. Le contrat personnel vérifie automatiquement le plugin demandé via le Plugin Registry — pour s’assurer qu’il est sûr et audité — avant d’effectuer l’opération.

*Remarque : Certains plugins nécessitent un NFT verrouillé pour être activés.*

***

### Sécurité des plugins

* Tous les plugins sont pré-approuvés par le DAO multisig via le Plugin Registry, avec le soutien de sociétés de sécurité et de protocoles partenaires.
* Chaque plugin fait l’objet d’un audit approfondi réalisé par des entreprises de sécurité indépendantes.
* Les plugins adoptent une approche minimaliste pour réduire la complexité et renforcer la sécurité.
* Lors de l’ajout de plugins, les utilisateurs n’interagissent qu’avec leurs contrats personnels, ce qui diminue les risques.
* Le Plugin Registry vise une décentralisation maximale, en impliquant initialement des sociétés de sécurité de confiance et des partenaires protocolaires.

***

### Plugins disponibles

* **Base Plugin** – Fournit la logique de base pour les contrats CryptoLegacy.
* **NFT Legacy Plugin** – Gère les fonctionnalités liées aux NFTs au sein de CryptoLegacy.
* **Trusted Guardians Plugin** – Permet à des gardiens de confiance de contourner les délais et de déclencher la distribution des actifs en cas d’urgence.
* **Recovery Plugin** – Met en place des adresses de récupération cachées qui peuvent reprendre les actifs de manière indépendante en cas de besoin.
* **Beneficiary Plugin** – Permet aux bénéficiaires d’ajouter des plugins supplémentaires lors de la phase de distribution des actifs.

***

### Plugins à venir

* **Uniswap Position Closure Plugin** – Retire et ferme automatiquement vos positions Uniswap NFT.
* **Fixed Transfer Plugin** – Transfère des montants d’actifs fixes aux bénéficiaires immédiatement ou selon un calendrier d’acquisition, au lieu de distribuer des parts.
* **Beneficiary Share Transfer Plugin** – Autorise les bénéficiaires à transférer leurs parts à d’autres bénéficiaires ou à en ajouter de nouveaux.

Les plugins peuvent être gérés de manière flexible en fonction de l’évolution des besoins, garantissant que les contrats CryptoLegacy restent sécurisés, adaptables et prêts pour l’avenir.


# CryptoLegacy NFT : Accès à vie et droits DAO

CryptoLegacy permet de minter un unique NFT cross-chain à vie, classé par métaux rares, offrant vote et airdrops dans la DAO pour 1 ETH, avec réductions via parrainage disponibles.

CryptoLegacy propose des fonctionnalités NFT pour simplifier votre accès. Au lieu de faire un don à la DAO à chaque création de contrat ou mise à jour de délai sur plusieurs blockchains, vous pouvez frapper un seul NFT une bonne fois pour toutes et profiter d’un accès CryptoLegacy à vie, partout. Pour utiliser votre NFT sur différentes chaînes, verrouillez-le via le protocole de messagerie **deBridge**. Chaque verrouillage dure trois mois, après quoi vous pouvez déverrouiller et retirer votre NFT.

## NFT Tiers

Les NFT CryptoLegacy ont des niveaux on-chain basés sur leur numéro de frappe, inspirés par des métaux rares indispensables à notre ère numérique.

Les différents niveaux incluent :

* **Silicium (1–100)** : Essentiel pour les puces informatiques et les semi-conducteurs ; la base des technologies comme les téléphones, les ordinateurs et les systèmes d’IA.
* **Gallium (101–301)** : Important pour les semi-conducteurs, LED et l’électronique à haute vitesse ; vital pour les smartphones, la technologie sans fil et les panneaux solaires.
* **Indium (301–700)** : Élément clé pour les écrans tactiles et LCD ; indispensable pour les smartphones, les tablettes et les écrans modernes.
* **Tantale (701–1500)** : Crucial pour les condensateurs dans les circuits électroniques ; contribue à la miniaturisation des smartphones, ordinateurs portables et appareils électroniques avancés.
* **Base Tier (1501 et plus)** : Niveau général de NFT avec des avantages standard.

Les NFT à numéros plus bas, associés à des métaux de plus haute qualité, ont plus de valeur — on adore tous les NFT !

## Droits DAO

Les CryptoLegacy NFT constituent le socle de la DAO CryptoLegacy :

* Chaque NFT octroie des droits de vote proportionnels à son niveau, influençant les décisions de la DAO.
* Si la DAO décide d’émettre un token ERC20, les différents niveaux des NFT serviront de base pour les airdrops.

## Prix du CryptoLegacy NFT

Le prix est simple : chaque NFT coûte **1 ETH**, avec des réductions de parrainage disponibles.

## Groupes NFT CryptoLegacy

Les CryptoLegacy NFT donnent accès à un groupe Telegram exclusif réservé aux détenteurs, vérifié en signant un message pour prouver la propriété du NFT.


# Gouvernance de CryptoLegacy et chemin vers une véritable décentralisation

CryptoLegacy vise une solution décentralisée open-source pilotée par DAO de détenteurs NFT décidant des règles clés, avec possibilité future de lancer un token ERC20 de gouvernance.

Nous ne serions pas ici si nous n’étions pas des défenseurs de la décentralisation et de la force de la communauté. À terme, CryptoLegacy deviendra une solution entièrement décentralisée et open-source — mais il nous reste encore un long chemin à parcourir.

Dans un premier temps, la DAO sera formée par nos premiers utilisateurs et soutiens qui détiennent des NFTs CryptoLegacy. Ils voteront sur le **Manifeste**, la **Mission** et définiront les **règles** de la DAO. Cette phase initiale de décentralisation s’appuiera sur des portefeuilles multisig gérés par la DAO pour administrer les contrats, avec le soutien d’entreprises de sécurité et de protocoles partenaires. Même si la plupart des smart contracts sont robustes et immuables, la gouvernance du **Plugin Registry** reste cruciale, compte tenu de son importance.

À un moment donné, il se pourrait qu’un **token ERC20 de gouvernance et d’utilité** soit nécessaire, mais nous n’en sommes pas encore certains. L’avenir nous guidera.


# CryptoLegacy : Approche axée sur la sécurité pour la récupération et l’héritage

CryptoLegacy sécurise la récupération et transmission d’héritage crypto, conservant les actifs dans le wallet utilisateur, transférés par multisig ou après délais prédéfinis.

CryptoLegacy a été développé dès le premier jour avec une priorité absolue sur la sécurité.

## Sécurité des Smart Contracts CryptoLegacy

* CryptoLegacy a réussi à passer trois audits de sécurité indépendants (en cours de finalisation).
* La DAO lancera bientôt un programme de bug bounty sur Immunefi.
* Vous êtes l’unique propriétaire de votre contrat CryptoLegacy personnel et contrôlez toutes les fonctions d’administration, comme le transfert de propriété, la mise en pause/dépause et les approbations de tokens. Même si d’autres contrats ou leurs propriétaires multisig sont compromis (ce qui est très improbable), vos actifs et le processus de distribution ou de récupération resteront entièrement sécurisés, car votre contrat ne dépend d’aucun appel externe.
* Votre contrat personnel ne stocke pas d’actifs — ils restent à l’abri dans votre wallet et ne sont qu’approuvés pour le transfert. Les actifs ne peuvent être transférés par les Bénéficiaires qu’après un délai spécifié et l’expiration d’une période de contestation, ou par des Gardiens de confiance lorsqu’ils atteignent le seuil multisig (là aussi avec une éventuelle période de contestation).
* Votre contrat personnel suit la **norme Diamond (EIP-2535)**, ce qui signifie que vous êtes le seul à pouvoir ajouter, retirer, remplacer ou mettre à jour ses Plugins (facettes). Tous les Plugins sont préapprouvés via le registre de Plugins par la DAO multisig, soutenue par des sociétés de sécurité et des protocoles partenaires.
* Vous interagissez uniquement avec le **Build Manager** (pour créer de nouveaux contrats), le **Fee Registry** (pour verrouiller des NFTs) et votre **contrat CryptoLegacy personnel**. Vérifiez toujours les adresses pour vous protéger contre les attaques de phishing.
* Une application dédiée à la vérification des transactions hébergée sur GitHub Pages et des simulations de transactions via Tenderly sont en cours de développement pour renforcer la sécurité.
* Tous les smart contracts, à l’exception du **Fee Registry**, ne sont pas basés sur un proxy afin d’augmenter la sécurité.
* Tous les appels externes émis par le contrat CryptoLegacy pendant la période normale et la distribution utilisent un schéma try/catch avec une limite de gas. Cela garantit que les fonds ne se retrouveront pas bloqués si un contrat externe est compromis et modifié avec du code malveillant conçu pour augmenter la consommation de gas.
* Les demandes de retrait d’actifs par les Bénéficiaires sont protégées contre les attaques impliquant le remplacement de code malveillant visant à augmenter les frais. Pendant la distribution, le montant des frais est défini dans l’interface et fourni comme argument à la fonction.

## Sécurité de l’interface CryptoLegacy

L’interface de CryptoLegacy est sécurisée par Cloudflare, offrant une protection solide contre l’usurpation DNS, l’empoisonnement du cache et les attaques MitM. Pour une sécurité maximale, vous pouvez aisément exécuter CryptoLegacy en mode autohébergé, avec des instructions pas-à-pas claires.

## Dépendances d’infrastructure de CryptoLegacy

CryptoLegacy utilise des RPC, des indexeurs SubQuery et des APIs de projet, mais il est possible de les remplacer à tout moment via les paramètres. Cela garantit que la dApp fonctionne sans encombre en toutes circonstances. De plus, CryptoLegacy sera hébergé sur des plateformes décentralisées comme IPFS et Arweave.


# CryptoLegacy : La confidentialité est essentielle pour la récupération et l’héritage

CryptoLegacy protège votre vie privée en stockant localement les données sensibles, chiffrées sur blockchain, accessibles aux Bénéficiaires et Gardiens uniquement en cas d’urgence.

Nous pensons que la confidentialité est cruciale pour la récupération et la transmission de vos actifs. Bien qu’il soit difficile de créer une solution totalement privée dans une architecture où les actifs sont approuvés (approved) depuis les portefeuilles principaux vers le contrat personnel CryptoLegacy, nous estimons qu’il est très peu probable que les Gardiens ou les Bénéficiaires inspectent le code ou développent des outils d’indexation personnalisés. Par conséquent, les données sensibles ne sont pas divulguées prématurément dans l’interface utilisateur, et les informations concernant les actifs restent chiffrées tant que le **challenge timeout** n’a pas expiré ou que le **Guardian threshold** (seuil de Gardiens) n’est pas atteint (accompagné, si besoin, du **Guardian timeout**).

#### Principaux points de confidentialité

* Les noms, les Bénéficiaires, les Gardiens, les adresses de Récupération (Recovery addresses), les détenteurs d’actifs (vos portefeuilles), les adresses ERC20 et les clés publiques de chiffrement sont stockés localement dans votre navigateur. Les sauvegardes sont chiffrées avec votre clé publique personnelle et enregistrées on-chain sous forme d’événements de transaction dans un contrat séparé.
* Les détenteurs d’actifs (vos portefeuilles) et les adresses ERC20 sont chiffrés individuellement pour chaque Bénéficiaire, Gardien et adresse de Récupération, en utilisant leurs clés publiques respectives, puis enregistrés on-chain dans des événements de transaction sur le contrat CryptoLegacy.
* Nous utilisons le chiffrement intégré de MetaMask (**eth-sig-util**), qui s’appuie sur une cryptographie elliptique avancée (**x25519-xsalsa20-poly1305**). Pour les portefeuilles dépourvus de fonctionnalités de chiffrement, nous mettrons en place une solution alternative.

***

### **Développements futurs**

Pour renforcer la confidentialité dans CryptoLegacy, nous prévoyons de développer le **ZK Approval Plugin**, qui fonctionnera de la manière suivante :

1. **Owner** ajoute le plugin à son contrat personnel CryptoLegacy.
2. **Owner** n’approuve plus directement ses actifs sur le contrat CryptoLegacy, mais les oriente vers le **ZK CryptoLegacy Transfer Contract**.
3. **Owner** envoie une transaction au contrat CryptoLegacy via ce plugin et y stocke un Merkle Tree contenant la liste de ses portefeuilles, de ses actifs et du contrat CryptoLegacy.
4. Quand il devient nécessaire de transférer les actifs des portefeuilles principaux vers le contrat CryptoLegacy, les **Bénéficiaires ou Gardiens** produisent une preuve ZK (ZK proof) et la soumettent au **ZK CryptoLegacy Transfer Contract**. Celui-ci autorise alors le retrait des actifs des portefeuilles principaux pour les transférer vers le contrat CryptoLegacy.

Au final, ce processus garantit qu’il devient impossible de retracer le lien entre les portefeuilles et les contrats CryptoLegacy.

En combinant des pratiques de chiffrement robustes à une gestion minutieuse des données, CryptoLegacy propose une protection de la vie privée à la fois pratique et efficace pour l’héritage et la récupération d’actifs, sans pour autant sacrifier la convivialité.


# CryptoLegacy : Intégrations de protocoles pour plus de flexibilité

CryptoLegacy intègre des dApps et protocoles populaires, permettant aux Bénéficiaires de gérer, staker, échanger, emprunter et transférer leurs actifs en toute simplicité et en toute sécurité.

L’intégration de CryptoLegacy à des protocoles et dApps blockchain établis facilite la protection et la récupération des actifs pour les Propriétaires, tout en offrant aux Bénéficiaires un moyen simple et sécurisé de gérer leurs cryptos pendant le processus de Distribution.

## Intégration dApp

CryptoLegacy sera d’abord lancé sous la forme d’une Safe App, permettant aux utilisateurs qui conservent des actifs importants dans des portefeuilles Safe de gérer ces actifs de manière pratique et sécurisée.

## Intégrations futures prévues

Nos prochaines intégrations incluent :

* **Aave** – Déposez, retirez, empruntez ou changez des actifs crypto directement via CryptoLegacy.
* **Uniswap** – Échangez rapidement et en toute sécurité vos tokens depuis CryptoLegacy.
* **1inch** – Échangez des tokens, stakez et unstakez des tokens 1INCH en toute fluidité.
* **Lido** – Stakez vos ETH/WETH ou unstakez vos stETH/wstETH en quelques clics.
* **DeBridge** – Échangez des tokens entre plusieurs réseaux blockchain via les contrats CryptoLegacy qui partagent la même adresse.

En intégrant ces protocoles largement adoptés, CryptoLegacy gagne en praticité et en sécurité, permettant aux utilisateurs et aux bénéficiaires de gérer leurs actifs en toute confiance dans les principaux écosystèmes blockchain.


# Cas d’utilisation : Introduction

Cette section explore comment CryptoLegacy peut gérer divers scénarios concrets – de la planification successorale et la récupération urgente d’actifs à l’incertitude juridique internationale.

Chaque chapitre présente un exemple ou un défi unique et montre en quoi la conception de CryptoLegacy offre une solution sécurisée, flexible et automatisée.

En parcourant ces cas d’utilisation, vous verrez exactement comment CryptoLegacy peut protéger vos actifs, préserver votre confidentialité et veiller à ce que vos proches reçoivent votre héritage crypto de manière fluide et fiable.


# Prologue - Pourquoi l’héritage et la récupération sont importants

Les détenteurs de crypto ont besoin de systèmes de self-custody qui définissent ce qui se passe lorsque le propriétaire ne peut plus agir, afin que les actifs restent accessibles.

La plupart des détenteurs de crypto n’aiment pas y penser — mais ils devraient vraiment le faire :\
Que deviennent vos actifs si vous ne pouvez plus agir?

Ce n’est pas agréable d’imaginer le pire. Pourtant, sur de longues périodes, une absence inattendue n’est pas un cas marginal. Maladie, perte d’appareil, contraintes juridiques ou géopolitiques — ce ne sont pas des risques théoriques, mais des situations bien réelles qui finissent par toucher beaucoup de holders sur le long terme.

Depuis le début, notre conviction est simple : Vos clés, vos cryptos.\
La vraie self‑custody est puissante — mais elle implique aussi une responsabilité qui dépasse la simple gestion des clés.

Le problème le plus difficile en finance décentralisée n’est pas la technologie. C’est l’exécution quand le propriétaire est indisponible. La self‑custody fonctionne parfaitement tant que vous pouvez signer des transactions. Quand ce n’est plus le cas, elle ne fournit, à elle seule, aucune voie d’exécution.

Si quelque chose tourne mal, qui peut agir?\
Dans quelles conditions?\
Et peut-on arrêter cette action si la situation change?

On travaille sur ce problème depuis 2017. À l’époque, les enjeux semblaient plus faibles. Aujourd’hui, avec des portefeuilles plus importants et des horizons plus longs, impossible d’ignorer le problème de l’absence.

CryptoLegacy est conçu pour ce moment précis — non pas en remplaçant la self‑custody, mais en l’étendant avec des règles on-chain, définies à l’avance, pour la récupération et l’héritage.

Discret. Sécurisé. Transférable.

Parce qu’au fond, il ne s’agit pas seulement de contrôler des actifs quand vous êtes là —\
mais de définir ce qui se passe quand vous ne l’êtes pas.

Vos clés. Vos cryptos. Votre héritage.


# Chapitre 0 - Choisir le bon chemin pour votre Crypto Legacy

CryptoLegacy est un système de self-custody pour l’absence du propriétaire, définissant des règles on-chain d’héritage et de récupération sans risque de garde ni dépendance au multisig ou MPC.

La plupart des détenteurs de crypto priorisent la sécurité — mais oublient souvent une question essentielle: Que se passe-t-il pour votre crypto si vous ne pouvez plus agir? Le choix que vous faites aujourd’hui détermine si vous gardez le contrôle tant que vous êtes là. Et si des règles prédéfinies existent pour gérer votre crypto quand vous ne l’êtes plus. Sinon, vos actifs risquent la confusion, une perte irréversible, ou des conflits humains… au pire moment. Voici les approches les plus courantes — et pourquoi elles échouent souvent:

* **Wallets Multisig:** Populaires, mais dépendants de la coordination. Si un participant devient indisponible, l’exécution peut être bloquée indéfiniment. Les soldes sont visibles, ce qui augmente les risques (sécurité, pression sociale).
* **Partage de phrase mnémonique (Seed Phrases):** Simple, mais fragile. Un seul fragment divulgué, perdu ou mal utilisé peut entraîner une perte immédiate et définitive, sans retour en arrière ni contrôle.
* **Exchanges custodiaux:** Pratiques, mais discrétionnaires. Vos actifs dépendent de tiers, exposés aux hacks, à l’insolvabilité, ou à l’intervention réglementaire.
* **Héritage légal traditionnel:** Lent, coûteux et lié à une juridiction. Les tribunaux et les avocats ne peuvent pas exécuter des transactions on-chain, et cela introduit souvent de longs délais et une perte de confidentialité.
* **Wallets de social recovery:** Séduisants en théorie, mais dépendants d’une confiance et d’une coordination humaines sur le long terme — et ça s’érode avec le temps.
* **Multi-Party Computation (MPC):** Techniquement avancé, mais fragile. Si suffisamment de parts de clé sont perdues ou compromises, l’accès est perdu définitivement. Le MPC ne fournit pas non plus une logique d’exécution on-chain native pour les délais, la Récupération, ou une distribution progressive par étapes.
* **Solutions DIY (Smart Contracts sur mesure):** Attirantes pour les utilisateurs avancés, mais complexes et risquées. Une seule erreur peut verrouiller les actifs à vie, et les implémentations individuelles égalent rarement des systèmes réellement éprouvés.

Et puis, il y a CryptoLegacy.&#x20;

CryptoLegacy ne remplace pas l’auto-garde. C’est un système conçu pour définir ce qui se passe quand l’auto-garde, à elle seule, ne suffit plus. Discret. Sécurisé. Transférable.

* **Confidentialité masquée:** Les actifs, les soldes et les relations entre rôles restent privés jusqu’à ce que des conditions on-chain prédéfinies autorisent l’exécution.
* **Garants de confiance:** Les Garants sont des personnes que vous choisissez à l’avance. Ils ne contrôlent pas les actifs et ne peuvent pas accéder directement aux fonds. Leur rôle se limite à confirmer l’indisponibilité du Propriétaire selon un Seuil de confirmations prédéfini, afin d’activer l’exécution sans décisions discrétionnaires.
* **Les actifs restent sous le contrôle du Propriétaire:** Les contrats CryptoLegacy ne détiennent pas les actifs en fonctionnement normal. Les actifs restent dans les wallets du Propriétaire jusqu’à ce que les conditions prédéfinies autorisent le transfert.
* **Récupération intégrée:** Les Adresses de récupération fournissent un mécanisme de secours prédéfini. Elles permettent de retirer les actifs détenus par le contrat si la situation change, sans réécrire l’historique ni annuler des transferts déjà exécutés.
* **Exécution déterministe:** Les transferts suivent des règles et un calendrier prédéfinis. L’exécution est automatisée au niveau des règles, pas via une intervention discrétionnaire.
* **Flexible par design:** Les Bénéficiaires, les wallets et les paramètres de distribution peuvent évoluer dans le temps, tandis que le modèle d’exécution de base reste stable, quel que soit l’actif ou la chaîne.

CryptoLegacy ne promet pas un résultat. Il définit et fait respecter des règles d’exécution à l’avance. Votre crypto mérite plus qu’un stockage sécurisé. Elle mérite un chemin défini pour l’absence.

Vos clés. Votre crypto. Votre héritage.


# Chapitre 1 – Confidentialité : comment CryptoLegacy vous protège de la coercition

CryptoLegacy réduit les risques de coercition en limitant la divulgation précoce et en appliquant des règles d’exécution on-chain, avec des données chiffrées jusqu’aux conditions prévues.

Imagine Bob, en voyage à l’étranger, soudain détenu sans explication. Les autorités confisquent son ordinateur et son téléphone, et il ne peut plus accéder à ses actifs crypto ni les contrôler. La pression se reporte alors sur sa famille, où de vieilles tensions — rivalités entre frères et sœurs, conflits non réglés — deviennent un levier.

Avec des wallets multisig, la famille de Bob doit coordonner des signatures en urgence. Et ce faisant, ses soldes complets sont exposés immédiatement. Sous la pression et l’incertitude, les conflits s’intensifient, ce qui augmente le risque de coercition et de manipulation.

Avec une phrase mnémonique partagée, c’est encore plus direct: les Bénéficiaires voient instantanément l’ensemble des avoirs de Bob, ce qui concentre à la fois le pouvoir et la pression au pire moment possible.

Les approches juridiques traditionnelles aident peu. Elles sont lentes, dépendantes des juridictions, et inefficaces dans des situations où le contrôle doit se jouer tout de suite on-chain — surtout quand ça dépasse les frontières.

CryptoLegacy aborde le problème autrement, en réduisant le levier créé par une divulgation prématurée:

* **Garants de confiance:** Les Garants sont choisis à l’avance et fonctionnent avec des seuils de confirmations prédéfinis. Ils n’ont pas accès aux fonds et ne contrôlent pas les actifs. Leur rôle se limite à confirmer l’indisponibilité du Propriétaire selon des règles on-chain, ce qui permet l’exécution sans décisions discrétionnaires.
* **Métadonnées des actifs chiffrées:** Les informations sur les wallets et les actifs sont chiffrées par rôle et restent inaccessibles tant que les conditions prédéfinies ne sont pas remplies. Ni les Garants ni les Bénéficiaires n’ont de visibilité sur les soldes ou la structure des actifs avant que l’exécution ne soit autorisée.
* **Accès progressif des Bénéficiaires:** Une fois les actifs transférés dans le contrat CryptoLegacy, les Bénéficiaires ne peuvent réclamer les actifs que dans la limite de ce que le calendrier prédéfini autorise. Cet accès par étapes évite une concentration brutale du contrôle et réduit la pression externe.
* **Mécanisme de récupération masqué:** Les Adresses de récupération sont stockées sous forme de hashs cryptographiques et restent impossibles à relier tant qu’elles ne sont pas utilisées. Elles offrent un chemin de Récupération prédéfini pour les actifs restant dans le contrat si la situation évolue, sans exposer à l’avance les chemins de contrôle.

En séparant la visibilité de l’autorité, CryptoLegacy limite le levier que des tiers peuvent exercer dans les moments d’incertitude.

La famille de Bob peut agir dans un cadre clair, sans exposer les soldes complets, sans concentrer le pouvoir, et sans faire monter la pression — pile au moment où la retenue compte le plus.

Vos clés. Vos cryptos. Votre vie privée.


# Chapitre 2 – Sécurité: garder vos actifs en sécurité, quoi qu’il arrive

CryptoLegacy maintient les actifs sous le contrôle du propriétaire en fonctionnement normal et applique un modèle d’exécution par états lorsque celui-ci ne peut agir, avec des transferts après seuils.

Alice a toujours pris la sécurité crypto très au sérieux. Elle protégeait ses wallets, faisait régulièrement des sauvegardes sécurisées, et suivait les bonnes pratiques. Pourtant, les solutions d’accès d’urgence, de Récupération ou de transmission continuaient de l’inquiéter :

* **Wallets multisig ou MPC:** Le risque de coordination est bien réel. Si une clé est perdue ou compromise, les actifs peuvent se retrouver bloqués… ou exposés. Et compter sur plusieurs signataires ajoute aussi des risques humains : conflits, désaccords, indisponibilité.
* **Partage de phrase mnémonique:** Simple, mais fragile. Un seul fragment divulgué ou perdu peut entraîner une perte immédiate et irréversible.
* **Garde juridique traditionnelle (avocats, notaires, sociétés fiduciaires):** Confier des sauvegardes ou des clés à des intermédiaires crée de nouvelles surfaces d’attaque. Les documents peuvent être copiés, perdus ou détournés, et les procédures légales ne peuvent pas exécuter des actions on-chain.

C’est pour ça qu’Alice a choisi CryptoLegacy.

Avec CryptoLegacy, Alice gardait le contrôle total tant qu’elle était active. Ses actifs restaient dans ses propres wallets et n’étaient jamais déposés dans des contrats de tiers. Le système fonctionnait comme une machine à états prédéfinie : tant qu’Alice restait active, personne ne pouvait initier des transferts ni déplacer des actifs.

Elle avait désigné à l’avance des Garants — des membres de sa famille, des amis, ou des conseillers — qui ne pouvaient agir que dans des limites strictes définies par le protocole. Aucun Garant, à lui seul, ne pouvait déclencher l’exécution. Il fallait un seuil de confirmations prédéfini, suivi d’une période de contestation obligatoire avant que le moindre transfert ne devienne possible.

Les Garants n’avaient aucun accès direct aux fonds, et aucune visibilité sur les soldes. Même si le compte d’un Garant était compromis, cela ne pouvait pas provoquer une exécution immédiate. Leur rôle se limitait à apporter une confirmation pour une transition d’état — pas à donner le contrôle.

Les Bénéficiaires étaient eux aussi limités par conception. Même si le compte d’un bénéficiaire était compromis, les actifs ne pouvaient pas être retirés d’un seul coup. Les demandes de retrait n’étaient possibles qu’une fois le système entré en Période de distribution, et en respectant le calendrier prédéfini par Alice, avec une libération progressive des actifs.

Quand Alice a eu un grave accident et est restée inconsciente pendant des semaines, l’incertitude s’est propagée autour d’elle. Malgré ça, ses actifs sont restés inaccessibles à toute action non autorisée. Impossible de contourner les seuils, de zapper la période de contestation, ou d’accélérer l’exécution. Ce n’est qu’après validation des confirmations requises et des vérifications basées sur le temps que le système a changé d’état et a permis l’application des règles de distribution prévues.

Alice s’est ensuite rétablie. Grâce au mécanisme de Récupération prédéfini, elle a repris le contrôle des actifs restants détenus par le contrat. Les transferts déjà effectués étaient définitifs, mais aucun actif supplémentaire n’a été exposé ni déplacé trop tôt.

CryptoLegacy n’a pas éliminé le risque. Mais il a réduit les modes de défaillance critiques par conception:

* **Les actifs restent sous le contrôle du Propriétaire** tant que les seuils et les conditions basées sur le temps ne sont pas remplis.
* **L’exécution nécessite plusieurs confirmations**, pas un seul acteur compromis.
* **Les périodes de contestation empêchent les exécutions précipitées ou erronées.**
* **La Récupération ne s’applique qu’aux actifs restants**, sans réécrire l’historique.

CryptoLegacy a offert à Alice quelque chose que les autres approches ne pouvaient pas : un modèle de sécurité qui continue de fonctionner correctement même quand le Propriétaire ne peut pas agir.

**Vos clés. Votre crypto. Votre sécurité.**


# Chapitre 3 – Flexibilité : des investissements qui changent vite

CryptoLegacy reste stable quand actifs et stratégies changent, permettant aux portefeuilles d’évoluer entre chaînes sans bloquer les fonds ni reconstruire la logique de garde ou d’héritage.

Bob adorait explorer de nouvelles opportunités blockchain — mint des NFT, staker des tokens, fournir de la liquidité sur différentes chaînes, et tester des protocoles DeFi émergents. À mesure que son portefeuille grandissait, le vrai défi n’était pas l’accès, mais la continuité: comment continuer à investir librement tout en gardant un modèle cohérent de récupération et de transmission.

* **Wallets multisig ou MPC:** Bob a testé des setups multisig pour la sauvegarde et la transmission. Mais à chaque nouvelle chaîne ou protocole, il fallait une nouvelle configuration et une nouvelle coordination. Perdre l’accès signifiait dépendre des autres pile au mauvais moment. Avec le temps, l’activité du quotidien se transformait en vraie friction opérationnelle.
* **Partage de mnémonique:** Couper une seed phrase en morceaux semblait simple au début. Puis, quand le portefeuille a grandi, c’est devenu fragile. Chaque nouveau wallet, protocole ou chaîne demandait des mises à jour, des explications et de la coordination manuelle. De petits oublis finissaient par s’accumuler… et devenir un risque réel.
* **Garde juridique traditionnelle (avocats, notaires, sociétés fiduciaires):** Mettre à jour des documents légaux à chaque nouvel investissement était lent et cher. Les procédures “papier” ne suivaient pas le rythme de l’on-chain et ajoutaient en plus de nouveaux soucis de sécurité.
* **Plateformes custodiales:** Au début, les services custodial semblaient flexibles. Ils masquaient la complexité, proposaient une interface unifiée et facilitaient l’activité cross-chain. Mais cette flexibilité dépendait de politiques externes, de juridictions et de décisions opérationnelles hors du contrôle de Bob. Quand les conditions changeaient, l’accès pouvait changer avec — sans garanties on-chain ni chemin de récupération défini à l’avance.

C’est pour ça que Bob a choisi CryptoLegacy.

Avec CryptoLegacy, Bob a continué à investir sans bloquer ses actifs ni changer sa façon de faire au quotidien. Ses fonds restaient dans ses propres wallets. Les contrats CryptoLegacy ne détenaient pas les actifs — ils définissaient uniquement des permissions et des règles d’exécution. Et de nouveaux wallets pouvaient être ajoutés simplement en donnant les autorisations nécessaires, sous les mêmes conditions pré-définies.

Quand Bob s’est étendu vers de nouvelles blockchains, il a réutilisé la même configuration de Bénéficiaires et d’Adresses de récupération. Les contrats étaient déployés avec une logique identique : pas en déplaçant les actifs, mais en copiant les règles. Résultat : Bob pouvait protéger de nouveaux investissements immédiatement, sans renégocier la confiance ni redessiner la transmission à chaque fois.

Le système de plugins de CryptoLegacy rendait cette flexibilité possible, avec des limites claires. Pendant la période de distribution, les Bénéficiaires pouvaient interagir avec les actifs uniquement via les actions que Bob avait explicitement autorisées — staker, swapper, ou fermer des positions — sans prendre le contrôle du timing, des seuils, ou des règles d’exécution. Les plugins étendent ce qu’on peut faire, pas qui décide.

Les outils cross-chain prévus suivent le même principe. Les actifs peuvent passer d’un environnement à l’autre uniquement lorsque les conditions du protocole sont remplies, en conservant les transitions d’état, les seuils et les contraintes liées au temps d’une chaîne à l’autre.

Et si Bob perdait un jour l’accès, les Adresses de récupération offraient un chemin défini à l’avance pour reprendre le contrôle des actifs restants — sans geler des fonds à l’avance, ni limiter la structure de son portefeuille.

CryptoLegacy n’optimise pas les investissements. Il garantit que la liberté d’investir ne se fasse pas au détriment de la continuité.

Bob pouvait changer de stratégie, de chaîne et de protocole sans bloquer ses actifs, sans reconstruire sa garde, et sans élargir les hypothèses de confiance au-delà de ce qu’il avait déjà défini.

**Vos clés. Vos cryptos. Votre flexibilité.**


# Chapitre 4 – Automatisation: une crypto qui s’exécute toute seule

CryptoLegacy automatise l’application des règles d’héritage et de récupération, réduisant la coordination en temps réel. Délais, confirmations et distribution suivent des règles on-chain.

Le parcours crypto d’Alice a grandi à toute vitesse — NFTs, projets DeFi, innovations Layer-2. À mesure que ses investissements se multipliaient, le vrai défi n’était pas l’activité, mais la fiabilité : comment s’assurer que la transmission et la Récupération s’exécuteraient correctement, sans devoir coordonner tout le monde au pire moment.

* **Mnémoniques partagées — contrôles manuels sans fin:** Au début, Alice a réparti des morceaux de sa seed phrase entre des amis de confiance. Pour que cette approche tienne, il fallait une surveillance manuelle constante afin de s’assurer que chaque fragment restait sécurisé et accessible. La moindre défaillance pouvait tout faire basculer : risque de perte définitive, et une “certitude” remplacée par une vigilance permanente.
* **Portefeuilles multisig — dépendance continue aux signataires:** Les wallets multisig offraient un contrôle partagé, mais aucune automatisation. Si Alice perdait l’accès, la Récupération dépendait entièrement de la disponibilité des signataires et de leur volonté d’agir. En pratique, une Récupération d’urgence signifiait une coordination immédiate, précisément au moment où coordonner devient le plus difficile.
* **Approche juridique classique — toujours en retard sur la réalité:** Les méthodes légales traditionnelles exigeaient des mises à jour répétées à mesure que le portefeuille d’Alice évoluait. Chaque nouvelle blockchain ou chaque nouvel actif ajoutait de la paperasse, des relectures, et de l’intervention humaine. Ces processus ne pouvaient pas suivre le rythme de l’activité on-chain, ni garantir une exécution au bon moment.

CryptoLegacy a supprimé le besoin de coordination au cas par cas en automatisant l’application des règles — pas les actions elles-mêmes. Alice a défini à l’avance les délais, les rôles et les seuils de confirmations. Une fois configuré, le système appliquait ces conditions de manière déterministe on-chain.

Si Alice devenait indisponible, les Garants pouvaient confirmer cet état via des transactions on-chain. Leurs confirmations ne leur donnaient aucun contrôle sur les actifs — elles déclenchaient des transitions d’état prédéfinies. Les transferts d’actifs n’étaient possibles qu’une fois les conditions du protocole remplies.

Si les Garants étaient injoignables, les mêmes règles basées sur le temps permettaient au processus d’avancer sans décisions “au feeling”. Les Bénéficiaires ne pouvaient agir que dans les limites définies par Alice, et seulement après l’entrée du système dans l’état approprié.

La Récupération suivait la même logique. Alice gardait des adresses de récupération prédéfinies, permettant de récupérer les actifs encore détenus par le contrat si la situation changeait — sans annuler les transferts déjà effectués, ni réécrire l’historique.

Avec CryptoLegacy, rien ne “se gérait tout seul” en arrière-plan. Ce qui a changé, c’est que l’exécution ne dépendait plus de la coordination, de l’interprétation ou d’une intervention manuelle au moment où ça comptait.

Les règles étaient définies une seule fois. L’exécution suivait automatiquement.

**Ta crypto. Ton héritage. Appliqué par des règles, pas par la coordination.**


# Chapitre 5 – Fiabilité: s’assurer que votre plan de transmission fonctionne comme prévu

CryptoLegacy renforce la fiabilité en appliquant des règles on-chain pour l’héritage et la récupération, réduisant la dépendance à la coordination humaine et les risques de blocage.

Pour Bob, la fiabilité passait avant tout quand il pensait à son héritage crypto. Il avait compris que beaucoup d’approches “classiques” échouent, non pas à cause d’attaques, mais parce que l’exécution finit par se dégrader avec le temps :

* **Seed phrases partagées (phrases mnémoniques):** Perdre, retenir, ou mal gérer ne serait-ce qu’un seul fragment peut bloquer l’accès définitivement ou déclencher des conflits entre les bénéficiaires.
* **Shamir’s Secret Sharing:** C’est plus structuré, mais des participants absents ou non coopératifs peuvent quand même retarder ou empêcher la Récupération.
* **Wallets multisig:** Un seul signataire indisponible peut bloquer la distribution indéfiniment, et la disponibilité devient un point de défaillance critique.
* **Procédures juridiques traditionnelles:** Cher et lent, souvent freiné par des conflits, la bureaucratie ou des erreurs de tiers. Et les procédures légales ne peuvent pas garantir une exécution on-chain dans les temps.

Bob a choisi CryptoLegacy pour réduire ces modes d’échec.

Avec CryptoLegacy, les actifs de Bob restaient dans ses propres wallets pendant la Période normale. La fiabilité ne venait pas de la coordination humaine, mais de règles d’exécution prédéfinies, appliquées on-chain :

* **Des délais d’expiration imposés par la blockchain** garantissaient que les actifs ne pouvaient pas rester inaccessibles indéfiniment une fois les conditions d’inactivité remplies.
* **Les confirmations des Garants** servaient de couche de vérification, pas de mécanisme de contrôle. Les Garants n’avaient pas accès aux actifs ; ils confirmaient l’indisponibilité de Bob selon des seuils de confirmations prédéfinis.
* **Les Adresses de récupération** offraient un chemin prédéfini pour récupérer les actifs encore détenus par le contrat si la situation changeait — sans réécrire l’historique, et sans dépendre d’une intervention improvisée.

Quand Bob a temporairement perdu l’accès à son wallet, le système s’est comporté de façon prévisible. Les Garants ont confirmé son indisponibilité on-chain, ce qui a permis au processus d’exécution d’avancer selon les règles définies. En parallèle, les Adresses de récupération restaient disponibles comme solution de secours pour les actifs qui n’avaient pas encore été distribués.

CryptoLegacy n’a pas supprimé l’incertitude de la vie. Il a supprimé l’incertitude de l’exécution.

La fiabilité venait du fait qu’une fois les conditions remplies, le système se comporte de manière cohérente — sans retards causés par des ratés de coordination, des conflits, ou des participants indisponibles.

**Vos clés. Votre crypto. Votre fiabilité — imposée par des règles, pas par des suppositions.**


# Chapitre 6 – Complexité : Pourquoi la simplicité est la clé de la sécurité

CryptoLegacy garantit une sécurité maximale grâce à la simplicité : contrat personnel sécurisé, confirmations des gardiens, transferts automatiques, aucune complexité.

Alice appréciait la simplicité. Elle savait par expérience que les solutions d’héritage trop complexes créent souvent plus de problèmes qu’elles n’en résolvent, entraînant des erreurs, des malentendus ou même la perte définitive des actifs.

## Mnémoniques partagés

Au départ, Alice pensait qu’il serait plus simple de partager ses seed phrases avec sa famille. Cependant, chaque bénéficiaire supplémentaire augmentait le risque. Si quelqu’un égarait sa partie de la phrase mnémonique ou refusait de collaborer, ses actifs pouvaient être perdus à jamais ou mal distribués.

## Portefeuilles multisig

Elle a envisagé d’utiliser des portefeuilles multisig pour simplifier la transmission de patrimoine. Mais elle s’est vite rendu compte que coordonner plusieurs signatures pour chaque transaction était contraignant. Si ne serait-ce qu’un signataire était indisponible, réticent ou injoignable, les actifs pouvaient rester bloqués indéfiniment ou être distribués de manière injuste.

## Approche légale traditionnelle

Les testaments et fiducies traditionnels semblaient sécurisés, mais la complexité des procédures légales, des actions en justice et d’une paperasse interminable pouvait immobiliser ses actifs pendant des mois, voire des années. Alice savait que les bénéficiaires pouvaient facilement se retrouver piégés dans de longs différends et des retards sans fin.

## CryptoLegacy : la simplicité qui garantit la sécurité

Alice a choisi CryptoLegacy car il offrait l’approche la plus simple et la plus sûre. Ses actifs restaient dans ses portefeuilles personnels — sans intervention de tiers, sans barrières légales ni coordination complexe.

CryptoLegacy ne demandait qu’une configuration initiale du contrat et quelques transactions occasionnelles pour rafraîchir le délai d’expiration automatique intégré, assurant la distribution automatique des actifs après une période d’inactivité définie à l’avance.

De plus, elle a désigné des Gardiens de confiance — amis proches ou membres de la famille — pour renforcer la sécurité. Ces Gardiens ne voyaient ni ses actifs ni ses soldes, et ne pouvaient pas y accéder directement. Leur unique rôle : confirmer de manière indépendante l’inactivité d’Alice grâce à des transactions sur la blockchain. Une fois qu’une majorité de Gardiens (par exemple, deux sur trois) confirmait qu’Alice était injoignable, ses actifs étaient transférés automatiquement et en toute sécurité vers son contrat CryptoLegacy, prêts pour la distribution.

Alice a également défini des adresses de récupération — adresses de sauvegarde sécurisées et privées, distinctes de son contrat CryptoLegacy. En cas d’urgence, elles lui permettaient, à elle ou à des personnes de confiance, de reprendre instantanément le contrôle total, éliminant tout risque de perte permanente de ses actifs.

Quand Alice est devenue injoignable lors d’une catastrophe naturelle, ses Gardiens ont rapidement et indépendamment déclenché le transfert, sans confusion ni retard. CryptoLegacy a géré la distribution parfaitement, selon ses volontés, sans litiges, erreurs de tiers ni coordination compliquée.

CryptoLegacy a offert à Alice clarté, fiabilité et sécurité — tout cela grâce à une simplicité remarquable.

Vos clés. Votre crypto. Votre héritage.


# Chapitre 7 – Risques juridiques : Naviguer dans l’incertitude légale de l’héritage crypto

CryptoLegacy offre une succession décentralisée et on-chain, éliminant les risques juridiques, l’incertitude et les litiges transfrontaliers.

Bob savait que la crypto était sans frontières, mais l’héritage ne l’était pas. Les réglementations variaient énormément d’un pays à l’autre, et les lois changeaient fréquemment. Cette incertitude inquiétait Bob, qui voulait être sûr que ses actifs parviendraient à ses bénéficiaires sans interruption, sans retard ni litige juridique.

## Mnémoniques partagés

Au départ, Bob partageait ses phrases de récupération (seed phrases) directement avec des membres de sa famille. Bien que simple et indépendant de toute juridiction, cette méthode rendait ses bénéficiaires vulnérables. Sans reconnaissance légale claire, des conflits entre héritiers pouvaient éclater, entraînant le gel des fonds pour une durée indéterminée ou provoquant de vives querelles familiales.

## Portefeuilles multisig

Les portefeuilles multisig semblaient d’abord sécurisés, puisqu’ils ne dépendaient pas directement des lois locales. Mais Bob s’est vite rendu compte que des conflits entre signataires dans différents pays pouvaient provoquer des blocages. Pire encore, l’évolution constante des réglementations pouvait restreindre la manière dont les bénéficiaires accédaient aux portefeuilles multisig, laissant potentiellement les actifs bloqués dans un vide juridique.

## Approche juridique traditionnelle

Bob a envisagé les testaments et fiducies traditionnels, mais il les a vite jugés peu pratiques. Chaque juridiction avait ses propres règles, et la réglementation crypto en évolution rapide compliquait encore plus la situation. Son plan successoral risquait de devenir obsolète du jour au lendemain, pris dans la bureaucratie, des batailles juridiques coûteuses ou des reports interminables devant les tribunaux.

## CryptoLegacy : décentralisé et à l’épreuve des juridictions

Avec CryptoLegacy, Bob a trouvé la solution idéale. Entièrement décentralisé et fonctionnant exclusivement on-chain, CryptoLegacy n’était pas soumis aux lois locales changeantes ni aux réglementations incertaines. Sa distribution automatisée s’activait après un délai prédéfini ou via des Gardiens de confiance — famille ou amis proches qui confirmaient son inactivité de manière indépendante, sans voir ou accéder directement à ses actifs.

Bob a également défini des adresses de récupération totalement distinctes de son contrat d’héritage. Ces adresses indépendantes lui permettaient, à lui ou à ses bénéficiaires, de récupérer les actifs en toute sécurité, à tout moment et n’importe où, entièrement en dehors du contrat lui-même.

Avec CryptoLegacy, Bob disposait enfin d’une certitude : les risques juridictionnels étaient éliminés. Son plan successoral est devenu fluide, sécurisé à l’échelle mondiale et totalement indépendant des frontières légales.

CryptoLegacy : une protection sans frontières pour un monde sans frontières.

**Vos clés. Votre crypto. Votre héritage.**


# Chapitre 8 – Coûts : Trouver l’équilibre entre sécurité et rentabilité

CryptoLegacy propose un héritage et une récupération décentralisés avec des tarifs clairs – sans frais cachés, sans risques juridiques et sans coûts de tiers.

Alice savait que protéger son héritage crypto ne se limitait pas à la mise en place initiale : il s’agissait aussi de réduire les frais cachés et d’éviter les pertes inattendues. Elle a comparé chaque option attentivement, réalisant que certaines méthodes soi-disant « gratuites » pouvaient coûter très cher en cas de problème.

## Partage de Mnémoniques

Diviser sa seed phrase entre plusieurs amis semblait gratuit au premier abord. Mais Alice a vite compris l’énorme coût caché : un seul fragment perdu ou compromis pouvait bloquer ses actifs pour toujours, entraînant une perte totale. Ce genre de risque dépassait largement toute économie initiale.

## Portefeuilles Multisig

Avec un multisig, Alice ne payait que de petites gas fees pour chaque transaction nécessitant plusieurs signatures. Ça paraissait gérable—jusqu’à ce qu’elle prenne en compte toutes les futures transactions et la complexité de coordonner les signataires. Au fil du temps, la somme de ces frais, ajoutée aux éventuels retards, pouvait devenir importante.

## Approche Légale Classique

Au départ, un testament ou une fiducie paraissait être une solution standard. Cependant, les honoraires d’avocat, les frais de notaire et les procédures judiciaires ont rapidement fait grimper la facture. Comme le droit des successions crypto est encore en évolution, Alice a vu le risque de coûts supplémentaires – consultations d’avocats à l’international, traductions de documents et éventuelles taxes – transformant une solution « sûre » en un parcours long et onéreux.

## CryptoLegacy : Tarification Transparente et Prévisible

Quand Alice a découvert CryptoLegacy, elle a trouvé un moyen de payer seulement pour ce dont elle avait vraiment besoin :

* **Frais de Création de Contrat** : Un paiement unique pour déployer son contrat CryptoLegacy personnel.
* **Frais de Mise à Jour Régulière (tous les six mois)** : Un petit gas fee pour des « check-ins » confirmant qu’elle est toujours active. Cela maintient son contrat opérationnel, sans faire appel à des avocats coûteux ou à des procédures complexes.
* **Option NFT à Vie** : Pour un confort total, Alice pouvait aussi acheter un NFT unique couvrant la création du contrat et toutes les mises à jour à vie — pas de frais récurrents, aucune mauvaise surprise.

Avec CryptoLegacy, il n’y avait ni frais juridiques cachés, ni marges prélevées par des tiers, ni risque de longues batailles judiciaires. Alice pouvait planifier son héritage en toute confiance, en sachant exactement ce qu’elle allait payer — soit des frais de check-in périodiques, soit un seul NFT. Tout aussi important, la fonction de récupération intégrée garantissait qu’elle n’aurait jamais à subir le coût énorme d’actifs perdus à cause d’une clé égarée ou d’une complication légale.

En comparant ces options, Alice a compris que des coûts transparents et prévisibles étaient aussi essentiels qu’une sécurité solide. Avec CryptoLegacy, elle évitait les configurations « gratuites » susceptibles de causer des erreurs catastrophiques, ainsi que l’envolée des frais légaux des méthodes traditionnelles. Elle ne payait que pour la plateforme d’héritage on-chain fiable dont elle avait réellement besoin.

**Vos clés. Votre crypto. Votre héritage.**


# Aperçu de l’exemple de flux CryptoLegacy

Cette section présente des scénarios détaillés pour utiliser le contrat CryptoLegacy. Tous les paramètres (nombre de bénéficiaires, gardiens, adresses de récupération, seuils d’approbation, délais et périodes de distribution) ne sont fournis qu’à titre d’illustration.

Vous pouvez ajuster ces paramètres selon vos préférences, vos exigences ou le niveau de sécurité souhaité. Ces exemples montrent comment :

* Définir des bénéficiaires et chiffrer leurs données de manière sécurisée.
* Désigner des gardiens et gérer les approbations d’urgence.
* Utiliser des adresses de récupération pour renforcer la sécurité.
* Déclencher la distribution des actifs de façon sûre et prévisible.

N’hésitez pas à adapter les paramètres à vos besoins spécifiques.


# Flux détaillé de configuration du contrat

CryptoLegacy définit les bénéficiaires, sécurise la distribution des actifs, chiffre les données et stocke les sauvegardes en toute sécurité sur la blockchain.

## Créer le contrat CryptoLegacy

* **Bénéficiaires** :
  * Les bénéficiaires fournissent leurs adresses et leurs clés de chiffrement publiques.
  * Ajoutez 5 bénéficiaires (fournissez leurs adresses et leurs clés publiques).
  * Définissez un délai d’un mois par bénéficiaire.
  * Répartissez des parts égales (20 % chacune) sur 10 ans.
* **Déploiement** :
  * Payez la donation DAO et déployez le contrat via la Factory.
  * Les plugins Guardians et Recovery sont ajoutés automatiquement.
* **Stockage des données** :
  * Les adresses des bénéficiaires sont stockées sous forme de hachages.
  * Les adresses originales et les clés de chiffrement sont enregistrées localement dans votre navigateur.

## Approbation des tokens

* Vous disposez de :
  * 3 portefeuilles multisig détenant des actifs.
  * 4 adresses de portefeuille classiques.
* Approuvez tous les tokens de tous ces portefeuilles vers le nouveau contrat CryptoLegacy.
* Les adresses de portefeuille et de tokens ERC20 sont automatiquement enregistrées localement dans votre navigateur.

**Chiffrement de la sauvegarde**

* Votre sauvegarde est automatiquement chiffrée avec votre clé de chiffrement publique.
* Envoyez une transaction pour stocker la sauvegarde chiffrée dans un événement du smart contract.

## Chiffrement des données bénéficiaires

* Les adresses de portefeuille et d’actifs sont automatiquement chiffrées pour chaque bénéficiaire à l’aide de ses clés publiques.
* Envoyez une transaction pour stocker les données chiffrées dans un événement du smart contract.

## Accès et tests des bénéficiaires

* Les bénéficiaires n’ont **pas** d’accès direct aux messages chiffrés.
* Demandez-leur de vérifier le chiffrement en testant avec un message de test fourni.

## Mettre à jour le délai sur le contrat CryptoLegacy

* Tous les 6 mois, envoyez une transaction pour mettre à jour le délai.


# Flux détaillé de configuration des Gardiens

CryptoLegacy attribue des gardiens, définit des seuils d’approbation, chiffre les données des gardiens, stocke des sauvegardes et teste l’accès en toute sécurité sur la blockchain.

## Configuration des Gardiens pour le contrat CryptoLegacy

* **Gardiens par défaut**:
  * Les bénéficiaires deviennent automatiquement Gardiens (ceci peut être modifié).
  * Seuil d’approbation par défaut : **2 sur 3** Gardiens requis pour les retraits d’urgence.
  * Les retraits d’urgence déclenchent une **période de contestation de 30 jours** avant la distribution.
* **Ajout de Gardiens supplémentaires**:
  * Invitez **2 amis** à devenir Gardiens supplémentaires. Il n’y a pas de limite — c’est juste un exemple.
  * Obtenez leurs adresses et leurs clés de chiffrement publiques.
  * Définissez le seuil d’approbation à **4 sur 7 Gardiens**. Vous pouvez choisir n’importe quel nombre entre 1 et le nombre total de Gardiens.
  * Définissez le délai de contestation des Gardiens à **5 jours**.
  * Confirmez ces paramètres en envoyant une transaction.
* **Stockage des données**:
  * Les adresses des Gardiens sont enregistrées sous forme de hachages on-chain.
  * Les adresses originales des Gardiens et leurs clés de chiffrement sont stockées localement dans votre navigateur.

## Chiffrement de la sauvegarde

* La sauvegarde est automatiquement chiffrée grâce à votre clé de chiffrement publique.
* Stockez la sauvegarde chiffrée en envoyant une transaction à l’événement du smart contract.

## Chiffrement des données des Gardiens

* Chiffrez automatiquement les adresses de portefeuille et d’actifs pour chaque Gardien en utilisant leurs clés de chiffrement publiques.
* Stockez ces données chiffrées en envoyant une transaction à l’événement du smart contract.

## Accès et tests des Gardiens

* Les Gardiens n’ont **pas** d’accès direct aux messages chiffrés.
* Demandez aux Gardiens de vérifier le chiffrement en testant avec un message de test fourni.


# Démarrage et annulation détaillés de la période de challenge

CryptoLegacy permet aux bénéficiaires de lancer des challenges, de transférer les actifs en toute sécurité après l’expiration du délai du propriétaire, et de réclamer leurs parts.

* Vous avez oublié d’envoyer la transaction pour mettre à jour le **délai de 6 mois**.
* Tout bénéficiaire peut envoyer une transaction pour **démarrer la période de challenge**.
* En tant que propriétaire du contrat, vous pouvez envoyer une transaction pour **annuler la période de challenge**.


# Processus détaillé de configuration de la récupération

CryptoLegacy configure des adresses de récupération avec chiffrement, stocke des données hachées en toute sécurité on-chain et offre un accès d’urgence direct si besoin.

### Configuration de la récupération pour le contrat CryptoLegacy

* Créez **3 adresses de récupération** et fournissez leurs clés publiques de chiffrement.
* Envoyez une transaction pour définir ces adresses de récupération avec un seuil de **2 sur 3**.
* Les adresses de récupération sont stockées sous forme de hachages on-chain.
* Les adresses de récupération d’origine et les clés de chiffrement sont enregistrées localement dans votre navigateur.

### Chiffrement des données de récupération

* Chiffrez automatiquement les adresses de portefeuilles et d’actifs pour chaque adresse de récupération à l’aide de leurs clés publiques de chiffrement.
* Stockez ces données chiffrées en envoyant une transaction à un événement du smart contract.

### Accès à la récupération

* Les **adresses de récupération** ont un accès direct aux messages chiffrés.


# Début détaillé du retrait d’urgence et de la distribution d’actifs par les Gardiens

Les Gardiens lancent un retrait d’urgence ; si le propriétaire ne l’annule pas dans les 5 jours, ils déchiffrent les données du wallet et transfèrent tous les actifs on-chain.

* Le Gardien **#1** envoie une transaction pour initier le retrait d’urgence et la distribution.
* Les Gardiens **#2, #3 et #4** envoient des transactions confirmant le retrait d’urgence.
* Le **seuil de 4 Gardiens sur 7** est atteint ; un **délai de 5 jours** commence.
* En tant que Propriétaire du contrat, vous pouvez envoyer une transaction pour **annuler** pendant ces 5 jours.
* Sinon, **2 des 3 adresses de récupération** peuvent également envoyer des transactions pour annuler pendant ce même délai.
* Vous **n’annulez pas** avant la fin des 5 jours.
* Une fois les 5 jours écoulés, ni le Propriétaire ni les adresses de récupération ne peuvent annuler.
* Après ce délai, n’importe quel Gardien récupère automatiquement les données du wallet et les adresses ERC20, puis les déchiffre avec ses clés de chiffrement privées.
* Un Gardien envoie alors une transaction pour transférer **tous les actifs** des wallets vers le contrat CryptoLegacy.


# Détails de la Récupération d’Urgence pour le Retrait d’Actifs

CryptoLegacy permet une récupération d’urgence. Deux adresses de récupération confirment les transactions, retirant automatiquement tous les actifs en toute sécurité.

* Lancez la récupération d’urgence en envoyant une transaction depuis **l’Adresse de Récupération n°1**.
* Confirmez la récupération en envoyant une transaction depuis **l’Adresse de Récupération n°2**.
* Une fois que le **seuil de 2 sur 3** est atteint, **tous les actifs actuellement** pris en charge sont automatiquement transférés depuis le contrat CryptoLegacy vers une autre adresse.


# Flux détaillé de copie de contrats cross-chain

Créez et répliquez des contrats CryptoLegacy sur plusieurs chaînes avec les mêmes paramètres, puis configurez les Guardians et la Recovery pour chaque chaîne.

* **Créer des contrats :**\
  Sur chaque chaîne prise en charge, vous pouvez créer autant de contrats CryptoLegacy que souhaité pour chaque propriétaire, chacun doté d’une adresse unique.
* **Répliquer les contrats :**\
  Vous pouvez répliquer chaque contrat sur d’autres chaînes en conservant la même adresse, les mêmes bénéficiaires, les mêmes parts, le même délai et les mêmes règles de distribution.
* **Configurer les Guardians et la Recovery :**\
  Sur chaque nouvelle chaîne, vous devez configurer les Guardians et les paramètres de Recovery.


# Flux détaillé de mint, verrouillage et déverrouillage d’un NFT cross-chain

Mintez un NFT pour éviter les dons à la DAO en cross-chain. Le NFT se verrouille automatiquement pour 5 mois à chaque action. Déverrouillez-le via Ethereum après confirmation sur toutes les chaînes.

* **Mint et verrouillage du NFT :**
  * Mintez et verrouillez un Unlimited NFT Pass en payant une donation DAO lors de la création d’un contrat, de la mise à jour d’un délai (timeout) ou de l’annulation d’une période de challenge.
* **Avantages du NFT verrouillé :**
  * Éviter les dons DAO habituels pour la création de contrats et les mises à jour de délais sur toutes les chaînes prises en charge.
* **Mint automatique sur Ethereum :**
  * Lors de la création d’un contrat ou de la mise à jour d’un délai sur Ethereum sans posséder de NFT, vous pouvez choisir l’option de mint et verrouillage automatique du NFT.
* **Mint cross-chain via Ethereum :**
  * Pour créer un contrat ou mettre à jour un délai sur d’autres chaînes sans posséder de NFT :
    1. Basculez sur Ethereum pour minter et verrouiller le NFT, ce qui envoie automatiquement les données de verrouillage aux autres chaînes via deBridge.
    2. Après les confirmations du bridge, retournez sur la chaîne cible et validez la transaction.
  * Une fois la confirmation effectuée, les futures créations de contrat et mises à jour de délais sur cette chaîne sont gratuites pour les contrats existants et nouveaux.
* **Déverrouillage cross-chain du NFT via Ethereum :**
  * Le NFT verrouillé est bloqué pour 5 mois sur chaque chaîne, à partir du moment du verrouillage.
  * Chaque mise à jour de délai ou nouvelle création de contrat prolonge automatiquement le verrouillage de 5 mois supplémentaires si la période de verrouillage précédente est expirée.
  * Pour déverrouiller le NFT après la fin de la période de verrouillage :
    1. Envoyez une transaction de déverrouillage sur la chaîne cible. Cette transaction enverra automatiquement un message cross-chain à Ethereum via deBridge.
    2. Attendez les confirmations du bridge, puis basculez sur Ethereum et validez la transaction de déverrouillage.
* **Déverrouillage du NFT sur Ethereum :**
  * Pour déverrouiller le NFT sur Ethereum, il doit d’abord être déverrouillé sur toutes les autres chaînes.
  * Après avoir débloqué le NFT sur toutes les autres chaînes et lorsque la période de verrouillage sur Ethereum est terminée, envoyez une transaction de déverrouillage sur Ethereum. Le NFT sera alors retiré directement à votre adresse.
* **Mint de multiples NFT sur Ethereum :**
  * Le multisig de la DAO peut fixer un seuil de supply total pour les NFT. Au-delà de ce seuil, il devient possible de minter plusieurs NFT sans verrouillage, pour différents destinataires.
  * Cela peut servir à offrir des NFT ou à obtenir de meilleurs niveaux et IDs pour vos futurs contrats ou ceux de vos amis.
  * Pour minter, envoyez une transaction incluant les adresses destinataires et les quantités de NFT, accompagnée de la donation DAO.
  * Au départ, ce seuil est fixé à 500.


# Flux détaillé des fonctions administratives

Transférez la propriété, mettez en pause ou reprenez vos contrats, gérez les autorisations de jetons et déplacez en toute sécurité des NFTs verrouillés entre différentes chaînes via Ethereum.

* En tant que propriétaire du contrat, vous disposez de tous les droits d’administration sur votre contrat CryptoLegacy personnel.
* **Transfert de propriété :**
  * Transférez la propriété du contrat à tout moment en envoyant une transaction pour chaque contrat sur chaque chaîne.
* **Mise en pause du contrat :**
  * Mettez le contrat en pause à tout moment, afin d’empêcher les retraits d’actifs de vos portefeuilles principaux.
  * Vous pouvez également supprimer les autorisations de jetons pendant cette période.
* **Reprise du contrat :**
  * Réactivez le contrat à tout moment.
  * Après la reprise, mettez à jour le délai (timeout) si nécessaire en envoyant une nouvelle transaction.
* **Transfert d’un NFT sur Ethereum :**
  * Transférez votre NFT verrouillé sur Ethereum à tout moment via une seule transaction.
* **Transfert d’un NFT sur d’autres chaînes :**
  1. Basculez sur Ethereum et envoyez une transaction pour mettre à jour le propriétaire du NFT verrouillé, ce qui propage les informations via deBridge.
  2. Attendez les confirmations du bridge.
  3. Basculez sur la chaîne cible et envoyez une transaction pour confirmer le transfert.


# Flux détaillé de réclamation des bénéficiaires

Les bénéficiaires réclament des tokens selon leurs parts et leurs délais ; les réclamations s’ajustent automatiquement si les soldes de tokens changent à cause d’un rebase ou de la logique d’un plugin

* Vous n’avez **pas** annulé la période de contestation.
* Les bénéficiaires récupèrent automatiquement les informations de vos portefeuilles et l’adresse de votre token ERC20, qu’ils déchiffrent à l’aide de leurs clés de chiffrement privées.
* Une fois la distribution lancée, tout bénéficiaire peut initier une transaction pour transférer l’ensemble des actifs de vos portefeuilles principaux vers le contrat personnel CryptoLegacy. Cette transaction enregistre également le numéro de bloc du transfert dans le contrat CryptoLegacy et consigne les détails du transfert dans l’événement de la transaction.
* Les bénéficiaires peuvent soumettre des transactions pour réclamer leurs actifs en fonction de leur part (dans cet exemple, 20 %), de leur délai (dans cet exemple, 1 mois) et de leur calendrier de distribution (dans cet exemple, 10 ans).
* Les montants initiaux de distribution de tokens sont enregistrés dans le contrat au moment du transfert.
* Les montants réclamés par chaque bénéficiaire sont suivis et consignés dans le contrat.
* Les bénéficiaires peuvent réclamer la totalité des tokens disponibles en une seule fois ou les réclamer individuellement par token en soumettant des transactions.
* Si les soldes de tokens changent en raison de rebases (par exemple, stETH) ou d’une logique de réclamation personnalisée ajoutée via un plugin, les montants initiaux de distribution s’ajustent automatiquement en fonction du solde actuel du contrat et des montants déjà réclamés.


# Flux détaillé de gestion des plugins

Gérez en toute sécurité les plugins CryptoLegacy : le propriétaire peut les ajouter ou les supprimer avant la distribution, tandis que les bénéficiaires peuvent les gérer sous réserve d’approbations.

Votre contrat CryptoLegacy adopte le modèle Diamond Standard, qui facilite l’ajout de fonctionnalités et l’intégration à divers protocoles (par exemple, support NFT, distribution à montant fixe, swap d’actifs via Uniswap, prêts via Aave ou staking/déstaking sur Lido pendant la distribution).

***

#### Gestion des plugins par le propriétaire

* **Période Normale :** En tant que propriétaire du contrat, vous pouvez ajouter, supprimer ou remplacer des plugins à tout moment.
* **Vérification des plugins :** Les plugins ajoutés ou remplacés sont contrôlés via un registre (Plugin Registry) géré par le DAO Multisig, qui inclut l’équipe principale, des protocoles partenaires et des entreprises leaders en sécurité. Seuls les plugins ayant subi plusieurs audits de sécurité indépendants sont acceptés.
* **Comment faire :** Pour ajouter, supprimer ou remplacer un plugin, envoyez simplement une transaction à votre contrat CryptoLegacy.
* **Période de distribution :** Vous perdez ces droits une fois la période de distribution commencée.

***

#### Gestion des plugins par les bénéficiaires

* **Plugin dédié :** Vous avez la possibilité d’ajouter un plugin qui autorise les bénéficiaires à gérer les plugins pendant la période de distribution.
* **Utilité :** Cela permet de maintenir à jour les intégrations de protocoles.
* **Seuil d’approbation :** Par défaut, un seuil de 2 approbations sur 3 est requis pour ajouter un plugin (deux bénéficiaires sur trois doivent valider l’ajout).
* **Personnalisation :** Vous pouvez modifier ce seuil via une transaction.
* **Règles de distribution :** Le DAO n’approuvera jamais de plugins qui modifient les règles de distribution.


# Flux détaillé des dons DAO

Les dons DAO permettent d’accéder à un NFT à vie ou de payer par contrat, débloquant ainsi des fonctionnalités et assurant la pérennité du projet.

Nous construisons un produit conçu pour vivre et évoluer indéfiniment. Les cycles de marché crypto à court terme – dominés par les VC, les exchanges centralisés et la spéculation sur le prix des tokens – ne conviennent pas à cet objectif. Pour y remédier, nous utilisons un modèle de dons DAO axé sur la valeur réelle, plutôt que sur la spéculation ou la dépendance à l’augmentation future du prix d’un token.

Vous pouvez choisir de faire un don pour chaque création et mise à jour de contrat ou de faire un don unique pour recevoir un NFT offrant un accès à vie. Vous pouvez aussi créer un contrat sans faire de don DAO, mais votre contrat CryptoLegacy restera en pause tant que vous n’en aurez pas fait un.

***

### Donation lors de la création d’un contrat sans don (état en pause)

* Lors de la création initiale d’un contrat sans don, un montant de don DAO unique est enregistré dans votre contrat CryptoLegacy.
* Pour activer le contrat en pause, soumettez une transaction avec le don DAO requis.
* Vous pouvez également faire un don DAO plus important pour créer (mint) et verrouiller un NFT (décrit ci-dessous).

***

### Donation lors de la création d’un contrat sur Ethereum

* Lors de la création d’un contrat sur Ethereum, vous payez un don DAO spécifié dans le contrat `FeeRegistry`, sauf si vous possédez déjà un NFT verrouillé.
* Vous pouvez aussi faire un don DAO plus important lors de la création du contrat pour automatiquement créer et verrouiller un NFT.
* Une fois le NFT créé (mint) et verrouillé, toutes les futures créations et mises à jour de contrats sur Ethereum deviennent gratuites.

***

### Donation lors de la création d’un contrat sur d’autres blockchains

* Lors de la création d’un contrat sur d’autres chaînes, vous payez un don DAO spécifié dans le contrat `FeeRegistry` correspondant, à moins de posséder déjà un NFT verrouillé sur cette chaîne.

#### Pour verrouiller un NFT sur Ethereum et l’utiliser sur une autre chaîne :

1. Passez sur Ethereum.
2. Soumettez une transaction avec le don DAO pour créer (mint) et verrouiller le NFT. Les données de verrouillage sont automatiquement envoyées à la chaîne cible via **deBridge**.
3. Attendez les confirmations du pont.
4. Passez sur la chaîne cible.
5. Soumettez une transaction pour confirmer les données de verrouillage transmises via le pont.
6. Une fois la confirmation effectuée, vous pouvez créer de nouveaux contrats sans dons supplémentaires sur cette chaîne.

#### Si vous possédez déjà un NFT verrouillé sur Ethereum mais pas sur la chaîne cible :

1. Passez sur Ethereum.
2. Soumettez une transaction pour envoyer les données de verrouillage existantes à la chaîne cible via **deBridge**.
3. Attendez les confirmations du pont.
4. Passez sur la chaîne cible.
5. Soumettez une transaction pour confirmer les données de verrouillage sur la chaîne cible.
6. Une fois la confirmation effectuée, vous pouvez créer de nouveaux contrats sans dons supplémentaires sur cette chaîne.

***

### Donation lors de la mise à jour d’un contrat sur Ethereum

* Lors de la mise à jour du délai de 6 mois, vous payez un don DAO spécifié dans le contrat `FeeRegistry`, à moins de posséder déjà un NFT verrouillé.
* Si la fonction standard de récupération du montant du don échoue pour une raison quelconque, une fonction *view* de secours est utilisée. Elle met automatiquement à jour le montant enregistré dans votre contrat s’il y a un écart.
* Vous pouvez également faire un don DAO plus important lors de la création ou de la mise à jour du contrat pour créer (mint) et verrouiller un NFT.
* Une fois le NFT créé et verrouillé, toutes les futures créations et mises à jour de contrats sur Ethereum deviennent gratuites.

***

### Donation lors de la mise à jour d’un contrat sur d’autres blockchains

* Lors de la mise à jour du délai de 6 mois, vous payez un don DAO spécifié dans le contrat `FeeRegistry` de la chaîne, à moins de posséder déjà un NFT verrouillé sur cette même chaîne.
* Si la fonction standard de récupération du montant du don échoue, une fonction *view* de secours est utilisée. Elle met automatiquement à jour le montant enregistré dans votre contrat s’il y a un écart.
* Vous pouvez aussi faire un don DAO plus important lors de la mise à jour pour créer (mint) et verrouiller un NFT.

#### Processus de verrouillage du NFT (si vous n’en possédez pas ou s’il n’est verrouillé que sur Ethereum) :

1. Passez sur Ethereum.
2. Soumettez une transaction avec le don DAO pour créer (mint) et verrouiller un NFT, ou pour envoyer les données de verrouillage de NFT existantes via **deBridge** à la chaîne cible.
3. Attendez les confirmations du pont.
4. Passez sur la chaîne cible.
5. Soumettez une transaction pour confirmer les données de verrouillage sur la chaîne cible.
6. Une fois la confirmation effectuée, les futures créations et mises à jour de contrats sur cette chaîne deviennent gratuites.

***

### Donation lors de la réclamation par le bénéficiaire

* Les réclamations par les bénéficiaires sont gratuites s’il existe un NFT verrouillé sur cette chaîne.
* S’il n’y a pas de NFT verrouillé sur la chaîne, la transaction de réclamation inclut automatiquement un don DAO ainsi qu’une commission de parrainage.
* Pour des raisons de sécurité, les informations sur le don et le référent ne sont **pas** récupérées depuis `FeeRegistry`; elles sont transmises directement via l’interface au moment de la transaction.
* Cette approche garantit que les réclamations du bénéficiaire restent indépendantes de `FeeRegistry` ou de toute autre opération de contrat.

## Gestion des dons DAO

* Les montants des dons DAO, qu’ils soient ponctuels ou liés à un NFT à vie, sont gérés par la DAO et une multisig.
* À l’avenir, cette gestion sera décentralisée.


# Flux détaillé du programme de parrainage

Les codes de parrainage cross-chain permettent aux utilisateurs de gagner des commissions et d’offrir des réductions sur les dons DAO, favorisant ainsi une croissance sans spéculation.

Pour obtenir un effet de réseau sans recourir à une tokenomique spéculative, nous utilisons un programme de parrainage équitable pour les dons DAO. N’importe qui peut créer un code de parrainage *cross-chain* et toucher des commissions. Dans ce modèle, le parrain perçoit un pourcentage tandis que le filleul bénéficie d’une remise.

* Tous les codes de parrainage sont *cross-chain*, ce qui signifie qu’un même code peut être utilisé pour la création de contrats sur chaque chaîne supportée.
* Pour réduire les frais de gas, les codes sont d’abord créés sur Arbitrum, puis transférés vers les autres chaînes supportées.
* Chaque code de parrainage possède un propriétaire (administrateur) et une adresse de paiement où les commissions sont automatiquement envoyées.

***

### Création d’un code de parrainage

1. Passez sur Arbitrum pour créer un code de parrainage.
2. Soumettez une transaction en indiquant toutes les chaînes sur lesquelles vous souhaitez créer le code. Vous pouvez fournir votre propre code ou en générer un automatiquement.
3. Attendez les confirmations du pont (*bridge*).
4. Basculez sur chaque chaîne cible et confirmez la création du code. Une fois confirmé, vous pouvez partager votre lien de parrainage et commencer à toucher des commissions.

***

### Mise à jour *cross-chain* d’un code de parrainage

* Si vous n’avez pas initialement envoyé votre code de parrainage sur une chaîne spécifique, vous pouvez le faire à tout moment, par exemple lorsqu’une nouvelle chaîne est supportée.
* Passez sur Arbitrum.
* Soumettez une transaction pour envoyer le code vers la chaîne cible.
* Attendez les confirmations du pont, basculez sur le réseau cible, puis soumettez une transaction pour confirmer.

***

### Don DAO avec code de parrainage

* Lorsqu’un filleul utilise un lien contenant un code de parrainage, ce code est automatiquement enregistré dans son navigateur.
* En créant un contrat avec un don DAO ponctuel, le code de parrainage est enregistré dans son contrat CryptoLegacy personnel. Le contrat récupère automatiquement l’adresse de paiement et lui envoie des ETH.
* Toutes les futures mises à jour de *timeout* enverront automatiquement des commissions à l’adresse de paiement actuelle.
* Si le filleul effectue un don DAO à vie via un NFT, la commission est également envoyée directement à l’adresse de paiement.

***

### Changement de propriétaire et d’adresse de paiement

* Vous pouvez modifier à tout moment le propriétaire et l’adresse de paiement de votre code de parrainage sur chaque chaîne. Les paiements transitent toujours par le code de parrainage permanent.
* Soumettez une transaction sur chaque chaîne où vous souhaitez mettre à jour le propriétaire ou l’adresse de paiement.

***

### Remise et commission personnalisées

* La DAO peut attribuer des remises et des taux de commission plus élevés à certains codes de parrainage sur chaque chaîne.
* En général, la DAO réserve ces avantages à des membres particulièrement actifs de la communauté.

***

### Gestion de la remise et de la commission par défaut

* La DAO, conjointement avec son multisig, gère les remises et taux de commission par défaut.


# Propriété et Rôles

Vous contrôlez votre contrat personnel. Les autres contrats du protocole s’appuient sur des rôles attribués à des DAO multisigs composés de l’équipe principale, de protocoles partenaires et de société

Bien que vous — et vous seul — soyez le propriétaire de votre contrat personnel CryptoLegacy, il existe d’autres contrats au sein du protocole. Nous utilisons une approche flexible mais fiable, basée sur les rôles, pour gérer ces contrats. Différents DAO multisigs incluent des signataires issus de l’équipe centrale, de partenaires du protocole et de sociétés de sécurité de premier plan.

Les noms de rôles sont simplifiés en:

* Msig 1.&#x20;
* Msig 2.&#x20;
* Msig 3.&#x20;

Des informations détaillées sur les portefeuilles multisigs correspondants sont disponibles dans des articles séparés.

Le tableau ci-dessous répertorie les contrats, leurs fonctions et les rôles qui leur sont attribués. Chaque fonction est protégée par un timelock personnel pour l’exécution.

<table><thead><tr><th width="246.88671875">Contrat</th><th width="238.58984375">Fonction</th><th width="368.515625">Objectif</th><th width="93.57421875">Rôle</th><th width="97.99609375">Timelock</th></tr></thead><tbody><tr><td>BuildManagerOwnable</td><td>setBuildManager()</td><td>Ajoute ou supprime une adresse de build manager. Seul le propriétaire peut l’appeler.</td><td>Msig 3</td><td>5 jours</td></tr><tr><td>CryptoLegacyBuildManager</td><td>setRegistries()</td><td>Définit les références pour la fee registry, la plugins registry et la beneficiary registry.</td><td>Msig 3</td><td>5 jours</td></tr><tr><td>CryptoLegacyBuildManager</td><td>setFactory()</td><td>Définit le contrat factory.</td><td>Msig 3</td><td>5 jours</td></tr><tr><td>CryptoLegacyBuildManager</td><td>setSupplyLimit()</td><td>Définit la limite de supply pour les Lifetime NFTs, après quoi plusieurs mint sans lock deviennent possibles.</td><td>Msig 2</td><td>5 jours</td></tr><tr><td>CryptoLegacyBuildManager</td><td>setExternalLens()</td><td>Définit l’adresse du contrat external lens.</td><td>Msig 2</td><td>5 jours</td></tr><tr><td>CryptoLegacyBuildManager</td><td>withdrawFee()</td><td>Retire les frais du contrat vers un destinataire.</td><td>Msig 2</td><td>5 jours</td></tr><tr><td>CryptoLegacyFactory</td><td>setBuildOperator()</td><td>Ajoute ou supprime un opérateur autorisé à créer des contrats CryptoLegacy.</td><td>Msig 3</td><td>5 jours</td></tr><tr><td>FeeRegistry</td><td>setCodeOperator()</td><td>Définit une adresse d’opérateur pouvant gérer les referral codes.</td><td>Msig 2</td><td>5 jours</td></tr><tr><td>FeeRegistry</td><td>setSupportedRefCodeInChains()</td><td>Ajoute ou supprime des IDs de chaîne pris en charge pour les referral codes.</td><td>Msig 2</td><td>5 jours</td></tr><tr><td>FeeRegistry</td><td>setFeeBeneficiaries()</td><td>Définit les bénéficiaires de frais personnalisés pour la registry.</td><td>Msig 2</td><td>5 jours</td></tr><tr><td>FeeRegistry</td><td>setDefaultPct()</td><td>Définit le pourcentage de réduction et le pourcentage de partage par défaut.</td><td>Msig 2</td><td>5 jours</td></tr><tr><td>FeeRegistry</td><td>setRefererSpecificPct()</td><td>Définit les pourcentages de réduction et de partage spécifiques à un référent.</td><td>Msig 2</td><td>0 jours</td></tr><tr><td>FeeRegistry</td><td>setContractCaseFee()</td><td>Définit les frais pour un cas de contrat particulier.</td><td>Msig 2</td><td>5 jours</td></tr><tr><td>LifetimeNft</td><td>setBaseUri()</td><td>Définit une nouvelle base URI pour les jetons.</td><td>Msig 2</td><td>0 jours</td></tr><tr><td>LifetimeNft</td><td>setMinterOperator()</td><td>Accorde ou révoque l’autorisation de mint de nouveaux jetons.</td><td>Msig 3</td><td>5 jours</td></tr><tr><td>LockChainGate</td><td>setDebridgeGate()</td><td>Définit le contrat deBridgeGate.</td><td>Msig 3</td><td>5 jours</td></tr><tr><td>LockChainGate</td><td>setDebridgeNativeFee()</td><td>Définit les frais en natif pour une chaîne spécifique.</td><td>Msig 2</td><td>5 jours</td></tr><tr><td>LockChainGate</td><td>setDestinationChainContract()</td><td>Définit le contrat de la chaîne de destination.</td><td>Msig 2</td><td>5 jours</td></tr><tr><td>LockChainGate</td><td>setSourceChainContract()</td><td>Définit le contrat de la chaîne source.</td><td>Msig 2</td><td>5 jours</td></tr><tr><td>LockChainGate</td><td>setSourceAndDestinationChainContract()</td><td>Définit simultanément les contrats de la chaîne source et de la chaîne de destination à la même adresse.</td><td>Msig 2</td><td>5 jours</td></tr><tr><td>LockChainGate</td><td>setLockPeriod()</td><td>Définit la période de lock du NFT.</td><td>Msig 2</td><td>5 jours</td></tr><tr><td>LockChainGate</td><td>setReferralCode()</td><td>Définit le referral code pour deBridge.</td><td>Msig 2</td><td>0 jours</td></tr><tr><td>LockChainGate</td><td>setCustomChainId()</td><td>Définit un ID de chaîne personnalisé.</td><td>Msig 2</td><td>5 jours</td></tr><tr><td>PluginsRegistry</td><td>addPlugin()</td><td>Enregistre un plugin et journalise un numéro de bloc descriptif.</td><td>Msig 3</td><td>5 jours</td></tr><tr><td>PluginsRegistry</td><td>addPluginDescription()</td><td>Ajoute une nouvelle note descriptive pour un plugin déjà enregistré.</td><td>Msig 3</td><td>5 jours</td></tr><tr><td>PluginsRegistry</td><td>removePlugin()</td><td>Désenregistre un plugin.</td><td>Msig 3</td><td>5 jours</td></tr><tr><td>SignatureRoleTimelock</td><td>setMaxExecutionPeriod()</td><td>Définit la période maximale d’exécution autorisée pour les appels programmés.</td><td>Msig 1</td><td>0 jours</td></tr><tr><td>SignatureRoleTimelock</td><td>setRoleAccounts()</td><td>Gère l’association rôle-compte en ajoutant, supprimant ou mettant à jour des comptes pour des rôles spécifiés.</td><td>Msig 1</td><td>0 jours</td></tr><tr><td>SignatureRoleTimelock</td><td>cancelCallList()</td><td>Annule les appels programmés pour un contrat.</td><td>Msig 1</td><td>0 jours</td></tr><tr><td>All contracts</td><td>transferOwnership()</td><td>Transfère la propriété du contrat.</td><td>Msig 1</td><td>5 jours</td></tr></tbody></table>


# Foire aux questions

Des réponses claires sur la récupération, les Gardiens, les Bénéficiaires, la confidentialité, la sécurité, les frais, les NFTs, la flexibilité et plus encore — FAQ CryptoLegacy.

## C’est quoi les Adresses de récupération ?

Les Adresses de récupération sont une ou plusieurs adresses configurées par le Propriétaire pour exécuter des actions de Récupération, avec un Seuil de confirmations défini par le Propriétaire. La Récupération peut aussi inclure (optionnellement) une authentification supplémentaire via un mot de passe. Les Adresses de récupération sont hashées avec le mot de passe et restent non associables à un contrat CryptoLegacy précis tant qu’elles ne sont pas utilisées on-chain.

Les métadonnées d’actifs liées à la Récupération sont chiffrées par rôle de récupération. Les Adresses de récupération peuvent déchiffrer ces métadonnées à tout moment pour préparer des transactions de récupération. Le simple déchiffrement ne donne pas accès aux actifs et ne permet pas de transferts.

Les Adresses de récupération peuvent annuler un vote des Garants en cours et des Périodes de contestation actives, et peuvent lancer le processus de Récupération on-chain prédéfini. Ce processus transfère d’abord les actifs vers le contrat CryptoLegacy, puis les envoie vers n’importe quelle adresse indiquée, strictement selon les règles configurées.

***

## Qui sont les Bénéficiaires ?

Les Bénéficiaires sont des adresses désignées par le Propriétaire pour recevoir des actifs pendant la Période de distribution. Pour chaque Bénéficiaire, le Propriétaire définit une part, un Délai avant accès (optionnel) et une Période de distribution — et tout ça détermine comment et quand les actifs deviennent Disponibles à réclamer.

Les métadonnées d’actifs liées aux Bénéficiaires sont chiffrées individuellement, Bénéficiaire par Bénéficiaire. Les Bénéficiaires n’ont aucune visibilité sur les soldes des wallets, les métadonnées des actifs, ni l’état du contrat tant que les conditions de distribution ne sont pas remplies.

Si la Période d’inactivité de 6 mois expire, n’importe quel Bénéficiaire peut lancer une Période de contestation de 3 mois. Si cette Période de contestation n’est pas annulée, les Bénéficiaires peuvent déchiffrer les métadonnées chiffrées, déclencher le processus on-chain qui transfère les actifs vers le contrat CryptoLegacy, puis Réclamer les actifs progressivement selon leur calendrier configuré.

Si des plugins approuvés sont activés, les Bénéficiaires peuvent aussi utiliser la logique de plugin prédéfinie pendant la Période de distribution. Toutes les actions des Bénéficiaires s’exécutent strictement selon les règles on-chain et ne donnent ni accès direct aux clés privées, ni contrôle illimité sur les actifs.

***

## Qui sont les Garants ?

Les Garants sont des adresses autorisées à contourner la Période d’inactivité de 6 mois et à déclencher la distribution en votant, selon un Seuil de confirmations prédéfini.

Une fois le seuil atteint, une Période de contestation configurée par le Propriétaire (jusqu’à 30 jours) peut s’appliquer. Pendant cette période, le Propriétaire ou une Adresse de récupération peut annuler le processus.

Après la Période de contestation, n’importe quel Garant peut déclencher le processus on-chain qui transfère les actifs vers le contrat CryptoLegacy pour la distribution. Les Garants ne peuvent pas retirer les actifs vers leurs propres adresses ni les rediriger.

Par défaut, les Bénéficiaires agissent comme Garants, avec un Seuil de confirmations de 3 sur 5 et une Période de contestation de 30 jours.

***

## Ça veut dire quoi Période normale, Période de contestation et Période de distribution ?

Ce sont les états d’un contrat CryptoLegacy :

* **Période normale** — Le contrat est actif, ne détient aucun actif, et nécessite une transaction on-chain tous les 6 mois pour confirmer l’activité du Propriétaire (Confirmation d’activité). Pendant cette période, le Propriétaire garde le contrôle total et gère les actifs directement dans ses wallets.
* **Période de contestation** — Déclenchée quand la Période d’inactivité de 6 mois expire, ou quand les Garants votent pour contourner le délai selon le Seuil de confirmations configuré. Cette période dure jusqu’à 3 mois et peut être annulée par le Propriétaire ou une Adresse de récupération.
* **Période de distribution** — Les métadonnées des actifs deviennent déchiffrables, et les Garants ou les Bénéficiaires peuvent déclencher le processus on-chain qui transfère les actifs vers le contrat CryptoLegacy. Les Bénéficiaires Réclament ensuite leur part progressivement selon le calendrier de distribution configuré. Les Adresses de récupération peuvent aussi exécuter le Flux de récupération pour transférer tous les actifs selon les règles du contrat.

***

## Mes Bénéficiaires ne connaissent pas le Web3, la crypto et la blockchain. C’est obligatoire ?

Non.

Les Bénéficiaires n’ont pas besoin d’expérience préalable en Web3 ou en blockchain pour participer au process de distribution. Ils suivent uniquement des parcours prédéfinis par le contrat, comme déchiffrer les métadonnées et Réclamer les actifs selon le calendrier configuré.

La documentation et les indications dans l’interface sont là pour expliquer les étapes. Toutes les actions liées aux actifs s’exécutent automatiquement via le protocole, selon les règles on-chain.

***

## Quels sont les avantages de CryptoLegacy par rapport aux wallets multisig pour la récupération et l’héritage ?

Les wallets multi-signature (multisig) sont faits pour le contrôle partagé, pas pour l’héritage. Ils demandent aux Bénéficiaires de détenir des clés de signature à l’avance, ce qui peut exposer les soldes trop tôt et rend la gestion des clés très sensible sur de longues périodes.

CryptoLegacy suit une approche différente :

* Les actifs restent dans les wallets du Propriétaire tant que les conditions de distribution ne sont pas remplies. Ça évite d’exposer les soldes trop tôt et d’avoir une garde partagée.
* Les règles de distribution sont définies à l’avance et appliquées on-chain, pour une exécution claire et déterministe quand la distribution démarre.
* Les fonds ne sont pas bloqués dans un wallet partagé, ce qui réduit le risque de verrouillage définitif à cause de clés perdues, inactives ou indisponibles.
* La Récupération passe par un Flux de récupération séparé et prédéfini. Les Adresses de récupération peuvent exécuter une récupération complète selon les règles du contrat, sans avoir besoin d’un accès partagé aux fonds pendant la Période normale.

Les deux modèles ne servent pas le même objectif : le multisig est centré sur l’accès partagé et la coordination, alors que CryptoLegacy est centré sur la distribution basée sur le temps, la récupération, et une séparation stricte des rôles entre Propriétaire, Garants, Adresses de récupération et Bénéficiaires.

***

## En quoi CryptoLegacy est différent du partage physique d’une phrase mnémonique ?

Le partage physique d’une phrase mnémonique consiste à découper la phrase de récupération d’un wallet et à en distribuer des parties à plusieurs personnes pour un stockage longue durée. Cette approche demande à tout le monde de bien se coordonner, de comprendre son rôle, de conserver son “morceau” en sécurité pendant longtemps, et d’agir correctement au bon moment. La moindre erreur, perte, incompréhension ou absence de coopération peut bloquer l’accès aux actifs pour de bon.

CryptoLegacy suit un autre modèle :

* Aucun partage physique ou numérique de phrase mnémonique — les phrases de récupération et les clés privées ne sont jamais découpées, copiées ou distribuées.
* Pas d’exigences de coordination sur le long terme — Bénéficiaires, Garants et Adresses de récupération n’ont pas besoin de stocker des secrets, mémoriser des procédures, ni se coordonner en dehors des règles prédéfinies.
* Exécution basée sur des règles plutôt que sur la confiance — les transferts d’actifs et les actions de récupération passent par des processus on-chain prédéfinis, pas par la reconstruction d’une clé privée via un accord humain.
* Flux de récupération dédié — la récupération est gérée par une logique de contrat explicite, ce qui évite d’avoir à “trancher” manuellement ou à faire confiance à quelqu’un au moment d’exécuter.

Les deux approches ne gèrent pas les mêmes risques : le partage physique de phrase mnémonique repose sur le secret, la coordination et la confiance sur le long terme, alors que CryptoLegacy supprime totalement la distribution de secrets et applique la récupération et la distribution via des règles on-chain.

***

## Comment CryptoLegacy se compare à l’héritage légal ?

L’héritage légal “classique” transfère une propriété juridique, mais en self-custody ça ne règle pas deux problèmes pratiques. D’abord, des clés privées ou des hardware wallets doivent finir par être stockés, transportés ou communiqués à quelqu’un, ce qui introduit forcément des risques de perte, de copie ou de mauvais usage. Ensuite, l’exécution dépend de procédures propres à chaque juridiction — tribunaux, intermédiaires et délais — ce qui peut être lent, contesté, ou difficile à coordonner entre plusieurs pays.

CryptoLegacy suit un autre modèle : il ne s’appuie pas sur des intermédiaires pour gérer les clés. À la place, la Récupération et la distribution s’exécutent on-chain selon des règles prédéfinies, indépendamment des procédures judiciaires au moment du transfert. L’héritage légal et CryptoLegacy ne couvrent pas le même “niveau” : le système légal définit des droits, tandis que CryptoLegacy fournit un mécanisme déterministe pour exécuter des transferts sans exposer de clés privées.

***

## Comment CryptoLegacy se compare à l’héritage ou la récupération via MPC ?

Dans les setups basés sur MPC, le contrôle des actifs est réparti entre plusieurs participants qui autorisent les actions ensemble. Quand on utilise MPC pour l’héritage, les Bénéficiaires deviennent, de fait, une partie du groupe MPC chargé d’approuver les transferts.

En pratique, ça crée de l’ambiguïté. Ce n’est pas toujours clair qui initie la récupération, combien de participants doivent coopérer, ce qui se passe si certains Bénéficiaires sont indisponibles, ou comment les désaccords se règlent. L’exécution dépend d’une coordination off-chain, de la disponibilité des participants, et d’un comportement correct au moment exact où les actifs doivent être transférés.

CryptoLegacy suit un autre modèle. Les Bénéficiaires n’ont pas besoin de coordonner l’usage de clés ni de participer à des validations off-chain. À la place, la Récupération et la distribution s’exécutent on-chain selon des règles prédéfinies, avec des rôles, des seuils et des conditions temporelles clairement définis à l’avance.

Les deux approches reposent sur des hypothèses différentes : MPC suppose une coordination active entre participants, alors que CryptoLegacy part du principe que la coordination peut échouer et encode donc les règles d’exécution directement dans le protocole.

***

## Comment CryptoLegacy se compare au Shamir’s Secret Sharing ?

Le Shamir’s Secret Sharing découpe une clé privée ou une phrase mnémonique en plusieurs fragments, avec un seuil de fragments nécessaire pour reconstruire le secret original. Dans un contexte d’héritage, ces fragments sont souvent distribués à des Bénéficiaires ou à des personnes de confiance pour un stockage longue durée.

En pratique, ça crée des défis similaires au partage physique de phrase mnémonique. Les fragments doivent être stockés en sécurité pendant longtemps, les participants doivent rester disponibles, et quelqu’un doit finir par coordonner la reconstruction. Si des fragments sont perdus, retenus, ou assemblés de travers, les actifs peuvent devenir inaccessibles définitivement. L’exécution dépend d’une coordination humaine au moment exact où la récupération est nécessaire.

CryptoLegacy suit un autre modèle. Les clés privées et les phrases mnémoniques ne sont jamais reconstruites ni révélées. Au lieu de réassembler un secret, la Récupération et la distribution s’exécutent on-chain selon des règles, des seuils et des conditions temporelles prédéfinis. Les Bénéficiaires n’ont pas besoin de détenir ou de combiner des fragments, et aucune coordination off-chain n’est requise au moment de l’exécution.

Les deux approches reposent sur des hypothèses différentes : Shamir’s Secret Sharing suppose une disponibilité et une coopération sur le long terme, tandis que CryptoLegacy suppose que la coordination peut échouer et encode donc la logique d’exécution directement dans le protocole.

***

## Comment CryptoLegacy assure la sécurité des smart contracts ?

CryptoLegacy utilise des smart contracts personnels qui ne détiennent pas de fonds pendant la Période normale, ce qui réduit la surface d’attaque avant que des conditions de distribution ou de Récupération soient déclenchées.

La logique du contrat est volontairement minimale et n’exécute que des actions prédéfinies. Le protocole a passé des audits de sécurité indépendants, et toutes les opérations liées aux actifs sont encadrées par des conditions on-chain explicites plutôt que par une logique “discrétionnaire”.

Les actifs restent dans les wallets du Propriétaire jusqu’à ce que la distribution ou la Récupération soit déclenchée selon les règles du contrat. Aucun actif n’est détenu ni géré par le protocole en dehors de ces parcours d’exécution prédéfinis.

***

## Comment CryptoLegacy assure la sécurité de l’interface (UI) ?

L’interface de CryptoLegacy ne stocke pas de clés privées ni de données d’actifs sensibles, et ne participe pas à l’exécution des actifs. Toute la logique critique est appliquée par les smart contracts on-chain, pas par le frontend.

L’interface hébergée est livrée avec des pratiques de sécurité web standard et des protections contre les attaques réseau les plus courantes. Et si vous voulez encore plus de contrôle, le frontend peut être auto-hébergé, ce qui réduit la dépendance à une infrastructure tierce sans changer le comportement des contrats.

***

## Que se passe-t-il si je n’envoie pas la transaction requise tous les six mois ?

Si la Période d’inactivité de 6 mois expire, une Période de contestation de 3 mois peut être lancée. La contestation peut être initiée par les Bénéficiaires ou les Garants, selon le Seuil de confirmations configuré.

Pendant la Période de contestation, le processus peut être annulé par le Propriétaire ou une Adresse de récupération. Si la Période de contestation se termine sans annulation, la Période de distribution démarre selon les règles prédéfinies du contrat.

À ce moment-là, les Garants ou les Bénéficiaires peuvent déclencher le processus on-chain qui transfère les actifs vers le contrat CryptoLegacy. Les Bénéficiaires Réclament ensuite leur part progressivement selon le calendrier de distribution configuré, tandis que les Adresses de récupération peuvent exécuter le Flux de récupération pour transférer tous les actifs comme défini par le contrat.

***

## Je peux héberger le frontend de CryptoLegacy moi-même ?

Oui.

Le frontend de CryptoLegacy peut être auto-hébergé à partir du repo publié. L’auto-hébergement vous permet de faire tourner l’interface sur votre propre infra, comme IPFS, Arweave, ou un serveur privé, sans dépendre du frontend hébergé.

L’auto-hébergement ne change ni le comportement des contrats ni la logique d’exécution. Toutes les actions critiques restent appliquées par les smart contracts on-chain, peu importe d’où l’interface est servie.

***

## Comment CryptoLegacy protège la confidentialité des Bénéficiaires et des actifs ?

CryptoLegacy est conçu pour limiter la divulgation d’informations et retarder la visibilité jusqu’à ce que les conditions de distribution ou de Récupération soient remplies.

* Chaque contrat CryptoLegacy utilise sa propre adresse unique, qui n’est pas directement liée au wallet du Propriétaire ni aux autres contrats.
* Les adresses des Bénéficiaires, Garants et Adresses de récupération sont stockées sous forme de hash, ce qui empêche de les associer à un contrat précis tant qu’elles ne sont pas utilisées on-chain.
* Les métadonnées liées aux actifs sont chiffrées par rôle et ne peuvent être déchiffrées que quand les conditions on-chain correspondantes sont satisfaites.
* Pendant la Période normale, les actifs restent dans les wallets du Propriétaire. Le contrat ne détient aucun fonds et n’expose ni soldes ni données d’actifs avant l’exécution.

La confidentialité dans CryptoLegacy est assurée par la séparation des rôles, des identités hashées, des métadonnées chiffrées et une exécution basée sur des règles — pas par de l’obfuscation “custodiale” ou du secret off-chain.

***

## Est-ce que les Bénéficiaires ou les Garants peuvent accéder aux données chiffrées à l’avance en inspectant la blockchain ou le code ?

Les métadonnées chiffrées sont visibles publiquement on-chain et peuvent être analysées off-chain.

Mais ces métadonnées ne peuvent pas être déchiffrées de façon utile sans les clés privées correspondantes, et même un déchiffrement réussi ne donne pas la capacité de déplacer des actifs. Tous les transferts restent encadrés par des conditions on-chain, des Seuils de confirmations, et des Flux d’exécution définis par le contrat.

Inspecter le frontend, auto-héberger l’interface, ou relire le code source ne donne pas plus d’accès que ce qui est déjà visible publiquement on-chain. L’interface ne stocke pas de clés privées ni de données d’actifs en clair, et elle ne contourne pas les protections cryptographiques ou celles du contrat.

CryptoLegacy ne compte pas sur l’obscurité ou des restrictions côté frontend pour la confidentialité. Il s’appuie sur le chiffrement, la séparation des rôles, et l’exécution on-chain basée sur des règles — en assumant que les données blockchain sont publiques par nature.

***

## Mais les autorisations et les données chiffrées sont on-chain — donc c’est techniquement accessible, non ?

Oui. Les métadonnées chiffrées et les données d’autorisation sont visibles publiquement on-chain et peuvent être analysées off-chain.

Mais le fait que ce soit techniquement disponible ne veut pas dire que c’est exploitable en pratique. Les données chiffrées ne peuvent pas être déchiffrées de façon utile sans les clés privées, et même un déchiffrement réussi ne permet pas de sortir les actifs des parcours d’exécution prédéfinis.

CryptoLegacy part du principe que les données blockchain sont publiques par défaut, et se concentre sur un point clé : la visibilité ne doit jamais se transformer en autorité. La Récupération et la distribution ne peuvent s’exécuter que via des règles on-chain prédéfinies, peu importe l’analyse off-chain ou le reverse engineering.

***

## CryptoLegacy peut gérer des NFTs et d’autres protocoles ?

CryptoLegacy est conçu pour être extensible via un système de plugins basé sur le Diamond Standard (EIP-2535).

Cette architecture de plugins permet d’ajouter de la logique d’exécution sans modifier le comportement du cœur du contrat. Ça inclut le support de types d’actifs et d’interactions avec des protocoles au-delà de simples transferts de tokens.

Au lancement, le système de plugins est déjà en place, et le support des NFTs et d’autres intégrations de protocoles est prévu via des plugins approuvés au fil du temps. L’enregistrement et l’exécution des plugins restent soumis à des règles prédéfinies et ne modifient pas la logique de distribution.

***

## Que se passe-t-il si une clé privée est compromise ?

Si une clé privée est compromise pendant la Période normale, le Propriétaire peut mettre à jour la configuration du contrat selon les règles prédéfinies. Ça peut inclure le changement d’adresse du Propriétaire, la mise à jour des adresses des Bénéficiaires ou des Garants, ou l’ajustement de la config de Récupération.

Une fois la Période de distribution commencée, le contrôle du Propriétaire est suspendu et ne peut pas être utilisé pour modifier l’exécution. À ce stade, les transferts se font strictement selon les règles de distribution ou de Récupération prédéfinies, indépendamment de la clé compromise.

Les Bénéficiaires peuvent mettre à jour leurs adresses de réception pendant la Période de distribution, selon ce que permet la logique du contrat. Aucun rôle ne peut utiliser une clé compromise pour contourner des conditions on-chain ou modifier les Flux d’exécution.

***

## Que faire si mes clés sont potentiellement compromises et que je n’ai plus accès à mes appareils ou à mes backups ?

Pendant la Période normale, des mécanismes de Récupération prédéfinis peuvent être utilisés selon la configuration du contrat.

Les Garants peuvent déclencher le processus on-chain prédéfini qui transfère les actifs vers le contrat CryptoLegacy, sous réserve des Seuils de confirmations et de la Période de contestation configurée. Pendant la Période de contestation, le processus peut être annulé par le Propriétaire ou une Adresse de récupération.

Les Adresses de récupération peuvent aussi exécuter le Flux de récupération selon les règles prédéfinies. Ce Flux transfère les actifs vers le contrat CryptoLegacy et permet ensuite de les envoyer comme défini par la configuration de récupération.

Toutes les actions s’exécutent strictement selon les règles on-chain. Aucun rôle ne peut contourner les Seuils de confirmations, les délais, ou les conditions d’exécution.

***

## Je peux mettre le contrat en Pause / le retirer de la Pause ?

Le contrat CryptoLegacy inclut un mécanisme de Pause qui bloque les transferts d’actifs et les autres actions d’exécution.

Tant que le contrat est en Pause, les actifs ne peuvent pas être déplacés et le démarrage d’une Période de contestation est bloqué. Le Propriétaire peut quand même mettre à jour la configuration du contrat (paramètres des Bénéficiaires, config des Garants, paramètres de Récupération, et autres options hors exécution) selon les règles du protocole.

La Période d’inactivité continue de s’écouler pendant que le contrat est en Pause. Pour éviter de passer en état “contestation”, le Propriétaire doit rafraîchir la Période d’inactivité de 6 mois en envoyant la transaction on-chain requise (et le Don DAO, si applicable).

Si la Période d’inactivité a déjà expiré, une Période de contestation ne peut pas être lancée tant que le contrat est en Pause, mais peut être lancée immédiatement après la reprise.

Retirer la Pause réactive l’exécution avec les mêmes conditions on-chain. Les Autorisations de tokens (approvals) peuvent être révoquées séparément à tout moment, indépendamment du mécanisme de Pause.

***

## Je peux personnaliser le calendrier de distribution des Bénéficiaires ?

Oui.

Pour chaque Bénéficiaire, le Propriétaire définit une part, un Délai avant accès (optionnel) et une Période de distribution. Ces paramètres déterminent quand la Réclamation d’actifs commence et comment les actifs deviennent Disponibles à réclamer au fil du temps.

* **Délai avant accès** — la période d’attente avant qu’un Bénéficiaire puisse commencer à Réclamer les actifs.
* **Période de distribution** — la durée pendant laquelle les actifs deviennent Disponibles à réclamer progressivement selon le calendrier configuré.

Les paramètres de distribution peuvent être mis à jour par le Propriétaire pendant la Période normale. Une fois la Période de distribution commencée, ces paramètres sont figés et appliqués on-chain selon les règles configurées.

***

## Quels frais CryptoLegacy demande ?

CryptoLegacy est soutenu via des dons à la DAO (Don DAO).

Un don fixe est requis lors du déploiement d’un contrat personnel et lors du rafraîchissement de la Période d’inactivité au bon intervalle.

Une option alternative “accès illimité” peut être utilisée selon la configuration du protocole, et couvre les déploiements de contrats ainsi que les mises à jour de timeout sur les chaînes supportées.

***

## C’est quoi le mécanisme de parrainage, et comment ça marche ?

CryptoLegacy inclut un mécanisme de parrainage optionnel, pensé pour des introductions de confiance.

Quand un code de parrainage est utilisé, une réduction prédéfinie s’applique à la personne qui déploie, et une allocation prédéfinie est attribuée au détenteur du code, selon les règles du protocole.

Les codes de parrainage sont faits pour un usage privé, dans des contextes de confiance — pas pour une distribution publique ou des campagnes de croissance. Les adresses de paiement associées aux codes peuvent être mises à jour selon la configuration du protocole.

***

## Que se passe-t-il si l’équipe core ne peut plus supporter le produit ?

CryptoLegacy ne dépend pas d’une implication continue d’une équipe core pour l’exécution des contrats.

Une fois déployés, les contrats CryptoLegacy fonctionnent de façon autonome on-chain et ne dépendent pas de services centralisés pour exécuter la Récupération ou la distribution. Le frontend peut être auto-hébergé, et les contrats peuvent être utilisés directement on-chain, indépendamment d’une interface hébergée.

La disponibilité du code et sa maintenance peuvent évoluer selon la gouvernance du projet, mais les contrats déjà déployés restent fonctionnels et appliquent leurs règles prédéfinies, même sans support continu de l’équipe.

***

## Pourquoi le code du contrat est public, mais sous copyright et pas sous licence open-source ?

Le code du contrat CryptoLegacy est lisible publiquement pour permettre une revue indépendante et des audits.

En parallèle, le code est distribué sous droit d’auteur (copyright) pour limiter la réutilisation non vérifiée, le clonage, ou le déploiement dans des contextes trompeurs ou risqués. L’objectif est de réduire le risque d’arnaques, de forks mal configurés, ou de déploiements non autorisés qui pourraient nuire aux utilisateurs.

La licence et la disponibilité du code peuvent évoluer avec la gouvernance et la maturité du projet. Quelle que soit la licence, les contrats déjà déployés continuent de fonctionner de façon autonome et d’appliquer leurs règles on-chain.

***

## Pourquoi le code de l’UI est fermé et obfusqué ?

L’interface CryptoLegacy n’est pas une “barrière de sécurité”. Elle ne stocke pas de clés privées, de métadonnées d’actifs déchiffrées, ni d’autorité d’exécution. Toute la logique critique est appliquée par les smart contracts on-chain.

Le code UI est distribué sous une forme obfusquée pour réduire les risques de phishing, de frontends usurpés et de copies trompeuses qui pourraient pousser des utilisateurs à signer des transactions non voulues. L’obfuscation sert à limiter une réutilisation ou modification triviale de l’interface dans des contextes risqués, pas à remplacer la sécurité cryptographique ou celle du contrat.

Les utilisateurs peuvent auto-héberger l’interface ou interagir directement avec les contrats on-chain. La disponibilité du code UI et sa licence peuvent évoluer selon la gouvernance du projet, mais les contrats déjà déployés restent entièrement auditables et appliquent leurs règles indépendamment du frontend.


# Hello World, somos CryptoCustoms 👋

CryptoCustoms presenta CryptoLegacy, una aplicación multichain y segura que garantiza la transferencia de criptoactivos a los beneficiarios tras periodos de espera o en caso de emergencia.

Encantados de conocerte — seremos breves.

Somos constructores del ecosistema Web3 desde sus inicios: GPUs sobrecalentadas, forks de Bitcoin, el colapso de Mt. Gox, ICOs de Ethereum. Ha sido un viaje salvaje.

Desde el auge de las ICOs y los veranos DeFi hasta los NFTs, Rollups, RWAs, DePin e incluso los meme coins — lo hemos vivido todo, y lo hemos construido todo. Desde 2017, hemos creado proyectos por diversión, por innovación y, sí, a veces por beneficio. Pero siempre con principios claros, enfoque en el usuario y bases tecnológicas sólidas.

En 2024, decidimos crear algo distinto — no otro DEX, protocolo de préstamos o Rollup — sino algo que las personas realmente necesitan: una forma de proteger y preservar sus criptoactivos.

Desde el primer día, tuvimos esta idea: CryptoLegacy, una dApp multichain y segura, diseñada para mantener tus criptos protegidas y transferibles en tiempos de incertidumbre.

CryptoLegacy no almacena tus fondos — en su lugar, gestiona de forma segura la distribución de activos mediante contratos personales que activan transferencias privadas a tus beneficiarios en caso de emergencia o tras un tiempo predefinido. Es minimalista, segura, fácil de usar y con opciones de recuperación integradas.

Porque no se trata solo de ganar cripto, sino de conservarla — para ti y para las generaciones futuras.

Mantente atento — lo mejor está por venir.

Síguenos en X para actualizaciones [aquí](https://x.com/0xcust).

Visita <https://cryptolegacy.app/>.

Si no te apetece leer mucho, solo pregúntale a nuestro GPT [aquí](https://chatgpt.com/g/g-68c9f2e3d5ec8191a86f75068462c886-cryptolegacy-ai).


# Nuestra Visión

Construimos productos Web3 seguros, simples y descentralizados, enfocados en crear valor duradero - no en la especulación - poniendo siempre a los usuarios primero y sin presión de inversionistas.

No se puede construir un gran producto sin una visión sólida. La mayoría de los proyectos en este espacio están diseñados para ganancias rápidas y esquemas especulativos con tokens. Nosotros rechazamos ese enfoque y, en cambio, creamos valor duradero e inspiración — porque tus activos digitales merecen permanencia.

### Principios Clave:

* **Los usuarios primero:** Creamos este producto para nosotros mismos, las personas que queremos, para ti y tus seres queridos.
* **La seguridad ante todo:** Apuntamos a los estándares más altos de seguridad, colaborando con firmas de seguridad de primer nivel.
* **Los tokens pueden llegar a cero — los productos Web3 deberían durar para siempre:** Desde el primer día eliminamos los riesgos especulativos para asegurar la longevidad. Nuestro efecto de red proviene de un programa de referidos justo, nunca de la especulación.
* **La descentralización importa:** Eventualmente, todo lo que hagamos será completamente descentralizado.
* **Sin presión de inversionistas:** Evitamos inversores externos para mantener nuestra independencia. Si quieres apoyarnos, simplemente usa el producto si satisface tus necesidades.
* **El valor ante todo:** Nuestro principal objetivo es ofrecer valor significativo a nuestros usuarios.
* **Simplicidad:** Nuestro producto está diseñado para ser extremadamente intuitivo, con una interfaz intuitiva y tutoriales paso a paso que incluso tus padres podrían seguir fácilmente.


# Estado

**Estado actual del proyecto CryptoLegacy al 4 de agosto de 2025:**

* El código de los smart contracts está finalizado y ha sido auditado con éxito por [Mixbytes](https://github.com/mixbytes/audits_public/tree/master/CryptoLegacy/CryptoLegacy), [Decurity](https://github.com/Decurity/audits/blob/master/Cryptolegacy/cryptolegacy-audit-report-2025-1.1.pdf), [Pessimistic](https://github.com/pessimistic-io/audits/blob/main/CryptoLegacy%20Security%20Analysis%20by%20Pessimistic.pdf) y [Kamensec](https://github.com/kamensec/solo-audits-public/blob/main/crypto-legacy-report-1.pdf).
* Los contratos están desplegados en Ethereum, Arbitrum, Base, Optimism y Linea.
* La interfaz está completamente lanzada y disponible en [my.cryptolegacy.app](https://my.cryptolegacy.app).
* La plataforma está plenamente operativa en todas las redes compatibles.


# Cómo funciona CryptoLegacy

CryptoLegacy automatiza de forma segura la herencia y recuperación de criptomonedas mediante contratos inteligentes, calendarios predefinidos, aprobaciones de guardianes y direcciones de recuperación.

## Herencia

### Paso 1: Configuración

Despliegas un contrato inteligente personal desde una plataforma Factory, pagando una pequeña comisión al DAO. Configuras beneficiarios con sus porcentajes y calendarios (incluyendo retrasos y periodos de distribución), autorizas transferencias de tokens desde tus wallets principales al contrato, y encriptas los datos de activos individualmente para cada beneficiario. Cada seis meses actualizas el plazo límite enviando una transacción que incluye la comisión del DAO.

### Paso 2: Desafío (3 meses)

Si el plazo límite expira, cualquier beneficiario puede iniciar un periodo de desafío. Durante este tiempo, todavía puedes cancelar el proceso. Al terminar este periodo, los beneficiarios pueden desencriptar los datos de activos (que permanecen ocultos hasta ese momento) y transferir activos desde tus wallets principales al contrato CryptoLegacy para su distribución.

### Paso 3: Distribución

Los beneficiarios reclaman los activos según sus porcentajes y calendarios (retrasos y periodos de distribución). Pueden actualizar sus direcciones en cualquier momento si son comprometidas. Los activos permanecen seguros en el contrato CryptoLegacy durante la distribución.

## Recuperación

### Paso 1: Agregar recuperación

Al crear el contrato se agregan automáticamente dos plugins. Por defecto, los beneficiarios quedan configurados como guardianes con un umbral de aprobación de 2 de 3 y un plazo de desafío para guardianes de 30 días. Puedes cambiar guardianes, umbrales y plazos cuando quieras. Además, puedes configurar direcciones de recuperación con sus propios umbrales de aprobación (por ejemplo, 1 de 3, 2 de 3, 3 de 5). Tanto las direcciones de guardianes como las de recuperación están almacenadas de forma segura mediante hashes, evitando que sean vinculadas directamente a tu contrato CryptoLegacy.

### Paso 2: Retiro de emergencia

Cada guardián debe enviar una transacción para iniciar la distribución antes de que venza el plazo principal de 6 meses. Al alcanzar el umbral de aprobación, comienza un plazo de desafío opcional para guardianes (entre 0 y 30 días). Tú o cualquier dirección de recuperación pueden cancelar este plazo. Al finalizar el plazo de desafío, los guardianes pueden desencriptar los datos de activos (ocultos hasta ese momento) y transferirlos a tu contrato personal para distribución. Los guardianes nunca tienen acceso directo a tus fondos.

### Paso 3: Distribución y recuperación

Los beneficiarios reclaman activos según sus porcentajes y calendarios predefinidos. Mantienes control total y puedes recuperar todos tus activos en cualquier momento utilizando tus direcciones de recuperación almacenadas de forma segura, completamente separadas del contrato CryptoLegacy.

## Gestión

### Paso 1: Agregar plugins para gestionar activos

Puedes añadir plugins que permitan a los beneficiarios gestionar activos durante la distribución, como intercambiar tokens, hacer stake de ETH en Lido, mover activos cross-chain o administrar liquidez en Uniswap. La mayoría de los plugins requieren un número específico de confirmaciones por parte de los beneficiarios (similar a una multisig), que puedes configurar libremente.

### Paso 2: Permitir que beneficiarios agreguen plugins

Puedes permitir que los beneficiarios añadan plugins una vez comenzada la distribución, lo cual resulta útil cuando los protocolos integrados necesitan actualizaciones. Por seguridad, los beneficiarios no pueden eliminar plugins existentes.

### Paso 3: Gestión de activos durante la distribución

Durante el periodo de distribución, los beneficiarios pueden usar plugins para gestionar activos, los cuales permanecen seguros en tu contrato personal CryptoLegacy. Cada acción requiere un número específico de confirmaciones. Los beneficiarios continúan reclamando activos según sus porcentajes y calendarios preestablecidos.

## Personalización

### Paso 1: Agregar plugins con lógica personalizada

Puedes añadir plugins para personalizar la lógica de tu contrato CryptoLegacy; por ejemplo, transferir NFTs, cerrar automáticamente posiciones NFT en Uniswap, distribuir cantidades fijas (en lugar de porcentajes) a beneficiarios, o establecer reglas completamente nuevas.

### Paso 2: Permitir que beneficiarios agreguen lógica personalizada

Puedes permitir que los beneficiarios agreguen sus propios plugins cuando inicie la distribución. Estos plugins pueden incluir lógica personalizada, como transferir participaciones, añadir nuevos beneficiarios o crear otras reglas específicas.

### Paso 3: Verificación de seguridad de plugins

Todos los plugins se verifican mediante el Plugin Registry, un contrato inteligente administrado por el equipo central, protocolos asociados y empresas reconocidas de seguridad. Esto garantiza que tu contrato permanezca seguro, aceptando únicamente plugins que hayan superado múltiples auditorías rigurosas.


# Transferencia Segura de Datos de Activos con CryptoLegacy

CryptoLegacy gestiona activos seguros con cifrado de curva elíptica, almacenando copias cifradas en cadena hasta cumplirse condiciones.

CryptoLegacy ofrece total confidencialidad al nunca almacenar información sensible del titular de activos — como direcciones de billetera o de tokens — directamente en el contrato inteligente. En su lugar, depende totalmente de aprobaciones de tokens, cifrando y almacenando los datos de activos de forma segura en tu navegador y en la blockchain, garantizando un control total para el usuario.

***

## Copias de Seguridad Cifradas en la Cadena

CryptoLegacy aprovecha el cifrado incorporado de MetaMask (eth-sig-util), que utiliza criptografía robusta de curva elíptica (x25519-xsalsa20-poly1305). Los propietarios del contrato crean de forma rutinaria copias de seguridad cifradas que contienen:

* Direcciones de los titulares de activos
* Direcciones de los tokens
* Direcciones de los beneficiarios, guardianes y de recuperación
* Claves públicas de cifrado asociadas

Estas copias se integran de manera segura en los eventos de transacciones en la cadena. Aunque son accesibles públicamente, permanecen totalmente cifradas y confidenciales.

* **Copias de Seguridad del Propietario:**\
  Cifradas con la clave pública del propio propietario y almacenadas por separado en contratos de respaldo dedicados en cualquier blockchain compatible.
* **Copias de Seguridad para Beneficiarios, Guardianes y Recuperación:**\
  Cifradas de manera individual con la clave pública que cada parte proporcione, y alojadas directamente dentro del contrato de CryptoLegacy.

***

## Acceso y Disponibilidad de Datos

Los beneficiarios, guardianes y direcciones de recuperación no pueden acceder a los datos cifrados hasta que se cumplan criterios específicos:

* Se alcance el tiempo de espera establecido, lo que activa la distribución de activos, o
* Se cumpla el umbral de guardianes (por ejemplo, 2 de 3) y finalice el período de impugnación para los guardianes.

Para garantizar la fiabilidad, CryptoLegacy recomienda comprobar de antemano los mecanismos de cifrado usando mensajes de prueba.

***

## Desarrollos Futuros

Próximamente, CryptoLegacy implementará opciones de cifrado adicionales para brindar mayor seguridad, especialmente diseñadas para wallets que no cuentan con cifrado interno basado en frases semilla.

***

## Consideraciones de Seguridad

Aunque, en teoría, beneficiarios y guardianes con vastos recursos, conocimientos avanzados y suficiente tiempo podrían intentar descifrar las copias de seguridad almacenadas, el riesgo práctico sigue siendo muy bajo. Normalmente, beneficiarios y guardianes son tus contactos personales más confiables, por lo que ataques complejos — como indexación personalizada de la cadena o criptoanálisis a profundidad — son muy poco probables.

CryptoLegacy integra de manera fluida la privacidad, la facilidad de uso y sólidas protecciones criptográficas, brindando una gestión y transferencia de tu legado digital seguras, convenientes y confidenciales.


# Cómo funcionan los Períodos del Contrato de CryptoLegacy y los Controles de Guardianes

CryptoLegacy automatiza la herencia cripto con check-ins programados, transferencias de emergencia aprobadas por Guardianes y mecanismos de recuperación seguros.

## Estados del Contrato de CryptoLegacy

### Período Normal

* El contrato está activo, desplegado y, por ahora, no posee activos.
* Cada 6 meses, tú (como propietario) confirmas que sigues activo enviando una transacción on-chain.
* Este intervalo de 6 meses para el check-in es permanente y no se puede modificar. Así se garantiza fiabilidad y claridad para todos los participantes.

### Período de Desafío

* Si no realizas el check-in obligatorio a los 6 meses, cualquier beneficiario puede activar un Período de Desafío de 3 meses.
* Durante esos 3 meses, puedes intervenir en cualquier momento para confirmar que sigues presente y cancelar el proceso de distribución.
* Este Período de Desafío de 3 meses es fijo e inalterable, lo que garantiza previsibilidad y equidad.

### Período de Distribución

* Si el Período de Desafío concluye sin tu intervención, los beneficiarios desencriptan los detalles de los activos, almacenados de forma segura como datos cifrados en los eventos de transacción on-chain.
* A continuación, transfieren los activos que habías aprobado desde tus billeteras principales hacia el contrato de CryptoLegacy, según los permisos que otorgaste.
* Los beneficiarios reclaman su parte basándose en tus parámetros predefinidos:
  * **Retraso (Delay)**: Tiempo de espera después de que inicia la distribución, antes de que un beneficiario pueda reclamar.
  * **Duración (Duration)**: Período durante el cual los activos se van desbloqueando progresivamente, permitiendo reclamarlos de forma escalonada.

***

## Guardianes y Controles de Recuperación

### Guardianes

* Los Guardianes son personas de confianza, designadas para situaciones de emergencia.
* Tú eliges quiénes serán Guardianes y fijas un umbral de aprobación (ej. 1-de-3, 2-de-3, 3-de-5).
* Por defecto, tus Beneficiarios se asignan como Guardianes con un umbral de 2-de-3. Si hubiera menos de 2 Beneficiarios, el umbral es igual al número de Beneficiarios.
* El Período de Desafío por defecto para los Guardianes es de 30 días, aunque puedes modificarlo.
* Las direcciones de Guardianes se almacenan en forma de hash, sin relacionarlas directamente con tu contrato de CryptoLegacy.
* Los Guardianes pueden desencriptar los datos cifrados de los activos solo cuando se cumple el umbral de aprobación, permitiendo la transferencia de emergencia de activos hacia tu contrato de CryptoLegacy.
* Los Guardianes nunca controlan ni retiran tus activos directamente. Solo activan la transferencia y el inicio de la distribución según tus configuraciones.

### Direcciones de Recuperación

* Las direcciones de recuperación actúan como mecanismos de emergencia ocultos, almacenadas de forma segura como hashes y sin estar vinculadas directamente al contrato de CryptoLegacy hasta que se activa una acción de recuperación. Una vez utilizadas, se vuelven visibles — lo cual es esperado, ya que su función está diseñada para usarse una sola vez. Lo importante es que permanezcan privadas hasta el momento de su uso. Después de eso, el propietario recupera el control y puede utilizar cualquier herramienta adicional de privacidad si lo desea.
* Estas direcciones pueden desencriptar los datos cifrados en los eventos de transacción, transferir y retirar activos de forma independiente, si fuera necesario, anulando el calendario regular de beneficiarios.
* Pueden cancelar el Período de Desafío de Guardianes antes de que comience la distribución.

***

### Notas de Seguridad Adicionales

* Beneficiarios y Guardianes solo pueden acceder a los detalles cifrados de los activos cuando:
  * Inicia el Período de Distribución, o
  * Se cumple el umbral de Guardianes, expira el tiempo de desafío y comienza la Distribución.
* Es esencial validar previamente los procesos de cifrado mediante mensajes de prueba.

***

CryptoLegacy combina procedimientos transparentes, métodos de cifrado seguros y mecanismos de Guardianes y Recuperación bien definidos, dándote la confianza para manejar tus activos digitales y tu legado con total tranquilidad.


# Integración Cross-chain para NFTs vitalicios y Programa de Referidos

CryptoLegacy usa deBridge ofreciendo NFTs vitalicios y referidos cross-chain fácilmente: mintea una vez, usa donde quieras y sincroniza códigos en todas las cadenas automáticamente.

Al diseñar **CryptoLegacy**, nuestro principal objetivo fue ofrecer una accesibilidad fluida en todas las redes blockchain, maximizando así los efectos de red y acelerando el crecimiento del ecosistema.

Para simplificar la experiencia del usuario, presentamos el **Unlimited NFT Pass**, que permite crear y actualizar contratos en cualquier blockchain compatible, sin costo alguno y para siempre. Sin embargo, lograr una funcionalidad cross-chain realmente fluida presentó importantes desafíos técnicos.

Además, creamos un sólido **Programa de referidos** que permite a los usuarios ganar recompensas invitando a otras personas. Garantizar que un solo código de referido funcionara universalmente en todas las blockchains compatibles fue otro reto técnico.

Solucionamos ambos desafíos al integrar el protocolo **deBridge**, que posibilita una mensajería e interoperabilidad cross-chain eficientes.

***

## NFTs Cross-chain: Cómo Funciona

### 1. Mintea y bloquea en Ethereum

* Mintea y bloquea tu NFT en Ethereum para asegurar acceso de por vida.

### 2. Bloqueo Cross-chain

Transfiere sin esfuerzo los datos de tu NFT bloqueada a cualquier blockchain compatible con EVM:

* Envía una transacción en Ethereum.
* Espera la confirmación del bridge.
* Cambia a la blockchain deseada.
* Confirma la transacción de bloqueo.

Ahora estás listo para desplegar y actualizar contratos en esa blockchain sin costos adicionales.

### 3. Desbloqueo de NFTs

Para desbloquear tu NFT en Ethereum, primero debes desbloquearla en todas las demás blockchains:

* Envía transacciones de desbloqueo en cada blockchain donde esté bloqueada tu NFT.
* Espera las confirmaciones del bridge.
* Regresa a Ethereum.
* Confirma el desbloqueo.

**Principales Ventajas**:

* Bloquea tu NFT simultáneamente en múltiples cadenas con una sola transacción.
* Actualiza fácilmente la propiedad de tu NFT en diversas cadenas con una única transacción.
* Nuestra interfaz intuitiva garantiza una experiencia fluida y sin complicaciones.

***

## Programa de Referidos Cross-chain

Así es como funciona el programa de referidos en múltiples blockchains:

### 1. Genera tu código de referido

* Crea un shortcode personalizado o autogenerado (inicialmente se crea en Arbitrum para optimizar costos).

### 2. Despliega el código de referido en varias blockchains

Los datos de referidos se propagan automáticamente a todas las blockchains compatibles mediante deBridge:

* Espera la confirmación del bridge.
* Cambia de red y confirma la creación del código de referido en cada blockchain.

**Los códigos de referido son únicos y flexibles**:

* Actualiza fácilmente el propietario del código o la dirección de pago simultáneamente en múltiples blockchains.

**Notas Importantes**:

* Si CryptoLegacy se expande a más blockchains, solo tendrás que actualizar la información de referidos en esas nuevas redes.
* Por ahora, cambiar el propietario del código de referido o la dirección de pago requiere transacciones separadas en cada blockchain.

***

## Transferencia de Activos Cross-chain

Actualmente, CryptoLegacy no admite transferencias cross-chain de activos bloqueados. Sin embargo, planeamos desarrollar un plugin en el futuro. Los dueños de contratos podrán agregar este plugin a sus contratos, permitiendo que los beneficiarios transfieran fácilmente activos bloqueados entre diferentes cadenas.

***

## Copia de Contratos Cross-chain

Para simplificar la configuración, puedes desplegar rápidamente contratos con la misma dirección y datos de beneficiarios en múltiples cadenas compatibles con EVM.


# Los Plugins de CryptoLegacy amplían la funcionalidad de los contratos

CryptoLegacy usa plugins modulares validados por la DAO para gestionar funciones de forma segura, mejorando así la adaptabilidad, seguridad y eficiencia económica de sus contratos.

CryptoLegacy aprovecha el estándar Diamond para ofrecer funciones esenciales, respaldar casos de uso avanzados e integrarse sin problemas con diversos protocolos blockchain. Todos los contratos inteligentes personales de CryptoLegacy comparten la misma lógica de plugin, lo que reduce significativamente los costos de implementación.

***

### Agregar, eliminar, reemplazar o actualizar plugins

Los propietarios de los contratos pueden agregar nuevos plugins con facilidad, eliminar los innecesarios o reemplazar y actualizar los existentes simplemente enviando una transacción a su contrato personal de CryptoLegacy. El contrato personal verifica automáticamente el plugin solicitado en el Plugin Registry —asegurándose de que sea seguro y esté auditado— antes de completar la operación.

> **Nota**: Algunos plugins requieren un NFT bloqueado para su activación.

***

### Seguridad de los Plugins

* Todos los plugins están preaprobados a través del Plugin Registry por el multisig de la DAO, con el apoyo de firmas de seguridad y protocolos asociados.
* Cada plugin es auditado exhaustivamente por firmas de seguridad independientes.
* Los plugins siguen un enfoque minimalista para reducir la complejidad y mejorar la seguridad.
* Al agregar plugins, los usuarios solo interactúan con sus contratos personales, minimizando el riesgo.
* El Plugin Registry busca la máxima descentralización, involucrando inicialmente a firmas de seguridad de confianza y socios de protocolo.

***

### Plugins Disponibles

* **Base Plugin** – Ofrece la lógica fundamental para los contratos de CryptoLegacy.
* **NFT Legacy Plugin** – Administra las funcionalidades relacionadas con NFTs dentro de CryptoLegacy.
* **Trusted Guardians Plugin** – Permite que guardianes de confianza omitan los periodos de espera y activen la distribución de activos en emergencias.
* **Recovery Plugin** – Implementa direcciones de recuperación ocultas que pueden reclamar activos de forma independiente cuando sea necesario.
* **Beneficiary Plugin** – Permite a los beneficiarios agregar plugins adicionales durante la fase de distribución de activos.

***

### Plugins Futuros

* **Uniswap Position Closure Plugin** – Retira y cierra automáticamente tus posiciones de Uniswap NFT.
* **Fixed Transfer Plugin** – Transfiere montos fijos de activos a beneficiarios de inmediato o según un cronograma de asignación, en lugar de distribuir participaciones.
* **Beneficiary Share Transfer Plugin** – Permite a los beneficiarios transferir sus participaciones a otros beneficiarios o agregar nuevos beneficiarios.

Los plugins pueden administrarse con flexibilidad a medida que cambien las necesidades, asegurando que los contratos de CryptoLegacy sigan siendo seguros, adaptables y preparados para el futuro.




---

[Next Page](/llms-full.txt/1)

