Skip to content

Commit

Permalink
split some code to avoid schizofrenia
Browse files Browse the repository at this point in the history
  • Loading branch information
svilenkov committed Jun 8, 2021
1 parent 20a2925 commit be5b9df
Show file tree
Hide file tree
Showing 5 changed files with 115 additions and 60 deletions.
4 changes: 3 additions & 1 deletion AltLabs/dex-token-swap/plutus-starter.cabal
Expand Up @@ -38,9 +38,11 @@ library
Plutus.Contracts
-- Plutus.PAB.Effects.ContractTest.Uniswap
Effects.Uniswap
Plutus.Contracts.Data
Plutus.Contracts.PubKey
Plutus.Contracts.Uniswap
Plutus.Contracts.Currency
Plutus.Contracts.LiquidityPool
build-depends:
base >= 4.9 && < 5,
directory,
Expand All @@ -63,7 +65,7 @@ library
default-language: Haskell2010
ghc-options:
-- See Plutus Tx readme
-fobject-code -fno-ignore-interface-pragmas -fno-omit-interface-pragmas
-fobject-code -fno-ignore-interface-pragmas -fno-omit-interface-pragmas -haddock

test-suite plutus-example-projects-test
type: exitcode-stdio-1.0
Expand Down
2 changes: 2 additions & 0 deletions AltLabs/dex-token-swap/src/Plutus/Contracts/Currency.hs
Expand Up @@ -91,6 +91,8 @@ mkCurrency (TxOutRef h i) amts =
, curAmounts = AssocMap.fromList amts
}

