• SettleMintSettleMint
    • Introduction
    • Market pain points
    • Lifecycle platform approach
    • Platform capabilities
    • Use cases
    • Compliance & security
    • Glossary
    • Core component overview
    • Frontend layer
    • API layer
    • Blockchain layer
    • Data layer
    • Deployment layer
    • System architecture
    • Smart contracts
      • SMART protocol (ERC-3643)
      • Asset contracts
      • Identity & compliance
      • Addon modules
      • Factory patterns & upgradeability
    • Application layer
    • Data & indexing
    • Integration & operations
    • Performance
    • Quality
    • Getting started
    • Asset issuance
    • Platform operations
    • Troubleshooting
    • Development environment
    • Code structure
    • Smart contracts
    • API integration
    • Data model
    • Deployment & ops
    • Testing and QA
    • Developer FAQ
Back to the application
  1. Documentation
  2. Architecture
  3. Smart contracts

Factory pattern and upgradeable architecture

Factory contracts and upgradeable proxy architecture enable standardized deployment and safe contract evolution in production environments. This infrastructure provides deterministic addressing, consistent initialization, and controlled upgrade paths for tokenized assets at enterprise scale.

Factory contract architecture

Factory contracts establish standardized deployment infrastructure for tokenized assets. Rather than deploying token contracts manually with varying initialization patterns, factories ensure every token instance follows identical deployment procedures, inherits verified implementations, and integrates correctly with the broader system.

The factory pattern separates deployment logic from business logic. Token contracts define what a bond or equity does; factory contracts define how those tokens are created, initialized, and registered within the ATK ecosystem.

Deployment consistency guarantees

Manual contract deployment introduces variation. Different operators might use different constructor parameters, skip initialization steps, or misconfigure access control. Factory deployment eliminates this variability through enforced deployment scripts.

When a factory deploys a token, it executes a deterministic sequence: deploy the proxy contract at a CREATE2 address, link it to the verified implementation, initialize the token with validated parameters, register the token's OnchainID identity, assign required system roles, and emit standardized events for indexing. This sequence executes atomically—either all steps succeed, or the deployment reverts.

The AbstractATKTokenFactoryImplementation contract defines this common deployment sequence for all asset types. Asset-specific factories (bonds, equities, funds) extend this base implementation with type-specific initialization logic while inheriting the core deployment guarantees.

Deployment discovery and tracking

Factories maintain deployment registries. Each deployed token is recorded in the factory's state with its address, type identifier, and deployment timestamp. The ATK System queries these registries to enumerate all tokens of a given type, verify deployment authenticity, and track system growth.

The IATKTokenFactory interface defines the deployment tracking methods. Factories emit TokenDeployed events containing the token address, implementation version, and deployer identity. The subgraph indexes these events, making deployment history queryable through GraphQL.

Observability dashboards track factory usage metrics: deployment frequency, gas costs per deployment, implementation version distribution, and factory utilization rates. These metrics inform capacity planning and identify deployment bottlenecks as the platform scales.

Token factory registry

The Token Factory Registry serves as the central directory for all factory contracts in the ATK system. Rather than hardcoding factory addresses throughout the platform, contracts query the registry to discover the appropriate factory for each asset type.

Registry-based factory discovery

The ATKTokenFactoryRegistry maps asset type identifiers to factory addresses. When the frontend needs to deploy a bond, it queries the registry for the "BOND" type and receives the current bond factory address. This indirection enables factory upgrades without modifying client code.

Type identifiers use consistent string constants: BOND, EQUITY, FUND, DEPOSIT, STABLECOIN. The registry validates type identifiers during registration to prevent typos or duplicate registrations.

Rendering chart...

Registry access control

Only addresses with SYSTEM_MANAGER_ROLE can register or update factory addresses in the registry. This prevents unauthorized parties from redirecting deployment requests to malicious factory contracts.

Factory registration requires both the factory address and its implementation address. The registry verifies that the factory contract exists at the provided address before recording the registration. This validation prevents registration of invalid or non-existent contracts.

Factory versioning and updates

The registry supports factory replacement. When a factory implementation is upgraded, the SYSTEM_MANAGER_ROLE registers the new factory address for the same type identifier. Existing tokens deployed by the old factory remain unchanged; new deployments use the updated factory.

The registry emits FactoryRegistered and FactoryUpdated events when factories are added or replaced. These events include the type identifier, old factory address (if applicable), and new factory address. The subgraph tracks factory version history, enabling auditors to determine which factory deployed each token.

Upgradeable proxy architecture

