> For the complete documentation index, see [llms.txt](https://docs.cryptolegacy.app/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.cryptolegacy.app/documentation/functions-reference.md).

# Contract Functions Reference

## 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.md) 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**


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.cryptolegacy.app/documentation/functions-reference.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
