This repository hosts on-chain code part of aada-lend project.
app/
- Exectuable filessrc/
- Smartcontracts. Files ending with Nft are minting policies.test/
- Files for testing project.
- Borrower
- Lender
- Oracle
- Create loan request
- Cancel loan request
- Return loan
- Retrieve rest of liquidated collateral
- Lend
- Liquidate borrower loan by taking collateral
- Retrieve loan and loan interest
- Up until loan is given to Borrower Borrower should always be able to cancel his loan request.
- When canceling loan request Borrower should always be able to get all of his collateral back.
- Only Borrowers Nft owner can cancel loan request. Loan request can be canceled only if Borrowers nft is burnt.
- Loan receiver is identified by data encoded with datum.
- Loan request is created by locking collateral funds into
Request.hs
smartcontract together with datum. - Borrower must provide this information when creating request:
- borrowersNftTn - Borrowers token name encoding utxo to be consumed when minting token. See
AadaNft.hs
. - borrowersAddress - Who should receive the loan.
- loan - Asset of requested loan.
- loanAmnt - Amount of requested loan.
- interest - Asset of interest to be paid.
- interestAmnt - Amount of interest to be paid for loan.
- collateral - Asset of collateral.
- collateralAmnt - Amount of collateral.
- loanDuration - How long till Lender gains rights to claim collateral. Once loan duration passes borrower must pay full interestAmnt to claim collateral back.
- liquidateNft - Currency symbol of Nft which when minted grants Lender rights to take collateral.
- collateralFactor - Collateral factor used for liquidation.
- liquidationComission - How much % borrower will pay lender when liquidated (before loanDuration passes).
- requestExpiration - When does loan request expire. Lender should not be able to provide Loan past this time value.
- borrowersNftTn - Borrowers token name encoding utxo to be consumed when minting token. See
- Lender can get Vesting rights to borrowers collateral only when exact amount loanAmnt of loan is given to borrowersAddress and collateral funds are transfered to
Collateral.hs
smartcontract or when liquidateNft is minted. - Lender can't get Vesting rights to borrowers collateral if loan is not given to owner of borrowersAddress which
is encoded in
Request.hs
smartcontract datum. - Lender can't get Vesting rights to borrowers collateral if collateral from
Request.hs
smartcontract is not transfered toCollateral.hs
smartcontract. - Lender can't get Vesting rights to borrower collateral if lenderNftTn is not minted.
- Lender can't retrieve collateral from
Collateral.hs
if loanDuration didn't pass in datum provided liquidate nft is not minted unless liqudation OracleNft is burnt. - Borrower can't retrieve his collateral if borrowers nft encoded in datum is not burnt.
- Borrower can't retrieve his collateral if loan is not sent to
Interest.hs
smartcontract. - Borrower can't retrieve his collateral if enough interest (depends on when loan is returned based on loanDuration) is not sent to
Interest.hs
smartcontract. - Borrower can't retrieve his collateral if there are more than 3 different assets in repay transaction.
- If Borrower returns loan sooner than repayinterval he only needs to pay
(current time - loan taken time) / repay
interval amount of interest. - Lender shouldn't be able to provide loan to borrower if loan request has expired.
- Lender shouldn't be able to provide loan if there is incoming utxo in transaction other than from
Request.hs
- Lender shouldn't be able to provide loan if these correct datum fields are not provided together with datum already locked in
Request.hs
:- lenderTn - Lenders token name encoding utxo to be consumed when minting token. See
AadaNft.hs
. - lendDate - upper bound of transaction is valid to submit range.
- lenderTn - Lenders token name encoding utxo to be consumed when minting token. See
- Lender shouldn't be able to provide loan if rqeuestExpiration is later than the the end of transaction is valid interval.
- Lender shouldn't be able to provide loan if there are more than 3 different types of assets in lend transaction.
- It shouldn't be possible to mint more than one token at a time
- It shouldn't be possible to burn more than one token at a time
- It shouldn't be possible to have two Nfts with same token name
- It shouldn't be possible to mint token unless utxo is consumed which hash is set as a token name
- LenderNft is depicted by
isLender
minting policy parameter inAadaNft.hs
if it is set toTrue
.
- BorrowerNft is depicted by
isLender
minting policy parameter inAadaNft.hs
if it is set toFalse
.
M1 Macs uses different instruction set (Arm is RISC) than the usuall Intel or AMD processors (CISC - Complex Instruction Set Computing). As of writing this readme I haven't managed to make this project work and compile out of the box on M1 Mac and to solve that one solution I have found to work is by using virtualization with lima-vm
Steps to set up environment for using lima-vm
:
- Install
lima-vm
- Launch lima and select ubuntu image
- Edit default lima-vm config. Most import parts are:
- Memory. I had 4GiB at first and it wasn't enough, but once I set it to 8Gib everything went smoothly
- Arch.
x86_64
- Mounts - writeable: set it to
True
- Open lima
- Dont forget to apt update
- Install
nix
- Download
ghcup
dependencies. (These ghcup steps are probably optional because we are using nix? But its nice to have ghci at hand) - Download and install haskell with
ghcup
- Set up nix cache inside lima instance
- Clone plutus repo.
nix-shell
- Clone this repository. Cd into it. Cabal build.
It does work slower than native, but it works.
Example lima-vm
resulting configuration file lima.yaml
:
arch: x86_64
images:
- location: "https://cloud-images.ubuntu.com/releases/21.10/release-20220201/ubuntu-21.10-server-cloudimg-amd64.img"
arch: "x86_64"
digest: "sha256:73fe1785c60edeb506f191affff0440abcc2de02420bb70865d51d0ff9b28223"
- location: "https://cloud-images.ubuntu.com/releases/21.10/release-20220201/ubuntu-21.10-server-cloudimg-arm64.img"
arch: "aarch64"
digest: "sha256:1b5b3fe616e1eea4176049d434a360344a7d471f799e151190f21b0a27f0b424"
- location: "https://cloud-images.ubuntu.com/releases/21.10/release/ubuntu-21.10-server-cloudimg-amd64.img"
arch: "x86_64"
- location: "https://cloud-images.ubuntu.com/releases/21.10/release/ubuntu-21.10-server-cloudimg-arm64.img"
arch: "aarch64"
cpus: null
memory: 12GiB
disk: null
mounts:
- location: "~"
writable: true
sshfs:
cache: null
followSymlinks: null
- location: "/tmp/lima"
writable: true
ssh:
localPort: 0
loadDotSSHPubKeys: null
forwardAgent: null
containerd:
system: null
user: null
cpuType:
aarch64: null
x86_64: null
firmware:
legacyBIOS: null
video:
display: null
networks:
propagateProxyEnv: null
hostResolver:
enabled: null
ipv6: null
Install docker.
git clone https://github.com/aada-finance/aada-finance.git
cd aada-finance
docker build -t aada_lend .
To compile and create validators use compile-validators
executable like so:
docker run -v <host_directory>:/app aada_lend bash -c "/usr/local/bin/compile-validators <options>"
Available options:
Usage: compile-validators [--hash STRING ((-k|--pubkey) | (-v|--validator)) |
--first INTEGER --second INTEGER --third INTEGER]
[-i|--interest FILEPATH] [-c|--collateral FILEPATH]
[-r|--request FILEPATH] [-l|--liquidation FILEPATH]
[--version]
Available options:
-h,--help Show this help text
--hash STRING Staking credential used to assign rewards. The
transaction that spends this output must be signed by
the key which hash is provided by this parameter
-k,--pubkey Interpret provided staking key hash as PubKeyHash
-v,--validator Interpret provided staking key hash as a Validator
Hash
--first INTEGER first StakingKey pointer parameter
--second INTEGER second StakingKey pointer parameter
--third INTEGER third StakingKey pointer parameter
-i,--interest FILEPATH Enter name of interest validator
(default: "interest.plutus")
-c,--collateral FILEPATH Enter name of collateral validator
(default: "collateral.plutus")
-r,--request FILEPATH Enter name of request validator
(default: "request.plutus")
-l,--liquidation FILEPATH
Enter name of liquidation validator
(default: "liquidation.plutus")
--version Show project version
To get minting policies use mint-aada-nft
executable like so:
General:
docker run -v <host_directory>:/app aada_lend bash -c "/usr/local/bin/mint-aada-nft minting-policy <options>"
Options:
Usage: mint-aada-nft minting-policy [-p|--name FILEPATH]
((-b|--borrower) | (-l|--lender))
Generate LenderNFT minting policy
Available options:
-h,--help Show this help text
-p,--name FILEPATH Enter name of aada nft minting policy. Default is
aada.nft (default: "aada.nft")
-b,--borrower choose borrower policy
-l,--lender choose lender policy
Geting example OracleNft minting script:
docker run -v <host_directory>:/app aada_lend bash -c "/usr/local/bin/mint-oracle-nft <pkh1> <pkh2> <pkh3> <valh> <tn>"
Options:
pkh1 -> PubKeyHash of party which mush sign to mint this Nft
pkh2 -> PubKeyHash of party which mush sign to mint this Nft
pkh3 -> PubKeyHash of party which mush sign to mint this Nft
valh -> ValidatorHash where Nft Must be sent to be minted
tn -> TokenName for Nft to be minted
Example:
docker run -v /home/user/Programming/aada-finance:/app aada_lend bash -c "/usr/local/bin/mint-oracle-nft ff ff ff ff ff"
To get example datum and redeemer files use generate-example-jsons
executable like so:
docker run -v <host_directory>:/app aada_lend bash -c "/usr/local/bin/generate-example-jsons"
To get TokenName for minting Borrower or Lender token use mint-aada-nft
executable like so:
docker run -v <host_directory>:/app aada_lend bash -c "/usr/local/bin/mint-aada-nft token-name --utxo ff#0"
Options:
Usage: mint-aada-nft token-name (-u|--utxo UTXO)
Hash utxo get get Lender NFT token name
Available options:
-h,--help Show this help text
-u,--utxo UTXO Enter utxo to be consumed when minting LenderNFT.
- Compile smartcontracts (see Instalation and usage)
- Get addreesses of compiled smartcontracts:
cardano-cli address build --payment-script-file <script.plutus> --out-file validator.addr
- Form datum following this format:
{
"fields": [
{
"bytes": "6666"
},
{
"fields": [
{
"fields": [
{
"bytes": "ff"
}
],
"constructor": 0
},
{
"fields": [
{
"fields": [
{
"fields": [
{
"bytes": "6666"
}
],
"constructor": 0
}
],
"constructor": 0
}
],
"constructor": 0
}
],
"constructor": 0
},
{
"fields": [
{
"bytes": "10555a8c6aa2217ed76522758b804a7531d01ff5ee53012ad81ebf23"
},
{
"bytes": "6c6f616e2d636f696e2d434f4e594d4f4e59"
}
],
"constructor": 0
},
{
"int": 150
},
{
"fields": [
{
"bytes": "5a1a36a39eb541a7db0e7211ae16ed958c55414ed1ef51e2e7d763bb"
},
{
"bytes": "696e7465726573742d636f696e2d4d4f4e59"
}
],
"constructor": 0
},
{
"int": 50
},
{
"fields": [
{
"bytes": "57cbe9798a05a712df222de7defd4b37a0d783bb40710ea63f64f99e"
},
{
"bytes": "636f6c6c61746572616c2d636f696e2d434f4e59"
}
],
"constructor": 0
},
{
"int": 100
},
{
"int": 0
},
{
"bytes": "ff"
},
{
"int": 5
},
{
"int": 150
},
{
"int": 0
},
{
"bytes": "6e6674746e"
},
{
"int": 0
}
],
"constructor": 0
}
Important parameters to be provided are:
- borrowersNftTn - Borrowers token name encoding utxo to be consumed when minting token. See
AadaNft.hs
. - borrowersAddress - Who should receive the loan.
- loan - Asset of requested loan.
- loanAmnt - Amount of requested loan.
- interest - Asset of interest to be paid.
- interestAmnt - Amount of interest to be paid for loan.
- collateral - Asset of collateral.
- collateralAmnt - Amount of collateral.
- loanDuration - How long till Lender gains rights to claim collateral. Once loan duration passes borrower must pay full interestAmnt to claim collateral back.
- liquidateNft - Currency symbol of Nft which when minted grants Lender rights to take collateral.
- collateralFactor - Collateral factor used for liquidation.
- liquidationComission - How much % borrower will pay lender when liquidated (before loanDuration passes).
- requestExpiration - When does loan request expire. Lender should not be able to provide Loan past this time value.
- Create transaction like so:
collateralAmnt ┌──┐ collateralAmnt of ┌──────────┐
┌────────┐ of collateral + │ │─────────collateral + ────▶│Request.hs│
│Borrower│─datum + tx fees─▶│ │ datum + 2 Ada └──────────┘
└────────┘ + 4 Ada │ │
│Tx│
┌────────┐ borrower token │ │ 2 Ada + 1 ┌──────────┐
│AadaNft │─minting policy──▶│ ├───AadaNft.borrowerNftTn──▶│ Borrower │
└────────┘ script │ │ └──────────┘
└──┘
Warning: Borrower won't be able to claim his collateral back if correct Borrower Token is not minted when locking collateral!
- Submit transaction
- Compile smartcontracts (see Instalation and usage)
- Get addreesses of compiled smartcontracts:
cardano-cli address build --payment-script-file <script.plutus> --out-file validator.addr
- Form datum. (See #### Creating Loan Request for example) Important parameters to be updated are:
- lenderNftTn - Lenders token name encoding utxo to be consumed when minting token. See
AadaNft.hs
. - lendDate - Upper bound of transaction is valid to submit range.
- Form redeemer with lenderNftTn like so:
{
"bytes": "4b3a43f592f577fcfcb5b0e1f42bec5182c9edc414e1f667528f56e7cf0be11d"
}
- Create transaction like so:
┌──┐
┌──────┐ loanAmnt of loan + │ │ 2 Ada + 1 ┌──────┐
│Lender│───tx fees + 6 Ada + ─▶│ │────AadaNft.lenderNftTn───▶│Lender│
└──────┘ datum + redeemer │ │ └──────┘
│ │
┌──────────┐ collateralAmnt of │ │ collateralAmnt of ┌───────────────┐
│Request.hs│───collateral + ──▶│Tx├───collateral + ──▶│ Collateral.hs │
└──────────┘ datum + 2 Ada │ │ datum + 2 Ada └───────────────┘
│ │
┌────────┐ lender token │ │ loanAmnt of ┌──────────┐
│AadaNft │───minting policy───▶│ ├───loan + 2 Ada────────▶│ Borrower │
└────────┘ script │ │ └──────────┘
└──┘
- Submit transaction
- Compile smartcontracts (see Instalation and usage)
- Get addreesses of compiled smartcontracts:
cardano-cli address build --payment-script-file <script.plutus> --out-file validator.addr
- Form datum with lenderNftTn like so:
{"bytes":"4b3a43f592f577fcfcb5b0e1f42bec5182c9edc414e1f667528f56e7cf0be11d"}
- Create transaction like so:
loanAmnt of loan + x ┌──┐
┌────────┐ of interest + tx fees │ │
│Borrower│──────────+ 1 ─────────▶│ │
└────────┘ AadaNft.borrowerNftTn │ │
+ 4 Ada + datum │ │ loanAmnt of loan + x ┌───────────┐
│ │─of interest + 2 Ada +─▶│Interest.hs│
│ │ datum └───────────┘
┌─────────────┐ collateralAmnt of │Tx│
│Collateral.hs│───collateral + ──▶│ │
└─────────────┘ datum + 2 Ada │ │ collateralAmnt ┌──────────┐
│ ├──of collateral +──────▶│ Borrower │
┌────────┐ borrower token │ │ 2 Ada └──────────┘
│AadaNft │──────minting policy───▶│ │
└────────┘ script │ │
└──┘
- Submit transaction
- Compile smartcontracts (see Instalation and usage)
- Get addreesses of compiled smartcontracts:
cardano-cli address build --payment-script-file <script.plutus> --out-file validator.addr
- Form datum with lenderNftTn like so:
{"bytes":"4b3a43f592f577fcfcb5b0e1f42bec5182c9edc414e1f667528f56e7cf0be11d"}
- Create transaction like so:
┌───────┐ ┌──┐
│Lender │───────tx fees + 1 ─────▶│ │
└───────┘ AadaNft.lenderNftTn + 2 │ │
Ada + datum │ │
│ │
┌─────────────┐ loanAmnt of loan │Tx│ loanAmnt of loan + ┌──────────┐
│ Interest.hs │─+ x of interest +▶│ ├───x of interest + 2 ──▶│ Lender │
└─────────────┘ 2 Ada + datum │ │ Ada └──────────┘
│ │
┌────────┐ lender token │ │
│AadaNft │──────minting policy───▶│ │
└────────┘ script └──┘
- Submit transaction
- Compile smartcontracts (see Instalation and usage)
- Get addreesses of compiled smartcontracts:
cardano-cli address build --payment-script-file <script.plutus> --out-file validator.addr
- Create transaction like so:
┌──┐
┌────────┐ 2 Ada + 1 │ │
│ Lender │─AadaNft.lenderNftTn +─▶│ │
└────────┘ tx fees + datum │ │
│ │
┌─────────────┐ collateralAmnt of │Tx│ collateralAmnt ┌──────────┐
│Collateral.hs│───collateral + ──▶│ ├────of collateral +────▶│ Lender │
└─────────────┘ datum + 2 Ada │ │ 2 Ada └──────────┘
│ │
┌────────┐ lender token │ │
│AadaNft │──────minting policy───▶│ │
└────────┘ script └──┘
- Form datum for
Liquidate.hs
, provideborrowerNftTn
like so:
{"bytes":"4b3a43f592f577fcfcb5b0e1f42bec5182c9edc414e1f667528f56e7cf0be11d"}
- Create transaction like so:
┌──┐
┌────────┐ 2 Ada + 1 │ │
│ Lender │─AadaNft.lenderNftTn +─▶│ │
└────────┘ tx fees + datum │ │ ┌──────────┐
│ ├───x of collateral─────▶│ Lender │
┌─────────────┐ collateralAmnt of │ │ + 2 Ada └──────────┘
│Collateral.hs│───collateral + ──▶│ │
└─────────────┘ datum + 2 Ada │Tx│
│ │
┌────────┐ lender token │ │ borrowerNftTn Datum +
│AadaNft │──────minting policy───▶│ │ 2 Ada + ┌────────────┐
└────────┘ script │ ├─(collateralAmnt - x) │Liquidate.hs│
│ │ of collateral └────────────┘
┌────────┐ minting policy + rest │ │
│ Oracle │─what is required like ▶│ │
└────────┘ signatures └──┘
- Submit transaction
It is possible to receive staking rewards from the funds kept in smartcontracts. Smartcontracts can be compiled with wanted staking key by providing it either:
--hash STRING ((-k|--pubkey) | (-v|--validator))
with concrete hash or--first INTEGER --second INTEGER --third INTEGER
with staking key pointer
docker build -t aada_staking .
docker run -v <host_directory>:/app aada_staking bash -c "/usr/local/bin/aada-staking 0 <validation_script_name>"
General:
docker run -v <host_directory>:/app aada_staking bash -c "/usr/local/bin/aada-staking 1 <minting_script_name> <PubKeyHash> <utxo>"
Example:
docker run -v /home/user/Programming/aada-finance:/app aada_staking bash -c "/usr/local/bin/aada-staking 1 mint.script 72193caa8e2eaca97c8461f837e7a4d7cd781b0ba6bf626a883cc102 0a630191d2ba7fa96ecdc9096b826a1f9c210028e02fabc9c0288e2e37d3e2b8#0"
Raise an issue with a title proposal - <proposal name>
!
Use this template:
# <Proposal name>
## What would you like to be different?
## Why do you think this change would improve this project?
Raise an issue with a feature request proposal!
- Raise a proposal issue
- Create tests to cover changes
- Implement changes
- Make sure nothing breaks, run tests with
cabal test
- Create PR
- Wait for approval
Raise an issue with a title bug - <bug name>
!
- Use this template:
# <bug name>
## Your setup
## What is not working as expected?
## What behaviour did you expect?
## What do you think is causing unexpected behaviour?
## How do you think this problem could be resolved?
- Create branch
- Implement changes
- Create tests to cover changes
- Create pull request
- email:
[email protected]