{"id":13535840,"url":"https://github.com/ProjectOpenSea/shipyard-core","last_synced_at":"2025-04-02T02:31:37.382Z","repository":{"id":196138166,"uuid":"666110470","full_name":"ProjectOpenSea/shipyard-core","owner":"ProjectOpenSea","description":null,"archived":false,"fork":false,"pushed_at":"2024-07-29T21:31:48.000Z","size":3872,"stargazers_count":46,"open_issues_count":2,"forks_count":10,"subscribers_count":7,"default_branch":"main","last_synced_at":"2024-08-02T09:23:29.824Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Solidity","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ProjectOpenSea.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2023-07-13T18:30:25.000Z","updated_at":"2024-05-19T13:24:00.000Z","dependencies_parsed_at":null,"dependency_job_id":"fd2cb4e3-ef94-4027-98ce-a7106f047ab0","html_url":"https://github.com/ProjectOpenSea/shipyard-core","commit_stats":null,"previous_names":["projectopensea/shipyard-core"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ProjectOpenSea%2Fshipyard-core","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ProjectOpenSea%2Fshipyard-core/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ProjectOpenSea%2Fshipyard-core/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ProjectOpenSea%2Fshipyard-core/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ProjectOpenSea","download_url":"https://codeload.github.com/ProjectOpenSea/shipyard-core/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":222791943,"owners_count":17038320,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":[],"created_at":"2024-08-01T09:00:29.862Z","updated_at":"2024-11-03T00:31:33.644Z","avatar_url":"https://github.com/ProjectOpenSea.png","language":"Solidity","readme":"![Shipyard](img/shipyard-banner.jpg)\n\n# Quick Start Guide\n\nTo deploy an NFT contract to the Goerli testnet, fund an address with 0.25 Goerli ETH, swap in the appropriate values for `\u003cyour_key\u003e` and `\u003cyour_pk\u003e` in this command, open a terminal window, and run the following:\n\n```\ngit clone git@github.com:ProjectOpenSea/shipyard-core.git \u0026\u0026\ncd shipyard-core \u0026\u0026\ncurl -L https://foundry.paradigm.xyz | bash \u0026\u0026\nfoundryup \u0026\u0026\nforge build \u0026\u0026\nexport GOERLI_RPC='https://goerli.blockpi.network/v1/rpc/public \u0026\u0026\nexport ETHERSCAN_API_KEY='\u003cyour_key\u003e' \u0026\u0026\nexport MY_ACTUAL_PK_BE_CAREFUL='\u003cyour_pk\u003e' \u0026\u0026\nforge create --rpc-url $GOERLI_RPC \\\n    --private-key $MY_ACTUAL_PK_BE_CAREFUL \\\n    --etherscan-api-key $ETHERSCAN_API_KEY \\\n    --verify \\\n    src/reference/ExampleNFT.sol:ExampleNFT\n```\n\nA quick breakdown of each step follows.\n\nClone the `shipyard-core` repository and change directories into it:\n\n```\ngit clone git@github.com:ProjectOpenSea/shipyard-core.git \u0026\u0026\ncd shipyard-core\n```\n\nInstall the `foundryup` up command and run it, which in turn installs forge, cast, anvil, and chisel:\n\n```\ncurl -L https://foundry.paradigm.xyz | bash \u0026\u0026\nfoundryup\n```\n\nInstall dependencies and compile the contracts:\n\n```\nforge build\n```\n\nSet up your environment variables:\n\n```\nexport GOERLI_RPC='https://goerli.blockpi.network/v1/rpc/public\t \u0026\u0026\nexport ETHERSCAN_API_KEY='\u003cyour_key\u003e' \u0026\u0026\nexport MY_ACTUAL_PK_BE_CAREFUL='\u003cyour_pk\u003e'\n```\n\nRun the `forge create` command, which deploys the contract:\n\n```\nforge create --rpc-url $GOERLI_RPC \\\n    --private-key $MY_ACTUAL_PK_BE_CAREFUL \\\n    --etherscan-api-key $ETHERSCAN_API_KEY \\\n    --verify \\\n    src/reference/ExampleNFT.sol:ExampleNFT\n```\n\nSee https://book.getfoundry.sh/reference/forge/forge-create for more information on `forge create`.\n\n## Deploying to mainnet\n\n\u003e Warning: these contracts have not yet been formally audited. Exercise caution when deploying to mainnet and consider additional review and independent audits.\n\nTo deploy to mainnet, replace the value supplied to `--rpc-url` with a mainnet RPC URL. For example:\n\n```\nexport MAINNET_RPC='https://eth.llamarpc.com' \u0026\u0026\nforge create --rpc-url $MAINNET_RPC \\\n    --private-key $MY_ACTUAL_PK_BE_CAREFUL \\\n    --etherscan-api-key $ETHERSCAN_API_KEY \\\n    --verify \\\n    src/reference/ExampleNFT.sol:ExampleNFT\n```\n\nNote that this will deploy ExampleNFT to mainnet, which will cost real money and will not produce much value as a result.\n\n# Running ffi tests\n\nCurrently, the ffi tests are the only way to test the output of ExampleNFT's tokenURI response. More options soon™.\n\nIn general, it's wise to be especially wary of ffi code. In the words of the Foundrybook, \"It is generally advised to use this cheat code as a last resort, and to not enable it by default, as anyone who can change the tests of a project will be able to execute arbitrary commands on devices that run the tests.\"\n\n## Environment configuration\n\nTo run the ffi tests locally, set `FOUNDRY_PROFILE='ffi'` in your `.env` file, and then source the `.env` file. This will permit Forge to make foreign calls (`ffi = true`) and read and write within the `./test-ffi/` directory. It also tells Forge to run the tests in the `./test-ffi/` directory instead of the tests in the `./test/` directory, which are run by default. Check out the `foundry.toml` file, where all of this and more is configured.\n\nIt's necessary to install the dependencies in `./test-ffi/scripts` before running the ffi tests. From the top level, run `cd test-ffi/scripts \u0026\u0026 yarn \u0026\u0026 ../..`. Then, running `forge test -vvv` should result in the tests passing.\n\nBoth the local profile and the CI profile for the ffi tests use a low number of fuzz runs, because the ffi lifecycle is slow. Before yeeting a project to mainnet, it's advisable to crank up the number of fuzz runs to increase the likelihood of catching an issue. It'll take more time, but it increases the likelihood of catching an issue.\n\n## Expected local behavior\n\nThe `ExampleNFT.t.sol` file will call `ExampleNFT.sol`'s `tokenURI` function, decode the base64 encoded response, write the decoded version to `./test-ffi/tmp/temp.json`, and then call the `process_json.js` file a few times to get string values. If the expected values and the actual values match, the test will pass and the files will be cleaned up. If they fail, a `temp-*.json` file will be left behind for reference. You can ignore it or delete it after you're done inspecting it. Forge makes a new one on the fly if it's not there. And it's ignored in the `.gitignore` file, so there's no need to worry about pushing cruft or top secret metadata to a shared/public repo. The tests in `svg.t.sol` behave more or less the same way, except that they'll produce many more temporary files.\n\n## Expected CI behavior\n\nWhen a PR is opened or when a new commit is pushed, Github runs a series of actions defined in the files in `.github/workflows/*.yml`. The normal Forge tests and linting are set up in `test.yml`. The ffi tests are set up in `test-ffi.yml`. Forks of this repository can safely disregard it or if it's not necessary, remove it entirely.\n","funding_links":[],"categories":["Starter Kits"],"sub_categories":["Smart Contract Starter Kits"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FProjectOpenSea%2Fshipyard-core","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FProjectOpenSea%2Fshipyard-core","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FProjectOpenSea%2Fshipyard-core/lists"}