{"id":40983161,"url":"https://github.com/dapperlabs/nba-smart-contracts","last_synced_at":"2026-01-22T07:19:26.515Z","repository":{"id":37790718,"uuid":"197422466","full_name":"dapperlabs/nba-smart-contracts","owner":"dapperlabs","description":"Smart contracts and transactions for Topshot, the official NBA digital collectibles game on the Flow Blockchain","archived":false,"fork":false,"pushed_at":"2025-11-07T19:15:24.000Z","size":4316,"stargazers_count":335,"open_issues_count":17,"forks_count":105,"subscribers_count":60,"default_branch":"master","last_synced_at":"2025-11-07T19:21:04.323Z","etag":null,"topics":["blockchain","collectibles","nba","nft","smart-contracts"],"latest_commit_sha":null,"homepage":"https://www.nbatopshot.com","language":"Cadence","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"unlicense","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dapperlabs.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":"NOTICE","maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2019-07-17T16:06:37.000Z","updated_at":"2025-07-14T22:32:40.000Z","dependencies_parsed_at":"2023-09-29T00:34:17.103Z","dependency_job_id":"42817019-f24c-480b-93c8-e1642c7e966c","html_url":"https://github.com/dapperlabs/nba-smart-contracts","commit_stats":null,"previous_names":[],"tags_count":66,"template":false,"template_full_name":null,"purl":"pkg:github/dapperlabs/nba-smart-contracts","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dapperlabs%2Fnba-smart-contracts","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dapperlabs%2Fnba-smart-contracts/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dapperlabs%2Fnba-smart-contracts/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dapperlabs%2Fnba-smart-contracts/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dapperlabs","download_url":"https://codeload.github.com/dapperlabs/nba-smart-contracts/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dapperlabs%2Fnba-smart-contracts/sbom","scorecard":{"id":322230,"data":{"date":"2025-08-11","repo":{"name":"github.com/dapperlabs/nba-smart-contracts","commit":"ab3cf08772f7762022d6cd01fa63ea84b6bad290"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":5.3,"checks":[{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Info: jobLevel 'actions' permission set to 'read': .github/workflows/codeql-analysis.yml:28","Info: jobLevel 'contents' permission set to 'read': .github/workflows/codeql-analysis.yml:29","Warn: no topLevel permission defined: .github/workflows/ci.yml:1","Warn: no topLevel permission defined: .github/workflows/codeql-analysis.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Code-Review","score":10,"reason":"all changesets reviewed","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Security-Policy","score":10,"reason":"security policy file detected","details":["Info: security policy file detected: SECURITY.md:1","Info: Found linked content: SECURITY.md:1","Info: Found disclosure, vulnerability, and/or timelines in security policy: SECURITY.md:1","Info: Found text in security policy: SECURITY.md:1"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Maintained","score":1,"reason":"2 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 1","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:9: update your workflow using https://app.stepsecurity.io/secureworkflow/dapperlabs/nba-smart-contracts/ci.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:10: update your workflow using https://app.stepsecurity.io/secureworkflow/dapperlabs/nba-smart-contracts/ci.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/codeql-analysis.yml:42: update your workflow using https://app.stepsecurity.io/secureworkflow/dapperlabs/nba-smart-contracts/codeql-analysis.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/codeql-analysis.yml:46: update your workflow using https://app.stepsecurity.io/secureworkflow/dapperlabs/nba-smart-contracts/codeql-analysis.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/codeql-analysis.yml:57: update your workflow using https://app.stepsecurity.io/secureworkflow/dapperlabs/nba-smart-contracts/codeql-analysis.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/codeql-analysis.yml:71: update your workflow using https://app.stepsecurity.io/secureworkflow/dapperlabs/nba-smart-contracts/codeql-analysis.yml/master?enable=pin","Info:   0 out of   6 GitHub-owned GitHubAction dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: The Unlicense: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Branch-Protection","score":-1,"reason":"internal error: error during branchesHandler.setup: internal error: githubv4.Query: Resource not accessible by integration","details":null,"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"SAST","score":7,"reason":"SAST tool detected but not run on all commits","details":["Info: SAST configuration detected: CodeQL","Warn: 0 commits out of 30 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Vulnerabilities","score":2,"reason":"8 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GO-2025-3372 / GHSA-6wxm-mpqj-6jpf","Warn: Project is vulnerable to: GO-2025-3487 / GHSA-hcg3-q754-cr77","Warn: Project is vulnerable to: GO-2025-3503 / GHSA-qxp5-gwg8-xv66","Warn: Project is vulnerable to: GO-2025-3595 / GHSA-vvgc-356p-c3xw","Warn: Project is vulnerable to: GO-2025-3488 / GHSA-6v2p-p543-phr9","Warn: Project is vulnerable to: GO-2024-3321 / GHSA-v778-237x-gjrc","Warn: Project is vulnerable to: GO-2024-2819 / GHSA-4xc9-8hmq-j652","Warn: Project is vulnerable to: GO-2024-3333"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-18T01:39:39.694Z","repository_id":37790718,"created_at":"2025-08-18T01:39:39.701Z","updated_at":"2025-08-18T01:39:39.701Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28658102,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-22T01:17:37.254Z","status":"online","status_checked_at":"2026-01-22T02:00:07.137Z","response_time":144,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["blockchain","collectibles","nba","nft","smart-contracts"],"created_at":"2026-01-22T07:19:25.863Z","updated_at":"2026-01-22T07:19:26.507Z","avatar_url":"https://github.com/dapperlabs.png","language":"Cadence","funding_links":[],"categories":[],"sub_categories":[],"readme":"# NBA Top Shot\n\n## Introduction\n\nThis repository contains the smart contracts and transactions that implement\nthe core functionality of NBA Top Shot.\n\nThe smart contracts are written in Cadence, a new resource oriented\nsmart contract programming language designed for the Flow Blockchain.\n\n### What is NBA Top Shot\n\nNBA Top Shot is the official digital collectibles\ngame for the National Basketball Association. Players collect and trade\ndigital collectibles that represent highlights from the best players \nin the world. See more at nbatopshot.com\n\n### What is Flow?\n\nFlow is a new blockchain for open worlds. Read more about it [here](https://www.onflow.org/).\n\n### What is Cadence?\n\nCadence is a new Resource-oriented programming language \nfor developing smart contracts for the Flow Blockchain.\nRead more about it [here](https://www.docs.onflow.org)\n\nWe recommend that anyone who is reading this should have already\ncompleted the [Cadence Tutorials](https://docs.onflow.org/cadence) \nso they can build a basic understanding of the programming language.\n\nResource-oriented programming, and by extension Cadence, \nis the perfect programming environment for Non-Fungible Tokens (NFTs), because users are able\nto store their NFT objects directly in their accounts and transact\npeer-to-peer. Please see the [blog post about resources](https://medium.com/dapperlabs/resource-oriented-programming-bee4d69c8f8e)\nto understand why they are perfect for digital assets like NBA Top Shot Moments.\n\n### Contributing\n\nIf you see an issue with the code for the contracts, the transactions, scripts,\ndocumentation, or anything else, please do not hesitate to make an issue or\na pull request with your desired changes. This is an open source project\nand we welcome all assistance from the community!\n\n## Top Shot Contract Addresses\n\n`TopShot.cdc`: This is the main Top Shot smart contract that defines\nthe core functionality of the NFT.\n\n| Network | Contract Address     |\n|---------|----------------------|\n| Testnet | [`0x877931736ee77cff`](https://contractbrowser.com/A.877931736ee77cff.TopShot) |\n| Mainnet | [`0x0b2a3299cc857e29`](https://contractbrowser.com/A.0b2a3299cc857e29.TopShot) |\n\n\u003e **Note**: Bridged Top Shot Moments are available on Flow EVM. See the [EVM Bridging README](evm-bridging/README.md) for contract addresses and details.\n\n`MarketTopShot.cdc`: This is the top shot marketplace contract that allows users\nto buy and sell their NFTs.\n\n| Network | Contract Address     |\n|---------|----------------------|\n| Testnet | [`0x547f177b243b4d80`](https://contractbrowser.com/A.547f177b243b4d80.TopShotMarketV3) |\n| Mainnet | [`0xc1e4f4f4c4257510`](https://contractbrowser.com/A.c1e4f4f4c4257510.TopShotMarketV3) |\n\n### Non Fungible Token Standard\n\nThe NBA Top Shot contracts utilize the [Flow NFT standard](https://github.com/onflow/flow-nft)\nwhich is equivalent to ERC-721 or ERC-1155 on Ethereum. If you want to build an NFT contract,\nplease familiarize yourself with the Flow NFT standard before starting and make sure you utilize it \nin your project in order to be interoperable with other tokens and contracts that implement the standard.\n\n### Top Shot Marketplace contract\n\nThe top shot marketplace contract was designed in the very early days of Cadence, and therefore\nuses some language features that are NOT RECOMMENDED to use by newer projects.\nFor example, the marketplace contract stores the moments that are for sale in the sale collection.\nThe correct way to manage this in cadence is to give a collection capability to the market collection\nso that the nfts do not have to leave the main collection when going up for sale. The sale collection\nwould use this capability to withdraw moments from the main collection when they are purchased.\n\nThis way, any other smart contracts that need to check a user's account for what they own only need to check\nthe main collection and not all of the sale collections that could possibly be in their account.\n\nSee the [kitty items marketplace contract](https://github.com/onflow/kitty-items/blob/master/cadence/contracts/KittyItemsMarket.cdc) for an example of the current best practices when\nit comes to marketplace contracts.\n\n## Directory Structure\n\nThe directories here are organized into contracts, scripts, and transactions.\n\nContracts contain the source code for the Top Shot contracts that are deployed to Flow.\n\nScripts contain read-only transactions to get information about\nthe state of someone's Collection or about the state of the TopShot contract.\n\nTransactions contain the transactions that various admins and users can use\nto perform actions in the smart contract like creating plays and sets,\nminting Moments, and transferring Moments.\n\n - `contracts/` : Where the Top Shot related smart contracts live.\n - `transactions/` : This directory contains all the transactions and scripts\n that are associated with the Top Shot smart contracts.\n - `transactions/scripts/`  : This contains all the read-only Cadence scripts \n that are used to read information from the smart contract\n or from a resource in account storage.\n - `lib/` : This directory contains packages for specific programming languages\n to be able to read copies of the Top Shot smart contracts, transaction templates,\n and scripts. Also contains automated tests written in those languages. Currently,\n Go is the only language that is supported, but we are hoping to add javascript\n and other languages soon. See the README in `lib/go/` for more information\n about how to use the Go packages.\n - `evm-bridging/` : This directory contains the smart contracts and transactions\n for the EVM bridging functionality.\n\n## Top Shot Contract Overview\n\nEach Top Shot Moment NFT represents a play from a game in the NBA season.\nPlays are grouped into sets which usually have some overarching theme,\nlike rarity or the type of the play. \n\nA set can have one or more plays in it and the same play can exist in\nmultiple sets, but the combination of a play and a set, \notherwise known as an edition, is unique and is what classifies an individual Moment.\n\nMultiple Moments can be minted from the same edition and each receives a \nserial number that indicates where in the edition it was minted.\n\nEach Moment is a resource object \nwith roughly the following structure:\n\n```cadence\npub resource Moment {\n\n    // global unique Moment ID\n    pub let id: UInt64\n    \n    // the ID of the Set that the Moment comes from\n    pub let setID: UInt32\n\n    // the ID of the Play that the Moment references\n    pub let playID: UInt32\n\n    // the place in the edition that this Moment was minted\n    // Otherwise known as the serial number\n    pub let serialNumber: UInt32\n}\n```\n\nThe other types that are defined in `TopShot` are as follows:\n\n - `Play`: A struct type that holds most of the metadata for the Moments.\n    All plays in Top Shot will be stored and modified in the main contract.\n - `SetData`: A struct that contains constant information about sets in Top Shot\n    like the name, the series, the id, and such.\n - `Set`: A resource that contains variable data for sets \n    and the functionality to modify sets,\n    like adding and retiring plays, locking the set, and minting Moments from\n    the set.\n - `MomentData`: A struct that contains the metadata associated with a Moment.\n    instances of it will be stored in each Moment.\n - `NFT`: A resource type that is the NFT that represents the Moment\n    highlight a user owns. It stores its unique ID and other metadata. This\n    is the collectible object that the users store in their accounts.\n - `Collection`: Similar to the `NFTCollection` resource from the NFT\n    example, this resource is a repository for a user's Moments.  Users can\n    withdraw and deposit from this collection and get information about the \n    contained Moments.\n - `Admin`: This is a resource type that can be used by admins to perform\n    various actions in the smart contract like starting a new series, \n    creating a new play or set, and getting a reference to an existing set.\n - `QuerySetData`: A struct that contains the metadata associated with a set.\n    This is currently the only way to access the metadata of a set.\n    Can be accessed by calling the public function in the `TopShot` smart contract called `getSetData(setID)`\n\nMetadata structs associated with plays and sets are stored in the main smart contract\nand can be queried by anyone. For example, If a player wanted to find out the \nname of the team that the player represented in their Moment plays for, they\nwould call a public function in the `TopShot` smart contract \ncalled `getPlayMetaDataByField`, providing, from their owned Moment,\nthe play and field that they want to query. \nThey can do the same with information about sets by calling `getSetData` with the setID.\n\nThe power to create new plays, sets, and Moments rests \nwith the owner of the `Admin` resource.\n\nAdmins create plays and sets which are stored in the main smart contract,\nAdmins can add plays to sets to create editions, which Moments can be minted from.\n\nAdmins also can restrict the abilities of sets and editions to be further expanded.\nA set begins as being unlocked, which means plays can be added to it,\nbut when an admin locks the set, plays can no longer be added to it. \nThis cannot be reversed.\n\nThe same applies to editions. Editions start out open, and an admin can mint as\nmany Moments they want from the edition. When an admin retires the edition, \nMoments can no longer be minted from that edition. This cannot be reversed.\n\nThese rules are in place to ensure the scarcity of sets and editions\nonce they are closed.\n\nOnce a user owns a Moment object, that Moment is stored directly \nin their account storage via their `Collection` object. The collection object\ncontains a dictionary that stores the Moments and gives utility functions\nto move them in and out and to read data about the collection and its Moments.\n\n## How to Deploy and Test the Top Shot Contract in VSCode\n\nThe first step for using any smart contract is deploying it to the blockchain,\nor emulator in our case. Do these commands in vscode. \nSee the [vscode extension instructions](https://docs.onflow.org/vscode-extension/) \nto learn how to use it.\n\n 1. Start the emulator with the `Run emulator` vscode command.\n 2. Open the `NonFungibleToken.cdc` file from the [flow-nft repo](https://github.com/onflow/flow-nft/blob/master/contracts/NonFungibleToken.cdc) and the `TopShot.cdc` file.  Feel free to read as much as you want to familiarize yourself with the contracts.\n 3. In `NonFungibleToken.cdc`, click the `deploy contract to account` \n above the `Dummy` contract at the bottom of the file to deploy it.\n This also deploys the `NonFungbleToken` interface.\n 4. In `TopShot.cdc`, make sure it imports `NonFungibleToken` from the account you deployed it to.\n 5. Click the `deploy contract to account` button that appears over the \n    `TopShot` contract declaration to deploy it to a new account.\n\nThis deploys the contract code. It also runs the contract's\n`init` function, which initializes the contract storage variables,\nstores the `Collection` and `Admin` resources \nin account storage, and creates links to the `Collection`.\n\nAs you can see, whenever we want to call a function, read a field,\nor use a type that is defined in a smart contract, we simply import\nthat contract from the address it is defined in and then use the imported\ncontract to access those type definitions and fields.\n\nAfter the contracts have been deployed, you can run the sample transactions\nto interact with the contracts. The sample transactions are meant to be used\nin an automated context, so they use transaction arguments and string template\nfields. These make it easier for a program to use and interact with them.\nIf you are running these transactions manually in the Flow Playground or\nvscode extension, you will need to remove the transaction arguments and\nhard code the values that they are used for. \n\nYou also need to replace the `ADDRESS` placeholders with the actual Flow \naddresses that you want to import from.\n\n## How to Run Transactions Against the Top Shot Contract\nThis repository contains sample transactions that can be executed against the Top Shot contract either via Flow CLI or using VSCode. This section will describe how to create a new Top Shot set on the Flow emulator.\n\n#### Send Transaction with Flow CLI\n1. Install the [Flow CLI and emulator](https://docs.onflow.org/flow-cli/install/)\n2. Initialize the flow emulator configuration.  \n`flow emulator --init`\n3. [Configure the contracts \u0026 deployment section](https://docs.onflow.org/flow-cli/configuration/) of the initialized flow.json file. \n4. Start the emulator.  \n`flow emulator`\n5. On TopShot.cdc substitute the placeholder address `import NonFungibleToken from 0xNFTADDRESS` with the address the NonFungibleToken was deployed to. This will be the emulator address found in the accounts object of the initialized flow.json.\n6. Deploy the NonFungibleToken \u0026 TopShot contracts to the flow emulator.  \n`flow project deploy --network=emulator`\n7. Use the Flow CLI to execute transactions against the emulator. This transaction creates a new set on the flow emulator called \"new set name\".   \n`flow transactions send ./transactions/admin/create_set.cdc \"new set name\"`\n\n#### Send Transaction with VSCode\n1. [Install and configure](https://docs.onflow.org/vscode-extension/) VSCode extension.\n2. Start flow emulator by running the VSCode command.  \n`Cadence: Run emulator`\n3. On TopShot.cdc substitute the placeholder address `import NonFungibleToken from 0xNFTADDRESS` with the address the NonFungibleToken was deployed to. Typically, this will be the service account address.\n4. Above the contract definition `pub contract interface NonFungibleToken` you will see and press text to deploy this contract to the service account.\n5. Above the contract definition `pub contract TopShot: NonFungibleToken` you will see and press text to deploy this contract to the service account.\n6. Navigate to `transactions/admin/create_set.cdc` Substitute the placeholder address `import TopShot from 0xNFTADDRESS` with the address TopShot.cdc was deployed to.\n7. Transactions run in VSCode cannot take arguments. Replace the line `transaction(setName : String)` with `transaction()` and find every instance of setName in the contract and replace with a hard coded value like \"new set name\".\n8. Above the line `transaction()` you will now see and press the text `Send signed by service account`. This will create a set on the flow emulator called \"new set name\".\n\n## How to run the automated tests for the contracts\n\nSee the `lib/go` README for instructions about how to run the automated tests.\n\n## Instructions for creating plays and minting moments\n\nA common order of creating new Moments would be\n\n1. Creating new plays with `transactions/admin/create_play.cdc`.\n2. Creating new sets with `transactions/admin/create_set.cdc`.\n3. Adding plays to the sets to create editions\n   with `transactions/admin/add_plays_to_set.cdc`.\n4. Minting Moments from those editions with \n   `transactions/admin/batch_mint_moment.cdc`.\n\nYou can also see the scripts in `transactions/scripts` to see how information\ncan be read from the real Top Shot smart contract deployed on the\nFlow Beta Mainnet. \n\n### Accessing the NBA Top Shot smart contract on Flow Beta Mainnet\n\nThe Flow Beta mainnet is still a work in progress and still has\na limited number of accounts that can run nodes and submit transactions.\nAnyone can read data from the contract by running any of the scripts in the \n`transactions` directory using one of the public access nodes.\n\nFor example, this is how you would query the total supply via the Flow CLI.\n\n`flow scripts execute transactions/scripts/get_totalSupply.cdc --host access.mainnet.nodes.onflow.org:9000`\n\nMake sure that the import address in the script is correct for mainnet.\n\n## NBA Top Shot Events\n\nThe smart contract and its various resources will emit certain events\nthat show when specific actions are taken, like transferring an NFT. This\nis a list of events that can be emitted, and what each event means.\nYou can find definitions for interpreting these events in Go by seeing\nthe `lib/go/events` package.\n    \n\n#### Events for plays\n- `pub event PlayCreated(id: UInt32, metadata: {String:String})`\n    \n    Emitted when a new play has been created and added to the smart contract by an admin.\n\n- `pub event NewSeriesStarted(newCurrentSeries: UInt32)`\n    \n    Emitted when a new series has been triggered by an admin.\n\n#### Events for set-Related actions\n\n- `pub event SetCreated(setID: UInt32, series: UInt32)`\n    \n    Emitted when a new set is created.\n    \n- `pub event PlayAddedToSet(setID: UInt32, playID: UInt32)`\n    \n    Emitted when a new play is added to a set.\n    \n- `pub event PlayRetiredFromSet(setID: UInt32, playID: UInt32, numMoments: UInt32)`\n\n    Emitted when a play is retired from a set. Indicates that \n    that play/set combination and cannot be used to mint moments any more.\n    \n- `pub event SetLocked(setID: UInt32)`\n\n    Emitted when a set is locked, meaning plays cannot be added.\n    \n- `pub event MomentMinted(momentID: UInt64, playID: UInt32, setID: UInt32, serialNumber: UInt32)`\n\n    Emitted when a Moment is minted from a set. The `momentID` is the global unique identifier that differentiates a Moment from all other Top Shot Moments in existence. The `serialNumber` is the identifier that differentiates the Moment within an Edition. It corresponds to the place in that edition where it was minted. \n\n#### Events for Collection-related actions\n    \n- `pub event Withdraw(id: UInt64, from: Address?)`\n\n    Emitted when a Moment is withdrawn from a collection. `id` refers to the global Moment ID. If the collection was in an account's storage when it was withdrawn, `from` will show the address of the account that it was withdrawn from. If the collection was not in storage when the Moment was withdrawn, `from` will be `nil`.\n\n- `pub event Deposit(id: UInt64, to: Address?)`\n\n    Emitted when a Moment is deposited into a collection. `id` refers to the global Moment ID. If the collection was in an account's storage when it was deposited, `to` will show the address of the account that it was deposited to. If the collection was not in storage when the Moment was deposited, `to` will be `nil`.\n\n### Top Shot NFT Metadata\n\nNFT metadata is represented in a flexible and modular way using the [standard proposed in FLIP-0636](https://github.com/onflow/flow/blob/master/flips/20210916-nft-metadata.md). The Top Shot contract implements the [`MetadataViews.Resolver`](https://github.com/onflow/flow-nft/blob/master/contracts/MetadataViews.cdc#L21) interface, which standardizes the display of Top Shot NFT in accordance with FLIP-0636. The Top Shot contract also defines a custom view of moment play data called TopShotMomentMetadataView.\n\n## NBA Top Shot Packs\n\nNBA Top Shot packs are currently off-chain and not managed by the NBA Top Shot smart contract. Moments in a pack are minted on-chain, and assembled into a pack for purchase off-chain on the NBA Top Shot platform. When a collector purchases a pack, the moments within the pack are transferred directly to this collector on-chain. The NBA Top Shot smart contract has no knowledge of packs.\n\n## NBA Top Shot Marketplace\n\nThe `contracts/MarketTopShot.cdc` contract allows users to create a sale object\nin their account to sell their Moments.\n\nWhen a user wants to sell their Moment, they create a sale collection\nin their account and specify a beneficiary of a cut of the sale if they wish.\n\nA Top Shot Sale Collection contains a capability to the owner's moment collection\nthat allows the sale to withdraw the moment when it is purchased.\n\nWhen another user wants to buy the Moment that is for sale, they simply send \ntheir fungible tokens to the `purchase` function \nand if they sent the correct amount, they get the Moment back.\n\n#### Events for Market-related actions\n\n- `pub event MomentListed(id: UInt64, price: UFix64, seller: Address?)`\n   \n   Emitted when a user lists a Moment for sale in their SaleCollection.\n\n- `pub event MomentPriceChanged(id: UInt64, newPrice: UFix64, seller: Address?)`\n\n   Emitted when a user changes the price of their Moment.\n\n- `pub event MomentPurchased(id: UInt64, price: UFix64, seller: Address?)`\n\n   Emitted when a user purchases a Moment that is for sale.\n\n- `pub event MomentWithdrawn(id: UInt64, owner: Address?)`\n\n   Emitted when a seller withdraws their Moment from their SaleCollection.\n\n- `pub event CutPercentageChanged(newPercent: UFix64, seller: Address?)`\n\n   Emitted when a seller changes the percentage cut that is taken\n   from their sales and sent to a beneficiary.\n\n### Different Versions of the Market Contract\n\nThere are two versions of the Top Shot Market Contract.\n`TopShotMarket.cdc` is the original version of the contract that was used\nfor the first set of sales in the p2p marketplace, but we made improvements\nto it which are now in `TopShotMarketV3.cdc`.\n\nThere is also a V2 version that was deployed to mainnet, but will never be used.\n\nBoth versions define a `SaleCollection` resource that users store in their account.\nThe resource manages the logic of the sale like listings, de-listing, prices, and \npurchases. The first version actually stores the moments that are for sale, but \nwe realized that this causes issues if other contracts need to access a user's\nmain collection to see what they own. We created the second version to simply\nstore a capability to the owner's moment collection so that the moments \nthat are for sale do not need to be removed from the main collection to be\nput up for sale. In this version, when a moment is purchased, the sale collection\nuses the capability to withdraw the moment from the main collection and \nreturns it to the buyer.\n\nThe new version of the market contract is currently NOT DEPLOYED to mainnet,\nbut it will be deployed and utilized in the near future.\n\n## TopShot contract improvement\nSome improvements were made to the Topshot contract to reflect some cadence best practices and fix a bug.\nIn-depth explanation on the changes and why we made them can be found in our [Blog Post](https://blog.nbatopshot.com/posts/nba-top-shot-smart-contract-improvements) \n\n## TopShot Locking Contract Overview\n\nContract Name: `TopShotLocking`\n\nTopShot NFTs can be locked for a duration meaning they are unable to be withdrawn, listed for sale, burned, etc. \nIn the NBA TopShot product users are rewarded for locking their moments.\n\nAn NFT may be unlocked after the lock duration has passed, or the contract admin has marked it eligible for unlocking.\n\nThe moment is locked even if expiry has passed until the owner requests it be unlocked.\nThe address which owns the locked NFT must make an unlocking transaction once it is eligible.\n\n### Available functions\n\n#### lockNFT\n`pub fun lockNFT(nft: @NonFungibleToken.NFT, expiryTimestamp: UFix64): @NonFungibleToken.NFT`  \nTakes a TopShot.NFT resource and sets it in the lockedNFTs dictionary, the value of the entry is the expiry timestamp  \nParams:  \n`nft` - a `NonFungibleToken.NFT` resource, but must conform to `TopShot.NFT` asserted at runtime  \n`expiryTimestamp` - the unix timestamp in seconds at which this nft can be unlocked\n\nExample:\n```cadence\nlet collectionRef = acct.borrow\u003c\u0026TopShot.Collection\u003e(from: /storage/MomentCollection)\n            ?? panic(\"Could not borrow from MomentCollection in storage\")\n\nlet ONE_YEAR_IN_SECONDS: UFix64 = UFix64(31536000)\ncollectionRef.lock(id: 1, duration: ONE_YEAR_IN_SECONDS)\n```\n\n#### unlockNFT\n`pub fun unlockNFT(nft: @NonFungibleToken.NFT): @NonFungibleToken.NFT`  \nTakes a `NonFungibleToken.NFT` resource and attempts to remove it from the lockedNFTs dictionary.\nThis function will panic if the nft lock has not expired or been overridden by an admin.\nParams:  \n`nft` - a `NonFungibleToken.NFT` resource \n\nExample:\n```cadence\nlet collectionRef = acct.borrow\u003c\u0026TopShot.Collection\u003e(from: /storage/MomentCollection)\n            ?? panic(\"Could not borrow from MomentCollection in storage\")\n\ncollectionRef.unlock(id: 1)\n```\n\n#### isLocked\n`pub fun isLocked(nftRef: \u0026NonFungibleToken.NFT): Bool`  \nReturns true if the moment is locked\n\n#### getLockExpiry\n`pub fun getLockExpiry(nftRef: \u0026NonFungibleToken.NFT): UFix64`  \nReturns the unix timestamp when the nft is eligible for unlock\n\n### Admin Functions\n\n#### markNFTUnlockable\n`pub fun markNFTUnlockable(nftRef: \u0026NonFungibleToken.NFT)`  \nPlaces the nft id in an unlockableNFTs dictionary. This dictionary is checked in the `unlockNFT` function and bypasses the `expiryTimestamp`\nParams:  \n`nftRef` - a reference to an `NonFungibleToken.NFT` resource  \n\nExample:\n```cadence\nlet adminRef: \u0026NFTLocking.Admin\n\nprepare(acct: AuthAccount) {\n    // Set TopShotLocking admin ref\n    self.adminRef = acct.borrow\u003c\u0026NFTLocking.Admin\u003e(from: /storage/TopShotLockingAdmin)!\n}\n\nexecute {\n    // Set Top Shot NFT Owner collection ref\n    let owner = getAccount(0x179b6b1cb6755e31)\n    let collectionRef = owner.getCapability(/public/MomentCollection).borrow\u003c\u0026{TopShot.MomentCollectionPublic}\u003e()\n        ?? panic(\"Could not reference owner's moment collection\")\n\n    let nftRef = collectionRef.borrowNFT(id: 1)\n    self.adminRef.markNFTUnlockable(nftRef: nftRef)\n}\n```\n### Contracts Honoring the Lock\n\n- TopShot `withdraw`\n- MarketTopShot relies on the NFT being withdrawn first so no additional code is needed\n- TopShotMarketV3 `listForSale`\n\n## License \n\nThe works in these folders \n/dapperlabs/nba-smart-contracts/blob/master/contracts/TopShot.cdc \n/dapperlabs/nba-smart-contracts/blob/master/contracts/MarketTopShot.cdc \n/dapperlabs/nba-smart-contracts/blob/master/contracts/MarketTopShotV3.cdc \n/dapperlabs/nba-smart-contracts/blob/master/contracts/TopShotAdminReceiver.cdc \n/dapperlabs/nba-smart-contracts/blob/master/contracts/TopShotShardedCollection.cdc \n\nare under the Unlicense\nhttps://github.com/onflow/flow-NFT/blob/master/LICENSE\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdapperlabs%2Fnba-smart-contracts","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdapperlabs%2Fnba-smart-contracts","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdapperlabs%2Fnba-smart-contracts/lists"}