Skip to content
This repository has been archived by the owner on Nov 10, 2021. It is now read-only.

Define target operating model for smart-contracts on NEAR #1

Closed
zahhar opened this issue Mar 24, 2021 · 7 comments
Closed

Define target operating model for smart-contracts on NEAR #1

zahhar opened this issue Mar 24, 2021 · 7 comments
Assignees
Labels
question Further information is requested

Comments

@zahhar
Copy link
Contributor

zahhar commented Mar 24, 2021

To be decided:

  1. For Marketplace contract:
  • (a) How many instances will exist?
    • (assumption) There will be only 1 instance of contract in Mainnet;
  • (b) Who will own them?
    • (assumption) Owned by Mintgate;
  • (c) Where they will be deployed?
    • (assumption) Deployed into Mintgate subaccount or separate account (tbd), e.g. marketplace.mintgate.near, or just mintgate.near.
  1. For NFT-contract:
  • (tbd) (a) How many instances will exist?
    • Option a1: each GateID gets its own NFT Contract deployed
    • Option a2: each Artist gets his/hers NFT Contract that consolidates all GateIDs that belong to this Artist
    • Option a3: all GateIDs ever exist will be placed into one NFT Contract
  • (tbd) (b) Who will own them?
    • Option b1: NFT contract is owned exclusively by Mintgate NEAR account (suitable for any - a1, a2 and a3)
    • Option b2: NFT contract is owned by Artist's NEAR account (suitable for a1 and a2)
    • Option b3: NFT contract is owned by User (probably not a viable one, mot much sense for any of cases)
  • (tbd) (c) Where they will be deployed?
    • Option c1: nft.mintgate.near (everything centralized, mega-large contract)
    • Option c2: <%GateID%>.mintgate.near
    • Option c3: <%GateID%>.marketplace.mintgate.near
    • Option c4: artist.mintgate.near
    • Option c5: nft.artist.near
    • Option c6: <%GateID%>.artist.near
@zahhar zahhar added the question Further information is requested label Mar 24, 2021
@zahhar zahhar added this to the M1: NFT Essentials milestone Mar 24, 2021
@mattlockyer
Copy link

mattlockyer commented Mar 24, 2021

Providing some high level context here. It comes down to access patterns for the NFTs.

If you know that a domain of NFTs (maybe this is GateID) will only be searched after knowing the GateID, then it's fine to have the following deployment:

gateid-1.mintgate.near
gateid-2.mintgate.near
...

HOWEVER, if you want to query NFTs ACROSS ALL GateIDs... then you have 2 options:

  1. build some sort of backend knowledge / indexer / etc... that is aware of all GateIds
  2. store all NFTs in the same contract and return groups of NFTs based on attributes

For (2) keep in mind this increases your storage requirements each time you add an attribute you'd like to query by at the smart contract level, and this is kind of an anti pattern in blockchain. The blockchain is used for the scarcity ownership layer and not intended to function as a high level database. So typically, prefer 1 access pattern only, get token by id.

Here are some access patterns:

  • get NFT by token_id
  • get all NFTs by owner_id - reasonable since it clusters nicely since much $$$ to get lots of NFTs into 1 account
  • get all NFTs by some attr - not preferred since there may be a TON of NFTs that match 1 attr

Summary, for access patterns, it's preferred to store 2 things off-chain in your own database, specifically:

  1. all token_id
  2. each token's metadata + owner_id, for query flexibility in finding specific token_ids

@Jshanks21
Copy link

Based on Matt's response and the system we want to develop, the below is what we're looking for.

(a) Yes, only 1 instance.
(b) Yes, owner by MintGate.
(c) Yes, that's correct.

(a) Option a1: each GateID gets its own NFT Contract deployed
(b) Option b1: NFT contract is owned exclusively by Mintgage NEAR account (suitable for any - a1, a2 and a3)
(c) Option c2: <%GateID%>.mintgate.near

Let me know if this all makes sense and appreciate any feedback if you see any potential for improvement or optimization.

@acuarica
Copy link
Contributor

Thanks for the feedback. It is interesting from the engineering perspective. Regarding the NFT contract I would like to discuss some issues:

  1. Deploy contract for each GateID. This creates an engineering overhead to deploy the NFT contract instance every time an Artist creates a GateID.
  2. Subaccount creation costs. The account mintgate.near needs to cover the costs for subaccount creation to hold the contract itself and Artist data. Moreover, since the contract WASM binary is the same across all <%GateID%>.mintgate.near accounts, this would represent a waste of NEARs. Finally, the WASM binary could be bloated, essentially due to Rust JSON serialization (serde library). Just for comparison, our Corgis contract (it is a big contract with several JSON interfaces) it's 1.8MB in size. Please refer to Investigate reported size discrepancy between Rust and AssemblyScript contracts near/near-sdk-rs#167 to find more details about this issue.
  3. Updating the contract for minor code changes. Probably the issue with less impact, but still worth considering it. If for, any reason, we want to make changes to the NFT contract[1] after initial deployment, we would need to re-deploy the contract to all GateIDs. Again, this imposes an engineering overhead.

