- todo
- [ ] multisig setup (multiple owners)
- [x] setup whitelist storage (vercel edge)
- [x] update smart contract according to the spec below
- [ ] complete smart contract testing
- [ ] verify hash function on the smart contract
- [ ] function to generate deterministic hashes from twitter handles
- [ ] function to generate merkle tree
- [ ]
- **Smart contract**
- SPEC
- `whitelistTransfersPaused` and `publicMintsPaused`
- bool variables
- can only be changed by the owner
- **`MINT_PRICE`**
- public variable, controllable by the multisig
- price of non-whitelisted mints
- default to 0.1ETH
- **`publicMint()`**
- public variable, controllable by the multisig
- if `true`, `mintTo()` function should allow mints without a `hash` provided
- if `false`, `mintTo()` will require a **valid** hash to mint successfully
- **`usedHashes(string => boolean)`**
- mapping to store all the hashes / merkle leaves that have been consumed
- **`minters(address => boolean)`**
- a mapping of all addresses that minted an NFT
- if an address has minted an NFT, they shouldn't be able to mint again
- **`mintTo(address, hash)`**
- address (reciever of the NFT), hash (optional)
- check if address is in `minters()`
- if yes, revert
- if not -> continue
- check if address owns an NFT already (`balanceOf`)
- if yes, revert
- if no --> continue
- **if hash provided**
- check if hash has been used already (`usedHashes`)
- if used, revert
- if not, continue
- check hash validity
- if not valid, revert
- if valid, continue
- check msg.value
- check value -> if > 0; revert
- if 0 -> continue
- mint
- increment counter
- add hash to `usedHashes`
- add address to `minters()`
- **if hash not provided**
- check if `publicMint()` is true
- if false -> revert
- if true, check `msg.value = MINT_PRICE`
- if false, revert
- if yes, mint
- **`updateMerkleRoot()`**
- admin only function
- updates the `root` public variable
- TESTING
- **mintTo**(address, bytes32)
- should not be able to mint if invalid hash
- address should not be able to mint if already has a token
- should not be able to mint twice - with two valid hashes
- should not be able to mint twice with a single valid hash
- should not be able to mint with a invalid hash
- function should not allow value transfer (free mint)
- address should not be able to mint if
- **mintTo**(address)
- should not mint if paused
- **App: Client**
- take the list of all twitter handles
- generate deterministic hashes
- create merkle tree
- update smart contract with the merkle root (`updateMerkleRoot()`)
- user connects their twitter account [nextauth???], the server checks if currently connected twitter account is in the whitelist or not [from the database]
- if it's not
- display a message saying you're not in the whitelist
- if publicMint() is true -> display an option to mint + display the mint price
- if publicMint() is false -> display a message asking to wait until public mint happens
- if it is
- display mint option and price as `0 ether`
- prompt to connect wallet
- api call to generate hash on the server (server generates the hash and returns it back)
- check if address is present in `minters()`
- check if hash is valid (on-chain call)
- send connected wallet address + hash as the params for `mintTo()` function
- wait for the transaction to go thru
- **App: Whitelist storage**
- key value store to keep maintain an array `whitelist`, a key `root`, and a json object `used`
- `whitelist`: array of strings - array of all whitelisted twitter handles
- `root`: merkle root of all the deterministic hashes of twitter handles
- `used`: json object of keys as twitter handles and value as the hash used to claim their nft (updated after a tx goes thru)
- **App: Server**
- api to update whitelist
- add new member in whitelist array (twitter handle)
- generate new hash
- update `root` (generate merkle tree)
- api to create whitelist
- accept an array of strings (twitter handles)
- create merkle tree, generate root
- update `root`
- api to fetch all whitelisted handles
- fetch `whitelist` array
- api to fetch if a give handle is whitelisted or not
- query `whitelist` array
- api to fetch all used hashes + twitter handles that have initiated the transaction
- query `used` object
- api to generate and return hash given a twitter handle
- run a util function
- Hash generation
- encrypt twitter handle using a secret key (server .env)