@sportsmetaverse/contracts v0.1.1
SportsMetaverse Contracts
This projects implements the core contracts for the SportsMetaverse. It uses a diamond proxy pattern to separate business logic and storage.
Getting Started
There is a makefile with a bunch of commands for interacting with the application. Most of the relevant tasks redirect to the package.json so npm can also be used.
# setup
make environment
# build
make build
# deploy locally
make deploy
# test
make test
Deployed Contracts
Contract | Description |
---|---|
Authorization | The Auth contract for verifying logins |
LandProxy | The Diamond proxy responsible for storage |
LandAdmin | Administrative functions |
LandMetadata | Metadata functions |
LandToken | ERC-1155 Implementation |
Token Implementations
In the ./contracts/token
folder. There are unit tests to demonstrate gas comparisons that you need to turn on. They are skipped by default to speed up testing. The deployed Land code only uses the ERC-1155NS
implementation.
Contract | Description |
---|---|
ERC-1155NS | 1155 "NS" the OZ impl with diamond storage |
- 1155D is useful for sequential mints that mimic an ERC-721.
- 1155DS is the same as above but uses a diamond storage pattern.
- 1155NS is useful for non-sequential mints that rely on diamonds or other proxies
Architecture
The project utilizes the Diamond Storage layout exclusively. Specifically, it relies on the SolidState Solidity implementation, however custom token imeplementations are used since the SolidState implementation relies on the generic OpenZepplin contracts.
Mechanism Design
The LandProxy
contract executes a land sale. The land sale is divided into several Zones
(e.g. Sports City, Lion Lands, etc.) and each Zone has four unique Segments
. Each Zone and Segment has a maximum allotment of land available for purchase (e.g. 2500 units in sports city). The initial land drop will be a smaller allocation (e.g. 20%). All of that is managed through ./settings.ts
where configuration values are defined.
Further, the contracts support assigning discounts for specific users (e.g. Holders of a Lion's Club NFT receveive a 30% discount in Lion's Land only).
Users are able to Mint
, MintMany
and MintDiscount
. Minting is controlled offchain via a digital signature that is distributed by a server. The user requests a quantity for mint to the server, and the server responds with a message
that includes a request
and a signature
. The request is verified by calling canMint
and is checked on-chain when the user calls one of the mint functions.
Core behavior is defined in tests in the ./spec
folder. Ancillary and integration behavior is defined in the ./test
folder.
An administrator has the ability to operate on the contract in a few ways:
- can change the baseURI to execute a token reveal or update metadata.
- Can adjust pricing
- Can change external account variables such as signers, proxies, other tokens, etc.
- Can add new zones
- Can adjust inventory availability
- Can withdraw funds
An administrator cannot:
- spend user tokens without prior authorization as an operator
A note on upgradeability
Because the contracts are upgradeable by design, an administrator could theoretically do anything by deploying an upgrade to the contract logic. Immutability is only guaranteed if ownership is renounced of the contract, however this is impractical given the product is under active development. Ownership will be transferred to a multi-sig wallet with multiple signers when the time is right and under the conditions amenable to the community.
To mitigate concerns, events are fired when specific administrative functions are called such as adding a signer or adding a proxy (which is automatically allowed to interact with user tokens). At launch, a single specific signer is defined as part of the deployment and the opensea proxies are defined as allowed in order to remove the need of users to SetApprovalForAll
when listing tokens on opensea.
Deployment
See the ./deploy
folder for deployments.
GSN v2
The token implementation has support for GSN v2 although it is not currently used.
Contract | Description |
---|---|
ERC2771Recipient | GSNv2 recipient |
EIP-3668 Gateway
An implementation for EIP-3668 is stubbed out but not used.
Typechain
The project automatically creates typescript bindings they are in the ./typechain-types
folder after compile.
Etherscan verification
To try out Etherscan verification, you first need to deploy a contract to an Ethereum network that's supported by Etherscan, such as Ropsten.
In this project, copy the .env.example file to a file named .env, and then edit it to fill in the details. Enter your Etherscan API key, your Ropsten node URL (eg from Alchemy), and the private key of the account which will send the deployment transaction. With a valid .env file in place, first deploy your contract:
npx hardhat --network rinkeby deploy --tags auth,land
npx hardhat etherscan-verify --network rinkeby
Performance optimizations
For faster runs of your tests and scripts, consider skipping ts-node's type checking by setting the environment variable TS_NODE_TRANSPILE_ONLY
to 1
in hardhat's environment. For more details see the documentation.