-
Notifications
You must be signed in to change notification settings - Fork 10
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
base: main
Are you sure you want to change the base?
Conversation
```ts | ||
interface Create { | ||
/** A unique ID of TBD type––perhaps a `UInt64`. */ | ||
id: TokenId |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hash of smth
There was a problem hiding this comment.
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). */ |
There was a problem hiding this comment.
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 :)
There was a problem hiding this comment.
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.
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) |
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 |
There was a problem hiding this comment.
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:
- bundle in all contracts it could ever interact with
- 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?
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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
- **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. |
There was a problem hiding this comment.
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?
- **Wallet-friendly**: wallets should be able to display and prove data of `FungibleTokenbase`s | ||
without needing to dynamically import 3rd party contract code. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- Where is the account balance stored?
- 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.
There was a problem hiding this comment.
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
An overview of the initial exploration into modeling fungible tokens on Mina.