> For the complete documentation index, see [llms.txt](https://calnix.gitbook.io/eth-dev/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://calnix.gitbook.io/eth-dev/archive/brownie-projects/aave-lending-and-borrowing/approve-and-deposit.md).

# Approve & Deposit

Aave `LendingPool` contract is the main contract of the protocol. It exposes all the user-oriented actions that can be invoked using either Solidity or web3 libraries.&#x20;

{% hint style="info" %}
<https://docs.aave.com/developers/v/2.0/the-core-protocol/lendingpool>
{% endhint %}

* `LendingPool` contracts are upgradable. This means that their addresses may change in the future.&#x20;
* To prevent third party DApps from falling behind, Aave provides a `LendingPoolAddressesProvider` contract that will never be upgraded.&#x20;
* This is used to retrieve the latest `LendingPool`. As soon as we have the latest `LendingPool`, we can start depositing.

To interact with `ILendingPoolAddressesProvider` contract, we will need its address and ABI.&#x20;

## ILendingPoolAddressesProvider

#### ABI

To obtain the ABI, we will use an interface.&#x20;

Since we only require a select few functions: deposit, withdraw and so forth, we can create our own interface.

* create ILendingPoolAddressesProvider.sol in interfaces folder.
* either create your own interface by defining the functions (refer to etherscan or github)&#x20;
* ![](/files/dew9hYtK6LeizsOHutu5)
* or, just copy aave's interfaces

#### Address

Addresses Provider -> Deployed Contracts Section

{% hint style="info" %}
<https://docs.aave.com/developers/v/2.0/deployed-contracts/deployed-contracts>
{% endhint %}

![](/files/pons1xMzT8VFbuVHJSZE)

Add these to brownie-config.yaml

```python
def get_lendingpool():
    # create lending_pool_addressess_provider contract object
    lending_pool_addressess_provider = interface.ILendingPoolAddressesProvider(config["networks"][network.show_active()]["lending_pool_addressess_provider"])
    lending_pool = lending_pool_addressess_provider.getLendingPool()
    return lending_pool
```

## Lending Pool

#### ABI -> interface

* <https://docs.aave.com/developers/v/2.0/the-core-protocol/lendingpool/ilendingpool>
* Change import path from local directories to github

{% tabs %}
{% tab title="ILendingPool.sol" %}
Original:

```python
import {ILendingPoolAddressesProvider} from './ILendingPoolAddressesProvider.sol';
import {DataTypes} from './DataTypes.sol';
```

Modified:

```python
import {ILendingPoolAddressesProvider} from '@aave/contract/interfaces/ILendingPoolAddressesProvider.sol';
import {DataTypes} from '@aave/contract/protocol/libraries/types/DataTypes.sol';
```

compile after, to check if interfaces are correct.
{% endtab %}

{% tab title="brownie-config.yaml" %}

```yaml
dependencies:
  - aave/protocol-v2@1.0.1

compiler:
  solc:
    remappings:
      - '@aave=aave/protocol-v2@1.0.1'
```

{% endtab %}
{% endtabs %}

#### Address

We will get the address by calling getLendingPool() from the ILendingPoolAddressesProvider

```python
def get_lendingpool():
    # create lending_pool_addressess_provider contract object
    lending_pool_addressess_provider = interface.ILendingPoolAddressesProvider(config["networks"][network.show_active()]["lending_pool_addressess_provider"])
    #get lending pool address
    lending_pool = lending_pool_addressess_provider.getLendingPool()
    return lending_pool
```

### Code thus far

{% tabs %}
{% tab title="aave\_borrow\.py" %}

```python
from code import interact
from distutils.command.config import config
from scripts.helpful_scripts import get_account
from brownie import network, config, interface
from scripts.get_weth import get_weth

def main():
    account = get_account()
    deposit_token = config["networks"][network.show_active()]["weth_token"]
    # if no WETH, get_weth()
    # local mainnet fork can use dummy acocunts to get WETH
    # since local mainnet fork, can use dummy accounts. if actual mainnet/testnet then use private key account.
    if network.show_active() in ["mainnet-fork"]:
        get_weth()

    # Get lending pool contract
    lending_pool_address = get_lendingpool()
    lending_pool = interface.ILendingPool(lending_pool_address)
    print(f"....Lending pool contract: {lending_pool_address}....")

    # Approve sending our ERC20(WETH) tokens
    approve_erc20(deposit_amount, lending_pool.address, deposit_token, account)

      
def get_lendingpool():
    # create lending_pool_addressess_provider contract object
    lending_pool_addressess_provider = interface.ILendingPoolAddressesProvider(config["networks"][network.show_active()]["lending_pool_addressess_provider"])
    #get lending pool address
    lending_pool = lending_pool_addressess_provider.getLendingPool()
    return lending_pool
```

![](/files/PtpfiLA32b11KLYTlMrl)
{% endtab %}

{% tab title="helpful\_scripts.py" %}

```python
from brownie import network,accounts,config

LOCAL_BLOCKCHAIN_ENV = ["development", "ganache-local"]
FORKED_LOCAL_ENV = ["mainnet-fork", "mainnet-fork-dev"]

def get_account(index=None,id=None):
    # accounts[0]  -- ganache accounts
    # accounts.add("env")  -- private key from env file ->  accounts.add(config["wallets"]["wallet1"])
    # accounts.load("id") -- load from brownie accounts list 
    if index:
        # if index was passed return ganache account
        return accounts[index]
    
    if id:
        return accounts.load(id)

    if network.show_active() in LOCAL_BLOCKCHAIN_ENV or network.show_active() in FORKED_LOCAL_ENV:
        return accounts[0]                                  #use ganache generated account.  
      
    else: #look in config.yaml
        return accounts.add(config["wallets"]["wallet1"])  

```

{% endtab %}

{% tab title="brownie-config.yaml" %}

```yaml
dependencies:
  - aave/protocol-v2@1.0.1

compiler:
  solc:
    remappings:
      - '@aave=aave/protocol-v2@1.0.1'

dotenv: .env

networks:
  default: development

  rinkeby:
    weth_token: '0xc778417E063141139Fce010982780140Aa0cD5Ab'  #WEthGateway contract
    lending_pool_addressess_provider: '0x88757f2f99175387ab4c6a4b3067c77a695b0349'
    verify: True

  kovan:
    weth_token: '0xd0A1E359811322d97991E03f863a0C30C2cF029C'  #WEthGateway contract
    lending_pool_addressess_provider: '0x88757f2f99175387ab4c6a4b3067c77a695b0349'
    verify: True
  
  mainnet-fork: #development env, fork uses live mainnet addresses 
    weth_token: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2'  #WEthGateway contract
    lending_pool_addressess_provider: '0xB53C1a33016B2DC2fF3653530bfF1848a515c8c5'

  mainnet: # for production
    weth_token: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2'  #WEthGateway contract

wallets:
  wallet1: ${PRIVATE_KEY
```

{% endtab %}
{% endtabs %}

## Approve

Before we can deposit we must approve Aave's contract to use our WETH tokens. This is done with the approve function.

![ERC20.sol](/files/kywVQc6xDmKskkxPOiRj)

{% hint style="info" %}
Because DApps (decentralized applications) use smart contracts to execute transactions, you must give permission for the smart contract to transfer up to a certain amount of your token (allowance).
{% endhint %}

To reiterate, transacting with ERC-20 tokens is a 2-step process:

1. Approval of token allowance
2. Submission of transaction&#x20;

### approve\_erc20()

{% tabs %}
{% tab title="approve\_erc20" %}

```python
def approve_erc20(amount,spender, erc20_address, account):
    print("....Approving ERC20 token...")
    # get ERC20 interface: https://github.com/PatrickAlphaC/aave_brownie_py_freecode/tree/main/interfaces
    erc20 = interface.IERC20(erc20_address)

    # approve(address spender, uint256 value)
    tx = erc20.approve(spender,amount,{"from": account})
    tx.wait(1)
    print("....Approved....")
    return tx
```

In a generic implementation, we would create IERC20.sol in our interfaces folder, and pass the ERC20 token contract into the interface as above. \
\
Subsequently, we call on the token contract to approve setting our allowance for another 3rd party contract (via erc20.approve).
{% endtab %}

{% tab title="aave\_borrow\.py" %}

```python
from scripts.helpful_scripts import get_account
from brownie import network, config, interface
from scripts.get_weth import get_weth
from web3 import Web3

#0.1 ETH - 0.1*(10**18)
deposit_amount = Web3.toWei(0.1, "ether")  

def get_lendingpool():
    # create lending_pool_addressess_provider contract object
    lending_pool_addressess_provider = interface.ILendingPoolAddressesProvider(config["networks"][network.show_active()]["lending_pool_addressess_provider"])
    #get lending pool address
    lending_pool = lending_pool_addressess_provider.getLendingPool()
    return lending_pool

def approve_erc20(amount,spender, erc20_address, account):
    print("....Approving ERC20 token...")
    # get ERC20 interface: https://github.com/PatrickAlphaC/aave_brownie_py_freecode/tree/main/interfaces
    # approve(address spender, uint256 value)
    erc20 = interface.IERC20(erc20_address)
    tx = erc20.approve(spender,amount,{"from": account})
    tx.wait(1)
    print("....Approved....")
    return tx



def main():
    account = get_account()
    deposit_token = config["networks"][network.show_active()]["weth_token"]
    # if no WETH, get_weth()
    # local mainnet fork can use dummy acocunts to get WETH
    # since local mainnet fork, can use dummy accounts. if actual mainnet/testnet then use private key account.
    if network.show_active() in ["mainnet-fork"]:
        get_weth()

    # Get lending pool contract
    lending_pool_address = get_lendingpool()
    lending_pool = interface.ILendingPool(lending_pool_address)
    print(f"....Lending pool contract: {lending_pool_address}....")

    # Approve sending our ERC20(WETH) tokens
    approve_erc20(deposit_amount, lending_pool.address, deposit_token, account)
```

{% endtab %}
{% endtabs %}

Added to main():

* approve\_erc20(deposit\_amount, lending\_pool.address, deposit\_token, account)
* deposit\_amount as global variable

{% hint style="info" %}
since we are always runnning on mainnet-fork, set default = mainnet-fork in brownie-config.yaml, under the networks section.
{% endhint %}

## Deposit&#x20;

{% hint style="warning" %}
When depositing, the `LendingPool` contract must hav&#x65;**`allowance()`**&#x74;o spend funds on behalf o&#x66;**`msg.sender`** for at-leas&#x74;**`amount`** for the **`asset`** being deposited. This can be done via the standard ERC20 `approve()` method.
{% endhint %}

{% hint style="danger" %}
The referral program is currently inactive and you can pass`0` as the`referralCode.`

In future for referral code to be active again, a governance proposal, with the list of unique referral codes for various integration must be passed via governance.&#x20;
{% endhint %}

We will the below to main():

{% tabs %}
{% tab title="addition" %}

```python
## Deposit: deposit(address asset, uint256 amount, address onBehalfOf, uint16 referralCode)
# referralCode is deprecated - pass a 0 as parameter
print("....Depositing....")
tx = lending_pool.deposit(deposit_token_address, deposit_amount, account.address,0, {"from": account})
tx.wait(1) # wait one block
print("....Deposited!....")
```

{% endtab %}

{% tab title="aave\_borrow\.py" %}

```python
from scripts.helpful_scripts import get_account
from brownie import network, config, interface
from scripts.get_weth import get_weth
from web3 import Web3

#0.1 ETH - 0.1*(10**18)
deposit_amount = Web3.toWei(0.1, "ether")  

def get_lendingpool():
    # create lending_pool_addressess_provider contract object
    lending_pool_addressess_provider = interface.ILendingPoolAddressesProvider(config["networks"][network.show_active()]["lending_pool_addressess_provider"])
    #get lending pool address
    lending_pool = lending_pool_addressess_provider.getLendingPool()
    return lending_pool

def approve_erc20(amount,spender, erc20_address, account):
    print("....Approving ERC20 token...")
    # get ERC20 interface: https://github.com/PatrickAlphaC/aave_brownie_py_freecode/tree/main/interfaces
    # approve(address spender, uint256 value)
    erc20 = interface.IERC20(erc20_address)
    tx = erc20.approve(spender,amount,{"from": account})
    tx.wait(1)
    print("....Approved....")
    return tx


def main():
    account = get_account()
    deposit_token_address = config["networks"][network.show_active()]["weth_token"]
    # if no WETH, get_weth()
    # local mainnet fork can use dummy acocunts to get WETH
    # since local mainnet fork, can use dummy accounts. if actual mainnet/testnet then use private key account.
    if network.show_active() in ["mainnet-fork"]:
        get_weth()

    # Get lending pool contract
    lending_pool_address = get_lendingpool()
    lending_pool = interface.ILendingPool(lending_pool_address)
    print(f"....Lending pool contract: {lending_pool_address}....")

    # Approve sending our ERC20(WETH) tokens
    approve_erc20(deposit_amount, lending_pool.address, deposit_token_address, account)

    ## Deposit: deposit(address asset, uint256 amount, address onBehalfOf, uint16 referralCode)
    # referralCode is deprecated - just pass a 0 as parameter
    print("....Depositing....")
    tx = lending_pool.deposit(deposit_token_address, deposit_amount, account.address,0, {"from": account})
    tx.wait(1) # wait one block
    print("....Deposited!....")
```

{% endtab %}
{% endtabs %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://calnix.gitbook.io/eth-dev/archive/brownie-projects/aave-lending-and-borrowing/approve-and-deposit.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
