eip: TBC
title: Anywhere Door - Fully Mutable Smart Contracts with Bytecode Activation
author: hiddenintheworld.eth (@hiddenintheworld)
discussions-to:
status: Draft
type: Standards Track
category: ERC
created: 2024-01-22
requires: None
Simple Summary
Inspired by “Doraemon’s” magical “Anywhere Door,” this EIP introduces a novel framework for smart contracts, enabling the dynamic addition, removal, or modification of ‘doors’ (functionalities) at any time post-deployment. This concept provides a level of full mutability in smart contracts, complemented by a mechanism for user-submitted door proposals and distinctions between mutable and immutable doors, achieved through “Bytecode Activation.”
Abstract
The “Anywhere Door” EIP proposes a smart contract architecture that allows for on-the-fly “Bytecode Activation,” enabling dynamic toggling of contract functionalities (referred to as ‘doors’) and state variables. Users can submit new functionalities as door proposals, which authorized parties can activate, deactivate, or mark as immutable. This approach ensures full mutability of the smart contract while preserving the ability to set specific doors as immutable, offering both adaptability and stability within the contract’s ecosystem.
Motivation
In the rapidly evolving world of decentralized applications, the need for smart contracts that can dynamically adapt to changing requirements and community inputs is paramount. The “Anywhere Door” EIP addresses this need by providing a mutable framework that supports immediate updates and modifications, without the overhead of redeployment. This ability to dynamically add or remove functionalities, as well as to toggle them on and off, fosters innovation and ensures efficiency and adaptability in smart contract development.
Specification
The following diagram (Figure 1) provides a comprehensive view of the Anywhere Door smart contract ecosystem. This flowchart visually represents the interconnected nature of doors across various smart contracts, demonstrating how they can be linked and interact with each other.
Each door is depicted with indicators (ticks and crosses) to signify their status (active/inactive or open/closed), and arrows or lines show the potential pathways or links between doors across different contracts. This architectural diagram highlights the versatility and complexity of the Anywhere Door system, emphasizing its capability to create a network of dynamic, interlinked functionalities across the blockchain landscape.
Figure 1 : Anywhere Door overall architecture
The following flowchart (Figure 2) illustrates the workflow for handling door proposals and updating door configurations in the smart contract. The process involves determining if the door is mutable, whether the user is the owner, and then either storing the door proposal or updating the door’s status.
Figure 2: Door Proposal and Update Mechanism
The following flowchart (Figure 3) demonstrates how the Anywhere Door functions as a proxy, determining the active status of doors and deciding the execution path. It starts with checking if a door is active (open or closed). If closed, it throws an error. If open, it checks for more doors, looping through the process until it reaches a door that is the final execution point.
Figure 3: Flowchart of Door Execution and Proxy Routing
Contract Storage:
-
mapping(bytes4 => address) public doorToImplementation;
: Maps door selectors to contract addresses for their implementation. -
mapping(bytes4 => bool) public doorActive;
: Indicates whether a door is currently active or inactive. -
mapping(bytes4 => bool) public doorImmutable;
: Denotes if a door is immutable.
Door Submission, Addition, and Update Mechanism:
- Users can propose new doors by submitting their intended door selector and implementation details.
- The contract owner can directly activate, deactivate, or update doors, providing a responsive approach to contract management.
- Essential doors can be marked as immutable upon activation, ensuring their permanence.
Door Calls:
The “Anywhere Door” contract handles incoming calls by determining the appropriate door to execute based on the call’s signature. It follows a structured process to decide how to handle each call:
- Identify the Target Door: The contract first identifies which door (functionality) is being called by examining the incoming call’s signature. This is matched against the
doorToImplementation
mapping to find the corresponding contract address. - Check Door Status: Before proceeding with execution, the contract checks the door’s status in
doorActive
. If the door is inactive, the call is rejected, and an error is thrown. This step ensures that only active doors can process calls. - Execution through Delegate Call: For active doors, the contract uses Ethereum’s
delegatecall
to execute the linked function’s bytecode. This allows the door’s code to execute in the context of the original contract, maintaining the contract’s state and allowing the door to interact seamlessly with other parts of the contract. - Handle Immutable Doors: If the door is marked as immutable in
doorImmutable
, any attempts to modify its implementation or status (apart from activation or deactivation) are rejected. This ensures the integrity and permanence of essential functionalities.
Rationale
- The “Anywhere Door” concept, combined with “Bytecode Activation,” introduces unprecedented flexibility and efficiency in smart contract management.
- This EIP represents a significant advancement in smart contract technology by enabling full mutability, yet accommodating the option for immutable functionalities.
- The framework suits a broad spectrum of use cases, offering both adaptability for evolving requirements and stability for core operations.
Security Considerations
- Ensuring the integrity and security of submitted door proposals and bytecode is crucial; robust verification processes are necessary.
- The management of door activation and immutability status must be handled meticulously to prevent any inadvertent alterations.
- Adherence to standard security practices in smart contract development is essential, with an emphasis on the mutable aspects of the contract.
Backwards Compatibility
- This EIP introduces a novel paradigm in smart contract functionality management, significantly differing from traditional models and existing standards like EIP-2535.
Implementation
This implementation provides a Solidity example of the Anywhere Door contract. It includes functions for proposing, setting, and toggling door functionalities. The contract owner has the authority to accept proposals, update door functionalities, and toggle their active status.
pragma solidity ^0.8.0;
contract AnywhereDoor {
address public owner;
mapping(bytes4 => address) public doorToImplementation;
mapping(bytes4 => bool) public doorActive;
mapping(bytes4 => bool) public doorImmutable;
struct DoorProposal {
address implementation;
bool isActive;
bool isImmutable;
}
mapping(bytes4 => DoorProposal) public proposedDoors;
constructor() {
owner = msg.sender;
}
modifier onlyOwner() {
require(msg.sender == owner, "Only owner can call this function.");
_;
}
function proposeOrSetDoorImplementation(bytes4 doorSelector, address implementation, bool isActive, bool isImmutable) external {
require(!doorImmutable[doorSelector], "Cannot modify immutable door.");
if (msg.sender == owner) {
doorToImplementation[doorSelector] = implementation;
doorActive[doorSelector] = isActive;
doorImmutable[doorSelector] = isImmutable;
} else {
proposedDoors[doorSelector] = DoorProposal(implementation, isActive, isImmutable);
}
}
function acceptDoorProposal(bytes4 doorSelector) external onlyOwner {
DoorProposal memory proposal = proposedDoors[doorSelector];
require(proposal.implementation != address(0), "Proposal does not exist.");
doorToImplementation[doorSelector] = proposal.implementation;
doorActive[doorSelector] = proposal.isActive;
doorImmutable[doorSelector] = proposal.isImmutable;
}
function toggleDoorActive(bytes4 doorSelector, bool isActive) external onlyOwner {
require(!doorImmutable[doorSelector], "Cannot modify immutable door.");
doorActive[doorSelector] = isActive;
}
fallback() external {
address implementation = doorToImplementation[msg.sig];
bool isActive = doorActive[msg.sig];
require(implementation != address(0) && isActive, "Door inactive or does not exist.");
assembly {
calldatacopy(0, 0, calldatasize())
let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)
returndatacopy(0, 0, returndatasize())
switch result
case 0 { revert(0, returndatasize()) }
default { return(0, returndatasize()) }
}
}
}
Copyright
Copyright and related rights waived via CC0.