Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
def synonymise(s):
return s.replace('int128', 'num').replace('uint256', 'num')
# for sig in sigs['self']
full_sig = cls.get_full_sig(
stmt_or_expr.func.attr,
expr_args,
None,
context.custom_units,
context.structs,
context.constants,
)
method_names_dict = dict(Counter([x.split('(')[0] for x in context.sigs['self']]))
if method_name not in method_names_dict:
raise FunctionDeclarationException(
"Function not declared yet (reminder: functions cannot "
f"call functions later in code than themselves): {method_name}"
)
if method_names_dict[method_name] == 1:
return next(
sig
for name, sig
in context.sigs['self'].items()
if name.split('(')[0] == method_name
)
if full_sig in context.sigs['self']:
return context.sigs['self'][full_sig]
else:
synonym_sig = synonymise(full_sig)
syn_sigs_test = [synonymise(k) for k in context.sigs.keys()]
def validate_private_function(code: ast.FunctionDef, sig: FunctionSignature) -> None:
""" Validate private function defintion """
if sig.is_default_func():
raise FunctionDeclarationException(
'Default function may only be public.', code
)
unpackers = ['pass']
clampers.append(LLLnode.from_list(
['seq_unchecked'] + unpackers + [0], # [0] to complete full overarching 'seq' statement, see private_label.
typ=None, annotation='dynamic unpacker', pos=getpos(code))
)
# Create "clampers" (input well-formedness checkers)
# Return function body
if sig.name == '__init__':
o = LLLnode.from_list(['seq'] + clampers + [parse_body(code.body, context)], pos=getpos(code))
elif is_default_func(sig):
if len(sig.args) > 0:
raise FunctionDeclarationException('Default function may not receive any arguments.', code)
if sig.private:
raise FunctionDeclarationException('Default function may only be public.', code)
o = LLLnode.from_list(['seq'] + clampers + [parse_body(code.body, context)], pos=getpos(code))
else:
if total_default_args > 0: # Function with default parameters.
function_routine = "{}_{}".format(sig.name, sig.method_id)
default_sigs = generate_default_arg_sigs(code, sigs, global_ctx._custom_units, global_ctx._structs)
sig_chain = ['seq']
for default_sig in default_sigs:
sig_compare, private_label = get_sig_statements(default_sig, getpos(code))
# Populate unset default variables
populate_arg_count = len(sig.args) - len(default_sig.args)
set_defaults = []
if populate_arg_count > 0:
current_sig_arg_names = {x.name for x in default_sig.args}
code,
sigs=None,
custom_units=None,
custom_structs=None,
contract_def=False,
constants=None,
constant_override=False):
if not custom_structs:
custom_structs = {}
name = code.name
mem_pos = 0
valid_name, msg = is_varname_valid(name, custom_units, custom_structs, constants)
if not valid_name and (not name.lower() in function_whitelist):
raise FunctionDeclarationException("Function name invalid. " + msg, code)
# Validate default values.
for default_value in getattr(code.args, 'defaults', []):
validate_default_values(default_value)
# Determine the arguments, expects something of the form def foo(arg1:
# int128, arg2: int128 ...
args = []
for arg in code.args.args:
# Each arg needs a type specified.
typ = arg.annotation
if not typ:
raise InvalidTypeException("Argument must have type", arg)
# Validate arg name.
check_valid_varname(
arg.arg,
['if', 0, # can only be jumped into
['seq',
['label', function_routine] if not sig.private else ['pass'],
['seq'] + _clampers + [parse_body(c, context) for c in code.body] + stop_func]]], typ=None, pos=getpos(code))
else:
# Function without default parameters.
sig_compare, private_label = get_sig_statements(sig, getpos(code))
o = LLLnode.from_list(
['if',
sig_compare,
['seq'] + [private_label] + clampers + [parse_body(c, context) for c in code.body] + stop_func], typ=None, pos=getpos(code))
# Check for at leasts one return statement if necessary.
if context.return_type and context.function_return_count == 0:
raise FunctionDeclarationException(
"Missing return statement in function '%s' " % sig.name, code
)
o.context = context
o.total_gas = o.gas + calc_mem_gas(o.context.next_mem)
o.func_name = sig.name
return o
def validate_public_function(code: ast.FunctionDef,
sig: FunctionSignature,
global_ctx: GlobalContext) -> None:
""" Validate public function definition. """
# __init__ function may not have defaults.
if sig.is_initializer() and sig.total_default_args > 0:
raise FunctionDeclarationException(
"__init__ function may not have default parameters.",
code
)
# Check for duplicate variables with globals
for arg in sig.args:
if arg.name in global_ctx._globals:
raise FunctionDeclarationException(
"Variable name duplicated between "
"function arguments and globals: " + arg.name,
code
)
def parse_func(code, sigs, origcode, global_ctx, _vars=None):
if _vars is None:
_vars = {}
sig = FunctionSignature.from_definition(code, sigs=sigs, custom_units=global_ctx._custom_units, custom_structs=global_ctx._structs)
# Get base args for function.
total_default_args = len(code.args.defaults)
base_args = sig.args[:-total_default_args] if total_default_args > 0 else sig.args
default_args = code.args.args[-total_default_args:]
default_values = dict(zip([arg.arg for arg in default_args], code.args.defaults))
# __init__ function may not have defaults.
if sig.name == '__init__' and total_default_args > 0:
raise FunctionDeclarationException("__init__ function may not have default parameters.")
# Check for duplicate variables with globals
for arg in sig.args:
if arg.name in global_ctx._globals:
raise FunctionDeclarationException("Variable name duplicated between function arguments and globals: " + arg.name)
# Create a local (per function) context.
context = Context(
vars=_vars,
global_ctx=global_ctx,
sigs=sigs,
return_type=sig.output_type,
is_constant=sig.const,
is_payable=sig.payable,
origcode=origcode,
is_private=sig.private,
method_id=sig.method_id
typ = arg.annotation
if not typ:
raise InvalidTypeException("Argument must have type", arg)
# Validate arg name.
check_valid_varname(
arg.arg,
custom_units,
custom_structs,
constants,
arg,
"Argument name invalid or reserved. ",
FunctionDeclarationException,
)
# Check for duplicate arg name.
if arg.arg in (x.name for x in args):
raise FunctionDeclarationException(
"Duplicate function argument name: " + arg.arg,
arg,
)
parsed_type = parse_type(
typ,
None,
sigs,
custom_units=custom_units,
custom_structs=custom_structs,
constants=constants,
)
args.append(VariableRecord(
arg.arg,
mem_pos,
parsed_type,
False,
def parse_func(code, sigs, origcode, global_ctx, _vars=None):
if _vars is None:
_vars = {}
sig = FunctionSignature.from_definition(code, sigs=sigs, custom_units=global_ctx._custom_units, custom_structs=global_ctx._structs)
# Get base args for function.
total_default_args = len(code.args.defaults)
base_args = sig.args[:-total_default_args] if total_default_args > 0 else sig.args
default_args = code.args.args[-total_default_args:]
default_values = dict(zip([arg.arg for arg in default_args], code.args.defaults))
# __init__ function may not have defaults.
if sig.name == '__init__' and total_default_args > 0:
raise FunctionDeclarationException("__init__ function may not have default parameters.")
# Check for duplicate variables with globals
for arg in sig.args:
if arg.name in global_ctx._globals:
raise FunctionDeclarationException("Variable name duplicated between function arguments and globals: " + arg.name)
# Create a local (per function) context.
context = Context(
vars=_vars,
global_ctx=global_ctx,
sigs=sigs,
return_type=sig.output_type,
is_constant=sig.const,
is_payable=sig.payable,
origcode=origcode,
is_private=sig.private,
method_id=sig.method_id
)
# Copy calldata to memory for fixed-size arguments
max_copy_size = sum([32 if isinstance(arg.typ, ByteArrayType) else get_size_of_type(arg.typ) * 32 for arg in sig.args])