-
Notifications
You must be signed in to change notification settings - Fork 8
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
Flippando Builder Journey #33
Comments
Flippando is a fully on-chain memory game, aiming at creating a virtual economy of goods. Initial implementation was in Solidity. This space documents porting the game to Gno. Game mechanicsThe user is presented with a square matrix, which must be "uncovered". Each matrix is made of pairs of different visual shapes and colors. In this initial version, we have 3 different tile types: colors, dice and hexagrams. In future versions we will use more basic geometric shapes (circle, square, triangle, hexagon), letters, logos (in sponsored games), etc. User taps two distinct, uncovered yet squares. A request is sent to the blockchain, which alters the state of the smart contract. The client app, a React/next.js frontend, receives the event after the state is modified, which may have 2 outcomes:
In both cases, the state is persisted on chain. As the game advances, when there are only After the entire matrix is solved, it is turned into an on-chain NFT (Base64 encoding it into the abi, using SVG). Along with the NFT minting, an ERC 20 token, called "Flip", is also minted, and it's associated with the NFT, by being "locked" into it. The ERC20 token cannot be spent unless it's unlocked. We will see later on how it can be unlocked. This NFT/ERC20 token pair is what we call a "primitive" for the rest of the game functionality. LevelsThe game starts with a 4x4 matrix. After uncovering 8 such matrixes, the game advances to the next level, which uses 8x8 matrixes (64 tiles). GoalThe goal of the game is to generate NFT primitives, or basic shapes that can be then assembled on-chain as art. Each NFT primitive can also be traded in a marketplace, so people looking for a specific combination needed for their digital painting can buy it, if it was already generated by someone else. Or they can choose to play the game again and again, until randomness will generate their specific tile. A buying event will break the level logic. For instance, if someone buys one of your 8 level 1 matrixes, you will be left with only 7, so yo need to generate a new one before being able to play at next level. The "painting" is done by dragging and dropping squares into an empty canvas. Assembling NFT primitives in larger, more complex creations, unlocks the ERC20 token. In other words, every time one of the NFT primitives, created by solving a matrix, is used in a complex NFT, in a "painting", its "locked" ERC20 token is unlocked and sent to the creator of the basic NFT. There's a caveat: you cannot use your own basic NFTs to create art, you must use other people assets, unlocking the tokens for them. The resulting, "art" NFT, can be sold in a normal NFT marketplace. At the moment of the writing of this document, the actual NFT display is using a proprietary approach, but we're aiming at implementing EIP 6150/GRC 6150. A normal marketplace will not see the combined NFTs, but a placeholder. This is by design. As we stabilize our composite NFT structure, we may use other ways. RandomnessAlthough the game proposition is that we have to uncover a matrix, the matrix starts empty. There is no pre-generated matrix that the user can inspect by looking up the smart contract variables. Instead, we generate random numbers on each request (in the matrix interval: so, if we have a 4x4 matrix, we only use 4 shapes, so we generate random numbers in the 1 - 4 interval). This approach reduces the possibility of cheating and validates each generated NFT as PoA (Proof of Attention). StatusAt the moment of writing, the base logic (random number generation and game state) has been implemented in a Gno package. Currently working on the realm that will handle user logic. AboutI'm a mobile app developer for 10+ years, with an interest in the technical part of crypto for 7 years. I'm familiar with maintaining PoS nodes. Flippando started as my pet project for learning Solidity. To my surprise, it won 2 hackathons this year, the Glitch hackathon in Incheon, South Korea, and the online Saga hackathon. |
@irreverentsimplicity This is awesome to hear about. How are you managing the randomness with both Gno as well as with the EVM chains- any oracles being used (ie, VRF)? |
@waymobetta Thank you, happy to hear you're interested. In Solidity, I am doing a very simple block-based random generation, which, obviously, in some rollups gives very weird results - some tiles are coming up mono-color, because there's no real random number generated. In Gno I didn't get there yet, still organizing the app logic in packages / realms - once this is done, I will move on to actually implementing true randomness. While obviously important, I don't see randomness as a make-it-or-break-it component for this game, at least not for now. The goal is to generate tiles which then are assembled in higher hierarchy "pieces of art", like bottom to top puzzles, by other people. True randomness is important to make sure the tiles are PoA (proof of attention) and not tampered with by manipulating the random number to obtain a specific tile design. But let's assume the game gets popular. Someone who wants to "cheat" will have to:
This is like MEV-level effort, and if we ever get there, I think we'll be Ethereum-level popular - which is not a bad place to be. We will find ways to cross the randomness bridge, once we get there. Of course, my assumptions can be wrong, and I'm always open to criticism and brainstorming. |
Later edit: I assumed that you're referring to true random generation, for very basic testing I'm using this code:
|
@irreverentsimplicity I see, thanks for the explanation. I was thinking true randomness which is not simple, but you may be able to eventually incorporate VRF realm functionality from Teritori to satisfy your randomness needs; you can also read more within the use-case section. |
@waymobetta thanks! I'm familiar with Teritori, the project, but not with their work on VRF, this looks like something that fits very well in my use case, I'll definitely keep an eye on it! |
October 3rd 2023 UpdatesTLDR: during the last month I've been making progress in the following areas: Onboarding
Backend
Frontend
Contract versioning brainstorming
OnboardingThe installing and building process are very straightforward, I had no difficulties here. What took a little more time was familiarizing myself with the folder structure, specifically examples, demo and p / r folders. Given we are so early, though, this is expected and not at all a major issue. I found the existence of packages and realms to be shaping the app development processes in a different way. In Solidity, for instance, we have a monolithic functionality package (even if spread over multiple contracts), whereas in Gno we may start organizing the app into basic, agnostic logic (packages), which then can be called by different realms. Realms, in turn, can be accessed via specific UIs. It's almost like a 3-tier system, which seem to offer significantly more flexibility. BackendOne of the most important issues I faced was a CORS-related problem which made local dev unusable. The issue was fixed swiftly, though. For reference, here's the PR: gnolang/gno#1118, thanks to @zivkovicmilos. Although I do most of the development using the recommended TDD pattern, there are still use cases in which I need to redeploy a package. To allow that, I had to "brute force" my local dev env in the following way:
I made a small shell script, which I paste here in case it is useful (I reckon we will be soon transitioning to a versioning system, see below, in brainstorming).
(should be run in I also started to split the logic into a package, Since the composite NFTs are arrays of basic NFTs, I need a new structure for it, so I'm looking at porting ERC6150 https://eips.ethereum.org/EIPS/eip-6150 (which has a tree-like structure) into a GRC6155 interface. There is already some code in my repo for it, once I'm happy with it, I'll open a PR. I'm also pondering adding ERC6220 https://eips.ethereum.org/EIPS/eip-6220. FrontendI was able to install and use both Contract versioning brainstormingnote: if there is more interest for this, I'm happy to put the text below in a separate issue In Solidity, there is a proxy-based pattern that allows a contract to be upgraded. This is achieved by deploying a proxy in front of the actual contract, which maintains in its state the address(es) of the actual contract(s). Calls are made to the proxy, which then forwards them to the contracts. When a contract is upgraded, the proxy state is modified with the new address. I tried to do something like this in gno/go, and I used flippando.gno
flippandoV1.gno
flippandoV2.gno
flippando_test.gno
This is just a basic example, and it still doesn't allow for arbitrary package names. I started to look into keeping a registry and use reflect:
At this point I stopped and used my brute-force approach to local dev env, as it just allows me to move faster with the actual game implementation. As I said, if there's more interest about this, I can put it in an issue. Bottom lineIf I can maintain the current rhythm, meaning if nothing major happens, I think we are on track for having a functional gno flippando by the end of October. |
The gno implementation of Flippando had its first live demo at the public Dev Call on November 8th. The demo included:
Challenges:The Joy Of RandomnessWhile taking on the task of porting Ideally, the The custom SetTokenURIThe gno implementation of the Hacking dev envMost of the development followed the standard TDD practices, but in the final stages I needed to actually upload all the packages to the chain. There were 2 custom basic modules:
I am pasting the actual shell scripts here, maybe someone will find them useful: reset.sh
^^^^ the above needs a copy of the flippandoDeploy.sh
sendTokens.sh
the above 2 scripts need to be run from Current statusYou can now follow the development status by tracking the public board here. |
Hey @irreverentsimplicity, reading a bit of backlog here now :)
We will have something slightly different; the idea I discussed with Jae was to make the realm upgrade mechanism an "implicit proxy pattern"; I still have to flesh out a full proposal with all the ideas we discussed. In any case, as realms are immutable now, your proxy pattern will likely work great. In GnoChess, an alternative approach I went for (keep in mind this was at a point where we were in full "out-ASAP" mode) was to have a "migration killswitch", which could redirect users to a new realm. This worked for GnoChess particularly as the realm path was a variable in the frontend's env file, and we could have changed that easily. Usability-wise, the proxy pattern is likely better.
I invite you to post a separate demo video on this issue as we're a bit backlogged with publishing calls on our channel, and it might be a while before we get to publish the last call. Your demo was great & it shows another great application of Gno.land to the outside world 🎉
This should be added by gnolang/gno#1153 , which ports over the rest of I suggest you to update gnolang/gno#1272 with up-to-date information :)
Do you actually mean I saw the section for your deployment scripts. With GnoChess, for a short while I used a setup which used docker + entr to re-start everything right after I made changes. This was the source code, though I imagine it won't be incredibly useful to you, as this one creates a new realm path each time. Still, I found that getting |
Thanks for the comments, really helpful. I updated this gnolang/gno/issues/1272 with my hacky rand implementation, I understand onblock is working on this now. And yes, I was actually meaning Separate video demo coming up in the following days. Getting ready to close this. |
As of Dec 6th, Flippando reached a launchable state. It still can't be deployed on a testnet, though, as there is an outstanding PR on the grc721 interface. Here are the main updates (if you want to check all the details, here's the updated board).
Finalized UIWith all the backend logic sorted out, the main focus of the last period has been around the user interface. There is now a consistent and clean theme across the entire app. The main UI elements have been simplified Loading states and proper error checking for each backend query, empty data states enriched with CTAs to lower friction: Improved copy and UX for playground Improved composite NFT (art) UI Faucet integrationA faucet server has been added to the stack, to ease the onboarding of users. On testnet / mainnet, we should revisit this to set up proper limits. TokenomicsThe $FLIP fungible token has an uncapped supply - and there will be no airdrop or premine. As long as someone solves a board and generates a basic NFT, that basic NFT will always have 1 locked $FLIP token inside. The $FLIP token can be unlocked and made really fungible, only if someone else includes that basic NFT into a composite one. So the actual liquid supply is not enforced by anything other than the players behavior. A composite NFT can be traded for $FLIP. Each composite NFT sale also triggers a fungible token supply reduction, using randomness in a specified range. When a trade is made and the buyer pays the requested amount, a part of that amount is burned. The burnable range subject to randomness is between 1% and 50% of the asking price. Example: seller lists a composite NFT for 10 $FLIP. A buyer agrees to pay 10 $FLIP to get that NFT. When the sale is initiated, the contract generates a random number between 1 and 50, let's say 25. In our case, 25% off of $10 FLIP means 2.5 $FLIP. This amount gets burned, and the seller gets $7.5 FLIP. Because the randomness range is between 1% and 50%, a seller can expect to receive between 99% and 50% of the asking price. To recap: the potential supply is never capped, and it's a direct result of 1) solving boards and 2) creating art using the solved boards as basic NFTs. The selling event of a composite NFT decreases the supply with a random amount, between 1 and 50% of the sale price. Board solvers are incentivized by the potential revenue for their painting blocks. Art collectors are incentivized by the actual designs (which are limitless) and by the fact that moving around goods decreases the $FLIP supply, hence accruing value to the fungible token. This dynamic may create in time a positive feedback loop, that will increase both engagement for NFT creation, and the value of the fungible token. We have no way of knowing this, though, so time will tell. Social mediaThere is now an official Twitter account for Flippando, feel free to follow and give feedback. |
Here's what's been done since last update:
|
Following the merging of the grc721 PR into main gno, Flippando is now launched in beta at https://gno.flippando.xyz. It's running off of a local node, synced with the latest version of the main gno repository. There's also a simple thread about going live on Flippando's twitter account. RoadmapThere is also a roadmap which I will paste here with a little more dev-related details: ✅ Ground Zero (beta, testnet) - target: Jan 2024
Land of the Flips (beta, testnet) - target: March 2024
this dynamic adjustment makes the size of the composite NFTs bigger or smaller, based on how many available basic NFTs are. The more basic NFTs available, the bigger the size of the artwork, allowing for more complex and interesting compositions. If there are less than 50 available basic NFTs, the size of the canvas in playground is 2x2. Between 50 and 100, the size is 3x3, and so on. Here are the levels for this milestone: < 50 basic NFTs: 2x2 The size of the composite NFTs has very big implications on gas consumptions, making bigger compositions significantly more expensive to mint (and potentially more expensive when sold). The levels in this milestone are subject to re-evaluation.
this feature intends to surface user's games, based on gameStatus. At the moment, if a user abandons a game, there's no UI for seeing that game and potentially allowing the user to continue.
as more work was done in the ecosystem to integrate VFR (thanks Teritori), the intention is to transition to this source for randomness, instead of the hacky, simple randomness internal library used now in Flippando.
right now all wallet interactions are done via gno_js, the intention is to use Adena for that, as it is more robust and has more features. This feature also intends to have a better faucet manegement (during testnet)
As far as I know, Gnoswap uses a registry now to list tokens in their UI. This feature intends to have a frozen realm for the FLIP fungible token, which will not be affected by future upgrades in other parts of the game, and use that as an entry point for the Gnoswap registry. This will make the GRC20 FLIP token tradeable on Gno swap. Flippando tokenomics are unusual, so it will be interesting to see how it performs with almost zero liquidity in the beginning.
this feature intends to make realms upgradeable, or at least to find a consistent way to upgrade the realms,, in the same way Solidity contracts are upgradeable. Awakening (production, mainnet) - target: June 2024
self explanatory, we need a stable codebase to launch on mainnet
there is already a Solidity version of Flippando, deployed on a few chains, this feature intends to have Gno and Solidity at feature parity, and launched, as much as possible, at the same time. The Flip Connection (production, mainnet, cross-chain integration) - target: September 2024
|
Hey Dragos,
Welcome to the Gno.land Grant Program, I've started an issue for you to share updates on Flippando and introduce yourself to the team and community.
The text was updated successfully, but these errors were encountered: