owned this note
owned this note
Published
Linked with GitHub
# NightMarket
Players can sell any, known planet coordinates (with provable biomes) to multiple buyers.
## Contract Specs
- Seller creates a `listing` specifying:
- `lock_time` (if no lock time, malicious buyer can mev `confirmSale` with `refundOrder`; letting sellers set `lock_time` encourages lower `lock_times`)
- `price`
- seller can put up multiple listings for the same coordinates playing around with the cost/locktimes
- Buyer creates a purchase `order` and sets a `H(shared_key)` expectation (prevents malicious seller using a nonreproducible shared_key**)
- Conversely, seller can ignore orders if they are not able to generate `H(shared_key)` (i.e. a spammy buyer)
- Seller can `confirmSale` which completes an `order`
- Seller can `unlist` listing which `refundsOrders` (i.e. seller wants to change terms/put up new listing)
- Anyone can `refundOrder()` once `escrow_time` as passed on an `order`
** *We can also verify ecdsa(sellerprivatekey) ==> public key within the circuits thanks to [circom-ecdsa](https://github.com/0xPARC/circom-ecdsa/), but it's much more constraints.*
### **Contract Escrow (new contract per round of game)**
Data:
- `listings` => H(listing_proof[4])
// listing metadata
- Listings => `cost`, `seller_addr`. `biomebase`, `key_commitments`, etc.
// buyer's active orders
- `orders`
- Orders => `listing`, `buyer_addr`, `start_time` // order metadata
- Listings => `orders[]`
### Constructor
NightMarket escrow contract creator can set:
- `current_game_contract` // active contract for current game
### Seller Interface
**Function List** (listing_proof, proof_input_vars, cost) **public payable**
- assert: circuit commitments
- key_commitment // store this, or can
- planet_id: // is within current_game_contract, see darkforestutils.sol
- biomebase
- seller_address // randos can't create listings
- assert: verify(CONSTANTS, listing_id, nonce, key_commitment, planet_id, biomebase)
- create listing
**Function Unlist** (listing) **public**
Sellers can unlist even with active orders
- assert: caller is `seller`
- refund `payment` to buyer
- delete orders
- delete listing
**Function ConfirmSale** (order, receipt_proof, proof_input_vars... ) **public**
- assert: caller is `seller`
- assert: is an active order
- assert: `shared_key_commitment` is same as what buyer specified
- assert: circuit commitments
- seller_pub_key[2] is same as seller (or caller?)
- key_commitment is same as before
- assert: verify(buyer_pubkey, receipt_id, nonce, key_commitment, seller_pub_key)
- close order
### Buyer Interface
**Function Buy** (listing, payment, H(sharedkey)) public payable
*We dont have to trust this H(sharedkey)*
- assert is valid `listing`
- assert payment == `cost`
- create `order`
- set `start_time`, `buyer_addr` etc.
### Public Interface
**Function refundOrder** (order) public // anyone
- assert `now` - `start_time` > `lock_time`
- refund buyer
- delete orders
## Appendix
**UI thoughts:**
- Show seller stats:
- last sale
- total sales
- total active listings
- total listings
-
-
- Sort listings by:
- locationhash
- timelisted
- cost
- seller
- Show grace periods and escrow expiry
- Q: to verify, should buyer retrieve calldata or do we need to store the nonce/public info seller used to construct proofs...
[slides](https://docs.google.com/presentation/d/1Dk9gZJF_GiitnknPJThJDwokEA1zd0ncwr6Jqawwtq0/edit#slide=id.gd5b15f0a3_5_26)
[some code/scaffolding here](https://github.com/0xSage/df-zkmarketplace)
### Chat notes:
- demand for this marketplace would be for very big planets, ~ 10 planets in practice
- incentivised behavior, e.g. escrow smart contract can interact with game contract, i.e. who owns this planet right now, put the bounty on a planet being captured by someone else.
- seller has to put up some sort of stake, have a penalty for nonresponsiveness. nice tokenomics solution
- nice-to-have: separate market of bounties for information. "if anyone can provide info, encrypted to my secret then they are paid." could make the ux easier by scraping block info to see which hash is attacking you.
- TODO/nicole: lobby feature/play the latest round.
## Open Questions
- Whats mvp?
- What other in game assets can be sold? nfts/coordinates of nebulas?
- need to verify proving times bc it can get complex, but would be cool to do it
- other attrs of the planet can be looked up with just the hash.
- [later] Should we tornado the transactions? maybe not users can tornado themselves.
- [later] Let users bid or sell at fixed price?
- Trivial at the smart contract level, but if bidding, we need an auto-close mechanism?
- Is it exclusive sale?
- This one: sell it to everyone for that price...
- Are there plugin sdk limitations? (will we be able to gen/verify proofs in plugin?) What are similar plugins we can reference
- What should we call it. `dfEx`, `zkEx`, or something space themed? `transit`, `astrometry`, `wobble`, `Kepler` are tools/methods for discovering new planets 😂
## Potential Spec
- Users can list and buy valid coordinates in DF plugin
- Sellers can attest their planet has certain biomes. *Trivial? Listing circuit can just output: `biomeperlin(x, y)`*
## Potential Stack
- circom/snarkjs/hardhat stack
- smart contracts for escrow logic
- [?] where to store proofs... ipfs or just onchain if small enough
- plugin: generates proofs, verifies proofs (incl proof outputs like coord_hashes), makes trx to contracts, decrypts final coordinates for buyer
## Circuit Design
#### LIST
Prove: I have `DATA`, *i.e. xy coords*, and sell a `SECRET` used to encrypt/decrypt this `DATA`
- `hash(DATA,PLANETHASH_KEY) ==> valid_coord` // output
- `hash(DATA, SECRET)` // I encrypted data correctly
- `hash(SECRET)` // I commit to the secret used for encryption
#### SALE
Prove: I encrypted `SECRET` correctly with the `BUYER_PUBKEY`
- `hash(SECRET) ==> output` // checked by contract
- `hash(SECRET, BUYER_PUBKEY) ==> output` // checked by contract
- `BUYER_PUBKEY` // watermark, checked by contract
## Escrow Contract (TODO)
function list(TODO)
function bid(TODO) ??
function close(TODO) // closes sale and issues refunds if any
## DF Circuit Splunking
#### INIT
Prove: I know (x,y) such that:
- x^2 + y^2 <= r^2
- perlin(x, y) = p
- MiMCSponge(x,y) = pub
#### MOVE
Prove: I know (x1,y1,x2,y2,p2,r2,distMax) such that:
- x2^2 + y2^2 <= r^2 // valid within the world
- perlin(x2, y2) = p2
- (x1-x2)^2 + (y1-y2)^2 <= distMax^2
- MiMCSponge(x1,y1) = pub1 // I know the coords
- MiMCSponge(x2,y2) = pub2
- where k is PLANETHASH_KEY
#### REVEAL
Prove: Public (x,y,PLANETHASH_KEY) is such that:
- MiMCSponge(x,y) = pub
- perlin(x, y) = perl
#### BIOMBASE
Prove: I know (x,y) such that:
- biomeperlin(x, y) = biomeBase
- MiMCSponge(x,y) = hash