diff --git a/CHIPs/chip-0010.md b/CHIPs/chip-0010.md new file mode 100644 index 00000000..2e6767fd --- /dev/null +++ b/CHIPs/chip-0010.md @@ -0,0 +1,116 @@ +CHIP Number | < Creator must leave this blank. Editor will assign a number.> +:-------------|:---- +Title | Owner-Editable Metadata Format for NFT1 +Description | A standard that allows NFT owners to update some or all of the metadata attributes and store those updates on-chain. +Author | [Josh Painter](https://github.com/joshpainter) +Editor | < Creator must leave this blank. Editor will be assigned.> +Comments-URI | < Creator must leave this blank. Editor will assign a URI.> +Status | < Creator must leave this blank. Editor will assign a status.> +Category | Process +Sub-Category | Informational +Created | 2022-10-17 +Requires | 0007 +Replaces | +Superseded-By | + +## Abstract +The Chia NFT1 standard enables an off-chain metadata file to be referenced by Non-Fungible Tokens (NFTs) on chain, along with a hash of the file that ensures its immutability. The format and schema of this metadata file is described by [CHIP-0007](chip-0007.md). This CHIP describes an easy way to allow the owner of the NFT to update some or all of that metadata, depending on which attributes have been marked as editable by the creator. It is intended to supplement the metadata schema described in [CHIP-0007](chip-0007.md). + +## Motivation +[CHIP-0007](chip-0007.md) specifies the format and schema of the off-chain metadata file. By design, this metadata file is immutable. If any user attempts to update any of the metadata attributes in the referenced metadata file, the hash of the metadata file will change. The NFT viewer program is responsible for checking this hash to make sure the metadata has not been tampered. + +However, the ability for the owner for a NFT to update some or all of the metadata for the NFT has some very interesting use-cases. Of particular interest is a Chia Name Service (CNS) that uses NFTs to resolve records. By allowing the owner to update their own NFT "pointer records," a CNS could enable full self-custody and self-sovereignty of these pointer records. + +As another example, imagine some sort of digital board game in which the player gets to choose where to place their token(s). These positions could be managed by updating the X/Y metadata attributes of NFTs that represents these digital player tokens. + +Another feature is the "Etching" attribute that exists for all existing and newly-minted NFTs. The owner could update the Etching with any personal information about the NFT, a story about where they got it, etc. The next owner could overwrite or append to this Etching, but the full history will always be stored on-chain as an additional bit of provenance. + +Finally, these metadata values could themselves be Merkel tree hashes, allowing proofs-of-inclusion while using minimal on-chain storage space! + +This CHIP will explain one method of enabling this feature using existing NFT1 and [CHIP-0007](chip-0007.md) standards with no required changes, including full backwards-compatibility. + +## Backwards Compatibility +This CHIP is fully backwards-compatible with [CHIP-0007](chip-0007.md). In fact, it proposes to add just a single new attribute to the [CHIP-0007](chip-0007.md) schema. NFT1 standard requires no changes whatsoever. + +## Rationale +The method described below is possible today even if this CHIP is never published because it requires no changes to any existing standards. However, by standardizing the "editable" attribute schema, it is hoped that the Chia NFT viewer itself will be able to make use of these editable attributes, along with other future NFT viewers. + +Another possible method to accomplish a similar result would involve Chia Data Layer. Data Layer will no doubt be an important addition to these metadata standards in the future and will enable a much higher amount of data storage. However, Data Layer requires more user interaction and the user must opt-in to the data. By contrast, the method described below is much simpler and works with just a full node. For use cases involving small, rarely-updated data, the impact to the blockchain should be low. + +Finally, this small addition to the work already done with CHIP-0007 is a good example of [Lateral Thinking with Withered Technology](https://medium.com/@uczlwha/nintendos-philosophy-lateral-thinking-with-withered-technology-f188f371e670). While the Chia NFT1 standard and [CHIP-0007](chip-0007.md) are certainly not already "withered" according to the normally-accepted definition, a big benefit of this standard is that it uses these existing standards in a new way without breaking them. + +## Specification + +This CHIP proposes a single new optional boolean property on the "trait" attribute defined in [CHIP-0007](chip-0007.md) called "editable." Here is an example of both a normal and an "editable" attribute (surrounding metadata removed for brevity): + +``` +... +{ + "trait_type": "Registered On", + "value": "{$registeredOn}" +}, +{ + "trait_type": "Target", + "value": "xch1v96m4cej23hpt4newv8hs9ejcsc760w3p8gh5p6989c7kyaq5juq9hzjgr", + "editable": true +}, +... +``` + +Only the NFT attributes may include this optional property. The collection attributes mentioned in [CHIP-0007](chip-0007.md) are meant to be the same for all NFTs in the collection and therefore should remain immutable. + +To edit this editable metadata, the owner of the NFT will add a new metadata URL to the NFT using the normal NFT1 standard. However, the URL will merely be a copy of the existing metadata URL with the addition of the editable names and values in the querystring. + +An example of a normal metadata URL: +https://bafkreig7fmhptchs2gv2o2l3bilkxtddr7r5eo7nkpr26rnetmx5icahvm.ipfs.nftstorage.link/ + +An example of a metadata URL that contains a new value for an editable attribute: +https://bafkreig7fmhptchs2gv2o2l3bilkxtddr7r5eo7nkpr26rnetmx5icahvm.ipfs.nftstorage.link/?Target=xch16nvgtzv2dcs86hmk99kfp3q09vj2k66x0t0z0ttk9k5zcx3yxzaqz9xxaf + +Notice that the second example has an additional querystring value that is ignored by the server - both URLs serve the same file regardless of querystring values. The hash is therefore unchanged. Existing NFT viewers, including the official Chia Wallet, will continue to "just work" with these enhanced URLs. + +However, NFT viewers or applications with editing capability can now be supported. These new NFT viewers will recognize the "editable" property on metadata attributes and they will instead look to the latest metadata URL's querystring values first to resolve the metadata value. If these values don't exist as querystring values, the values from the metadata file will be used as normal. + +The same viewers could allow basic editing by directing the user to add a new URL via CLI or RPC. Perhaps they could even use a web wallet like Goby to sign the transaction that adds the new enhanced URL to the NFT! + +### Etchings + +Additionally, this specification describes a single additional editable metadata field that all new and existing NFTs can use called "Etching." An Etching is a simple text field attribute. It is not defined in the metadata json file. It only exists as a querystring name/value pair, like this: + +https://bafkreig7fmhptchs2gv2o2l3bilkxtddr7r5eo7nkpr26rnetmx5icahvm.ipfs.nftstorage.link/?Etching=this%20is%20my%20super-cool%20etching + +Any viewer that supports CHIP-0010 should always look for this "Etching" querystring value on the metadata URI *even if there are no other editable metadata attributes defined in the metadata.* If the Etching attribute is defined in the metadata, it should be used as the default value like other editable attributes. The viewer should display it in the UI in addition to the other editable metadata. The viewer should allow the owner to edit the Etching using the same method described above for other editable metadata. + +An Etching could be used for any user-defined content, such as a story about how the owner acquired the NFT, or a critique of the art itself, or even structured data such as JSON or YAML. This data is stored on the blockchain in the metadata URI as querystring values just like the other editable metadata above. This feature allows existing NFTs minted before this CHIP was published to use a simple form of editable metadata too! + +Querystring names are not case-sensitive, so "?Etching=" and "?etching=" and ?ETCHING=" are all acceptable. + +### dApps/WalletConnect RPC Whitelist + +Ideally the /nft_add_uri RPC endpoint should be added to https://github.com/Chia-Network/chia-blockchain-gui/blob/main/packages/gui/src/constants/WalletConnectCommands.tsx so it can be used by dApps. + +Other dApps like Goby may also add simple functionality similar to how /nft_add_uri to support this CHIP. + +## Test Cases + +Not applicable + +## Reference Implementation + +The go4.me Chia Name Service (CNS) uses this standard for owner-editable pointer records. + +## Security + +No changes or security issues result from this CHIP. It uses the same rules as the NFT1 standard - only the current owner of the NFT can add a metadata URL to the NFT. + +## Additional Assets + +Presentation: https://bafybeieztz7kn7ykqao3dc6cop6t5kim4qg2ukvh6j32gk4e2r6i7heure.ipfs.nftstorage.link/Chia-CHIP-0010-01.webm +NFT Collection: https://mintgarden.io/collections/chip-0010-col1v6dnjyduum4pdw2r79wwz5mhvd0ejgjc2dqcf325lwwajddxzdpqymjhpr + +## Copyright +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). + + + + diff --git a/CHIPs/chip-joshpainter-auctions.md b/CHIPs/chip-joshpainter-auctions.md new file mode 100644 index 00000000..35a5153a --- /dev/null +++ b/CHIPs/chip-joshpainter-auctions.md @@ -0,0 +1,165 @@ +CHIP Number | < Creator must leave this blank. Editor will assign a number.> +:-------------|:---- +Title | Auctions +Description | A method for holding decentralized, zero-risk auctions for digital assets on the Chia blockchain +Author | [Josh Painter](https://github.com/joshpainter) ([@endertown](https://twitter.com/endertown) on Keybase and Twitter) +Comments-URI | < Creator must leave this blank. Editor will assign a URI.> +Status | < Creator must leave this blank. Editor will assign a status.> +Category | Informational +Sub-Category | Guideline +Created | 2022-05-22 +Requires | none +Replaces | none +Superseded-By | none + +## Abstract +Auction is one of the oldest methods of negotiating the exchange of goods and commodities between buyers and sellers. Babylonians held auctions as early as 500 BC. Later, ancient Greeks and Romans auctioned off their spoils of battle to gain treasure for the war effort. More recently, the Internet has enabled a massive new market for online auctions. Starting with eBay in 1995 and growing every year, online auctions continue to be an important method for trading assets to this day. + +However, even with all this history, auctions still have unsolved risks for the buyer, the seller, and especially the auction house holding the auction itself. The Chia blockchain, along with the coinset model and Chialisp, brings about new and unique opportunities to improve on this millenia-old practice and eliminate risk for all parties. This document will explore the counterparty risks and issues with modern-day auction. It will then propose high-level solutions to these problems using puzzles created in Chialisp and executed directly on the Chia blockchain. Finally, it will recommend detailed specifications that can be used to build these Chialisp puzzles to enable these solutions. + +## Motivation +Modern-day auctions continue to be a valuable tool for finding market value of new assets, quickly liquidating old assets, and everything in between. However, multiple risks still exist for the bidders, the sellers, and especially the auction house responsible for promoting and organizing the auction itself. + + * Seller risks + * High bidder may not complete transaction after auction ends. This forces seller to find another buyer who will usually not be willing to pay the same price. The best case is probably offering the auctioned item to the second-highest bidder at their second highest bid, but usually the second-highest bidder will recognize their negotiating power and drive the price even lower. Current solutions to this problem involve legal contracts and bidder deposits, both of which can add significant friction to the auction event itself. + * High bidders might hold back bids until the last minute, hoping to “snipe” other users. Ideally users would be incentivized to make lots of small bids over the entire auction event instead of a few large bids in a short time near the end. This promotes more engagement with the auction itself and might result in a higher price for the seller. + * The auction house might not properly market the auction resulting in low bidder attendance and a lower winning bid. Ideally the auction would at least be publicly discoverable via simple searching tools. The auction house might add additional marketing value above this baseline discoverability such as featured auctions, push notifications to interested buyers, etc. + * Bidder risks + * Seller may not complete transaction after auction ends. Perhaps the winning bid was lower than they expected and they now wish to rescind their decision to auction the item. Again, these risks can be mitigated with legal contracts binding the seller to the auction sale, but again these add friction to the process and still do not deter sellers if the cost of litigation is less than the perceived loss of value. + * High-bidders might be bidding against "dummy bids." In this context, a dummy bid is one that the seller (or someone working on behalf of the seller) creates in order to bid against the current high bidder to drive the price up. + * High-bidders might be “sniped.” In this context, being sniped means that another bidder bids at the last possible time before an auction ends and the current high bidder does not have enough time to respond. + * Auction House risks + * The auction house itself must worry about all risks above simultaneously to protect their reputation while also allocating and spending funds up front to market and operate the auction on behalf of the seller. If the buyer or seller ties up the finalization of the transaction, the auction house must usually wait for payment until the terms are finally settled. In some cases, and especially concerning items of very high value such as large properties or blue-chip art, the winning of the auction itself can sometimes simply be considered the opening offer of a long and strenuous transfer-of-ownership between two legal teams. + +By presenting solutions for all of these risks using the Chia blockchain and Chialisp, it is hoped that Chia's overall ecosystem will benefit from the inflow of digital assets as well as the transactions and fees used to fund bids. Auctions are also a natural sales method for NFTs and CATs and a great way to find the market value of these new digital assets. Furthermore, it is hoped that Auctions will be a natural fit for carbon credit asset trading, enabling advancement of Chia's commitment to improve and support the Climate Warehouse for World Bank. + +Although there are many auction variations, this proposal will focus on the use-cases of the two most popular methods of auction in use today: English and Dutch. + +* English Auction + + This is by far the most popular auction type in use today and is also known as an "ascending price auction." It is well-suited for unique or single assets, including NFTs. It begins with the minimum or opening bid, and each successive bid must be greater than or equal to the current bid increment. The auction ends when there are no further high bids. At that point, the high-bidder is declared the winner of the item for sale. + +* Dutch Auction + + This type of auction is also known as a "descending price auction" and it is well-suited for commmodities or lots of the same asset, including CATs. It begins with a high asking price and is successively lowered by the bid increment until a bidder is willing to pay it. The bidder may request any quantity of lots of the item at that bid price. If there are remaining lots of the asset left after the high bidder declares their lot quantity selection, the auction continues until another bidder is willing to pay the descending bid price. That second-highest bidder is also allowed to choose the quantity of lots that they desire, and the auction will continue on until the quantity of lots of the asset is exhausted or the minimum bid amount is met and no more bids are received. + +However, the specification is designed so that almost any kind of auction can be defined, limited only by the power of Chialisp and the auction author's imagination. + +## Quick Summary + +1. The initial seller "mints" the "egg" that represents the auction. The egg wraps any Chia asset (i.e. NFTs, CATs, DIDs, DL, etc). +2. The first bidder makes a bid on the egg by paying the seller the minimum bid amount. +3. The first bidder now becomes the new owner of the egg. +4. However, the current owner of the egg cannot "crack" the egg and claim the asset inside until a certain future time or blockheight. +5. Any other bidder may make a higher bid on the egg while it is uncracked. The second and subsequent bidders must pay back the current owner for that owner's last bid and must now pay the original seller the *difference* between the last bidder's bid and this new higher bid. +6. Continues from step 3 above and loops until the current owner "cracks" the egg and claims the asset. + +This guarantees that every bid is settled immediately, which removes all counter-party risk associated with transfer of ownership after the auction ends, as discussed above. + +## Conceptual Design +An auction on the Chia blockchain is a singleton (the "egg") that wraps any Chia asset, represented by an inner puzzle. A single-lot auction wraps an asset that represents a single unique item, such as an NFT. A multi-lot auction wraps an asset that represents multiple amounts of the same item, such as a CAT. + +The auction singleton puzzle will include several parameters that allow customization of the auction event itself. Bidders must follow all rules and parameters set by the auctioneer. + +The seller may not be the same entity as the auctioneer. This differentiation allows commissions and/or buyer's premiums to be paid to the auction house to cover promotion, marketing and any other expenses incurred for the real-world execution of the auction. Of course, the seller may also hold the auction on their own behalf. + +A normal real-world auction does not settle until after it has closed, which introduces all of the counterparty risks mentioned above. But by using a unique and novel auction protocol, we can completely "settle" each high bid as it happens in real-time. + +For *every successful high bid* the asset immediately trades ownership and all bid payments, commissions and fees are sent and confirmed at the same time. This means that an auction running on Chia blockchain does not have *any* of the counter-party risks mentioned above. Because the bid itself actually contains the payment transactions, it is not necessary to trust that either party will follow through with the agreed-upon sale after the auction has concluded. + +When a high-bidder successfully makes a high bid, the seller has been paid and the high-bidder now officially owns the asset. The only reason they will not hold the asset at the end of the auction is if another high-bidder successfully "steals" it from them by bidding higher. Of course, the original high-bidder then can "steal" it back, and so on. But if no other bidding action happens after a successful high bid, the auction will close and the high-bidder can then claim the wrapped asset. + +This concept is easy to understand for the first successful high bid. The high bidder actually sends their high bid amount to the seller as a normal transaction. The high bidder may also be required to send an additional buyer's premium fee and/or commission fees to the auctioneer, depending on the settings chosen when the auction singleton is minted. + +However, the second and subsequent successful high bids work quite differently. The new high bidder will first reimburse the current high bidder for their current high bid and commission fees via a normal transaction. The current high bidder is now "whole" and loses the ownership of the egg and also the asset contained within the auction singleton. Ownership is now transferred to the new high bidder. The difference between the new high bid and the current high bid is sent to the seller, along with any required buyer's premium fees and/or commission fees. The seller has now received the initial high bid amount (from the first high bidder) plus the difference between the initial high bid and the new high bid (from the second high bidder). This process continues until the auction has concluded. + +It should be understood that all of this happens "behind the scenes" from the user's perspective. The user's experience will be very familiar to all who have used any existing auction software. All of this complexity should be accessible via transaction logs of course, but most users will just make high bids on auctions as they always have. Perhaps the only new user education that needs to happen is to make sure that users understand the true immediacy and finality of high bids. Auction houses will be particularly excited with this technology as they will no longer be caught in the middle of buyer and seller disagreements that can arise during the time that the auction has concluded but has not yet settled. All auctions are now actually settled *before* they are concluded! + +## Specification +* Singleton launcher puzzle Parameters + * ASSET_PUZZLE - can be any inner-puzzle coin such as NFTs, CATs, etc. + * ORIGINAL_OWNER_PH - the original owner's puzzle hash to which the high bid payments should be sent. + * STARTING_BID_AMOUNT - the starting minimum bid amount, in mojos. + * CALC_MIN_LOT_AMOUNT - the Lisp program that calculates the minimum amount per lot. For a single-item auction, this value will be the same as TOTAL_ASSET_AMOUNT. + * TOTAL_ASSET_AMOUNT - The total amount of the asset, in mojos. + * CALC_MIN_BID_AMOUNT - the Lisp program that calculates the minimum bid amount required to make a new high bid. This allows smaller increments for lower amounts, larger increments for larger amounts, or any other custom logic. The program should output a minimum bid amount given the current_high_bid. + * CALC_HAMMER_TIME - the Lisp program that returns either the datetime or the blockheight after which the auction is considered closed. The could be either a static value (pre-committed datetime or blockheight) or a dynamic value (automatically extend until no more bids received). + * CALC_BUYERS_PREMIUM - the Lisp program that returns conditions for the Buyer's Premium, if applicable. + * CALC_COMMISSION - the Lisp program that returns conditions for the Commission, if applicable. + * PAY_HIGH_BID - the Lisp program that returns conditions for the High Bid payment. This is a public spend and can be made by anybody at any time. + * If this is the first bid + * Send new_high_bid amount to ORIGINAL_OWNER_PH. At this point, the original owner has been paid and the new owner officially owns the asset with the caveat that the asset may be "stolen" by another high bidder before the auction has ended. + * Else + * Send current_high_bid amount to current_owner_ph. This repays the last high bidder for their bid. The last high bidder no longer officially owns this asset, but they have been reimbursed for their previous bid by the new high bidder. The new high bidder now officially owns the asset. + * Send difference between new_high_bid and current_high_bid to ORIGINAL_OWNER_PH. This adds to the original owner's other high bid payments so total payments received equals current high bid at all times. + * Include conditions returned from CALC_BUYERS_PREMIUM, if any. This guarantees that the Buyer's Premium is paid for every bid. + * Include conditions returned from CALC_COMMISSION, if any. This guarantees that the Commission is paid for every bid. + * CLAIM_ASSET - the Lisp program that returns conditions needed to claim the asset. The basic implementation should validate that this claim spend is happening after CALC_HAMMER_TIME and only by the current owner. This program is also responsible for melting this Auction singleton once the wrapped assets are claimed. + +* Singleton puzzle Parameters + * current_high_bid - the amount of the current high bid, in mojos. + * current_owner_ph - the puzzlehash to be used when assigning this asset to the Auction Winner when the auction has completed. + * new_high_bid - the amount of this newly submitted high bid, in mojos. + * new_owner_ph - the puzzle hash of this new high bidder. + +## Test Cases +TESTING... + +## Reference Implementation +IMPLEMENTING... + +## Security +SECURING... + +## Community Feedback +6/15/2022: Twitter user @Engarneering suggested removing the historical fact about Babylonian auctions from the Abstract because "I mean, really??" This has been taken under advisement and in the meantime, a footnote has been added to the offending sentence. +6/15/2022: Twitter user @_nezzee suggested shortening the intro and notes that most intros just start with a simple definition. + +## Updates +6/15/2022: + * Added Community Feedback section + * Added feedback from @Engarneering and @nezzee + +6/17/2022: + * Added this Updates section + * Shortened intro to take into account community feedback. Thank you @Engarneering and @_nezzee! + * Added Credit section + * Added credit paragraph for @Omakasea_ - thank you! + +6/23/2022: + * Added Quick Summary section to make it even easier to digest concept. + * Edited formatting + * Added more details to CLAIM_ASSET after discussion with @DanPerry_Chia about how to end auctions - thanks Dan! + +## Terminology +This section describes common auction terminology for which the reader might not be familiar. Even more detailed information, including terminology, history and descriptions of different auction types can be found at https://en.wikipedia.org/wiki/Auction. The terms below are a subset of those found at the preceding link. + + * Auction house – the company operating the auction (i.e., establishing the date and time of the auction, the auction rules, determining which items are to be included in the auction, registering bidders, taking payments, and delivering the goods to the winning bidders). + * Buyer's premium – a fee paid by the buyer to the auction house; it is typically calculated as a percentage of the winning bid and added to it. Depending on the jurisdiction the buyer's premium, in addition to the sales price, may be subject to VAT or sales tax. + * Commission – a fee paid by a consignor/seller to the auction house; it is typically calculated as a percentage of the winning bid and deducted from the gross proceeds due to the consignor/seller. + * Consignee and consignor – as pertaining to auctions, the consignor (also called the seller, and in some contexts the vendor) is the person owning the item to be auctioned or the owner's representative, while the consignee is the auction house. The consignor maintains title until such time that an item is purchased by a bidder and the bidder pays the auction house. + * Dummy bid (a/k/a "ghost bid") – a false bid, made by someone in collusion with the seller or auctioneer, designed to create a sense of increased interest in the item (and, thus, increased bids). + * Dynamic closing – a mechanism used to prevent auction sniping, by which the closing time is extended for a small period to allow other bidders to increase their bids. + * Earnest money deposit (a/k/a "caution money deposit" or "registration deposit") – a payment that must be made by prospective bidders ahead of time in order to participate in an auction. + * Escrow – an arrangement in which the winning bidder pays the amount of his/her bid to a third party, who in turn releases the funds to the seller under agreed-upon terms. + * Hammer price – the nominal price at which a lot is sold; the winner is responsible for paying any additional fees and taxes on top of this amount + * Increment – a minimum amount by which a new bid must exceed the previous bid. An auctioneer may decrease the increment when it appears that bidding on an item may stop, so as to get a higher hammer price. + * Minimum bid – The smallest opening bid that will be accepted + * Opening bid – the first bid placed on a particular lot. The opening bid must be at least the minimum bid, but may be higher (e.g., a bidder may shout out a considerably larger bid than minimum, to discourage other bidders from bidding). + * Protecting a market – when a dealer places a bid on behalf of an artist he or she represents or otherwise has a financial interest in ensuring a high price. Artists represented by major galleries typically expect this kind of protection from their dealers. + * Reserve price – A minimum acceptable price established by the seller prior to the auction, which may or may not be disclosed to the bidders. + * Sealed bid – a submitted bid whose value is unknown to competitors. + * Sniping – the act of placing a bid just before the end of a timed auction, thus giving other bidders no time to enter new bids. + * Soft Close – When someone places a bid in the last set amount of minutes and the auction automatically extends a set period of time. Soft close prevents sniping. + +## Additional Assets +NONE YET... + +## Credit + * Around the end of April 2022, Omakasea (@Omakasea_) and team released the "onchain unicorn" (@onchainunicorn) on the Ethereum network. One of the features was the ability for it to be "stolen" from the current owner by a new buyer. Author recognized the ability for this idea to be the basis of an auction protocol running on the Chia blockchain and began working on the basic idea in early May. Author would like to thank Omakasea for his brilliant original "onchain unicorn" idea! + * Dan Perry (@DanPerry_Chia) and Ken Griggs (@fizpawiz) were instrumental in providing early feedback for the idea itself, along with great improvement ideas and lots of knowledge and motivation. Thank you both! + +## Copyright +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). + +## Footnotes