Create Core Contract

Installation

Install Forge from Foundry and add the modular contract framework:

forge init
forge install https://github.com/thirdweb-dev/modular-contracts.git
forge remappings > remappings.txt

Setup Core Contract

  • Create a Core Contract

    Create a new file in the src folder called CounterCore.sol, and inherit the Core contract.

    // SPDX-License-Identifier: UNLICENSED
    pragma solidity ^0.8.20;
    import {Core} from "modular-contracts/src/Core.sol";
    contract CounterCore is Core {
    constructor(address owner) {
    _initializeOwner(owner);
    }
    }

    Note
    The Core contract is the base contract that needs to be inherited for this contract to be recognized as a core contract.

  • Set Up Increment Function

    Define a function to increment a counter.

    // SPDX-License-Identifier: UNLICENSED
    pragma solidity ^0.8.20;
    import {Core} from "modular-contracts/src/Core.sol";
    contract CounterCore is Core {
    uint256 public count;
    constructor(address owner) {
    _initializeOwner(owner);
    }
    function increment() public {
    count += 1;
    }
    }
  • Add a Callback Function

    Introduce the _beforeIncrement function to use the beforeIncrement callback from a module.

    Note
    Callback functions are hook-like functionalities that can be used before or after the main functionality of a core contract.
    In this example, the beforeIncrement callback is executed before the main increment functionality.

    // SPDX-License-Identifier: UNLICENSED
    pragma solidity ^0.8.20;
    import {Core} from "modular-contracts/src/Core.sol";
    interface BeforeIncrementCallback {
    function beforeIncrement(uint256 count) external returns (uint256);
    }
    contract CounterCore is Core {
    uint256 public count;
    constructor(address owner) {
    _initializeOwner(owner);
    }
    function increment() public {
    uint256 newCount = _beforeIncrement(count);
    count = newCount;
    }
    function _beforeIncrement(
    uint256 count
    ) internal returns (uint256 newCount) {
    (, bytes memory returndata) = _executeCallbackFunction(
    BeforeIncrementCallback.beforeIncrement.selector,
    abi.encodeCall(BeforeIncrementCallback.beforeIncrement, (count))
    );
    newCount = abi.decode(returndata, (uint256));
    }
    }
  • Implement Supported Functions

    Implement the getSupportedCallbackFunctions and supportsInterface functions to expose which callback functions and interfaces this core contract supports.

    // SPDX-License-Identifier: UNLICENSED
    pragma solidity ^0.8.20;
    import {Core} from "modular-contracts/src/Core.sol";
    interface BeforeIncrementCallback {
    function beforeIncrement(uint256 count) external returns (uint256);
    }
    contract CounterCore is Core {
    uint256 public count;
    constructor(address owner) {
    _initializeOwner(owner);
    }
    function increment() public {
    uint256 newCount = _beforeIncrement(count);
    count = newCount;
    }
    function getSupportedCallbackFunctions()
    public
    pure
    override
    returns (SupportedCallbackFunction[] memory supportedCallbackFunctions)
    {
    supportedCallbackFunctions = new SupportedCallbackFunction ;
    supportedCallbackFunctions[0] = SupportedCallbackFunction({
    selector: BeforeIncrementCallback.beforeIncrement.selector,
    mode: CallbackMode.REQUIRED
    });
    }
    function supportsInterface(bytes4 interfaceId)
    public
    view
    override
    returns (bool)
    {
    return
    interfaceId == 0x00000001 || super.supportsInterface(interfaceId);
    }
    function _beforeIncrement(
    uint256 count
    ) internal returns (uint256 newCount) {
    (bool success, bytes memory returndata) = _executeCallbackFunction(
    BeforeIncrementCallback.beforeIncrement.selector,
    abi.encodeCall(BeforeIncrementCallback.beforeIncrement, (count))
    );
    newCount = abi.decode(returndata, (uint256));
    }
    }

This guide will help you create a core contract that can increment a counter with optional callback functions for additional modular functionality.