Error: invalid : too many application args, max 16

Hi everybody,
this error is caused by set of arguments I passed to Smart Contract. Actually I passed 129 arguments of total dimension 160 bytes (so less than 2048 that is the cap).

Is there a way to pass more than 16 arguments?
Or the only way is to merge some of these and then split them in Smart Contract? In this case, how can I split them in Smart Contract?

Thank you!

The limit is currently 16 arguments. Are these strings? You can use the substring commands to split if needed: Opcodes - Algorand Developer Portal

No, these are 128 integer arguments of 1 byte each and 1 string argument of 32 bytes, but before I pass them to Smart Contract, I convert all of these in bytes, in this way:
args.append(bytes([data[x]])))
where args is array I pass to Smart Contract, and data is the array contains 128 integers.
Then I append to args also last string argument converting it in this way: idUtente.encode()

Which can be the solution?
Is there a way to merge the integers in one argument of 128 bytes and then split it in Smart Contract? If yes, can you show me an example of implementation?

Hi @cotunho,

You can parse the string using TEAL substring opcode. Unfortunately I haven’t a TEAL snippet to share here, but this could be a solution.

Also, since most are bytes, take a look at the teal 3 opcodes for byte operators in this article: Introducing TEAL Version 3 | Algorand Developer Portal

Thank you for your help!

But I have a problem in passing arguments to Smart Contract. Because, before to know the cap of 16 arguments, I did this:

for x in range(0, 64):
    args.append(bytes([data[x]]))

where data is my array of 64 values and args is my array I pass to Smart Contract.

So, I no have idea how to pass all 64 integer values.

  • I can merge all values in one string like this:
    '00000000000000000000000006400000000000000000000000000000000000000'
    (64 values, one 64 and sixty-three 0).
    But to pass it to Smart Contract I have to convert it again in bytes and it gains a dimension of 65 bytes.
    This is a problem when in Smart Contract I want to get single value 64.

  • Same problem of too big dimension if I merge (not integer values, but) bytes values, like this string:
    b'\x00'b'\x00'b'\x00'b'\x00'b'\x00'b'\x00'b'\x00'b'\x00'b'\x00'b'\x00'b'\x00'b'\x00'b'\x00'b'\x00'b'\x00'b'\x00'b'\x00'b'\x00'b'\x00'b'\x00'b'\x00'b'\x00'b'\x00'b'\x00'b'\x00'b'@'b'\x00'b'\x00'b'\x00'b'\x00'b'\x00'b'\x00'b'\x00'b'\x00'b'\x00'b'\x00'b'\x00'b'\x00'b'\x00'b'\x00'b'\x00'b'\x00'b'\x00'b'\x00'b'\x00'b'\x00'b'\x00'b'\x00'b'\x00'b'\x00'b'\x00'b'\x00'b'\x00'b'\x00'b'\x00'b'\x00'b'\x00'b'\x00'b'\x00'b'\x00'b'\x00'b'\x00'b'\x00'b'\x00'

How could be a solution to pass more than 16 values and get it in Smart Contract?

What is the range of values for the ints that you are passing in?

Also what language are you using to call the smart contract?

I’m using Python.
By the way, the range of values is [0, 64]

Because no value is greater than 64 you should be able to pass the parameters as a bytearray and then use the Teal opcode to get each value out of the byte array and use as an integer. If you look at the opcode description that is what is does.

I will try to work up an example to illustrate.

1 Like

Take a look at this simple example.

import base64
import datetime

from algosdk.future import transaction
from algosdk import account, mnemonic
from algosdk.v2client import algod

# user declared account mnemonics
creator_mnemonic = "put your 25 word mnemonic here";

user_mnemonic = "put your 25 word mnemonic here";

# user declared algod connection parameters
#algod_address = "http://localhost:4001"
#algod_token = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"

algod_address = "http://localhost:8080";
algod_token = "f1dee49e36a82face92fdb21cd3d340a1b369925cd12f3ee7371378f1665b9b1";


# declare application state storage (immutable)
local_ints = 0
local_bytes = 0
global_ints = 0
global_bytes = 0
global_schema = transaction.StateSchema(global_ints, global_bytes)
local_schema = transaction.StateSchema(local_ints, local_bytes)

# user declared approval program (initial)
approval_program_source_initial = b"""#pragma version 3
int 0
txn ApplicationID
==
bnz creation
txna ApplicationArgs 0
int 0 //get 1sth int
getbyte
int 61
==
txna ApplicationArgs 0
int 1 //get 2nd int
getbyte
int 11
==
&&
txna ApplicationArgs 0
int 2 //get 3rd int
getbyte
int 33
==
&&
return
creation:
int 1
return
"""

 
# declare clear state program source
clear_program_source = b"""#pragma version 2
int 1
"""

# helper function to compile program source
def compile_program(client, source_code) :
    compile_response = client.compile(source_code.decode('utf-8'))
    return base64.b64decode(compile_response['result'])
    
# helper function that converts a mnemonic passphrase into a private signing key
def get_private_key_from_mnemonic(mn) :
    private_key = mnemonic.to_private_key(mn)
    return private_key

# helper function that waits for a given txid to be confirmed by the network
def wait_for_confirmation(client, txid) :
    last_round = client.status().get('last-round')
    txinfo = client.pending_transaction_info(txid)
    while not (txinfo.get('confirmed-round') and txinfo.get('confirmed-round') > 0):
        print("Waiting for confirmation...")
        last_round += 1
        client.status_after_block(last_round)
        txinfo = client.pending_transaction_info(txid)
    print("Transaction {} confirmed in round {}.".format(txid, txinfo.get('confirmed-round')))
    return txinfo

# create new application
def create_app(client, private_key, approval_program, clear_program, global_schema, local_schema) : 
    # define sender as creator
    sender = account.address_from_private_key(private_key)

    # declare on_complete as NoOp
    on_complete = transaction.OnComplete.NoOpOC.real

	# get node suggested parameters
    params = client.suggested_params()
    # comment out the next two (2) lines to use suggested fees
    params.flat_fee = True
    params.fee = 1000

    # create unsigned transaction
    txn = transaction.ApplicationCreateTxn(sender, params, on_complete, \
                                            approval_program, clear_program, \
                                            global_schema, local_schema)

    # sign transaction
    signed_txn = txn.sign(private_key)
    tx_id = signed_txn.transaction.get_txid()

    # send transaction
    client.send_transactions([signed_txn])

    # await confirmation
    wait_for_confirmation(client, tx_id)

    # display results
    transaction_response = client.pending_transaction_info(tx_id)
    app_id = transaction_response['application-index']
    print("Created new app-id: ",app_id)

    return app_id


# call application
def call_app(client, private_key, index, app_args) : 
    # declare sender
    sender = account.address_from_private_key(private_key)
    print("Call from account: ",sender)

	# get node suggested parameters
    params = client.suggested_params()
    # comment out the next two (2) lines to use suggested fees
    params.flat_fee = True
    params.fee = 1000

    # create unsigned transaction
    txn = transaction.ApplicationNoOpTxn(sender, params, index, app_args)

    # sign transaction
    signed_txn = txn.sign(private_key)
    tx_id = signed_txn.transaction.get_txid()

    # send transaction
    client.send_transactions([signed_txn])

    # await confirmation
    wait_for_confirmation(client, tx_id)

    # display results
    transaction_response = client.pending_transaction_info(tx_id)
    print("Called app-id: ",transaction_response['txn']['txn']['apid'])



def main() :
    # initialize an algodClient
    algod_client = algod.AlgodClient(algod_token, algod_address)

    # define private keys
    creator_private_key = get_private_key_from_mnemonic(creator_mnemonic)
    user_private_key = get_private_key_from_mnemonic(user_mnemonic)

    # compile programs 
    approval_program = compile_program(algod_client, approval_program_source_initial)
    clear_program = compile_program(algod_client, clear_program_source)

    # create new application
    app_id = create_app(algod_client, creator_private_key, approval_program, clear_program, global_schema, local_schema)

    # call application without arguments
    # create list of bytes for app args
    a = 61
    b = 11
    c = 33
    byt_combined = bytes([a, b, c])
    app_args = [
        byt_combined
    ]

    call_app(algod_client, user_private_key, app_id, app_args)

main()
1 Like

Hi,
thank you for your help, it works! So I can pass these values to Smart Contract.
But I have a doubt: how can I get them in Smart Contract?
I asked it because I get them through assignment like this: biometrics = Txn.application_args[0], then, to view the content in this way:

on_creation = Seq([
     App.globalPut(Bytes("biometrics"), biometrics),
     Return(Int(1))
])

But return me an error like this: logic eval error: store bytes count 1 exceeds schema bytes count 0

When you create the app you have to specify how much global and local storage you are using. Evidently from that error, you did not specify any.

1 Like