Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generate interface code in new slither.utils.code_generation #1730

Merged
merged 23 commits into from
Mar 22, 2023
Merged
Changes from 14 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
197ccb1
Add `Function.interface_signature_str`
webthethird Mar 8, 2023
4da0fb5
Add `Structure.interface_def_str`
webthethird Mar 8, 2023
6a2250f
Add `Contract.generate_interface`
webthethird Mar 8, 2023
772710c
Fix typo
webthethird Mar 8, 2023
9e70c3f
Fix typo
webthethird Mar 8, 2023
9238efc
Change contract type to address in `interface_signature_str`
webthethird Mar 8, 2023
289bd49
Black format
webthethird Mar 8, 2023
5a25c81
Locally import Contract to resolve pylint
webthethird Mar 14, 2023
0df2c23
Include events in `Contract.generate_interface`
webthethird Mar 14, 2023
c507b3b
Move code generation to a new util
webthethird Mar 14, 2023
67ece63
Revert unnecessary imports
webthethird Mar 14, 2023
6284e0a
Pylint and black
webthethird Mar 15, 2023
631f124
Include custom errors in `generate_interface`
webthethird Mar 15, 2023
c536b7c
Merge remote-tracking branch 'crytic/slither/dev' into dev-generate-i…
webthethird Mar 16, 2023
4d8181e
Check `contract.functions_entry_points` instead of `function.visibility`
webthethird Mar 17, 2023
4dfe457
Update docstring
webthethird Mar 17, 2023
1d35316
Use `convert_type_for_solidity_signature_to_string`
webthethird Mar 20, 2023
2c30d46
Minor formatting
webthethird Mar 20, 2023
dd1b2a8
Add test for interface code generation
webthethird Mar 20, 2023
b0dcc57
Add test for interface code generation
webthethird Mar 20, 2023
b78fa7f
Unwrap parameters as well
webthethird Mar 20, 2023
7532baa
Finish testing interface generation
webthethird Mar 20, 2023
6d68571
Pylint and black
webthethird Mar 20, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 96 additions & 0 deletions slither/utils/code_generation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
# Functions for generating Solidity code
from typing import TYPE_CHECKING, Optional

from slither.core.declarations.contract import Contract
from slither.core.solidity_types.user_defined_type import UserDefinedType

if TYPE_CHECKING:
from slither.core.declarations import Function, Structure


def generate_interface(contract: "Contract") -> str:
"""
Generates code for a Solidity interface to the contract.
Args:
contract: A Contract object

Returns:
A string with the code for an interface, with function stubs for all public or external functions and
state variables, as well as any events or structs declared in the contract.
"""
interface = f"interface I{contract.name} {{\n"
for event in contract.events:
name, args = event.signature
interface += f" event {name}({','.join(args)});\n"
for error in contract.custom_errors:
interface += f" error {error.solidity_signature};\n"
for struct in contract.structures:
interface += generate_struct_interface_str(struct)
for var in contract.state_variables_entry_points:
interface += f" function {var.signature_str.replace('returns', 'external returns ')};\n"
for func in contract.functions_entry_points:
if func.is_constructor or func.is_fallback or func.is_receive:
continue
interface += f" function {generate_interface_function_signature(func)};\n"
interface += "}\n\n"
return interface


def generate_interface_function_signature(func: "Function") -> Optional[str]:
"""
Generates a string of the form:
func_name(type1,type2) external {payable/view/pure} returns (type3)

Args:
func: A Function object

Returns:
The function interface as a str (contains the return values).
Returns None if the function is private or internal, or is a constructor/fallback/receive.
"""

name, parameters, return_vars = func.signature
visibility = func.visibility
if (
webthethird marked this conversation as resolved.
Show resolved Hide resolved
visibility in ["private", "internal"]
or func.is_constructor
or func.is_fallback
or func.is_receive
):
return None
view = " view" if func.view else ""
pure = " pure" if func.pure else ""
payable = " payable" if func.payable else ""
returns = [
"address"
if isinstance(ret.type, UserDefinedType) and isinstance(ret.type.type, Contract)
else str(ret.type)
for ret in func.returns
]
_interface_signature_str = (
name + "(" + ",".join(parameters) + ") external" + payable + pure + view
)
if len(return_vars) > 0:
_interface_signature_str += " returns (" + ",".join(returns) + ")"
return _interface_signature_str


def generate_struct_interface_str(struct: "Structure") -> str:
"""
Generates code for a structure declaration in an interface of the form:
struct struct_name {
elem1_type elem1_name;
elem2_type elem2_name;
... ...
}
Args:
struct: A Structure object

Returns:
The structure declaration code as a string.
"""
definition = f" struct {struct.name} {{\n"
for elem in struct.elems_ordered:
definition += f" {elem.type} {elem.name};\n"
definition += " }\n"
return definition