morley-upgradeable-0.3: src/Lorentz/Contracts/UpgradeableUnsafeLedger/V1.hs
-- SPDX-FileCopyrightText: 2020 Tocqueville Group
--
-- SPDX-License-Identifier: LicenseRef-MIT-TQ
-- | A buggy implementation of Unsafe ledger, returns balances multiplied by 2
module Lorentz.Contracts.UpgradeableUnsafeLedger.V1
( UnsafeLedgerV1
, Interface
, migrate
, unsafeLedgerContract
-- The following are used in V2
, UStoreTemplate
, UStoreV1
, TransferParams
, transfer
, getTotalSupply
) where
import Lorentz
import Lorentz.Contracts.Upgradeable.Common
import Lorentz.UStore
data UnsafeLedgerV1 :: VersionKind
type Interface =
[ "transfer" ?: TransferParams
, "getTotalSupply" ?: Void_ () Natural
, "getBalance" ?: Void_ Address (Maybe Natural)
]
type TransferParams = (Address, Natural)
data UStoreTemplate = UStoreTemplate
{ ledger :: Address |~> Natural
, totalSupply :: UStoreField Natural
} deriving stock (Eq, Generic)
type UStoreV1 = UStore UStoreTemplate
instance KnownContractVersion UnsafeLedgerV1 where
type VerInterface UnsafeLedgerV1 = Interface
type VerUStoreTemplate UnsafeLedgerV1 = UStoreTemplate
contractVersion _ = 1
-- | Like in UpgradeableCounter, this function populates the empty UStore_
-- with entries and initial values for each field. The result is expected
-- to adhere to V1.UStoreTemplate
migrate :: '[UStore_] :-> '[UStore_]
migrate = checkedCoercing_ @_ @UStoreV1 $ do
push @Natural 500
dup
dip $ ustoreSetField #totalSupply
sender
ustoreInsert #ledger
unsafeLedgerContract :: UContractRouter UnsafeLedgerV1
unsafeLedgerContract = mkUContractRouter $ do
caseUParamT @Interface
( #transfer /-> transfer
, #getTotalSupply /-> getTotalSupply
, #getBalance /-> buggyGetBalance
)
uparamFallbackFail
transfer :: '[TransferParams, UStoreV1]
:-> '[([Operation], UStoreV1)]
transfer = do
debitSource; creditTo; nil; pair;
getTotalSupply :: '[Void_ () Natural, UStoreV1]
:-> '[([Operation], UStoreV1)]
getTotalSupply = void_ (do drop @(); ustoreToField #totalSupply)
-- Buggy getBalance returns balance multiplied by 2
buggyGetBalance :: '[Void_ Address (Maybe Natural), UStoreV1]
:-> '[([Operation], UStoreV1)]
buggyGetBalance = void_ $ do
ustoreGet #ledger
if IsSome
then push @Natural 2 >> mul >> some
else none
debitSource :: '[TransferParams, UStoreV1]
:-> '[TransferParams, UStoreV1]
debitSource = do
dip $ do
sender
dip dup
ustoreGet #ledger
assertSome [mt|Sender address is not in ledger|]
swap
dip (dup # cdr)
subGt0
swap
dip (do sender; ustoreUpdate #ledger)
creditTo :: '[TransferParams, UStoreV1] :-> '[UStoreV1]
creditTo = do
dup; car
swap
dip (dip dup # ustoreGet #ledger)
swap
if IsSome then dip (dup >> cdr) >> add @Natural else (dup >> cdr)
some
dip (car)
swap
ustoreUpdate #ledger
subGt0 :: Natural ': Natural ': s :-> Maybe Natural ': s
subGt0 = do
sub;
dup; assertGe0 [mt|Transferred value is greater than balance|]
dup; eq0
if Holds
then drop >> none
else isNat