The ATK system uses the Universal Upgradeable Proxy Standard (UUPS) pattern to enable contract logic upgrades while preserving deployed addresses and contract state. This architecture separates storage (maintained in the proxy) from logic (implemented in upgradeable contracts).

Proxy delegation mechanism

The ATKTypedImplementationProxy contract implements the proxy pattern. When a user calls a function on a proxy address, the proxy uses delegatecall to execute the function in the implementation contract's code while operating on the proxy's storage.

This delegation preserves the proxy's address and state across upgrades. Users interact with the same contract address before and after an upgrade. The upgrade changes which implementation contract receives delegated calls, but the proxy address and stored data remain constant.

Rendering chart...

Storage layout compatibility

Upgrades must maintain storage layout compatibility. Since the proxy stores all state variables, the new implementation must interpret those storage slots identically to the old implementation. Adding new variables is safe (they occupy new slots); reordering existing variables corrupts state.

Solidity's storage layout rules assign slots sequentially based on variable declaration order. Implementation contracts use inheritance to preserve this order across upgrades. New versions extend the base contract and add new variables at the end, ensuring existing slots retain their meaning.

The ATK system uses OpenZeppelin's upgradeable contract library, which provides storage-safe base contracts and initialization patterns. These contracts prevent constructor usage (constructors don't affect proxy storage) and require explicit initialize functions called once after deployment.

Initialization protection

Initialization functions must execute exactly once per proxy deployment. Multiple initializations could reset state, reassign roles, or create inconsistencies. The Initializable base contract enforces single initialization through a storage flag.

When a proxy is deployed, the factory calls the implementation's initialize function through the proxy. The Initializable modifier checks the initialization flag, executes the initialization logic if uninitialized, sets the flag, and reverts if already initialized.

Upgrades may introduce new initialization logic for added features. These functions use versioned modifiers (initializerV2, initializerV3) that track which initialization versions have executed, allowing partial re-initialization while preventing duplicate execution of earlier initialization code.

Upgrade authorization and governance

The ATK system centralizes upgrade authority in the ATK System contract. Individual token proxies do not control their own upgrades; instead, the ATK System manages implementation addresses for all proxies it deploys.

Centralized upgrade management

The ATKSystemImplementation contract stores implementation addresses for every system component: identity registries, compliance modules, token implementations, and addon contracts. When the system needs to upgrade a component, it updates the corresponding implementation address in its registry.

This centralization provides consistent upgrade procedures across all components. Rather than each token proxy implementing its own upgrade authorization, proxies delegate upgrade decisions to the ATK System. The system verifies that only authorized roles (typically SYSTEM_MANAGER_ROLE) can trigger upgrades.

Upgrade execution flow

Upgrades follow a structured sequence to minimize risk and ensure atomicity. The process begins with implementation deployment, followed by upgrade proposal, authorization verification, proxy update, and post-upgrade validation.

The following sequence diagram illustrates the complete upgrade flow from the factory owner's initiation through the proxy's implementation pointer update:

Rendering chart...

This upgrade pattern ensures existing state remains intact while seamlessly transitioning to new logic. The old implementation contract remains deployed and accessible for historical reference, but the proxy redirects all future calls to the new implementation.

Rendering chart...

The upgrade proposal phase allows separation between deployment and execution. The system manager deploys the new implementation, registers it with the system, and validates its correctness. The actual upgrade execution occurs separately, after testing and review.

Multi-signature governance

Production deployments should protect upgrade authority with multi-signature wallets. Rather than assigning SYSTEM_MANAGER_ROLE to a single externally owned account, the role is granted to a multi-sig contract requiring multiple authorized signers to approve upgrades.

This governance structure prevents single points of compromise. An attacker who gains control of one signer's private key cannot unilaterally upgrade contracts. The multi-sig threshold (e.g., 3-of-5 signers) balances security with operational flexibility.

Time-locked upgrades provide additional security. The system manager proposes an upgrade, which enters a time-lock period (e.g., 48 hours) before execution. During this period, other signers review the proposal, the community is notified, and emergency procedures can halt the upgrade if issues are discovered.

Upgrade observability and auditing

Every upgrade emits detailed events captured by the observability stack. The ImplementationUpgraded event records the proxy address, old implementation address, new implementation address, upgrade timestamp, and executing manager address.

The subgraph indexes these events, building a complete upgrade history for every contract in the system. Auditors query this history to verify upgrade frequency, review upgrade authorization, and ensure upgrade procedures followed governance rules.

Observability dashboards display implementation version distributions across deployed contracts. These metrics identify contracts running outdated implementations, track upgrade adoption rates, and highlight potential security vulnerabilities in older versions requiring urgent upgrades.