-- The only input that the policy script gets is the Context
{-# INLINABLE validate #-}
validate :: OneShotCurrency -> V.ScriptContext -> Bool
validate c@(OneShotCurrency (refHash, refIdx) _) ctx@V.ScriptContext{V.scriptContextTxInfo=txinfo} =
let
Expand Down
53 changes: 53 additions & 0 deletions AltLabs/dex-token-swap/src/Plutus/Contracts/Data.hs
@@ -0,0 +1,53 @@
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# options_ghc -Wno-redundant-constraints #-}
{-# options_ghc -fno-strictness #-}
{-# options_ghc -fno-specialise #-}

{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE StandaloneDeriving #-}
module Plutus.Contracts.Data
where

import Ledger
import Ledger.Value (AssetClass (..), assetClass, assetClassValue, assetClassValueOf)
import Playground.Contract (FromJSON, Generic, ToJSON, ToSchema)
import qualified PlutusTx
import PlutusTx.Prelude hiding (Semigroup (..), unless)
import qualified Prelude as Haskell
import Text.Printf (PrintfArg)

-- uniswapTokenName and poolStateTokenName share the same minting policy
-- | A handy alias to put things in the language of "Coins" instead of
-- "AssetClass".
type Coin = AssetClass

-- Note: An orphan instance here because of the alias above.
deriving anyclass instance ToSchema AssetClass

-- 2 token liquidity Pool
-- Order does not matter A/B == B/A pool
data LiquidityPool = LiquidityPool
{ lpCoinA :: Coin
, lpCoinB :: Coin
}
deriving (Show, Generic, ToJSON, FromJSON, ToSchema)

PlutusTx.unstableMakeIsData ''LiquidityPool
PlutusTx.makeLift ''LiquidityPool

instance Eq LiquidityPool where
{-# INLINABLE (==) #-}
x == y = (lpCoinA x == lpCoinA y && lpCoinB x == lpCoinB y) ||
(lpCoinA x == lpCoinB y && lpCoinB x == lpCoinA y)
53 changes: 53 additions & 0 deletions AltLabs/dex-token-swap/src/Plutus/Contracts/LiquidityPool.hs
@@ -0,0 +1,53 @@
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}

module Plutus.Contracts.LiquidityPool
( calculateAdditionalLiquidity
, calculateInitialLiquidity
, calculateRemoval
-- , checkSwap
-- , lpTicker
, LiquidityPool
) where

import Ledger.Value (TokenName (..), unAssetClass, unCurrencySymbol)
import Plutus.Contracts.Data
import PlutusTx.Prelude
import PlutusTx.Sqrt


{-# INLINABLE calculateInitialLiquidity #-}
calculateInitialLiquidity :: Integer -> Integer -> Integer
calculateInitialLiquidity outA outB = case isqrt (outA * outB) of
Exact l
| l > 0 -> l
Irrational l
| l > 0 -> l + 1
_ -> traceError "insufficient liquidity"

-- helper for if you have an existing Pool, and someone adds liquidity to it
-- eg. A (n) tokens, B (n) tokens
-- someone adds (n) A or B, computes how many
-- liquidity tokens the person should receive
{-# INLINABLE calculateAdditionalLiquidity #-}
calculateAdditionalLiquidity :: Integer -> Integer -> Integer -> Integer -> Integer -> Integer
calculateAdditionalLiquidity oldA oldB liquidity delA delB =
case rsqrt ((liquidity * liquidity * newProd) % oldProd) of
Imaginary -> traceError "insufficient liquidity"
Exact x -> x - liquidity
Irrational x -> x - liquidity
where
oldProd, newProd :: Integer
oldProd = oldA * oldB
newProd = (oldA + delA) * (oldB + delB)

-- same as above just opposite
{-# INLINABLE calculateRemoval #-}
calculateRemoval :: Integer -> Integer -> Integer -> Integer -> (Integer, Integer)
calculateRemoval inA inB liquidity diff = (f inA, f inB)
where
f :: Integer -> Integer
f x = x - divide (x * diff) liquidity


63 changes: 4 additions & 59 deletions AltLabs/dex-token-swap/src/Plutus/Contracts/Uniswap.hs
Expand Up @@ -21,8 +21,8 @@
-- [Uniswap protocol](https://uniswap.org/whitepaper.pdf).
--
module Plutus.Contracts.Uniswap
( Coin
, coin, coinValueOf, mkCoin
(
coin, coinValueOf, mkCoin
, Uniswap (..), uniswap
, poolStateCoinFromUniswapCurrency, liquidityCoin
, CreateParams (..)
Expand Down Expand Up @@ -59,6 +59,8 @@ import PlutusTx.Sqrt
import Prelude (Semigroup (..))
import qualified Prelude
import Text.Printf (printf)
import Plutus.Contracts.Data
import Plutus.Contracts.LiquidityPool

uniswapTokenName, poolStateTokenName :: TokenName
-- state token for the "factory" (unique token)
Expand All @@ -69,14 +71,6 @@ uniswapTokenName = "Uniswap"
-- state token of the liquidity pools (each pool has same token)
poolStateTokenName = "Pool State"

-- uniswapTokenName and poolStateTokenName share the same minting policy
-- | A handy alias to put things in the language of "Coins" instead of
-- "AssetClass".
type Coin = AssetClass

-- Note: An orphan instance here because of the alias above.
deriving anyclass instance ToSchema AssetClass

-- helper function to construct Values
-- Value (Cardano) is a "bag" of coins (1 ADA, 3 NFT etc...)
-- Dictionary of Dictionary of Int { CurrencySymbol: { TokenName: Int }}
Expand All @@ -95,55 +89,6 @@ coinValueOf = assetClassValueOf
mkCoin:: CurrencySymbol -> TokenName -> AssetClass
mkCoin = assetClass

{-# INLINABLE calculateInitialLiquidity #-}
calculateInitialLiquidity :: Integer -> Integer -> Integer
calculateInitialLiquidity outA outB = case isqrt (outA * outB) of
Exact l
| l > 0 -> l
Irrational l
| l > 0 -> l + 1
_ -> traceError "insufficient liquidity"

-- helper for if you have an existing Pool, and someone adds liquidity to it
-- eg. A (n) tokens, B (n) tokens
-- someone adds (n) A or B, computes how many
-- liquidity tokens the person should receive
{-# INLINABLE calculateAdditionalLiquidity #-}
calculateAdditionalLiquidity :: Integer -> Integer -> Integer -> Integer -> Integer -> Integer
calculateAdditionalLiquidity oldA oldB liquidity delA delB =
case rsqrt ((liquidity * liquidity * newProd) % oldProd) of
Imaginary -> traceError "insufficient liquidity"
Exact x -> x - liquidity
Irrational x -> x - liquidity
where
oldProd, newProd :: Integer
oldProd = oldA * oldB
newProd = (oldA + delA) * (oldB + delB)

-- same as above just opposite
{-# INLINABLE calculateRemoval #-}
calculateRemoval :: Integer -> Integer -> Integer -> Integer -> (Integer, Integer)
calculateRemoval inA inB liquidity diff = (f inA, f inB)
where
f :: Integer -> Integer
f x = x - divide (x * diff) liquidity

-- 2 token liquidity Pool
-- Order does not matter A/B == B/A pool
data LiquidityPool = LiquidityPool
{ lpCoinA :: Coin
, lpCoinB :: Coin
}
deriving (Show, Generic, ToJSON, FromJSON, ToSchema)

PlutusTx.unstableMakeIsData ''LiquidityPool
PlutusTx.makeLift ''LiquidityPool

instance Eq LiquidityPool where
{-# INLINABLE (==) #-}
x == y = (lpCoinA x == lpCoinA y && lpCoinB x == lpCoinB y) ||
(lpCoinA x == lpCoinB y && lpCoinB x == lpCoinA y)

-- just a wrapper around the "Coin" type (CurrencySymbol + TokenNAme)
newtype Uniswap = Uniswap
{ usCoin :: Coin
Expand Down

0 comments on commit be5b9df

Please sign in to comment.