Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

General-purpose token contract #1384

Merged
merged 103 commits into from
Feb 12, 2024
Merged

General-purpose token contract #1384

merged 103 commits into from
Feb 12, 2024

Conversation

mitschabaude
Copy link
Collaborator

@mitschabaude mitschabaude commented Jan 25, 2024

Exports a TokenContract which can be extended and contains the blueprint for all token contracts.

TokenContract provides the hard parts of the proposed token standard MIP - namely, the Approvable and Transferable APIs.

  • The PR does the bare minimum to make the below sketched API work
  • To be assured that it works, we use the new token contract in existing token tests that run in CI: DEX, DEX with actions
  • Plus a unit test which tests the basic achievement: That a token contract prevents children from minting tokens
  • We introduce a new global context, called UnfinishedForest, which is used to record a zkApp's child forest as it gets built up, and that can be "finalized" at the end to get an AccountUpdateForest.
    • This runs in parallel to the old system of sticking child updates on AccountUpdate.children
    • In contrast to the old system, it correctly enables to pass children's children on from a zkapp call another (token) contract -- essential to make all this work.
    • It's not ideal to have two similar systems for collecting child updates in parallel. The plan is to get rid of AccountUpdate.children in a follow-up PR, and make everything based on UnfinishedForest.

Token contract API

The core method that approves other account updates, called approveBase(), is left abstract, i.e. has to be implemented by base classes. It has the following type signature:

approveBase(forest: AccountUpdateForest): void;

TokenContract contains methods that make it very easy to approve and iterate through the forest of child account updates.

The canonical implementation is as simple as:

@method approveBase(forest: AccountUpdateForest) {
  this.checkZeroBalanceChange(forest);
}

If you want to do something custom for every child account update, this is also pretty easy, using the forEachUpdate() helper:

@method
approveBase(updates: AccountUpdateForest) {
  let totalBalanceChange = Int64.zero;

  this.forEachUpdate(updates, (accountUpdate, usesToken) => {
    totalBalanceChange = totalBalanceChange.add(
      Provable.if(usesToken, accountUpdate.balanceChange, Int64.zero)
    );
    // maybe do something else here?
  });

  // prove that the total balance change is zero
  totalBalanceChange.assertEquals(0);
}

This is, of course, built with the TokenAccountUpdateIterator from #1398

We also provide easier-to-use wrappers for approveBase(), so that developers of token zkapps don't have to deal with creating the AccountUpdateForest correctly. These will be the main API entry-points when using token contracts:

abstract class TokenContract extends SmartContract {
    /**
     * Approve a single account update (with arbitrarily many children).
     */
    approveAccountUpdate(accountUpdate: AccountUpdate): void;
    /**
     * Approve a list of account updates (with arbitrarily many children).
     */
    approveAccountUpdates(accountUpdates: AccountUpdate[]): void;
    /**
     * Transfer `amount` of tokens from `from` to `to`.
     */
    transfer(from: PublicKey | AccountUpdate, to: PublicKey | AccountUpdate, amount: UInt64): void;
}

Base automatically changed from feature/call-forest-iterator to main February 12, 2024 15:21
Copy link
Member

@Trivo25 Trivo25 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm! but we should also queue up changes to https://docs.minaprotocol.com/zkapps/o1js/custom-tokens

src/examples/zkapps/dex/erc20.ts Outdated Show resolved Hide resolved
@mitschabaude mitschabaude merged commit baac0cb into main Feb 12, 2024
13 checks passed
@mitschabaude mitschabaude deleted the feature/token-contract branch February 12, 2024 18:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants