#What should an universal approval method for various AU layouts look like?

13 messages · Page 1 of 1 (latest)

mighty drift
#

I'm still working on a token standard, and currently trying to design a versatile enough approval method for AUs.

So far i've came up with the following (not saying it works):

interface Approvable {
  approveTransfer: (from: AccountUpdate, to: AccountUpdate) => void;
  approveDeploy: (deploy: AccountUpdate) => void;
}

@method
public approveDeploy(deploy: AccountUpdate): void {
  this.assertHasNoBalanceChange([deploy]);
  this.approve(deploy, AccountUpdate.Layout.NoChildren);
}

@method
public approveTransfer(from: AccountUpdate, to: AccountUpdate): void {
  this.assertHasNoBalanceChange([from, to]);
  this.approve(from, AccountUpdate.Layout.NoChildren);
  this.approve(to, AccountUpdate.Layout.NoChildren);
}

Depending on how the from / to account updates for balance change of the Token accounts are created, they might end up having various children.

In the case of a deployment as long as the self account update of the deployed contract stays simple => we can use NoChildren as a layout and things are just fine.
However i wonder in what cases would this break? I think adding an extra manual AU into init() could break it, since it will add another child AU with callDepth: 1 and then the approval method will run into trouble since it expects/asserts no children?

For the transfer approval, i've decided to go with the path of standalone from/to AUs, so that i can support arbitrarily proven AUs on both ends. Reasoning behind this was to support custom token accounts with permissions set to receive: proof, send: proof. However i also can't find an easy way to reason about the children layout of the from/to account updates.

Do you have any ideas how to generalise this? @primal plume @gritty crow @quiet rose @trim monolith 👀

#

One observation is that any account update beyond self automatically becomes a child account update, so depending on the logic of the approved account update, it might contain balance changes to the 'self' account, even in a nested account update.

#

Should the approval method traverse all different kinds of AU layouts, collect balance changes from accounts with the relevant tokenId (is this even available in the AU?) and check if the overall balance change is 0? (no mint or burn from children for transfers)

#

Would this mean that the only semi tangible solution would be to write or generate quite a few layout approval methods? Keeping in mind that the method code must be compilable as a circuit - must be static

mighty drift
#

One approach i can think of is to flatten the AU tree, look for AUs with a matching tokenId, accumulate all balance changes and check that they are 0 in total

#

Then, we can implement methods for various lenghts of the flattened tree, like .approve2(...) .approve3(...)

#

or we can have a universal approve method with a fixed amount of AUs to approve, like up to 8-ish? since thats about the limit of how much you can fit into a TX anyways? so probably less than 8.

#

this way the flattening could be done outside of the token contract, which means interoperability does not suffer

#

@primal plume can you please point me in the right direction re: AU tree flattening? I've looked here so far Types.AccountUpdate.toFields, trying to figure out how to flatten the tree and then reconstruct individual AUs to access tokenId and balanceChange on them

gritty crow
#

Okay so the way I think this would be possible (implemented it myself for Njord):
Your approve method can receive one AccountUpdates with arbitrary Layout. You then flatten this AU into a list as a Witness. Then you do your balance change checks against this list. After that, you have to link this list (which is esentially just a witness) to the actual public input, to check that you didn't swap out any of the flattened AccountUpdates. How I would do that is by bascially implementing CallForest.hashChildren inside your circuit (you need to bend your mind a bit to do that but I managed it in the end). If you want I can give you some hints on that

#

After that, you'd have to link into addMissingProofs somehow to assert the publicInput against your computed calls value

worthy ore