Skip to content

Repository files navigation

FeverTokens Packages

🔍 Overview

The FeverTokens Package-Oriented Framework is a composable smart contract architecture based on the EIP-2535 Diamond Standard. It provides a structured and modular approach for building scalable, upgradable, and reusable smart contract packages tailored to institutional and mission-critical systems.

By following a strict separation of concerns, this framework makes smart contracts:

  • Easier to audit and maintain

  • Highly composable and upgradable

  • Compatible with tooling for version management and deployment

  • Ready for integration into larger smart contract systems using the FeverTokens Hub


💎 Diamond Architecture Principles

Each package is a modular facet of a Diamond and adheres to the following design principles:

  • Separation of Concerns: Interfaces, logic, and storage are explicitly decoupled.

  • Interface Definitions: Cleanly specified internal and external interfaces for integration and documentation.

  • Storage Management: Explicit and namespaced layout management using custom storage slots.

  • Upgradeable Logic: Built to support safe upgrades via the Diamond proxy architecture.


📦 Package Structure

Each package must include five distinct components, each as a separate file:

FilePurpose
IMyPackageInternal.solInternal interface: declares events, structs, enums
IMyPackage.solExternal interface: defines externally callable functions
MyPackageStorage.solStorage layout using diamond storage pattern
MyPackageInternal.solInternal logic: uses and modifies package storage
MyPackagePackage.solExternal-facing contract: wraps internal logic

🔹 Internal Interface – IMyPackageInternal.sol

Defines the internal elements of the package: enums, structs, events, and errors.

interfaceIMyPackageInternal {
enum MyEnum {
Option1,
Option2
}
struct MyStruct1 {
uint256 value;
address addr;
}
struct MyStruct2 {
bool active;
uint256 count;
}
event MyEvent1(addressindexedsender, uint256value);
event MyEvent2(addressindexedactor, boolaction);
}

🔹 External Interface – IMyPackage.sol

Inherits the internal interface and exposes external functions.

import'./IMyPackageInternal.sol';
interfaceIMyPackageisIMyPackageInternal {
function myFunction1(uint256value1) external;
function myFunction2(addressaddr, uint256value2) external;
}

🔹 Storage Layout – MyPackageStorage.sol

Encapsulates the state in a Layout struct, using a dedicated slot for namespacing based on ERC-7201.

import'./IMyPackageInternal.sol';
libraryMyPackageStorage {
struct Layout {
uint256 value1;
address addr1;
uint256 value2;
MyStruct1 myObject1;
bool active;
}
bytes32constant STORAGE_SLOT =keccak256(abi.encode(uint256(keccak256('company.storage.MyPackage')) -1)) &~bytes32(uint256(0xff));
function layout() internalpurereturns (Layout storagel) {
bytes32 slot = STORAGE_SLOT;
assembly {
l.slot := slot
}
}
}

🔹 Internal Logic – MyPackageInternal.sol

Implements the core business logic using the namespaced storage.

import'./IMyPackageInternal.sol';
import { MyPackageStorage } from'./MyPackageStorage.sol';
abstractcontractMyPackageInternalisIMyPackageInternal {
using MyPackageStoragefor MyPackageStorage.Layout;
function _myFunction1(uint256value1) internal {
MyPackageStorage.Layout storage l = MyPackageStorage.layout();
// Logic using l.value1
}
function _myFunction2(addressaddr, uint256value2) internal {
MyPackageStorage.Layout storage l = MyPackageStorage.layout();
// Logic using l.addr1 and l.value2
}
}

🔹 Package Entry Point – MyPackage.sol

Implements external interface and delegates to internal logic.

import {IMyPackage} from "./IMyPackage.sol";
import {MyPackageInternal} from "./MyPackageInternal.sol";
contract MyPackagePackage is IMyPackage, MyPackageInternal {
function myFunction1(uint256 value1_) external override {
_myFunction1(value1_);
}
function myFunction2(address addr_, uint256 value2_) external override {
_myFunction2(addr_, value2_);
}
}

✅ Best Practices

  • Function naming: Prefix internal functions with _ (e.g., _myFunction1) for clarity.

  • External function implementation: Avoid direct calls to internal functions; always use the _ prefixed versions. Use override to ensure compliance with the interface.

  • Parameter naming: Use trailing underscores (e.g., value1_) to avoid variable shadowing.

  • Testing: Unit-test each package and integration-test multiple packages as part of a system.

  • Documentation: Comment the purpose and logic of each package, especially for critical functions.

  • Storage safety: Never change the order or type of variables in a layout struct once deployed.


🚀 Create Your Own Package (Quick Guide)

  1. Define internal elements in IMyPackageInternal.sol:

    • Enums, structs, events
  2. Define external interface in IMyPackage.sol:

    • Extend the internal interface

    • Declare externally accessible functions

  3. Create a storage layout in MyPackageStorage.sol:

    • Add a namespaced Layout struct

    • Declare the storage slot using keccak256

  4. Implement internal logic in MyPackageInternal.sol:

    • Use the layout via MyPackageStorage.layout()

    • Implement internal helper methods

  5. Build your package in MyPackagePackage.sol:

    • Inherit from IMyPackage and MyPackageInternal

    • Implement external methods by calling internal functions


📚 License

Open-source under the Apache License 2.0. You are free to use, modify, and integrate in compliance with the license.

About

Modular, upgradeable smart contracts using a package-oriented framework built on the EIP-2535 Diamond Standard.

Resources

Contributing

Stars

2 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages