Why you should make sure a Secret NFT is open source before buying

Ben Adams
12 min readDec 27, 2021

--

Most Secret NFT projects are not open source but should be.

With the minting of the Anons as well as a number of other projects, and the opening of the Stashh marketplace, Secret NFTs with private metadata have arrived on Secret Network. You can now purchase an NFT without worrying about instantly sharing your entire collection and purchase history on chain. In addition, private metadata means that creators can share information that is only accessible to the owner of the NFT. The possibilities for this feature have only begun to be explored, with endless potential innovations in gaming, art, and other media coming to the network.

However, as far as I can tell, none of the collections that have been released on Secret Network so far have released the source code for their NFT contracts. [See the update at the end of this article.] In this article I am going to explain why this is a problem, and what you as a consumer of these NFTs can do to protect yourself.

Background on smart contracts and NFTs

Before I go into the problems, let’s first explore what NFT contracts are. Like Ethereum, Solana, and other blockchain networks, Secret Network enables the creation of smart contracts, which are immutable programs put on chain that are guaranteed to execute when specific conditions are met, e.g. a specific type of message is sent to them. There is an implicit understanding that if you engage with a contract on chain that the source code is the contract. This concept pre-dates smart contracts and can be considered an aspect of any system where there is algorithmic governance. Lawrence Lessig termed this “code is law.” For this reason, nearly all fungible token contracts on blockchain networks are released with open-sourced code. Analogously, if you could not verify the text of a real-world contract that resulted in a transfer of money, would you be comfortable signing it?

The distinguishing feature of Secret Network is that the program state and data is encrypted, so that only permissioned users of a contract can access and read the data stored on chain. This is a huge advantage over other blockchain networks because it means we can preserve the privacy of users’ data on chain. But if only the compiled versions of contracts are on chain, how can we verify their source code is what we think it is? The solution is elegantly simple. The compiled bytecode of the contract is fed into a mathematical hash function that creates a 256-bit number, which uniquely identifies the source code on chain. Even a tiny change in the code will generate a completely different hash number. All the commonly traded fungible tokens on Secret Network (a.k.a. SNIP-20s) — including SSCRT, SEFI, SIENNA, BUTT, numerous wrapped secret tokens, such as SETH, as well as the liquidity provider tokens for Secret Swap — are open sourced and you can verify that the code running on Secret Network is the same by compiling the code and seeing that the hash of the code on chain matches. SCRT Labs provides Docker containers that will build optimized versions of contracts in a reproducible manner, so that code hashes can be verified regardless of the compute environment where the code is compiled.

Secret NFTs are smart contracts that follow the SNIP-721 specification for Private, Non-fungible Tokens. To satisfy the specification, a contract must implement a set number of functions, which manage how the NFTs are minted, transferred, and burned, and following the specification is what enables a marketplace like Stashh to automatically import and sell a number of different NFTs. The SNIP-721 specification combines features of the Ethereum ERC-721 specification and OpenSea’s metadata standard with new features for working with private metadata. Stashh developer Baedrik has also published a SNIP-721 reference implementation on GitHub. This reference implementation includes code that ensures only the owner or designated addresses can view private metadata, rules for how transfers of ownership can safely take place between users, etc. Importantly, the standard describes features that must be present in a SNIP-721, but contract designers might want to customize the reference implementation for their own use cases by altering existing functions or adding new functions, for example. This is to be expected as there might bespoke requirements for any given project. However, it also opens up the possibility of writing an NFT contract that has vulnerabilities or even malicious code.

Backdoors in SNIP-721 contracts

It is very easy to create an NFT contract with a backdoor that allows the creator of the contract to arbitrarily change the metadata, burn, or even steal NFTs after they are minted. For example, the contract writer could arrange to transfer and sell an NFT long after it is minted and there would be no notification to the owner until they checked and found the NFT was gone. In addition, it is just as easy for a creator to mint the rarest versions only for themselves, which they can sell later on the market once a rarity score table has been released. These are extremely quick changes to make, involving only a few lines of code, and anyone who can make a SNIP-721 contract could implement them in 10 minutes. If the contracts for an NFT project are closed-source there is no way for purchasers to verify that the NFTs do not have these kind of backdoors.

Not all backdoors are malicious. Given that contract code is immutable it is possible that a creator might add a backdoor as a failsafe to try and change things if they go wrong. But these kinds of backdoors are vulnerabilities that are waiting to be exploited, and if anyone got access to the creator’s account — for example, if a creator’s assets are confiscated for tax violation — then they would have control over the NFTs. (If you don’t think that might happen read this article.)

Apart from backdoors, there is also the simple issue of writing buggy code that creates vulnerabilities. As the number of Secret NFT projects grows and a number of developers enter into the arena of making SNIP-721 contracts, this issue will only grow. There is ample evidence that open source projects catch bugs much quicker than non-open source projects. Thus, even if you personally know and completely trust the creator, it is still to your benefit to ask for the code to be open-sourced. Open sourcing does not eliminate all risks but it does significantly mitigate them.

Finally, in a SNIP-721 there is an option to set another contract as the minter of the SNIP-721 contract, as well as options for this minter to set the metadata of the NFTs. This is how the Secret Skulls NFTs are minted, and is a model one might expect for games that need to change stats for a player NFT, for example. Though the minter contract has permission to change the NFT’s metadata, the code of the minter contract should be written to limit the conditions under which those changes can happen. Functions that make changes in metadata should only be triggered by owner-actions, unless there is another very good reason. In other words, e.g., the minter might have a function to enter a game which can result in a change of your token’s metadata (if you win or lose), but only the owner can trigger that to happen. In these cases, not only the SNIP-721 but also the minter contract should be open-sourced.

If you’ve gotten this far, you might be saying, “Yeah, that all makes sense, but I don’t know how to code anyway, so it wouldn’t make any difference to me to have access to the source.” The key point is that is if someone is doing a public sale of NFTs, then there should always be the option to inspect the source code — the code is the contract. Even if you as an individual cannot make sense of it, there will be others in the community who can, and ultimately it is the only way anyone can verify the NFT is safe. Simply put, it is the bare minimum that we should expect of any public sale NFT, before any other research you might do into the project.

This is no different than the approach that the community already takes for fungible tokens. The value of NFT assets on Ethereum matches some of the largest fungible cryptocurrencies. We are just starting to scratch the surface of what is possible with Secret NFTs and it is quite reasonable to expect that the total value of Secret NFTs on Secret Network will rise precipitously. Why then would we expect a different standard of transparency for NFT contracts than we do for SNIP-20 tokens?

Are there any good reasons to keep the contracts closed source?

