I want to create a child app as described here, but make it to accept parameters on creation:
from pyteal import *
from beaker import Application, ApplicationStateValue, decorators
class ChildApp(Application):
foo = ApplicationStateValue(
stack_type=TealType.uint64,
)
@decorators.create
def create(self, foo: abi.Uint64):
return Seq(
self.foo.set(foo.get()),
)
class ParentApp(Application):
child: AppPrecompile = AppPrecompile(ChildApp())
@decorators.external
def create_child(self, *, output: abi.Uint64):
return Seq(
InnerTxnBuilder.Execute({
**self.child.get_create_config(),
# ???
}),
output.set(InnerTxn.created_application_id()),
)
The question is – how do I pass those parameters to a child?
From what I see, the only thing that looks suitable, is application_args
:
InnerTxnBuilder.Execute({
**self.child.get_create_config(),
TxnField.application_args: [ Itob(42) ],
})
I have to use Itob
in this case, because application_args
only accepts Bytes
values.
This is weird already, but anyway it doesn't work: on attempt to call create_child
method I get this:
TransactionPool.Remember: transaction RIOKX6SHD2QC4CW3ZDMVKEWDP7DISFXEGOMQEZOVQQDY6OMMAN6Q:
logic eval error: err opcode executed. Details: pc=60, opcodes===\n' +
'bnz label4\n' +
'err\n' +
'label4:\n'
Which is not helpful at all. I don't understand what am I doing wrong.
So how do I properly pass params to a child app?
Firstly, thank you for trying out Beaker even though it is still in early development! Please don't be afraid to share your feedback on it through it's GitHub repository or Beaker channel on the Algorand Discord server.
From ARC 4 which details the ABI standard:
The method selector must be the first Application call argument (index 0), accessible as txna ApplicationArgs 0 from TEAL (except for bare Application calls, which use zero application call arguments).
Your TxnField.application_args
should therefore look something like the following so that your child contract knows which method it should route to upon creation:
TxnField.application_args: [
Bytes(get_method_spec(ChildApp.create).get_selector()),
Itob(Int(42)),
],
Also note that the number 42 must first be wrapped with Int
to convert it to a teal type.
You will likely want to pass an argument from the parent to the child on creation. If so, then it'd look more like the following assuming your parent receives an abi.Uint64
argument called my_int_arg
:
TxnField.application_args: [
Bytes(get_method_spec(ChildApp.create).get_selector()),
my_int_arg.encode(),
],
You may read more about ARC 4 here.