Upgrade vs. immutability: pattern selection

Not all contracts should be upgradeable. Upgradeability introduces complexity, governance requirements, and potential security risks. The decision between upgradeable and immutable deployments depends on the contract's role, expected evolution, and risk tolerance.

When to use upgradeable contracts

Upgradeable contracts suit system infrastructure where requirements evolve over time. Core system components like the identity registry, compliance engine, and token factories benefit from upgradeability because regulatory requirements change, new features emerge, and bugs may require fixes.

Consider a scenario where a new regulatory requirement mandates additional investor disclosures. If token contracts are upgradeable, the system manager deploys an updated implementation with the new disclosure logic, upgrades all tokens, and achieves compliance without migrating state or changing token addresses.

System-level infrastructure should prioritize upgradeability. The ATK System, factory contracts, and registries use UUPS proxies because these components orchestrate the entire platform. Bugs in these contracts affect all deployed tokens; upgradeability provides a path to fix critical issues without redeploying the entire system.

When to use immutable contracts

Immutable contracts suit final, well-understood logic where changes would undermine trust. Individual compliance modules, mathematical libraries, and cryptographic functions often work better as immutable contracts because their correctness is provable and any modification raises security concerns.

Consider an immutable compliance module that checks whether an investor's country is permitted. This logic is simple, well-tested, and regulatory authorities may have reviewed and approved the exact bytecode deployed on-chain. Making it upgradeable introduces risk: an upgrade could silently weaken compliance rules without external visibility.

Individual token deployments may prefer immutability after a stabilization period. During initial issuance, upgradeability allows fixing bugs and adding features. Once the token has been live for months, operated correctly, and passed audits, the issuer might intentionally revoke upgrade privileges, making the contract permanently immutable. This commitment strengthens investor confidence by removing the risk of malicious upgrades.

Hybrid approach: factory-managed immutability

The ATK factory pattern enables a hybrid approach. Factories are upgradeable, but the tokens they deploy can be immutable. When requirements change, the factory is upgraded to deploy tokens with new logic. Existing tokens remain unchanged; new tokens incorporate the improvements.

This strategy suits scenarios where backward compatibility isn't required. New bond issuances use the latest compliance rules and yield calculation logic, while older bonds continue operating under their original rules. Investors in legacy bonds have certainty about unchanging behavior; new investors benefit from improved implementations.

Rendering chart...

Real-world upgrade scenarios

Understanding upgrade patterns requires examining specific scenarios where implementations must change. These scenarios illustrate when upgrades are necessary, how they are executed, and what risks they mitigate.

Scenario: regulatory compliance update

A jurisdiction introduces a new regulation requiring token transfers to include a reference identifier linking to a disclosure document. Existing token contracts do not support this field; adding it requires an implementation upgrade.

The system manager deploys a new token implementation extending the transfer function to accept an optional reference parameter. The implementation maintains backward compatibility by making the reference optional and defaulting to an empty value if not provided.

The upgrade proposal is submitted to the multi-signature governance wallet. During the review period, the new implementation is deployed to testnet, tested with representative transactions, and audited for storage layout compatibility. After 48 hours, the multi-sig signers approve the upgrade.

The system manager executes the upgrade across all tokens deployed through the factory. The subgraph indexes the upgrade events, and the observability dashboard confirms all tokens now run the updated implementation. Transfer transactions include the new reference field, and the system achieves regulatory compliance without disrupting existing token holders.

Scenario: security vulnerability patch

A security researcher discovers a reentrancy vulnerability in the yield distribution logic. The vulnerability allows an attacker to recursively call the distribution function, potentially draining contract funds.

The vulnerability is disclosed privately to the development team. An emergency patch is prepared, fixing the reentrancy vector by adding a reentrancy guard to affected functions. The patch is reviewed, tested against exploit scenarios, and verified to prevent the attack.

Because the contracts are upgradeable, the patch can be deployed immediately. If the contracts were immutable, the only remediation would be migrating all state to new contract addresses—a complex, expensive, and risky operation. The upgrade executes within hours of vulnerability disclosure, securing user funds without requiring manual migration.

Scenario: feature enhancement

A new feature enables automatic yield reinvestment. Token holders can opt into a program where distributed yields are automatically used to purchase additional tokens rather than being paid out as currency.

This feature requires new state variables to track opt-in status and new functions to process reinvestment transactions. The implementation is deployed, tested, and proposed for upgrade. Because the feature is additive, it does not affect existing functionality; token holders who do not opt in experience no behavior change.

The upgrade demonstrates the value of upgradeability for non-critical enhancements. The feature can be deployed to existing tokens without requiring users to migrate to new contracts. Adoption is gradual; as users opt in, they benefit from the new functionality while maintaining their existing token balances and addresses.

