outsize param of raw_call doesn't accept a constant.
TEST_C: constant(int128) = 1
TEST_WEI: constant(uint256(wei)) = 1
# Expecting num_literal for argument 'outsize' of raw_call
@private
def test():
raw_call(0x0000000000000000000000000000000000000005, 'hello', outsize=TEST_C, gas=2000)
# Compiled!
@private
def test1():
# Expecting num_literal for argument 'outsize' of raw_call
raw_call(0x0000000000000000000000000000000000000005, 'hello', outsize=256, gas=TEST_WEI)

Here is the culprit I think @nrryuya
https://github.com/ethereum/vyper/blob/master/vyper/functions/signature.py#L81
Which appears to be a strange piece of code
we have this if statement checking :
if len(expected_arg_typelist) == 1:
raise TypeMismatchException("Expecting %s for argument %r of %s" %
(expected_arg, index, function_name), arg)
which appears to be the exact error
But what I find strange is the else clause
else:
raise TypeMismatchException("Expecting one of %r for argument %r of %s" %
(expected_arg_typelist, index, function_name), arg)
return arg.id
It seems if we reach this code block it will get an exception in either case, so I am wondering if it is meant to return before that
I'v dug into the code and it appears that the arg isin't getting validated as a ast.Num type.
It appears to go through the args with process_arg until it eventual gets to our num_literal, it correctly sees its a num_literal but then there is a check
if isinstance(arg, ast.Num) and get_original_if_0_prefixed(arg, context) is None:
the first part of the check always is false for me, as the type of arg here is ast.Name
Edit:
Also here we have a check to ensure a constant is of type ast.Name https://github.com/ethereum/vyper/blob/master/vyper/signatures/function_signature.py#L102
could this be the culprit ?
@Ryan-Gordon Thank you!
I found range() has a similar issue.
CONST: constant(uint256) = 8
@public
@constant
def test():
# "Range only accepts literal (constant) values"
for i in range(CONST / 4):
pass
Although, range(CONST) works well.
@Ryan-Gordon you were correct about the nature of the problem. I have created a fix with additional work to make the use of constant types easier. @nrryuya if you could review the PR / test the PR that would be great :)
@jacqueswww thanks for confirming.
To understand your change I looked over the PR and
if context.is_constant_of_base_type(arg, ('uint256', 'int128')):
return context.get_constant(arg.id).value
so would it be right to say this piece of code checks the base_type (as shown) and then acquires the value by using the id of the ast.Name to get a ast.Num representation ?
Great work !
@jacqueswww @Ryan-Gordon
Thank you!
I tested #1180 and it worked for the original issue ;)
How about the one in https://github.com/ethereum/vyper/issues/1178#issuecomment-451620170 ?
Something like range(CONST / 4) or raw_call(A, 'hello', outsize=CONST / 5, gas=G) are intentinally prohibited?
@nrryuya I am still working on #1178 will let you know how it goes.