Regarding the Marketplace contract, totally agree with it.

@mattlockyer @Jshanks21 Does this make sense? Is there any other issue I'm not seeing here?

[1] Here by changes I refer to only methods changes. Data changes are not included here since data changes could break the contract.

@zahhar
Copy link
Contributor Author

zahhar commented Mar 25, 2021

@Jshanks21 - let me bring few more examples.
What amount of GateIDs do you expect to be created by users daily in average?

Let me assume 100 new GateIDs created daily that Creators want to deploy to NEAR (probably I am too conservative, but just to start from smth). For you this means:

  • Build & deploy 100 new smart-contracts into 100 new subaccounts;
  • Take storage costs for each smart-contract, even if this will be just 1N per contract: 100N get frozen daily, even before any user started to claim their tokens and they start to circulate on aftermarket and generate some revenue;
  • If most of GateIDs will be a single-token assets, or assets with just handful of copies, then waste be even bigger, because we will operate whole smart-contract for each NFT; It could potentially make sense if majority of GateIDs will be smth similar to 'semi-fungible token' or ERC-20 tokens that have circulating supply of thousands of copies (say, concert tickets or licenses for reproduction of digital artworks).
  • One day later you have 10'000 of subaccounts, and you decide to adjust a fee a bit — say, increase by 0.5%. You will have to rebuild&redeploy 10'000 contracts to make it happen: you wither will rent a powerful cloud build pipeline that can do it in 1h, or will be waiting a week to get this done with an average build&test&deploy speed of 1 minute per contract.

Summary: technically idea looks appealing for me (e.g. thinking of future use-case when it could be possible to transfer whole subaccounts between accounts, or granularly manage access rights per subaccount), but I do not see benefits why to hunt for it right now.

@Jshanks21
Copy link

Jshanks21 commented Mar 25, 2021

That all makes sense. When building this on Ethereum, our original design was for an 1155 semi-fungible token for similar reasons of avoiding numerous deployments and re-use one instead. This design would be optimal to pursue for NEAR if possible.

Might I suggest the following then:

The NFT contract creates a new token ID for each new GateID that it's associated to. Similar to ERC-1155, a token ID can mint numerous copies with the same token ID that would all be associated to a GateID. When we introduce a new GateID, a new token ID is made with the quantity the Artist specifies. If this makes sense, is it also possible to make the token ID and GateID the same?

If this works,

  1. One contract holds multiple token IDs that are associated with a GateID. If we reach a limit on how many token IDs the contract can hold, that's when we'd deploy a new contract.
  2. I believe changing the NFT contract as described above would reduce the subaccount creation greatly, thus resolving this issue.
  3. Same as 2

Let me know if this would be a viable path to pursue for the NFT contract.

@zahhar
Copy link
Contributor Author

zahhar commented Mar 29, 2021

@Jshanks21: if we are talking about NFT standard, then tokenId must be unique. This is required to determine an owner of every copy and to implement NFT transfer to the new owner. Also granting access right to it to Marketplaces.

Otherwise, if there are numerous copies with the same tokenId, it will be very complicated to maintain the list of owners.

Consider the following: user A has 5 copies, user B has 10 copies, user C has 20 copies. Then User A wants to sell 3 copies on Marketplace A, and 2 copies on Marketplace B for different prices. User C is willing to buy only 1 token copy more from user A via Marketplace B. At the same time user C is selling his token via Marketplace A, and user B buys them :) It would be error prone to make all these calculations, grant rights and settle the balance - without having a standard similar to ERC-1155 in place in NEAR Protocol.

As standard for semi-fungible token is not there yet, I would suggest to:

  • go forward trying to implement NFT standard as close as possible, given it is also under active development and may change, and what we are building does not fit its purpose fully;
  • have every copy its own tokenId for simplicity of owner identification and adherence to the NFT standard draft;
  • store all tokens for all GateIDs in one NFT contract owned by Mintgate, and if/when it will show the signs it becomes too large (performance testing would be required), then you can open up another contract and start populating it. From the end user perspective it makes no difference in what contract his/hers assets are stored, and for Mintgate it would be also easy to know in what contract particular GateID is registered due to off-chain master database of all GateIDs you maintain that only requires a reference to the contract that handles all copies of thaty particular GateID.

If this sounds like a going-in position, please commend and we can conclude this ticket with a decision. Thanks!

@Jshanks21
Copy link

Thank you, this all sounds good.

@zahhar zahhar closed this as completed Mar 30, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

4 participants