Scenario: gas optimization

After several months in production, gas profiling reveals that certain compliance check functions consume excessive gas. An optimized implementation reduces gas usage by 30% through algorithmic improvements and storage pattern changes.

The optimization maintains identical external behavior but changes internal implementation details. Because the contracts are upgradeable, this optimization can be deployed to all tokens, immediately reducing transaction costs for all users without requiring code changes in client applications or modifications to user workflows.

Upgrade safety mechanisms

Upgrades introduce risk. Incorrect implementations can corrupt state, break functionality, or introduce vulnerabilities. The ATK system includes multiple safety mechanisms to mitigate upgrade risks and ensure upgrade procedures follow best practices.

Storage gap patterns

Upgradeable contracts reserve storage slots for future variables using the storage gap pattern. Rather than tightly packing storage variables, implementations include a __gap array sized to leave room for future additions.

contract TokenImplementationV1 {
    address public admin;
    uint256 public totalSupply;
    mapping(address => uint256) public balances;

    // Reserve 50 slots for future variables
    uint256[47] private __gap;
}

When V2 adds a new variable, it reduces the gap size by the number of new slots:

contract TokenImplementationV2 is TokenImplementationV1 {
    uint256 public feeBasisPoints; // New variable

    // Gap reduced to maintain total slot count
    uint256[46] private __gap;
}

This pattern ensures new variables occupy slots beyond the original implementation's variables, preventing storage collisions and maintaining compatibility.

Upgrade authorization functions

UUPS proxies require implementation contracts to include an _authorizeUpgrade function. This function is called before upgrade execution and can implement custom authorization logic.

In the ATK system, _authorizeUpgrade verifies that the caller has SYSTEM_MANAGER_ROLE in the ATK System contract. This prevents unauthorized parties from upgrading contracts even if they somehow gain control of the proxy's upgrade function.

function _authorizeUpgrade(address newImplementation) internal override {
    require(
        atkSystem.hasRole(SYSTEM_MANAGER_ROLE, msg.sender),
        "Unauthorized upgrade"
    );
    emit UpgradeAuthorized(newImplementation, msg.sender);
}

Initialization version tracking

Upgrades may require re-initialization to set up new features. The Initializable contract tracks initialization versions through bit flags, allowing implementations to define which initialization functions have executed.

When V2 adds a feature requiring initialization, it defines an initializeV2 function with the reinitializer(2) modifier. This modifier ensures V2 initialization executes exactly once, regardless of how many times the contract is upgraded or downgraded.

function initializeV2(uint256 newFeatureParam) public reinitializer(2) {
    _newFeatureParam = newFeatureParam;
    _setupNewFeature();
}

Implementation validation

The ATK System validates implementation contracts before recording them in registries. Validation checks that the implementation address contains contract code, implements required interfaces, and matches expected type identifiers.

This validation prevents misconfigurations where the wrong implementation address is registered for a token type. For example, registering the bond implementation address as the equity factory implementation would cause equity deployments to fail. The validation step catches these errors before they affect production.

Observability integration

The observability stack tracks contract versions, upgrade events, and implementation distribution across deployed tokens. This visibility enables operators to monitor upgrade adoption, identify outdated contracts, and verify upgrade execution.

Version tracking metrics

The subgraph indexes every deployment and upgrade event, building a database of which implementation version each proxy is running. The observability dashboard displays implementation version distributions for each token type.

Operators query these metrics to answer questions like: "What percentage of bonds are running the latest implementation?" or "Which tokens still use the vulnerable V1.2 implementation?" This information informs upgrade planning and identifies contracts requiring urgent attention.

Upgrade event monitoring

Upgrade events flow through the observability pipeline. When an upgrade executes, the ImplementationUpgraded event is emitted, indexed by the subgraph, stored in PostgreSQL, and displayed on real-time dashboards.

Alerts trigger if upgrades occur outside maintenance windows, if unauthorized addresses attempt upgrades, or if upgrade execution fails. These alerts enable rapid response to unexpected upgrade activity or potential security incidents.

Gas cost analysis

Observability dashboards track gas costs for factory deployments and upgrade transactions. These metrics inform capacity planning: as gas prices fluctuate, operators monitor whether deployment costs remain within acceptable ranges.

Gas cost trends also reveal optimization opportunities. If deployment costs increase over time, profiling identifies which initialization steps consume excessive gas and guides implementation improvements to reduce costs.

Production deployment strategy

Production environments require careful planning for factory deployment, implementation management, and upgrade procedures. The following strategy minimizes risk while enabling ongoing system evolution.

