Initialize & Managed Lending Pool

Pool Module Guide - Lending & Borrowing Platform

1. Pool Structure

1.1 Pool Struct

struct Pool<phantom CoinType> has key, store {
    token: coin::Coin<CoinType>,        // Token stored in the pool
    borrowed_amount: u64,                // Total tokens borrowed
    deposited_amount: u64,               // Total tokens deposited
    supply_rate: u64,                    // Interest rate for depositors
    borrow_rate: u64,                    // Lending interest rate
    supply_index: u64,                   // Accumulation index for depositors
    borrow_index: u64,                   // Accumulation index for borrowers
    updated_at: u64                      // Last update timestamp
}

2. Core Functions

2.1 Pool Initialization

public entry fun inititial<CoinType>(
    sender: &signer,
    supply_rate_init: u64,
    borrow_rate_init: u64
)
  • Only admin has permission to initialize pool
  • Set initial interest rates for depositors and borrowers
  • Initialize initial indices to 1

2.2 Token Deposit

public entry fun deposit<CoinType>(sender: &signer, amount: u64)
  • Withdraw token from user wallet
  • Deposit into pool
  • Update total deposited tokens
public entry fun deposit<CoinType>(sender: &signer, amount: u64) acquires Pool {
    let coins = coin::withdraw<CoinType>(sender, amount);
    let pool = borrow_global_mut<Pool<CoinType>>(utils::admin_address());
    coin::deposit<CoinType>(signer::address_of(sender), coins);
    pool.deposited_amount = pool.deposited_amount + amount;
}

Let's analyze each line of the deposit function:

1. Function declaration:

public entry fun deposit<CoinType>(sender: &signer, amount: u64) acquires Pool
  • Public function can be called from outside the module
  • Parameters include sender and token amount
  • acquires Pool: indicates function will access Pool resource

2. Withdraw tokens from user wallet:

let coins = coin::withdraw<CoinType>(sender, amount);
  • Use withdraw function from coin module to withdraw tokens from user wallet

3. Get Pool reference:

let pool = borrow_global_mut<Pool<CoinType>>(utils::admin_address());
  • Get mutable reference to Pool stored at admin address

4. Deposit tokens into Pool:

coin::deposit<CoinType>(signer::address_of(sender), coins);
  • Use deposit function to send tokens to Pool

5. Update amount:

pool.deposited_amount = pool.deposited_amount + amount;
  • Update total tokens deposited in Pool

2.3 Token Withdrawal

public entry fun withdraw<CoinType>(sender: &signer, amount: u64)
  • Withdraw tokens from pool
  • Transfer to user wallet
  • Update to decrease deposited tokens
public entry fun withdraw<CoinType>(sender: &signer, amount: u64) acquires Pool {
    let pool = borrow_global_mut<Pool<CoinType>>(utils::admin_address());
    let coins = coin::extract<CoinType>(&mut pool.token, amount);
    coin::deposit<CoinType>(signer::address_of(sender), coins);
    pool.deposited_amount = pool.deposited_amount - amount;
}

1. Function declaration:

public entry fun withdraw<CoinType>(sender: &signer, amount: u64) acquires Pool
  • Public function can be called from outside module
  • Takes 2 parameters: sender (withdrawer) and amount (withdrawal amount)
  • acquires Pool: indicates function will access Pool resource

2. Get Pool reference:

let pool = borrow_global_mut<Pool<CoinType>>(utils::admin_address());
  • Get mutable reference to Pool stored at admin address

3. Withdraw tokens from Pool:

let coins = coin::extract<CoinType>(&mut pool.token, amount);
  • Use extract function to take required amount of tokens from Pool

4. Transfer tokens to user wallet:

coin::deposit<CoinType>(signer::address_of(sender), coins);
  • Use deposit function to transfer tokens to withdrawer's wallet

5. Update Pool balance:

pool.deposited_amount = pool.deposited_amount - amount;
  • Decrease total tokens deposited in Pool.deposited_amount - amount;

2.4 Token Borrowing

public entry fun borrow<CoinType>(sender: &signer, amount: u64)
  • Check and register token for borrower if needed
  • Withdraw tokens from pool and transfer to borrower
  • Update to increase borrowed token amount
Let's analyze each step of the borrow function:

1. Function declaration:

public entry fun borrow<CoinType>(sender: &signer, amount: u64) acquires Pool
  • Public function can be called from outside the module
  • Takes borrower (sender) and desired borrow amount (amount) as parameters
  • acquires Pool: indicates function will access Pool resource

2. Get Pool reference:

let pool = borrow_global_mut<Pool<CoinType>>(utils::admin_address());
  • Get mutable reference to Pool at admin address

3. Withdraw tokens from Pool:

let coins = coin::extract<CoinType>(&mut pool.token, amount);
  • Use extract function to take required amount of tokens from Pool

4. Check and register token for borrower:

if (!coin::is_account_registered<CoinType>(signer::address_of(sender))) {
    managed_coin::register<CoinType>(sender);
};
  • Check if borrower's account is registered for the token
  • If not, register the token for them

5. Transfer tokens to borrower:

coin::deposit<CoinType>(signer::address_of(sender), coins);
  • Transfer withdrawn tokens to borrower's wallet

6. Update Pool balance:

pool.borrowed_amount = pool.borrowed_amount + amount;

2.5 Token Repayment

public entry fun repay<CoinType>(account: &signer, amount: u64)
  • Withdraw tokens from user wallet
  • Return to pool
  • Update to decrease debt amount
Let's analyze each line of code in the repay function:

1. Function declaration:

public entry fun repay<CoinType>(account: &signer, amount: u64) acquires Pool
  • Public function can be called from outside module
  • Takes 2 parameters: account (repayer) and amount (repayment amount)
  • acquires Pool: indicates function will access Pool resource

2. Get Pool reference:

let pool = borrow_global_mut<Pool<CoinType>>(utils::admin_address());
  • Get mutable reference to Pool stored at admin address

3. Withdraw tokens from user wallet:

let coins = coin::withdraw<CoinType>(account, amount);
  • Withdraw required tokens from repayer's wallet

4. Deposit tokens to Pool:

coin::merge<CoinType>(&mut pool.token, coins);
  • Merge withdrawn tokens into Pool

5. Update Pool balance:

pool.deposited_amount = pool.deposited_amount + amount;

FullCode

module movement::pool {
    use movement::utils;
    use movement::errors;

    use aptos_framework::timestamp;
    use aptos_framework::coin;
    use aptos_framework::managed_coin;

    use std::signer;

    struct Pool<phantom CoinType> has key, store {
        token: coin::Coin<CoinType>,
        borrowed_amount: u64,
        deposited_amount: u64,
        supply_rate: u64,
        borrow_rate: u64,
        supply_index: u64,
        borrow_index: u64,
        updated_at: u64
    }

    public entry fun inititial<CoinType>(
        sender: &signer,
        supply_rate_init: u64,
        borrow_rate_init: u64
    ) {
        assert!(utils::is_admin(sender), errors::get_e_not_admin());
        move_to(sender, Pool<CoinType>{
            token: coin::zero<CoinType>(),
            borrowed_amount: 0,
            deposited_amount: 0,
            supply_rate: supply_rate_init,
            borrow_rate: borrow_rate_init,
            supply_index: 1,
            borrow_index: 1,
            updated_at: timestamp::now_microseconds()
        });
    }

    public entry fun deposit<CoinType>(sender: &signer, amount: u64) acquires Pool {
        let coins = coin::withdraw<CoinType>(sender, amount);
        let pool = borrow_global_mut<Pool<CoinType>>(utils::admin_address());
        coin::deposit<CoinType>(signer::address_of(sender), coins);
        pool.deposited_amount = pool.deposited_amount + amount;
    }

    public entry fun withdraw<CoinType>(sender: &signer, amount: u64) acquires Pool {
        let pool = borrow_global_mut<Pool<CoinType>>(utils::admin_address());
        let coins = coin::extract<CoinType>(&mut pool.token, amount);
        coin::deposit<CoinType>(signer::address_of(sender), coins);
        pool.deposited_amount = pool.deposited_amount - amount;
    }

    public entry fun borrow<CoinType>(sender: &signer, amount: u64) acquires Pool {
        let pool = borrow_global_mut<Pool<CoinType>>(utils::admin_address());
        let coins = coin::extract<CoinType>(&mut pool.token, amount);
        if (!coin::is_account_registered<CoinType>(signer::address_of(sender))) {
            managed_coin::register<CoinType>(sender);
        };
        coin::deposit<CoinType>(signer::address_of(sender), coins);
        pool.borrowed_amount = pool.borrowed_amount + amount;
    }

    public entry fun repay<CoinType>(account: &signer, amount: u64) acquires Pool {
        let pool = borrow_global_mut<Pool<CoinType>>(utils::admin_address());
        let coins = coin::withdraw<CoinType>(account, amount);
        coin::merge<CoinType>(&mut pool.token, coins);
        pool.deposited_amount = pool.deposited_amount + amount;
    }
}