Skip to content
This repository has been archived by the owner on Mar 28, 2023. It is now read-only.

Vending machine sketch #364

Closed
wants to merge 3 commits into from
Closed

Conversation

NicholasDotSol
Copy link
Contributor

early vending machine sketch using
pseudocode, regular code and comments to outline behavior

refs:
implementation planing: #344
parent / epic: #334

Nicholas Evans added 2 commits November 21, 2019 08:17
Pseudocode, regualr code and comments used to outline behaviour of
an early vending machine
// return current number of blocks needed for qualification
}

// Use a DOT to obtain TBTC (ERC20)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does DOT mean here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DOT = Deposit Owner Token

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 on this abbreviation. Makes things a bit clearer

// pay required TBTC to retrieve given DOT (in unredeemed state)
function getDepositOwnerNFT(uint256 tokenid) public returns (address) {
require(sended approved sufficient TBTC to be burned);
if(tokenId == 0){
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For v1 I feel like we can require(tokenId != 0) and force folks to claim specific NFTs. Someone (potentially us) can write a wrapper contract that handles any market making around which token to pull out when. Thoughts?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't really like forcing to claim specific NFTs. I think we can create a pretty simple contract to determine redemption queue even without a real market. We can improve on it at a later stage. thoughts?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Three platitudes that convey my thoughts: complexity is bad, if it can be externalized it's better, and done is better than perfect 😁

I don't disagree with you that it's doable, but I don't think we lose much by not having this functionality available in a v1. Let's keep the possibility, but make it the last thing we do after the rest of the system is done.

Copy link
Contributor

@liamzebedee liamzebedee Nov 25, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Shadowfiend I like the platitudes, just saved them. 😃

I agree with Nich, a redemption queue would be rather simple/elegant. Right now, if two people redeem the same deposit, the higher gas payer will win. Since there's always 1:1 supply of TBTC and unlocked deposits, I'm not sure if a market would help here?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To elaborate, I imagine the vending machine might just hold all DOT's that aren't otherwise exclusively owned (ie. forfeited redemption rights). This is a bit more efficient than destroying/recreating DOT's, if we were to do that. And then we could do something like:

tbtc2Dot() {
    if(!depositOwnerTokenId) depositOwnerTokenId = publicDOTs.pop()
    DepositOwnerToken.transferFrom(this, msg.sender, depositOwnerTokenId);
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The vending machine should absolutely own any DOTs that have had TBTC minted off of them.

Again, I don't disagree that this is doable---or even desirable! But I'm okay with leaving it aside for now and only adding it if there's time, for the simple reason that it's achievable with an external contract. I think we'll have our hands full already, and this is the kind of thing that will probably take longer to write good tests for than to write in the first place.

Keep in mind that by having deposit owner tokens in the first place, we have the ability to list deposits, filter to open ones, and filter to the ones that are owned by the vending machine. Whether we want to do that in a wrapper contract or in a dApp is another question of interest.

Regardless, I think it's worth holding and starting by requiring that you redeem a specific DOT.

// only in redemption Wrapper: getDepositOwnerNFT(RedemptionQueue.Next()) -- not async, cool.
}
// check vending machine for given NFT, revert if it doesn't exist.
// transfer Deposit owner NFT
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is “transfer deposit owner NFT to msg.sender”, yes?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes it is

}

// redeem a Dposit using an unredeemed DOT. not TBTC requirement
function redeemDepositOwnerToken(uint256 TokenID) public {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure I'm following this one. What does it do exactly?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's meant to be a way to redeem a Deposit using an unredeemed Deposit Owner Token. There should be a redemption flow for the folks opting out of minting fungible TBTC.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah yes, of course. Redemption for unlocked tokens would still go through the vending machine because it requires burning TBTC, and we want the vending machine to manage that exclusively.

But there is a TBTC requirement in that case, no?

Copy link
Contributor Author

@NicholasDotSol NicholasDotSol Nov 22, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can redeem a Deposit Owner Token for TBTC, but I may chose not to. If I chose not to, the qualified Deposit Owner Token is unredeemed and has a full TBTC worth of value (since it is redeemable for that at any time) so there should be no TBTC requirement here.
Not totally clear on fee handling though. Maybe provide fees with this call

Copy link
Contributor

@Shadowfiend Shadowfiend Nov 25, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I finally understand some confusion I've had on a couple of your comments :)

The process of turning a DOT into TBTC should not be referred to as redemption. Redemption until now has been turning in TBTC and getting BTC, and for clarity's sake I think we should hold “redemption” to that exclusive meaning. Let's call the process you're referring to here as “redemption” as “minting TBTC off of a Deposit Owner Token”, or “turning a Deposit Owner Token in to the vending machine”. Similarly, if you go TBTC->DOT, let's call this “retrieving a Deposit Owner Token from the vending machine” or something like that.

In this approach, a Deposit Owner Token has no idea whether it's in the vending machine or not, it just changes owners. In fact, I'm a dumbo, and this means we don't need a locked/unlocked states. Deposits should always be locked to their owners. When someone mints TBTC off of a deposit, the deposit's ownership is transferred to the vending machine, allowing it to manage a future redemption transparently.

This leaves us with two flows in the vending machine:

  • Redeeming a deposit owned by the vending machine. This requires 1 TBTC + FEES TBTC.
  • Redeeming a deposit not owned by the vending machine. This requires FEES TBTC.

I can see this being implemented as two public functions, or as one public function with a branch; I think that's up to you. -> I'm finally getting what @NicholasDotSol was going for in his PR + this comment in particular... Following up accordingly.

Copy link
Contributor

@Shadowfiend Shadowfiend Nov 25, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Of note, the not-owned-by-the-vending-machine redemption flow can be mentally modeled as taking FEES TBTC, minting 1 TBTC (which transfers ownership to the vending machine), then directly entering the “deposit owned by vending machine” redemption path with the resulting 1 TBTC + FEES TBTC. The implementation should probably shortcut around some of this, of course. -> I'm finally getting what @NicholasDotSol was going for in his PR + this comment in particular... Following up accordingly.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And now, to finally understanding the model from the other PR! Because the fee exchange for redemption does not require minting/burning authority, this lands us on an even simpler model, which is what the comment above is describing.

Deposit redemption is managed by the deposit, as today, but it only takes FEES TBTC and distributes it. This is purely a TBTC transfer from the owner of TBTC to the signers.

  • Redeeming a deposit owned by the vending machine requires, as noted in the above-linked comment, exchanging 1 TBTC for the deposit ownership token, then redeeming the underlying deposit (which can be wrapped in a helper later) with FEES TBTC.
  • Redeeming a deposit I own requires a standard redemption, sending FEES TBTC to the deposit.
  • Redeeming a deposit someone else owns requires acquiring ownership from them, or alternatively it requires waiting for liquidation to remove the ownership restriction.

Notably this doesn't require tracking any additional states in the deposit. The only thing we need to do is, when requesting redemption, if the deposit is not in a liquidation state, only the owner is allowed to redeem. If it is in a liquidation state (i.e., a state after courtesy call), anyone may redeem with FEES TBTC.

This brings up the question of how this impacts the liquidation auction for deposits that are not owned by the vending machine ("locked deposits"). I think we need to pick that up next week, and can implement the first parts of this flow while leaving that to a separate consideration.

@Shadowfiend Shadowfiend mentioned this pull request Nov 22, 2019
function isQualified(tokenId) public view returns (bool);

// Qualify a DOT
function qualifyDepositOwnerToken(tokenID, proofRequirements) public view returns (bool){
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Shadowfiend, I would like the option to mint a qualified Deposit Owner Token before minting an unqualified 1-conf token. If a user has no need for immediate access The extra TX, time, and cost are all undesirable. I would personally take this option.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would file an issue for that. It's a nice-to-have, but seems straightforwardly accomplished with a wrapper contract if we don't have time to add it to the core functionality (simply by calling one function that calls both of the others).

@Shadowfiend
Copy link
Contributor

Shadowfiend commented Nov 25, 2019

I'm going to drop my final sense of how this might be structured at a high level, based on the two PRs:

contract Deposit {
  // Largely similar to the current situation, except that requesting
  // redemption is disallowed in non-liquidation states unless you own
  // the deposit. Redemption burns the associated deposit owner token.

  // May provide a shortcut whereby when you add proof, if there is no
  // associated DOT, it is automatically minted.
}

contract VendingMachine {
  // Solely charged with taking ownership of deposits via their DOTs and
  // returning TBTC.
  // Contains its requirement for minimum deposit proof in order to produce TBTC.

  // May provide shortcuts for adding proof to a deposit + minting TBTC off
  // of its owner token in one go.
}

contract DepositOwnerToken is ERC721whateverwewant {
  // Mints owner tokens off of a deposit.

  // If we do 1+-conf minting here, we may provide a shortcut for adding
  // proof + minting the owner token.
}

I think we can ignore the shortcuts for now and focus on the bare bones of the functionality: allowing access to proof level of the deposit, allowing DOT minting from a deposit (let's ignore the confirmation requirement for now), allowing exchange of DOT for TBTC and vice versa (basic vending machine), and simplifying deposit's redemption to only handle the TBTC for fees (and guard for ownership in non-liquidation flows). Let's make that the aim for this week.

One last note: this whole setup means we can't redeem a deposit if no one has minted TBTCs off of their DOTs. This is a known property of setting up the flow as it is. If there is a large need for deposit redemption, we would expect the price of TBTC to go up, thus incentivizing minting TBTC off of DOTs. Keep in mind the goal here is not to have the value of 1 TBTC equal that of 1 BTC at all times, but rather to know that 1 TBTC represents 1 BTC held by the system.

@mhluongo mhluongo deleted the implementation-planning branch June 8, 2020 18:28
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants