
SuMo (Solidity Mutator) is a mutation-testing framework designed to evaluate the effectiveness of test suites for Solidity smart contracts. It automatically generates mutants, synthetic variations of a contract that simulate common faults, and then executes the project’s existing tests against these modified versions. By measuring which mutants are “killed” (detected by tests), SuMo quantifies the fault-detection capability of the test suite through the mutation score.
Unlike general-purpose mutation tools, SuMo incorporates a rich set of Solidity-specific mutation operators, capturing typical programming errors such as address misuses, or event emission faults. It integrates seamlessly with popular smart-contract development environments (e.g., Hardhat, Foundry, Brownie) and supports automated reporting of mutation results.
Overall, SuMo contributes to higher reliability in decentralized applications by helping developers identify weakly tested contract behaviors.

Usage
This is the main SuMo repository, containing the complete source code of the tool, configuration examples, and full documentation. It provides detailed descriptions of all implemented mutation operators, and instructions for installing and running SuMo.
The demo repository provides a ready-to-use example of SuMo applied to a sample Solidity project. It includes a minimal smart contract, a configured testing framework, and a prebuilt SuMo configuration file. This repository is ideal to explore SuMo’s workflow, visualize mutation results, or experiment with different operator configurations.
The official NPM package allows users to install SuMo directly into their Solidity projects using the Node.js ecosystem.
SuMo was designed to run mutation testing on NodeJS Solidity projects. It can run test using Truffle, Hardhat, Brownie and Forge.
Mutation Operators
Traditional Mutation Operators
| Operator | Name | Mutation Example | Enabled by Default | Minimal Available |
|---|---|---|---|---|
| ACM | Argument Change of overloaded Method call | overloadedFunc(a,b); → overloadedFunc(a,b,c); | Y | N |
| AOR | Assignment Operator Replacement | += → = | Y | N |
| BCRD | Break and Continue Replacement and Deletion | break →continue → break | Y | N |
| BLR | Boolean Literal Replacement | true → false | Y | N |
| BOR | Binary Operator Replacement | + → -< → >= | Y | Y |
| CBD | Catch Block Deletion | catch{} → | Y | N |
| CSC | Conditional Statement Change | if(condition) → if(false)else{} → | Y | N |
| ER | Enum Replacemet | enum.member1 → enum.member2 | Y | Y |
| ECS | Explicit Conversion to Smaller type | uint256 → uint8 | Y | N |
| FCD | Function Call Deletion | foo() → | Y | N |
| HLR | Hexadecimal Literal Replacement | hex\"01\" → hex\"random\" | Y | N |
| ILR | Integer Literal Replacement | 1 → 0 | Y | N |
| LCS | Loop Statement Change | while(condition) → while(false) | Y | N |
| OLFD | Overloaded Function Deletion | function overloadedF(){} → | Y | N |
| ORFD | Overridden Function Deletion | function f() override {} → | Y | N |
| SKR | Super Keyword Replacement | x = getData() → x = super.getData() | Y | N |
| SLR | String Literal Replacement | "string" → "" | Y | N |
| UORD | Unary Operator Replacement and Deletion | ++ → --! → | Y | Y |
Solidity Mutation Operators
| Operator | Name | Mutation Example | Enabled by Default | Minimal version available |
|---|---|---|---|---|
| AVR | Address Value Replacement | 0x67ED2e5dD3d0... → address.this() | Y | Y |
| CCD | Contract Constructor Deletion | constructor(){} → | Y | N |
| DLR | Data Location Keyword Replacement | memory → storage | N | N |
| DOD | Delete Operator Deletion | delete → | Y | N |
| ETR | Ether Transfer function Replacement | delegatecall() → call() | Y | Y |
| EED | Event Emission Deletion | emit Deposit(...) → /*emit Deposit(...)*/ | Y | N |
| EHD | Exception Handling Deletion | require(...) → /*require(...)*/ | Y | N |
| FVR | Function Visibility Replacement | function f() public → function f() private | N | Y |
| GVR | Global Variable Replacement | msg.value() → tx.gasprice() | Y | Y |
| MCR | Mathematical and Cryptographic function Replacement | addmod → mulmodkeccak256 → sha256 | Y | Y |
| MOD | Modifier Deletion | function f() onlyOwner → function f() | Y | Y |
| MOI | Modifier Insertion | function f() → function f() onlyOwner | N | Y |
| OMD | Overridden Modifier Deletion | modifier m() override {} → | Y | N |
| PKD | Payable Keyword Deletion | function f() payable → function f() | Y | N |
| RSD | Return Statement Deletion | return amount; → //return amount; | Y | N |
| RVS | Return Values Swap | return (1, "msg", 100); → return (100, "msg", 1); | Y | Y |
| SCD | Selfdestruct Call Deletion | selfdestruct(); → //selfdestruct(); | Y | N |
| SFR | SafeMath Function Replacement | SafeMath.add → SafeMath.sub | Y | Y |
| SCEC | Switch Call Expression Casting | Contract c = Contract(0x86C9...); → Contract c = Contract(0x67ED...); | Y | N |
| TOR | Transaction Origin Replacement | msg.sender → tx.origin | Y | N |
| VUR | Variable Unit Replacement | wei → etherminutes → hours | Y | Y |
| VVR | Variable Visibility Replacement | uint private data; → uint public data; | N | Y |