Smart contracts deployed to Ethereum are, in theory, immutable. Bytecode is uploaded, a constructor function is executed, and the resulting code is stored on the blockchain and cannot be updated.
But in practice, contract execution is mutable.
Smart contracts can be mutated in different ways:
- Delete a contract through the
SELFDESTRUCT
opcode (and potentially re-upload different bytecode at the same address) - Call another contract's code with
DELEGATECALL
- Store the code in state and execute it using
CREATE2
In Solana, programs can be marked as upgradable and have a more straightforward upgrade pattern.
The mutability of programs makes sense for developers – bug fixes, patches, and new functionality can be implemented without making clients upgrade. However, the lack of versioning and the near (but not quite) immutability of programs creates problems for developers that depend on other contracts and security issues for customers who don't trust the owner but trust the code.
Some thoughts on alternative models:
- Automatic and semantic versioning (with content-addressed checksumming).
- Limits on external calls and execution
- True immutability for certain stateless contracts – utility contracts that cannot be deleted, modified, and don't rely on the internal state.