Initial system deployment

Begin by deploying the ATK System Factory and creating a new system instance. The factory deploys the ATK System proxy and initializes it with the founding admin address. This admin should be a multi-signature wallet, not an individual externally owned account.

Once the system exists, execute the bootstrap process. Bootstrap deploys core infrastructure contracts: identity registry, compliance module registry, trusted issuer registry, claim topics registry, token factory registry, and addon registry. Bootstrap is a one-time operation per system instance; subsequent configuration uses registry functions.

After bootstrap, register factory contracts for each asset type. Deploy bond factory implementation, deploy bond factory proxy, initialize factory with ATK System address, register factory in token factory registry. Repeat for equity, fund, deposit, and stablecoin factories.

Rendering chart...

Upgrade testing procedures

Never upgrade production implementations without comprehensive testing. Begin by deploying the new implementation to testnet. Execute representative transactions: token transfers, compliance checks, yield distributions, and administrative functions. Compare gas costs, verify state changes, and ensure no regressions.

Deploy the new implementation to a staging environment that mirrors production configuration. Perform upgrade dry runs on staging proxies, validate post-upgrade state, and test rollback procedures. Only after staging validation should production upgrades be considered.

Phased upgrade rollout

For large-scale upgrades affecting many tokens, phase the rollout. Begin by upgrading a small subset of tokens (e.g., internal test tokens or low-value assets). Monitor these tokens for issues over 24-48 hours. If no problems emerge, upgrade additional tokens in larger batches.

Phased rollout limits blast radius. If the upgrade introduces a subtle bug, only early-phase tokens are affected. The remaining tokens stay on the old implementation until the bug is fixed. This strategy prevents system-wide failures from untested implementation changes.

Rollback procedures

Despite careful testing, upgrades may need reverting. The UUPS pattern supports rollback: the proxy can be re-pointed to the previous implementation address. Rollback procedures should be documented, tested, and ready to execute on short notice.

Rollback decisions depend on the nature of the issue. If the upgrade corrupts state or introduces a critical vulnerability, immediate rollback is appropriate. If the upgrade merely degrades performance or introduces non-critical bugs, a scheduled rollback after user notification may be preferable.

Conclusion

Factory patterns and upgradeable proxies form the foundation of the ATK system's deployment and evolution infrastructure. Factories ensure consistent, auditable token deployment with deterministic addressing and standardized initialization. Upgradeable proxies enable the system to evolve—fixing bugs, adding features, and adapting to regulatory changes—without disrupting deployed tokens or requiring state migration.

This architecture balances flexibility with security. Centralized upgrade management through the ATK System prevents unauthorized modifications while enabling coordinated upgrades across all system components. Multi-signature governance and time-locked upgrades provide additional safety, ensuring upgrades cannot be executed unilaterally.

The choice between upgradeable and immutable contracts depends on context. System infrastructure benefits from upgradeability for ongoing evolution; individual tokens may transition to immutability after stabilization to maximize trust. The factory pattern enables both approaches, allowing new tokens to use improved implementations while legacy tokens remain unchanged.

Observability integration ensures visibility into deployment patterns, implementation versions, and upgrade history. Operators monitor upgrade adoption, track contract versions, and verify upgrade procedures follow governance rules. This visibility supports audit requirements and informs operational decisions.

Together, these patterns enable the ATK system to operate as production infrastructure for regulated financial instruments—secure enough for institutional adoption, flexible enough to evolve with regulatory requirements, and observable enough to meet enterprise operational standards.

Addon modules
Frontend design
llms-full.txt

On this page

Factory contract architectureDeployment consistency guaranteesDeployment discovery and trackingToken factory registryRegistry-based factory discoveryRegistry access controlFactory versioning and updatesUpgradeable proxy architectureProxy delegation mechanismStorage layout compatibilityInitialization protectionUpgrade authorization and governanceCentralized upgrade managementUpgrade execution flowMulti-signature governanceUpgrade observability and auditingUpgrade vs. immutability: pattern selectionWhen to use upgradeable contractsWhen to use immutable contractsHybrid approach: factory-managed immutabilityReal-world upgrade scenariosScenario: regulatory compliance updateScenario: security vulnerability patchScenario: feature enhancementScenario: gas optimizationUpgrade safety mechanismsStorage gap patternsUpgrade authorization functionsInitialization version trackingImplementation validationObservability integrationVersion tracking metricsUpgrade event monitoringGas cost analysisProduction deployment strategyInitial system deploymentUpgrade testing proceduresPhased upgrade rolloutRollback proceduresConclusion