Skip to main content

SDK Extensions Development

Guidance for SDK Extension Developers

If you are creating new extensions:

  1. Inherit first from BaseMiddleware (which also serves as BaseExtension) to gain access to internal VaultManager, OperatorManager, AccessManager, and KeyManager functions, or from one of the extendable managers such as KeyManager, CaptureTimestampManager, AccessManager, or StakePowerManager.
  2. Follow ERC-7201 storage standards to avoid storage collisions.
  3. Include a uint64 public constant {YourExtensionName}_VERSION = 1; variable for off-chain detection and indexing by dashboards.
  4. If your extension needs initialization, write __{ExtensionName}_init and use onlyInitializing.
  5. Try to avoid signature collisions with other extensions. If possible, consider how your extension might integrate with or complement existing ones.
  6. Provide hooks for customization in your extension. This allows middleware developers to add or replace logic as needed.
contract MyExtension is BaseMiddleware, SomeExtension {
uint64 public constant MY_EXTENSION_VERSION = 1;

struct MyExtensionStorage {
...
}

// keccak256(abi.encode(uint256(keccak256("symbiotic.storage.MyExtension")) - 1)) & ~bytes32(uint256(0xff))
bytes32 private constant MyExtensionStorageLocation =
0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef;

function _getMyExtensionStorage() internal pure returns (MyExtensionStorage storage $) {
bytes32 location = MyExtensionStorageLocation;
assembly {
$.slot := location
}
}

function __MyExtension_init() internal onlyInitializing {
...
}

function doSomething() external {
_beforeDoSomething();
_someBaseMiddlewareInternalFunction();
...
}

function _beforeDoSomething() internal virtual {
...
}
}