Skip to main content

Fallback Modules

Overview​

Fallback modules (IFallback) handle unknown function calls and provide default behavior for smart accounts, particularly useful for token reception and custom fallback logic.

Interface Definition​

interface IFallback is IModule {
// Core module functions inherited from IModule
}

Implementation Example: Token Receiver Fallback​

Based on the provided MockDefaultFallback implementation:

contract TokenReceiverFallback is 
IERC721Receiver,
IERC1155Receiver,
IFallback
{
// Interface IDs
bytes4 private constant _INTERFACE_ID_ERC721_RECEIVER =
type(IERC721Receiver).interfaceId;
bytes4 private constant _INTERFACE_ID_ERC1155_RECEIVER =
type(IERC1155Receiver).interfaceId;
bytes4 private constant _INTERFACE_ID_ERC165 = type(IERC165).interfaceId;

// Events
event ERC721Received(
address operator,
address from,
uint256 tokenId,
bytes data
);
event ERC1155Received(
address operator,
address from,
uint256 id,
uint256 value,
bytes data
);
event ERC1155BatchReceived(
address operator,
address from,
uint256[] ids,
uint256[] values,
bytes data
);

// Interface support check
function supportsInterface(
bytes4 interfaceId
) external view virtual returns (bool) {
return
interfaceId == _INTERFACE_ID_ERC721_RECEIVER ||
interfaceId == _INTERFACE_ID_ERC1155_RECEIVER ||
interfaceId == _INTERFACE_ID_ERC165;
}

// Token reception handlers
function onERC721Received(
address operator,
address from,
uint256 tokenId,
bytes calldata data
) external override returns (bytes4) {
emit ERC721Received(operator, from, tokenId, data);
return this.onERC721Received.selector;
}

function onERC1155Received(
address operator,
address from,
uint256 id,
uint256 value,
bytes calldata data
) external override returns (bytes4) {
emit ERC1155Received(operator, from, id, value, data);
return this.onERC1155Received.selector;
}

function onERC1155BatchReceived(
address operator,
address from,
uint256[] calldata ids,
uint256[] calldata values,
bytes calldata data
) external override returns (bytes4) {
emit ERC1155BatchReceived(operator, from, ids, values, data);
return this.onERC1155BatchReceived.selector;
}

// Core Module Functions
function onInstall(bytes calldata) external override {}

function onUninstall(bytes calldata) external override {}

function isModuleType(uint256 moduleTypeId) external view returns (bool) {
return moduleTypeId == MODULE_TYPE_FALLBACK;
}

function isInitialized(address) external pure returns (bool) {
return true;
}
}

Extended Implementation: Logging Fallback​

contract LoggingFallback is IFallback {
// Events for tracking unknown calls
event UnknownCallReceived(
address indexed sender,
uint256 value,
bytes data
);

event FallbackExecuted(
address indexed sender,
bool success,
bytes result
);

// State tracking
mapping(address => uint256) public callCount;
mapping(bytes4 => bool) public knownSelectors;

function handleUnknownCall(
address sender,
uint256 value,
bytes calldata data
) external returns (bool, bytes memory) {
// Log the unknown call
emit UnknownCallReceived(sender, value, data);

// Update call statistics
callCount[sender]++;

// Handle or forward the call as needed
return (true, "");
}
}

Common Use Cases​

  1. Token Reception

    • ERC721 token handling
    • ERC1155 token handling
    • Custom token support
  2. Fallback Behavior

    • Unknown call logging
    • Default responses
    • Call forwarding
  3. Security Features

    • Call filtering
    • Access control
    • Activity monitoring

Security Considerations​

  1. Token Handling

    • Safe token reception
    • Proper event emission
    • State consistency
  2. Unknown Calls

    • Parameter validation
    • Selective handling
    • Safe execution
  3. Access Control

    • Call authorization
    • Value handling
    • State protection

Best Practices​

  1. Implementation Guidelines

    • Complete interface support
    • Proper event emission
    • Clear documentation
  2. Error Handling

    • Graceful fallbacks
    • Clear error messages
    • State validation
  3. Gas Optimization

    • Efficient storage
    • Minimal operations
    • Clear patterns

Special Considerations​

  1. Token Standards

    • Support multiple standards
    • Proper interface declaration
    • Complete implementation
  2. Unknown Calls

    • Safe handling
    • Proper logging
    • Clear responses
  3. State Management

    • Consistent updates
    • Safe operations
    • Clear tracking