athenavm / athena

Athena monorepo
https://www.athenavm.org/
Apache License 2.0
21 stars 2 forks source link

`receive` template method #204

Open lrettig opened 3 weeks ago

lrettig commented 3 weeks ago

As in EVM, a template should be able to declare a receive method. The method cannot have any arguments and cannot have any return value. It should be executed whenever a program receives incoming coins with no calldata.

If there is no receive method, but a fallback method exists (#203), that method should be called instead. If there's no receive and no fallback method, a CALL or inbound tx with > 0 amount should fail.

We may need a new macro for this, or else we may be able to update the existing #[template] and #[callable] proc macros to do the additional work here (if they notice that the method name is receive).

Clarification from #206: we still allow coins to be sent to a stub account, i.e., one that hasn't been spawned yet. This only applies to spawned accounts.

poszu commented 3 weeks ago

@lrettig

If there's no receive and no fallback method, a CALL or inbound tx with > 0 amount should fail.

It means that single-entrypoint programs cannot receive coins at all (they only have a main()). Is it intended?

Clarification from https://github.com/athenavm/athena/pull/206: we still allow coins to be sent to a stub account, i.e., one that hasn't been spawned yet. This only applies to spawned accounts.

If an account is not spawned, we don't know its template yet and cannot tell whether it will have a receive() method. It will be possible to send coins to a stub account until it is spawned. Then if it is spawned with a template that doesn't have receive(), it will not be able to receive coins any more, right?

lrettig commented 2 weeks ago

It means that single-entrypoint programs cannot receive coins at all (they only have a main()). Is it intended?

Yup. This is a safety thing. It's quite possible to write a template that becomes a "black hole" for incoming coins or other assets, i.e., there's no mechanism to ever move them out. Programs need to explicitly opt into receiving.

If an account is not spawned, we don't know its template yet and cannot tell whether it will have a receive() method. It will be possible to send coins to a stub account until it is spawned. Then if it is spawned with a template that doesn't have receive(), it will not be able to receive coins any more, right?

Yes, exactly. There's no way to prevent this, without blocking all transfers to stub accounts, which we don't want to do.

poszu commented 2 weeks ago

Thanks for the explanations. The remaining question is whether this mechanism should be implemented in the VM or rather on the host side. WDYT?

lrettig commented 5 hours ago

Assuming by "this mechanism" that you mean specifically "reject inbound coin transfers to a single-entrypoint program", it's better if the host doesn't need to know the details of things like entrypoints, program type, etc. I think the cleanest way to do this is the following, let me know what you think:

  1. add a "virtual method" to each Athena program, called "receive". By "virtual method" I mean that there's no corresponding program code, but rather, the VM itself intercepts the call and handles it.
  2. the host calls this "receive" virtual method, passing in the number of incoming coins, whenever it moves coins to a program (assuming the program has been spawned).
  3. the VM can then implement the underlying logic discussed in this thread. If the actual, underlying receive (or fallback) method exists and reverts, or if no such method exists, this virtual method should indicate failure to the host, which should propagate that failure as a failed tx.