Smart contract written in [[Solidity]] for the Skin-Z NFTs.
Should have the following features
- Randomized mints
- Set # of each type of Skin to mint
- All data stored in a decentralized way (on chain or IPFS)
- Deployable on [[Arbitrum]]
- 0.01 ETH mint fee
- Ability for owner to withdraw portion of locked fee directly to a wallet (arbitrum) (tax savings)
Potential features:
- chainlink VRF for randomization on mints
- ability to add new NFTs for future mints
## Randomized Minting
A key aspect here is making it very difficult for people to "engineer" their way into getting a rare NFT.
Using the ETH mainnet, the best we can do is randomize based on the block number, which isn't super secure.
### Arbitrum randomization
On arbitrum, we can access the ETH block number, the Arbitrum block number, and the Arbitrum OS contract version.This allows us to make it even more difficult to game the system.
### Randomization seeds
Using a randomization seed, we can further increase the complexity.
#### Token ID as Seed
This adds complexity in that targetting a specific TokenID runs the risk of someone not gaming the system minting that ID before you get your desired state.
#### Chainlink VRF as Seed
Using Chainlink VRF, seeds could be randomly generated by paying a fee in LINK. This would ensure that gaming the system is as near to impossible as can be achieved on a blockchain.
## Minting fees
We need charge the user a fee in order to make a profit for artists.
Those fees will be held by the NFT contract, with the owner having the ability to withdraw those fees to a target address.
Making a deposit of 0.01 directly to the contract should return funds / revert. Must call the `claim` method with a token ID.
## Token Claiming
Following the standard layed out by Loot for Adventurers. Giving the minter control over token ID is important. This allows early adopters to snag cool numbers like *420* and *69*.
Tokens should only be mintable from this `claim` method.
`claim` should require a 0.01 ETH deposit be included with the call.
## TokenURI
We should generate the token JSON data URI on chain like Loot for Adventurers does. This way, we can customize the Name field of the NFT and include the TokenID in it.
This also significantly reduces the amount of IPFS files that need pinned.
The image section should be `ipfs://<content_id_here>` linking to a PNG/SVG/JPG or other format of artwork for the specified NFT.
This IPFS data should be pinned using pinata.cloud, but it should be noted that owners of these NFTs may want to pin their content as well to ensure the artwork lasts a lifetime.
## Premint Definitions
Needing a way to store IPFS CIDs and NFT amounts, this data should be stored on chain as well. This removes any need for a centralized minter.
By storing this data in a struct like
```solidity
structSkinData{
stringimage;
stringname;
uint256count;
}
```
We can define a set count of each NFT that should be minted.
Once a count reaches 0, no more of that NFT image should be created.
## Randomization optimizations
By only randomizing which type of NFT we mint, and not caring about the amount of those NFTs that remain to be minted, we can simplify our minting calculations.
For example, say we had `SkinData[]` which contained all the NFTs to mint. If we selected a random element from this array, and minted it, followed by reducing it's `count` field. We could then remove elements as their `count` hits 0, making the randomization calculation not require iterating over the entire list of skins (saving gas).
### Drawbacks
We'll likely mint all of the "rare" NFTs early, leaving only common ones to be minted by the end.
## TODO
1. Deploy to arbitrum testnet w/ testing artwork
2. ~~Require 0.01 deposit to run claim method~~
3. ~~Refund any excess funds deposited above 0.01 cost~~
4. ~~allow owner to transfer ETH out of contract to target wallet~~
5. ~~Block claims until owner flips a bool ~~
6. ~~refund any deposits not made during a claim~~
Smart contract written in [[Solidity]] for verifying eth wallet ownership for a provided SteamID. Meant for use within applications where SteamID ownership is already validated.
Problem: we need a way to get a player's NFTs from DayZ
Solution: If we know the players ETH wallet, and can validate that on chain, we can extract their SteamIDs.
## Validating Steam Accounts on Chain
We need a mechanism that stores our SteamID on chain and relates this to our ETH wallet.
To achieve this we'll use a mapping of Wallet->SteamID
## Remaining Anonymous
One key aspect of the blockchain is the ability for wallet holders to remain anonymous. Having a smart contract that identifies your steam account really breaks this feature, and would lead to a lot of users not willingly participating.
In order to remain anonymous, we need to:
1. Hash the SteamID value
2. Hash the Wallet value
In this fashion, the data stored on chain is Hash<->Hash. Therefore, it would be impossible to extrapolate a steam account from a wallet or the reverse of that.
This does, however, limit our actions of the contract to simply validating an account link.
### Anonyminity flaw
Calling LinkAccount creates a potential exposure. If an attacker dumped every call to LinkAccount, they could pre-hash the target's SteamID and compare that to the calling data of each transaction to find the original caller.
This could be done with Bloxy (to dump transactions) and `web3.toAscii(transactionID.input)` to dump the input SteamID hash.
This flaw is even more serious as the caller to LinkAccount must be the account we're linking the steamid to, otherwise it would be impossible to validate ETH wallet ownership.
## Putting it together
We need a few key functions
1.`LinkAccount` which will set the steamid hash associated with our account.
2.`Verify` which will validate an eth wallet and steam id are linked.
LinkAccount should hash the caller's wallet and map it to the hashed steamid input argument
Verify should extract the mapped wallet steamid link and compare it with the inputs to ensure a match.
## Deploying
This contract is deployed on networks under these addresses
```markdown
| Network | Address |
|:-: |:-: |
| ETH Mainnet | 0x0 |
| Rinkeby Testnet | 0x0 |
| Arbitrum Mainnet | 0x0 |
| Arbitrum Testnet | 0x0 |
```
## Vulnerabilities
Smart contracts have no real reason to link themselves to a steam account & therefore should be blocked from the LinkAccount method.
## TODO
- Any way to solve this flaw in the anonyminity process?
- If we can't solve the anonyminity, why are we wasting gas hashing the linker's ETH wallet?
Maybe? Could someone simply hash the targets steam id and look for the ETH wallet ? yes, but not if we also hash that ETH wallet
Proposed expansion:
- In VerifyOwnership we do `HASH( ETH_WALLET )`
- When storing, we store `mapping(HASH_OF_STEAMID64 => HASH_OF_ETH_WALLET)`
Under this solution, without previously knowing the ETH wallet and STEAMID64, we cannot get the ETH wallet of a steamID.
What about bruteforcing the ETH wallet? Not feasable.
##### end user perspective
The problem here is that the only way to determine the NFTs owned by a player is to also know what ETH wallet they have. The end user could tell us what their ETH wallet is, but that adds a layer of user-interaction.
We need a way to interact with the blockchain in a decentralized way. So we should directly send JSON_RPC requests from DayZ.
See [[Modding]] for info on Modding DayZ
## Initial Version
The goal of the initial version is to enable smart contract calling functionality without a signer. This should allow us to interact with "view" or "pure" methods on the blockchain.
See [[Solidity]] for info on view and pure methods.