The contracts on mainnet for Anons (code id #126), Secret Punks (code id #193), Redacted Club (code id #204), Mystic Skulls (code ids #218, 219, 220), Confidential Cats (code id #221), Secret Dogs (code id #222), and Secret Girlfriends (code id #224) all have different hashes, which indicates that their source code is different from the SNIP-721 reference implementation. The collections that are made directly using the Stashh user interface use the same NFT contract version (code id #216), as one would expect, however its hash also does not match the reference implementation. The hash for code id #216 is 9a48070f…c488acac, and the hash calculated when I compile the reference implementation using the latest version of the SCRT Labs optimizer (v1.0.5) is 44bd65c9…0f3f2ad0. It is possible that the Stashh developers used an older version of the optimizer to compile, but it seems unlikely and they could easily share that information, if so. Presumably, Stashh has created a safe custom SNIP-721 contract given that it has been developed by the same people who made the original reference implementation, but, as stated above, open sourcing would be much more likely to surface any bugs if there are any.

I have heard no explanation for why the first creators of NFT projects on Secret Network have chosen to keep their contracts closed source. The best I can do is speculate as to the reasons.

One reason might be that the code has innovations that the creator wants to protect. For example, it is a new kind of NFT used in a game and the creator wants to protect their intellectual property. In such a situation, the NFT contract itself is a very small part of a much larger system that includes a user interface front-end, possible back-end off-chain code, hardware setup, etc. Likewise, with artistic NFTs, the effort that is put into creating something that is unique and genuinely appeals to people cannot be underestimated. All of these other aspects of an NFT project, which are not trivial to implement, can be kept closed while making the NFT contract source code itself open. Importantly, the NFT contract is the only part of the system that governs a valuable, tradable commodity that people own.

Following on from the first reason, it is possible that the creator wants to keep certain randomized aspects of the minting process private. Originally when CryptoKitties (the first successful NFT project on Ethereum) was created, the developers kept the genetic algorithm that determined how new kitties were created closed source. Later on, in 2019 (in the spirit of decentralization) they open sourced it. It is easy to imagine that someone might want to create a similar gamified NFT contract on Secret Network where some aspect of a random process is not open to the players. Because data is encrypted on Secret Network there is an easy solution to keeping some aspects hidden while still allowing users to view the source code, and that is to parameterize the contract. Essentially, this just means that after the contract is initialized and before the mint begins, a function is called in the contract that sets the values of some variables (e.g., probabilities) that drive the random process. The code can be verified to not have any exploits, while the creator keeps some aspects of the generation of the NFTs hidden. Similarly, the assets that are used when generating the NFTs can also be parameterized, so there is no need to publish their locations on IPFS or wherever they might be stored.

It is hard to see how any perceived concerns around exposing parts of the project development justify obscuring the contract that a potential buyer signs on to when minting an NFT, or the potential exposure to harm that closed-source contracts can create. In addition, there is an advantage that comes from open sourcing contract code: it helps to spur on innovation in the wider ecosystem. Just look at what the creation and open-sourcing of the SNIP-721 reference implementation has already led to on the network. If all subsequent SNIP-721s remain closed, it will stagnate innovation.

Secret Network has differentiated itself from other blockchain networks because of its focus on programmable privacy and the end goal of empowering and protecting users of the decentralized web. Secret Swap was designed not only to protect the privacy of user’s data, but also to prevent the malicious practice of front-running which plagues AMMs on other networks. Front-running happens because of a power imbalance between validators/miners and the users of a network who do not have access to comparable resources or the technical know how to protect themselves. Similarly, closed-sourced NFT contracts create a power imbalance between people who know the ins and outs of manipulating contract code, and those who must trust without verification, if they want to participate. Currently, this is not even a question of providing a choice for informed users — as I have said none of the current NFT projects on Secret Network have linked to their contract source code prior to mint. Promoting projects that use closed-sourced SNIP-721 contracts flies in the face of Secret Network’s agenda — it leaves the users of the network vulnerable to rug pulls and code that has not been properly vetted. The argument that ¯\_(ツ)_/¯ this is crypto and buyer beware is exactly the sentiment that lets some miners on Ethereum keep talking about front-running in AMMs as a feature and not a bug.

It would be relatively straightforward for Stashh to add a form for NFT creators to submit a link to their contract’s source code and build configuration, and then write a script to compare it to the code hash on chain. That way they could flag projects that are verified, open source projects, and those that aren’t, and then let informed users make their own choice. It is true that other decentralized apps, such as Secret Swap, that use SNIP-20s (or ERC-20s, etc.) do not regularly provide any indicator as to whether the tokens are open source or not, because they don’t have to. The norm is that fungible tokens are open source and it is exceedingly rare when they are not. A fungible token can only ever accrue value when there is a very large community of users who invest in it, and any closed-source fungible token project on a decentralized network would be dead on arrival. The same should be true of NFTs, but because it takes a much smaller community to have a successful mint, it is much easier to find people who will mint anyway, especially when Secret Network leads are promoting them.

Such an indicator on Stashh, of course, would not prevent creators from putting closed-sourced NFTs on Secret Network (or even Stashh) if they want, as the network itself is permissionless. This small piece of information would simply work as a flag that indicates that the creator of an NFT project understands the role of the NFT as a “code-as-law” contract and puts potential buyers on an equal footing. It would provide a disincentive to create NFTs with backdoors or unfair distribution of tokens, and it would make NFTs on Secret Network safer and less vulnerable to code exploits. Open source is not a panacea — certainly bugs still exist in open source code and exploits happen (Secret Swap as a case in point) — but it is a reasonable request that we can make of NFT creators on Secret Network.

If NFT projects on Secret Network continue to require complete, blind trust in the developers, then effectively from the buyers perspective there is no advantage over a centralized system. Ultimately, it is incumbent on the community to put the question to NFT creators as to why they are not open sourcing their contracts. You can always vote with your wallet and choose not to buy until they do.

[Update 28 Dec, 2021: Since writing this article, I learned the Anons contract was open sourced in Nov. after mint (link), and Magic Skulls plans to open source after the mint is complete. While these are certainly improvements, ideally NFT contracts are open sourced before users interact with them, otherwise many of the advantages of open sourcing (less likelihood of bugs, full transparency, etc.) are nullified. I have yet to hear a compelling argument for why the custom changes in these contracts justify losing these advantages for the end consumers. It is true that other teams can copy ideas, but any sufficiently special and difficult-to-implement characteristics of an NFT mint will be tailored for the project and will require specific types of assets created, a community developed around it, etc. I find it difficult to imagine there are many cases where another team could easily swoop in in a few days and steal the idea before the original team mints. Plus, while it is laudable these two teams have done so (or stated they will), there’s little incentive left for many NFT creators to open source after they’ve already made hundreds of thousands or millions of dollars off of a mint, so there’s no guarantee that others will follow suit even if they say they will.]

--

--

Ben Adams

Associate Professor of Computer Science and Software Engineering at the University of Canterbury, New Zealand