Last active
April 14, 2020 16:52
-
-
Save mariano-aguero/b9a4e6ee8d1b3e7a814a021febb2656e to your computer and use it in GitHub Desktop.
Liquidity pool for tezos
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function natToTz(const val: nat): tez is val * 1tz | |
function natToMutez(const val: nat): tez is val * 1mutez | |
function tezToNatWithMutez(const val: tez): nat is val / 1mutez | |
function tezToNatWithTz(const val: tez): nat is val / 1tz | |
function natToInt(const val: nat): int is val + 0 | |
function intToNat(const val: int): nat is block { | |
var res: nat := 0n; | |
if(val >= 0) | |
then res := abs(val) | |
else failwith("Not posible to convert from negative values") | |
} with res |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Naive iterative solution to calculate pow(x, n), would be to multiply x exactly n times | |
function pow (var baseNumber : int; var exponent : int) : int is | |
block { | |
var result: int := 1; | |
while exponent =/= 0 block { | |
result := result * baseNumber; | |
exponent := exponent - 1; | |
} | |
} with result; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "./utils/conversions.ligo" | |
#include "./utils/math.ligo" | |
#include "./partials/tokenActions.ligo" | |
type tokenInformation is record | |
contractAddress: address; | |
tokenDecimals: nat; | |
tokenSupply: nat; | |
end | |
type action is | |
| Deposit of (unit) | |
| Withdraw of (nat) | |
| Borrow of (nat) | |
| RepayBorrow of (unit) | |
| AddLiquidity of (unit) | |
| UpdateCollateralRate of (nat) | |
| GetExchangeRate of (unit * contract(nat)) | |
| GetBalanceOf of (address * contract(tez)) | |
type balanceInfo is record | |
tezAmount: tez; | |
blockTimestamp: timestamp; | |
end | |
type store is record | |
owner: address; | |
deposits: big_map(address, balanceInfo); | |
borrows: big_map(address, balanceInfo); | |
totalDeposits: tez; | |
totalBorrows: tez; | |
collateralRate: nat; // The collateral ratio that borrows must maintain (e.g. 2 implies 2:1), this represents the percentage of supplied value that can be actively borrowed at any given time. | |
liquidity: tez; | |
token: tokenInformation; | |
end | |
const emptyOps: list(operation) = list end; | |
type return is list(operation) * store; | |
function getExchangeRateInternal(var store: store): nat is | |
block { | |
var exchangeRate :nat := 1n; | |
if store.token.tokenSupply >= 1n | |
then block { | |
const realTokenSupply: nat = store.token.tokenSupply / intToNat(pow(10, natToInt(store.token.tokenDecimals))); | |
exchangeRate := tezToNatWithTz(store.totalDeposits + store.totalBorrows) / realTokenSupply; | |
} | |
else skip; | |
} with exchangeRate; | |
function getCoefficientInterest(var store: store): nat is | |
block { | |
var coefficientInterest :nat := 1n; | |
if (store.totalDeposits + store.totalBorrows) > 0tez | |
then coefficientInterest := store.totalBorrows / (store.totalDeposits + store.totalBorrows); | |
else skip; | |
} with coefficientInterest; attributes ["inline"]; | |
function getBorrowInterestRate(var store: store): nat is (2n + getCoefficientInterest(store) * 20n); | |
function getDepositInterestRate(var store: store): nat is (getBorrowInterestRate(store) * getCoefficientInterest(store)); | |
function calculateBorrowInterest(const accountInfo: balanceInfo; var store: store): tez is | |
block { | |
const anualBlocks: int = 522119; | |
const dailyBlocks: int = anualBlocks / 365; | |
const elapsedBlocks :int = now - accountInfo.blockTimestamp; | |
const interestAmount :tez = 0tez; | |
if elapsedBlocks > dailyBlocks | |
then block { | |
const elapsedDays :int = elapsedBlocks / dailyBlocks; | |
const interestRatePercentage :int = natToInt(getBorrowInterestRate(store) / 100n); | |
const powExp :int = elapsedDays / 365; | |
interestAmount := accountInfo.tezAmount * intToNat(pow((1 + interestRatePercentage), powExp)); | |
} | |
else skip; | |
} with interestAmount; attributes ["inline"]; | |
function calculateDepositInterest(const accountInfo: balanceInfo; var store: store): tez is | |
block { | |
const anualBlocks: int = 522119; | |
const dailyBlocks: int = anualBlocks / 365; | |
const elapsedBlocks :int = now - accountInfo.blockTimestamp; | |
const interestAmount :tez = 0tez; | |
if elapsedBlocks > dailyBlocks | |
then block { | |
const elapsedDays :int = elapsedBlocks / dailyBlocks; | |
const interestRatePercentage :int = natToInt(getDepositInterestRate(store) / 100n); | |
const powExp :int = elapsedDays / 365; | |
interestAmount := accountInfo.tezAmount * intToNat(pow((1 + interestRatePercentage), powExp)); | |
} | |
else skip; | |
} with interestAmount; attributes ["inline"]; | |
function tokenProxy (const action : tokenAction; const store : store): operation is | |
block { | |
const tokenContract: contract (tokenAction) = | |
case (Tezos.get_contract_opt (store.token.contractAddress) : option (contract (tokenAction))) of | |
Some (contractAction) -> contractAction | |
| None -> (failwith ("Contract not found.") : contract (tokenAction)) | |
end; | |
const proxyOperation : operation = Tezos.transaction (action, 0mutez, tokenContract); | |
} with proxyOperation; | |
function getBorrow(var store: store): balanceInfo is | |
block { | |
var borrowsMap: big_map(address, balanceInfo) := store.borrows; | |
var borrow: option(balanceInfo) := borrowsMap[sender]; | |
} with | |
case borrow of | |
| Some(borrowItem) -> borrowItem | |
| None -> record tezAmount = 0tez; blockTimestamp = now; end | |
end; attributes ["inline"]; | |
function getDeposit(var store: store): balanceInfo is | |
block { | |
var depositsMap: big_map(address, balanceInfo) := store.deposits; | |
var deposit: option(balanceInfo) := depositsMap[sender]; | |
} with | |
case deposit of | |
| Some(depositItem) -> depositItem | |
| None -> record tezAmount = 0tez; blockTimestamp = now; end | |
end; attributes ["inline"]; | |
function updateDeposit(var amountToDeposit: tez; var store: store): store is | |
block { | |
var accountInfo: balanceInfo := getDeposit(store); | |
// calculate interest | |
const interest:tez = calculateDepositInterest(accountInfo, store); | |
store.deposits[sender] := record tezAmount = accountInfo.tezAmount + interest + amountToDeposit; blockTimestamp = now; end; | |
store.totalDeposits := store.totalDeposits + interest + amountToDeposit; | |
store.liquidity := store.liquidity + amountToDeposit; | |
} with store; | |
function updateBorrow(var amountToBorrow: tez; var store: store): store is | |
block { | |
var accountInfo: balanceInfo := getBorrow(store); | |
// calculate interest | |
const interest:tez = calculateBorrowInterest(accountInfo, store); | |
store.borrows[sender] := record tezAmount = accountInfo.tezAmount + interest + amountToBorrow; blockTimestamp = now; end; | |
store.totalBorrows := store.totalBorrows + interest + amountToBorrow; | |
store.liquidity := store.liquidity - amountToBorrow; | |
} with store; | |
function checkAccountLiquidity(var amountToValidate: nat; var store: store): unit is | |
block { | |
// account liquidity is defined as the total estimated tez value of an account's collateral | |
// supply balances multiplied by the protocol collateral rate factor, | |
// minus the total value of that account's borrow balances | |
var depositAccount: balanceInfo := getDeposit(store); | |
var borrowAccount: balanceInfo := getBorrow(store); | |
const depositAmountInInt: int = natToInt(tezToNatWithTz(depositAccount.tezAmount)); | |
const borrowAmountInInt: int = natToInt(tezToNatWithTz(borrowAccount.tezAmount)); | |
const amountOfCollateralAvailable: int = (depositAmountInInt * natToInt(store.collateralRate) / 100) - borrowAmountInInt + natToInt(amountToValidate); | |
const amountToValidateInTz: tez = natToTz(amountToValidate); | |
if amountOfCollateralAvailable < 0 or amountToValidateInTz >= store.liquidity | |
then failwith("Amount is greater than liquidity!"); | |
else skip; | |
} with unit; attributes ["inline"]; | |
function depositImp(var store: store): return is | |
block { | |
if amount = 0mutez | |
then failwith("No tez transferred!"); | |
else skip; | |
// Setting the deposit to the sender | |
store := updateDeposit(amount, store); | |
// TODO: try to get the decimals property from the token contract | |
// The user receives a quantity of pTokens equal to the underlying tokens supplied, divided by the current Exchange Rate. | |
const amountToMintInNat: nat = intToNat(natToInt(tezToNatWithTz(amount) / getExchangeRateInternal(store)) * pow(10, natToInt(store.token.tokenDecimals))); | |
// Increment token supply | |
const newTokenSupply :nat = store.token.tokenSupply + amountToMintInNat; | |
patch store.token with record [tokenSupply = newTokenSupply]; | |
// mintTo tokens to the senderAddress | |
const tokenProxyMintToOperation: operation = tokenProxy(MintTo(sender, amountToMintInNat), store); | |
const operations : list (operation) = list [tokenProxyMintToOperation]; | |
} with(operations, store); | |
function withdrawImp(var amountToWithdraw: nat; var store: store): return is | |
block { | |
// If the amount is zero, failwith | |
if amountToWithdraw = 0n | |
then failwith("No amount to withdraw!"); | |
else skip; | |
store := updateDeposit(0tez, store); | |
store := updateBorrow(0tez, store); | |
// Check account liquidity | |
checkAccountLiquidity(amountToWithdraw, store); | |
// Calculate amount to burn | |
const amountToBurnInNat: nat = intToNat(natToInt(amountToWithdraw / getExchangeRateInternal(store)) * pow(10, natToInt(store.token.tokenDecimals))); | |
// Decrement token supply | |
const newTokenSupply :nat = intToNat(store.token.tokenSupply - amountToBurnInNat); | |
patch store.token with record [tokenSupply = newTokenSupply]; | |
// Burn pTokens | |
const tokenProxyBurnToOperation: operation = tokenProxy(BurnTo(sender, amountToBurnInNat), store); | |
// Update user's balance | |
const amountToWithdrawInTz: tez = natToTz(amountToWithdraw); | |
var accountInfo: balanceInfo := getDeposit(store); | |
store.deposits[sender] := record tezAmount = accountInfo.tezAmount - amountToWithdrawInTz; blockTimestamp = now; end; | |
store.totalDeposits := store.totalDeposits - amountToWithdrawInTz; | |
// Update liquidity | |
store.liquidity := store.liquidity - amountToWithdrawInTz; | |
// Create the operation to transfer tez to sender | |
const receiver : contract (unit) = | |
case (Tezos.get_contract_opt (sender): option(contract(unit))) of | |
Some (contractSender) -> contractSender | |
| None -> (failwith ("Not a contract") : (contract(unit))) | |
end; | |
const payoutOperation: operation = Tezos.transaction(unit, amountToWithdrawInTz, receiver); | |
const operations : list (operation) = list [tokenProxyBurnToOperation ; payoutOperation]; | |
} with(operations, store); | |
function addLiquidity( var store : store) : return is | |
block { | |
if (sender =/= store.owner or amount = 0mutez) | |
then failwith("There was a problem trying to add liquidity"); | |
else store.liquidity := store.liquidity + amount; | |
} with (emptyOps, store); attributes ["inline"]; | |
function getExchangeRate (const callback : contract(nat); var store : store) : return is ( list [Tezos.transaction(getExchangeRateInternal(store), 0mutez, callback)], store); attributes ["inline"]; | |
function getBalanceOf (const accountAddress: address; const callback : contract(tez); var store : store) : return is | |
block { | |
var operations: list(operation) := nil; | |
var depositsMap: big_map(address, balanceInfo) := store.deposits; | |
var accountInfo: option(balanceInfo) := depositsMap[accountAddress]; | |
case accountInfo of | |
| None -> failwith("Account address not found") | |
| Some(accountInfoItem) -> operations := list [Tezos.transaction(accountInfoItem.tezAmount, 0mutez, callback)] | |
end; | |
} with (operations, store); attributes ["inline"]; | |
function borrow(var amountToBorrow: nat; var store: store): return is | |
block { | |
if amountToBorrow = 0n | |
then failwith("No amount to borrow!"); | |
else skip; | |
store := updateDeposit(0tez, store); | |
store := updateBorrow(0tez, store); | |
// Check account liquidity | |
checkAccountLiquidity(amountToBorrow, store); | |
// Setting the borrow to the sender | |
const amountToBorrowInTz: tez = natToTz(amountToBorrow); | |
store := updateBorrow(amountToBorrowInTz, store); | |
// Payout transaction to the sender address, with the amount to borrow | |
const receiver : contract (unit) = | |
case (Tezos.get_contract_opt (sender): option(contract(unit))) of | |
Some (contractSender) -> contractSender | |
| None -> (failwith ("Not a contract") : (contract(unit))) | |
end; | |
const operationTransfer: operation = Tezos.transaction(unit, amountToBorrowInTz, receiver); | |
const operations : list (operation) = list [operationTransfer]; | |
} with(operations, store); | |
function repayBorrow(var store: store): return is | |
block { | |
if amount = 0mutez | |
then failwith("No tez transferred!"); | |
else skip; | |
store := updateDeposit(0tez, store); | |
store := updateBorrow(0tez, store); | |
var accountInfo: balanceInfo := getBorrow(store); | |
// Check collateral ratio. | |
const borrowItemInNat: nat = tezToNatWithTz(accountInfo.tezAmount); | |
const borrowItemInTz: tez = natToTz(borrowItemInNat); | |
if amount > borrowItemInTz | |
then failwith("Amount to pay is greater than existing borrow amount!"); | |
else skip; | |
// Update user's borrow balance | |
store.borrows[sender] := record tezAmount = accountInfo.tezAmount - amount; blockTimestamp = now; end; | |
store.totalBorrows := store.totalBorrows - amount; | |
// Update liquidity | |
store.liquidity := store.liquidity + amount; | |
} with(emptyOps, store); | |
function updateCollateralRate(const value : nat ; var store : store) : return is | |
block { | |
// Fail if is not the owner | |
if (sender =/= store.owner) | |
then failwith("You must be the owner of the contract to update the collateral ratio"); | |
else store.collateralRate := value; | |
} with (emptyOps, store); attributes ["inline"]; | |
function main (const action: action; var store: store): return is | |
block { | |
skip | |
} with case action of | |
| Deposit(n) -> depositImp(store) | |
| Withdraw(n) -> withdrawImp(n, store) | |
| Borrow(n) -> borrow(n, store) | |
| RepayBorrow(n) -> repayBorrow(store) | |
| UpdateCollateralRate(n) -> updateCollateralRate(n, store) | |
| AddLiquidity(n) -> addLiquidity(store) | |
| GetExchangeRate(n) -> getExchangeRate(n.1, store) | |
| GetBalanceOf(n) -> getBalanceOf(n.0, n.1, store) | |
end; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "./partials/tokenActions.ligo" | |
type account is record | |
balance: nat; | |
allowances: map(address, nat); | |
end | |
type store is record | |
owners: set(address); | |
decimals: nat; // Added this property used in the erc20 ethereum specification | |
symbol: string; // Added this property used in the erc20 ethereum specification | |
name: string; // Added this property used in the erc20 ethereum specification | |
totalSupply: nat; | |
accounts: big_map(address, account); | |
end | |
type return is list(operation) * store; | |
const emptyOps : list(operation) = list end; | |
const emptyAllowances : map(address,nat) = map end; | |
function getAccount (const addressAccount : address ; const accounts: big_map(address, account)) : account is | |
block { skip } with | |
case accounts[addressAccount] of | |
| Some(account) -> account | |
| None -> record balance = 0n; allowances = emptyAllowances; end | |
end | |
function getAllowance(const addressAccount : address ; const allowances : map(address, nat)) : nat is | |
block { skip } with | |
case allowances[addressAccount] of | |
| Some(value) -> value | |
| None -> 0n | |
end | |
function allowance (const addressOwner : address; const addressSpender : address; const callback : contract(nat); var store : store) : return is | |
block { | |
const storeAccountOwner: account = getAccount(addressOwner, store.accounts); | |
var allowed: nat := getAllowance(addressSpender, storeAccountOwner.allowances); | |
const allowedOperation: operation = Tezos.transaction(allowed, 0tz, callback); | |
operations := list | |
allowedOperation | |
end; | |
} with (operations, store); | |
function isAllowed (const addressOwner : address; const addressSpender : address; const value : nat; var store : store) : bool is | |
block { | |
const storeAccountOwner: account = getAccount(addressOwner, store.accounts); | |
var allowedAmount: nat := getAllowance(addressSpender, storeAccountOwner.allowances); | |
const isAllowed: bool = allowedAmount >= value; | |
} with isAllowed; | |
function isOwner (const addressOwner : address; var store : store) : bool is | |
block { | |
const isOwner : bool = store.owners contains addressOwner; | |
} with isOwner; | |
function updateOwners (var newAddress: address; var owners : set (address)) : set (address) is | |
block { | |
patch owners with set [newAddress]; | |
} with owners; | |
function addOwner (const ownerAddress : address; var store : store) : return is | |
block { | |
case isOwner(sender, store) of | |
| False -> failwith ("Sender not allowed to perform this action") | |
| True -> skip | |
end; | |
store.owners := updateOwners(ownerAddress, store.owners); | |
} with (emptyOps, store); | |
function approve (const addressSpender : address; const value : nat; var store : store) : return is | |
block { | |
// If sender is the spender approving is not necessary | |
if sender = addressSpender then skip; | |
else block { | |
const senderAccount: account = getAccount(sender, store.accounts); | |
var allowed: nat := getAllowance(addressSpender, senderAccount.allowances); | |
// Changing allowance value from non-zero value to a non-zero value is forbidden to prevent the corresponding attack vector. | |
if allowed =/= 0n then failwith("UnsafeAllowanceChange"); | |
else block { | |
// TODO: maybe this need a patch ? | |
senderAccount.allowances[addressSpender] := value; | |
store.accounts[sender] := senderAccount; | |
} | |
} | |
} with (emptyOps, store); | |
function transfer (const addressFrom : address; const addressTo : address; const value : nat; var store : store) : return is | |
block { | |
// #1 First check: when called with "from" account equal to the transaction sender, we assume that | |
// the user transfers their own money and this does not require approval. | |
if addressFrom = addressTo then skip; | |
else block { | |
// #2 NotEnoughAllowance: the transaction sender must be previously authorized to transfer at | |
// least the requested number of tokens from the "from" account using the approve | |
case isAllowed(addressFrom, addressTo, value, store) of | |
| False -> block { | |
failwith ("NotEnoughAllowance"); | |
} | |
| True -> skip | |
end; | |
const addressFromAccount: account = getAccount(addressFrom, store.accounts); | |
// #3 NotEnoughBalance: check that the accountFrom can spend that much | |
if value > addressFromAccount.balance | |
then failwith ("NotEnoughBalance"); | |
else skip; | |
// Update balances | |
const newFromBalance :nat = abs(addressFromAccount.balance - value); // ensure non negative | |
patch addressFromAccount with record [balance = newFromBalance]; | |
store.accounts[addressFrom] := addressFromAccount; | |
const addressToAccount: account = getAccount(addressTo, store.accounts); | |
const newToBalance :nat = addressToAccount.balance + value; // ensure non negative | |
patch addressToAccount with record [balance = newToBalance]; | |
store.accounts[addressTo] := addressToAccount; | |
// Update allowances | |
case store.accounts[addressFrom] of | |
| None -> skip | |
| Some(account) -> block { | |
case account.allowances[addressTo] of | |
| None -> skip | |
| Some(allowanceAmount) -> block { | |
account.allowances[addressTo] := abs(allowanceAmount - value); | |
store.accounts[addressFrom] := record balance = addressFromAccount.balance; allowances = account.allowances; end; | |
} | |
end; | |
} | |
end; | |
} | |
} with (emptyOps, store); | |
function mint (const value : nat ; var store : store) : return is | |
block { | |
// Fail if is not an owner | |
if not isOwner(sender, store) then failwith("You must be an owner of the contract to mint tokens"); | |
else block { | |
var ownerAccount: account := record | |
balance = 0n; | |
allowances = (map end : map(address, nat)); | |
end; | |
case store.accounts[sender] of | |
| None -> skip | |
| Some(n) -> ownerAccount := n | |
end; | |
// Update the owner balance and totalSupply | |
const newBalance :nat = ownerAccount.balance + value; | |
patch ownerAccount with record [balance = newBalance]; | |
store.accounts[sender] := ownerAccount; | |
store.totalSupply := store.totalSupply + value; | |
} | |
} with (emptyOps, store) | |
function mintTo (const toAddress: address; const value : nat ; var store : store) : return is | |
block { | |
// Fail if is not an owner | |
if not isOwner(sender, store) then failwith("You must be an owner of the contract to mint tokens"); | |
else block { | |
var toAccount: account := record | |
balance = 0n; | |
allowances = (map end : map(address, nat)); | |
end; | |
case store.accounts[toAddress] of | |
| None -> skip | |
| Some(n) -> toAccount := n | |
end; | |
// Update the balance and totalSupply | |
const newBalance :nat = toAccount.balance + value; | |
patch toAccount with record [balance = newBalance]; | |
store.accounts[toAddress] := toAccount; | |
store.totalSupply := store.totalSupply + value; | |
} | |
} with (emptyOps, store) | |
function burn (const value : nat ; var store : store) : return is | |
block { | |
// Fail if is not an owner | |
if not isOwner(sender, store) then failwith("You must be an owner of the contract to burn tokens"); | |
else block { | |
var ownerAccount: account := record | |
balance = 0n; | |
allowances = (map end : map(address, nat)); | |
end; | |
case store.accounts[sender] of | |
| None -> skip | |
| Some(n) -> ownerAccount := n | |
end; | |
// Check that the owner can spend that much | |
if value > ownerAccount.balance | |
then failwith ("NotEnoughBalance"); | |
else skip; | |
// Check totalSupply | |
if value > store.totalSupply | |
then failwith ("TotalSupply is too low"); | |
else skip; | |
// Update balances and totalSupply | |
const newBalance :nat = abs(ownerAccount.balance - value); | |
patch ownerAccount with record [balance = newBalance]; | |
store.accounts[sender] := ownerAccount; | |
store.totalSupply := abs(store.totalSupply - value); | |
} | |
} with (emptyOps, store) | |
function burnTo (const toAddress: address ; const value : nat ; var store : store) : return is | |
block { | |
// Fail if is not an owner | |
if not isOwner(sender, store) then failwith("You must be an owner of the contract to burn tokens"); | |
else block { | |
var toAccount: account := record | |
balance = 0n; | |
allowances = (map end : map(address, nat)); | |
end; | |
case store.accounts[toAddress] of | |
| None -> skip | |
| Some(n) -> toAccount := n | |
end; | |
// Check that the owner can spend that much | |
if value > toAccount.balance | |
then failwith ("NotEnoughBalance"); | |
else skip; | |
// Check totalSupply | |
if value > store.totalSupply | |
then failwith ("TotalSupply is too low"); | |
else skip; | |
// Update balances and totalSupply | |
const newBalance :nat = abs(toAccount.balance - value); | |
patch toAccount with record [balance = newBalance]; | |
store.accounts[toAddress] := toAccount; | |
store.totalSupply := abs(store.totalSupply - value); | |
} | |
} with (emptyOps, store) | |
function balanceOf (const addressOwner : address; const callback : contract(nat); var store : store) : return is | |
block { | |
const addressOwnerAccount: account = getAccount(addressOwner, store.accounts); | |
const addressOwnerBalance: nat = addressOwnerAccount.balance; | |
const addressOwnerBalanceOperation: operation = Tezos.transaction(addressOwnerBalance, 0tz, callback); | |
operations := list | |
addressOwnerBalanceOperation | |
end; | |
} with (operations, store); | |
function totalSupply (const callback : contract(nat); var store : store) : return is | |
block { | |
var totalSupply: nat := store.totalSupply; | |
const totalSupplyOperation: operation = transaction(totalSupply, 0mutez, callback); | |
operations := list | |
totalSupplyOperation | |
end; | |
} with (operations, store); | |
function decimals (const callback : contract(nat); var store : store) : return is | |
block { | |
var decimals: nat := store.decimals; | |
const decimalsOperation: operation = Tezos.transaction(decimals, 0mutez, callback); | |
operations := list | |
decimalsOperation | |
end; | |
} with (operations, store); | |
function name (const callback : contract(string); var store : store) : return is | |
block { | |
var name: string := store.name; | |
const nameOperation: operation = Tezos.transaction(name, 0mutez, callback); | |
operations := list | |
nameOperation | |
end; | |
} with (operations, store); | |
function symbol (const callback : contract(string); var store : store) : return is | |
block { | |
var symbol: string := store.symbol; | |
const symbolOperation: operation = Tezos.transaction(symbol, 0mutez, callback); | |
operations := list | |
symbolOperation | |
end; | |
} with (operations, store); | |
function main (const action : tokenAction ; const store : store) : return is | |
block { | |
if amount =/= 0tz then failwith ("This contract do not accept token amount"); | |
else skip; | |
} with case action of | |
GetAllowance(n) -> allowance(n.0, n.1, n.2, store) | |
| Transfer(n) -> transfer(n.0, n.1, n.2, store) | |
| Approve(n) -> approve(n.0, n.1, store) | |
| GetBalance(n) -> balanceOf(n.0, n.1, store) | |
| GetTotalSupply(n) -> totalSupply(n.1, store) | |
| Mint(n) -> mint(n, store) | |
| MintTo(n) -> mintTo(n.0, n.1, store) | |
| Burn(n) -> burn(n, store) | |
| BurnTo(n) -> burnTo(n.0, n.1, store) | |
| AddOwner(n) -> addOwner(n, store) | |
| Decimals(n) -> decimals(n.1, store) | |
| Symbol(n) -> symbol(n.1, store) | |
| Name(n) -> name(n.1, store) | |
end; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
type tokenAction is | |
| GetAllowance of (address * address * contract(nat)) | |
| Transfer of (address * address * nat) | |
| Approve of (address * nat) | |
| GetBalance of (address * contract(nat)) | |
| GetTotalSupply of (unit * contract(nat)) | |
| Mint of (nat) | |
| MintTo of (address * nat) | |
| Burn of (nat) | |
| BurnTo of (address * nat) | |
| AddOwner of (address) | |
| Symbol of (unit * contract(string)) | |
| Name of (unit * contract(string)) | |
| Decimals of (unit * contract(nat)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment