morley-upgradeable-0.3: src/Lorentz/Contracts/UserUpgradeable/V1.hs
-- SPDX-FileCopyrightText: 2020 Tocqueville Group
--
-- SPDX-License-Identifier: LicenseRef-MIT-TQ
{-# OPTIONS_GHC -Wno-orphans #-}
-- | The first version of a minimal user-upgradeable ledger. It does not
-- offer common ledger functions like Transfer/GetTotalSupply/etc. to
-- demonstrate a concept and keep the code consise.
--
-- Note that the naming in this module is different from
-- Lorentz.Contracts.Upgradeable: by "migration" here we mean the process
-- of transferring the value from an old contract to the new one rather than
-- applying a transformation to storage. Thus, MigrationScript here is a lambda
-- that forges an operation to migrate user's funds rather than a function
-- that upgrades storage in-place.
module Lorentz.Contracts.UserUpgradeable.V1
( Parameter(..)
, Storage(..)
, mkStorage
, userUpgradeableContract
) where
import Lorentz
import Lorentz.Contracts.UserUpgradeable.Migrations
(MigrationTarget, callMigrationTarget, initiateMigration)
data Storage = Storage
{ ledger :: BigMap Address Natural
, admin :: Address
, migrationTarget :: Maybe MigrationTarget
}
deriving stock Generic
deriving anyclass (IsoValue, HasAnnotation)
mkStorage :: BigMap Address Natural -> Address -> Storage
mkStorage balances admin = Storage
{ ledger = balances
, admin = admin
, migrationTarget = Nothing
}
data Parameter
= InitiateMigration MigrationTarget
-- ^ Token admin calls this entrypoint and provides a lambda to forge
-- V2.MigrateFrom operation.
| MigrateMyTokens Natural
-- ^ Users are supposed to call this entrypoint if they want to upgrade
-- their tokens.
| GetBalance (View Address Natural)
-- ^ Returns the balance of a holder.
deriving stock Generic
deriving anyclass IsoValue
instance ParameterHasEntrypoints Parameter where
type ParameterEntrypointsDerivation Parameter = EpdPlain
type instance ErrorArg "userUpgradable'notEnoughTokens" = ()
instance CustomErrorHasDoc "userUpgradable'notEnoughTokens" where
customErrClass = ErrClassActionException
customErrDocMdCause = "Not enough tokens."
userUpgradeableContract :: Contract Parameter Storage
userUpgradeableContract = defaultContract $ do
unpair
caseT @Parameter
( #cInitiateMigration /-> initiateMigration
, #cMigrateMyTokens /-> do dup; dip burnFromSender; callMigrationTarget
, #cGetBalance /-> view_ $ do
dip (toField #ledger); get; ifSome nop (push 0)
)
-- | Burns tokens from the sender
burnFromSender :: '[Natural, Storage] :-> '[Storage]
burnFromSender = do
dip $ do
getField #ledger
sender
get
ifSome nop $ failCustom_ #userUpgradable'notEnoughTokens
swap
stackType @('[Natural, Natural, Storage])
sub
isNat
ifSome nop $ failCustom_ #userUpgradable'notEnoughTokens
dup; push @Natural 0
if IsEq
then drop # none
else some
stackType @('[Maybe Natural, Storage])
dip (getField #ledger);
sender; update; setField #ledger