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

speccing discussion #46

Draft
wants to merge 9 commits into
base: main
Choose a base branch
from
Draft

speccing discussion #46

wants to merge 9 commits into from

Conversation

harrysolovay
Copy link
Contributor

An overview of the initial exploration into modeling fungible tokens on Mina.

@harrysolovay harrysolovay requested review from kantp and qwadratic April 9, 2024 13:33
```ts
interface Create {
/** A unique ID of TBD type––perhaps a `UInt64`. */
id: TokenId
Copy link
Contributor

Choose a reason for hiding this comment

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

I would suggest to autogenerate it

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Is there a way to do so without breaking commutativity?

Copy link
Contributor

Choose a reason for hiding this comment

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

idk how it breaks commutativity. tokenID can be just a hash of some unique struct

Copy link
Contributor Author

Choose a reason for hiding this comment

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

How would this ID be generated within the contract? I'm not opposed to it, I just don't know how it could be implemented. I've contemplated tracking a tokenCount: UInt64 in state and returning the current count from every create call using the pending o1js @method.returns feature. Unfortunately, this would break commutativity / might cause the same nonce precondition errors we saw in the initial non-action/reducer approach. Ideas on how we might generate a token ID without breaking commutativity?

Copy link
Contributor

Choose a reason for hiding this comment

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

hash of smth

Copy link
Contributor

Choose a reason for hiding this comment

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

hash of previously created token id!))))

id: TokenId
/** The initial amount of the new token. */
supply: UInt64
/** The account that administrates this token (can ultimately be contract). */
Copy link
Contributor

Choose a reason for hiding this comment

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

not sure if a contract can be an owner, because in mina you can't check msg.sender. There is this.sender but it is a feepayer :)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Oof that's rough. Good to know though.

@qwadratic
Copy link
Contributor

qwadratic commented Apr 9, 2024

One thing we need to think about is fees.

In current design new accounts cost 1 MINA

In the proposed design this fee will be like 0.1-0.2 (for changing root hash in tokenbase)

@harrysolovay
Copy link
Contributor Author

harrysolovay commented Apr 10, 2024

It would be great if the token admin could—from another contract—hook into the Fungible Tokenbase to determine misc fees. Probably out of scope. How else might we want to enable the configuring of fees?

target contract. **This is not true of Mina**. To interact with a Mina contract, one needs to run
the contract code themselves. Each instruction affects how contract results are ultimately proven.
Interacting with a contract whose method signatures abide by a given spec is not necessarily aligned
with the desired behavior; in the world of Mina, the implementation is––more or less––the spec. This

Choose a reason for hiding this comment

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

in the world of Mina, the implementation is––more or less––the spec

This seems like an important point worth focusing on. It effectively means that a contract's code must either:

  1. bundle in all contracts it could ever interact with
  2. interact with contracts over a hosted API service boundary.

It hints that the version of a function is the most important part of the contract. It might be worth exploring how semantic versions, patch, minor and major, apply to changes in contract code. Is every change a "breaking" change because the proof will be different? What do consumers do when encountering a breaking change?

This looks like a dependency hell situation. Any tiny change in a function or change in its upstream dependencies could break the contract. It reminds me of Unison Lang's content-addressable functions where references are transformed into globally unique addresses to support branched versioning of programs. Two versions of the same function can safely run in the same unison app because they would have different addresses.

I think it ultimately means that having an easy way to upgrade a package is top priority or otherwise risk a situation where code can't be improved.

My question is: should this contract include an upgrade mechanism first-class?

(state, prevVersion, newVersion) -> newState

Or is this out of scope?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Spot-on. I agree with the stopgap approach you suggested of placing the contract behind a service. Otherwise, seemingly too much difficulty crops up for anyone who wants to interact with the contract. This difficulty is compounded as we get into large amounts of off-chain storage and upgradability.


## Design

### Goals

Choose a reason for hiding this comment

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

Should there be an "Upgradable" goal?

I suspect it's important since a proof is totally dependent on specific code versions. Is a consumer doomed to be pinned to a specific version indefinitely?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is a great question. Upgradability in Mina seems challenging. I believe one could use the approach of setting a target contract address in the state of a proxy contract. We'd want to scope down the proxy contract's permissions. The confusing part comes from whether the data pre-upgrade is still provable after the given upgrade. Definitely worth testing (#48).

- **Extensible**: the `FungibleTokenbase` contract should offer all functionality necessary for a
3rd-party contract to become the admin and craft use-case-specific functionality.
- **Scalability**: the contract should support concurrent transactions at scale.
- **Off-chain State Management API**: the contract-accompanying service should facilitate

Choose a reason for hiding this comment

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

Do you have a specific goal around whether the account balance will be public or private?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Great question. Imo it should be private by default. Which do you think is preferable?

mftb.md Outdated
Comment on lines 82 to 84
- **Forgo Deployment**: it should be possible to create custom token types without the deployment of
a custom fungible token contract. Token types are just data after all; token-type-specific
contracts––at least for would-be "standard" functionality––are unnecessary.

Choose a reason for hiding this comment

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

Can you elaborate on why this is a goal? Why is it important to avoid a deployment?

Comment on lines +80 to +81
- **Wallet-friendly**: wallets should be able to display and prove data of `FungibleTokenbase`s
without needing to dynamically import 3rd party contract code.

Choose a reason for hiding this comment

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

  1. Where is the account balance stored?
  2. How can I prove that balance is correct without the contract code? I won't be able to generate a valid proof.

Mina seems geared towards a micro-service architecture. I suspect it is necessary to encapsulate the custom code for tokens behind a standardized REST or RPC API that the generic wallet can invoke without needing to know the implementation details. Otherwise, every token will have to be compiled into the code of the wallet which won't scale.

Only other alternative I can think of is to have a registry of addressable contract code that is fetched on the fly and evaluated by the wallet. That is a big security risk though, would need to have a solid sandbox for running untrusted code.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I 100% agree. In the case of this proposal, the Fungible Tokenbase contract code would be depended upon by wallets, which would use it to prove balances. However, any admin contracts would not be represented within the wallet. Related work to be taken on: https://github.com/MinaFoundation/Core-Grants/pull/12/files

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.

3 participants