Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

EIP-0014: Decentralized Exchange Contracts #27

Open
wants to merge 61 commits into
base: master
Choose a base branch
from
Open

EIP-0014: Decentralized Exchange Contracts #27

wants to merge 61 commits into from

Conversation

kushti
Copy link
Member

@kushti kushti commented Mar 15, 2021

  • Author: kushti, Ilya Oskin
  • Status: Proposed
  • Created: 12-Mar-2021
  • Last edited: 15-Mar-2021
  • Track: Standards

Motivation

Act of exchange without trusted parties is a most basic primitive for decentralized finance on top of blockchains. Thus contracts for that were introduced early, and basic single-chain swap contract was introduced early in the ErgoScript whitepaper. Then a lot of other order contracts appeared: with partial filling, buyback guarantee and so on. What is good for traders in decentralized worlds, such contracts are usually composable.
While swap order contracts allows for orderbook-based decentralized exchanges (DEXes), now popular AMM-based DEXes (where AMM stands for Automated Market Maker) also possible on Ergo.
Interestingly, unlike other known blockchains, thanks to the extended UTXO model, liquidity pool contracts for AMM-based DEXes can be combined with order contracts (for orderbook-based DEXes). This gives unique possibility to have shared liquidity among different types of exchanges on top of the Ergo blockchain.

This PR provides known DEX contracts for both orderbook-based and AMM-based DEXes, and also provides info on their composability.

@kushti kushti changed the title EIP-0014: Decentalized Exchange Contracts EIP-0014: Decentralized Exchange Contracts Apr 6, 2021
else 0L

val feeCharged = rewardTokens * feePerToken
val isValidReward = (SELF.value.toBigInt - feeCharged) <= rewardTokens * price

Choose a reason for hiding this comment

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

Shouldn't this be >= instead? As we need enough ERGs to pay for the tokens.

Copy link
Member

@oskin1 oskin1 Apr 21, 2021

Choose a reason for hiding this comment

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

This contract only ensures a user gets at least (SELF.value.toBigInt - feeCharged) / price rewardTokens.

Copy link

@pragmaxim pragmaxim Apr 21, 2021

Choose a reason for hiding this comment

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

For a newbie this is very confusing as the condition looks like tokensUserCanAffordToPayFor <= tokensToBuy which is like saying "ensure that user buys at least as many tokens as he can afford to buy" but maybe there can be more INPUTS 🤷

@oskin1 oskin1 requested a review from scalahub June 7, 2021 08:15

- Depositing. An amount of LP tokens taken from LP reserves is proportional to an amount of underlying assets deposited. `LP = min(X_deposited * LP_supply / X_reserved, Y_deposited * LP_supply / Y_reserved)`
- Redemption. Amounts of underlying assets redeemed are proportional to an amount of LP tokens returned. `X_redeemed = LP_returned * X_reserved / LP_supply`, `Y_redeemed = LP_returned * Y_reserved / LP_supply`
- Swap. Tokens are exchanged at a price corresponding to a relation of a pair’s reserve balances while preserving constant product constraint (`CP = X_reserved * Y_reserved`). Correct amount of protocol fees is paid (0.03% currently). `X_output = X_reserved * Y_input * 997 / (Y_reserved * 1000 + Y_input * 997)`
Copy link
Member Author

Choose a reason for hiding this comment

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

0.03% => 0.3%

eip-0014.md Outdated
tokens[1] | LP token reserves
tokens[2] | Asset X
tokens[3] | Asset Y
R4[Long] | Fee multiplier numerator (e.g. 0.003% fee -> 997 fee_num)
Copy link
Member Author

Choose a reason for hiding this comment

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

0.003% => 0.3%

eip-0014.md Outdated
##### Contract parameters:
Constant | Type | Description
--------------------|------------|---------------
Pk | ProveDLog | User PublicKey
Copy link
Member Author

Choose a reason for hiding this comment

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

ProveDlog => SigmaProp

eip-0014.md Outdated
##### Contract parameters:
Constant | Type | Description
---------------|------------|---------------
Pk | ProveDLog | User PublicKey
Copy link
Member Author

Choose a reason for hiding this comment

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

ProveDlog => SigmaProp

eip-0014.md Outdated
##### Contract parameters:
Constant | Type | Description
---------------|------------|---------------
Pk | ProveDLog | User PublicKey
Copy link
Member Author

Choose a reason for hiding this comment

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

ProveDlog => SigmaProp

eip-0014.md Outdated
###### Contract parameters
Constant | Type | Description
--------------------|------------|---------------
Pk | ProveDLog | User PublicKey
Copy link
Member Author

Choose a reason for hiding this comment

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

ProveDlog => SigmaProp

eip-0014.md Outdated
###### Contract parameters:
Constant | Type | Description
--------------------|------------|---------------
Pk | ProveDLog | User PublicKey
Copy link
Member Author

Choose a reason for hiding this comment

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

ProveDlog => SigmaProp

}
```

#### Swap proxy-contract
Copy link
Member Author

Choose a reason for hiding this comment

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

Please describe why proxy contracts are needed, how are they used.

val quoteAsset = rewardBox.tokens(0)
val quoteAmount = quoteAsset._2.toBigInt
val fairDexFee = rewardBox.value >= SELF.value - quoteAmount * DexFeePerTokenNum / DexFeePerTokenDenom
val relaxedOutput = quoteAmount + 1L // handle rounding loss
Copy link
Member Author

Choose a reason for hiding this comment

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

We can imagine the case when there are no much tokens in the pool at all (maybe not so many issued), then this relaxation becomes significant?


val validDeposit =
if (INPUTS.size == 2 && poolIn.tokens.size == 4) {
val validPoolIn = poolIn.tokens(0) == (PoolNFT, 1L)
Copy link
Contributor

Choose a reason for hiding this comment

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

No need to check that NFT is in quantity 1, we can save a bit of space.


val validRedeem =
if (INPUTS.size == 2 && poolIn.tokens.size == 4) {
val validPoolIn = poolIn.tokens(0) == (PoolNFT, 1L)
Copy link
Contributor

Choose a reason for hiding this comment

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

Like before, avoid checking that NFT is in quantity 1

eip-0014.md Outdated Show resolved Hide resolved
eip-0014.md Outdated Show resolved Hide resolved
@arobsn arobsn mentioned this pull request Dec 7, 2022
8 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants