# AaveImpact

The AaveImpact contract manages deposits and withdrawal functionalities for Non-Governmental Organizations (NGOs). It enables users to deposit various ERC20 tokens such as USDT, USDC and DAI supported by the Aave protocol, allocating a portion to NGO operations while earning yields. The contract interacts with the Aave lending pool for supplying assets and withdrawing them. It incorporates percentage-based sharing mechanisms, reward distributions from yields, and comprehensive security controls. It includes various functions and modifiers to manage NGO operations, such as updating NGO details, handling donations, and ensuring compliance with specific rules. The notBanned modifier is used to restrict access to deposits, ensuring that only non-banned entities can deposit while everyone can withdraw their deposited funds. Supports deposits and withdrawals for tokens validated by the factory contract.

* [Source code](https://github.com/Launchnodes-Ltd/stablecoin-impact/blob/main/src/AaveImpact.sol)

## Contract Architecture

### Upgrade Mechanism

The contract implements the UUPS (Universal Upgradeable Proxy Standard) pattern:

* Uses OpenZeppelin's `UUPSUpgradeable` framework
* Upgrades are controlled through the `_authorizeUpgrade` function
* Only the contract owner can initiate upgrades
* State variables are preserved during upgrades through proxy delegation

### Upgrade Control

The upgrade process is controlled through two main components:

1. **Authorization Function**

```solidity
function _authorizeUpgrade(address newImplementation) internal override onlyOwner
```

Authorizes contract upgrades in the UUPS pattern.

**Access Control**:

* Restricted to contract owner

**Parameters**:

* newImplementation: Address of new implementation contract

**Security Considerations**:

* Critical function for contract upgradeability
* Must be called through proxy
* Requires careful implementation validation
* Should maintain contract invariants

**Usage**:

* Part of upgrade process
* Called automatically by upgrade mechanism
* Validates upgrade permissions

2. **Proxy Pattern**

* Uses ERC1967 proxy standard
* Maintains separation of concerns
* Preserves contract state

### Upgrade Process

1. Owner initiates upgrade with new implementation
2. `_authorizeUpgrade` validates permission
3. Proxy updates implementation pointer
4. State remains intact in proxy storage

### Core Logic and Operations

#### Supply Mechanism

1. **Percentage Calculation**
   * NGO share percentage uses a base of 10000 for precise calculations
   * 100% = 10000 and 1% = 100
   * Valid range: MIN\_SHARE\_PERCENT (100 = 1%) to MAX\_SHARE\_PERCENT (10000 = 100%)
   * Example: 5000 represents 50% share to NGO
2. **Minimum Deposit Requirements**
   * Minimum supply amount: 1000 wei (defined by MIN\_AMOUNT constant)
   * All supply operations require user not to be banned
   * Deposits cannot be made after NGO is marked as finished
3. **Asset Distribution**
   * User portion: (100% - NGO percentage) of deposited amount
   * NGO portion: NGO percentage of depsited amount
   * Rewards (yields) are calculated based on total shares, with NGO receiving proportional rewards
4. **Token Support**
   * USDT
   * USDC
   * DAI

### Reward Management

1. Reward Calculation
   * Rewards tracked through \_lastNGOBalance per token
   * pendingRewardsCalculation() updates pending rewards by:
     * Comparing current balance with last recorded NGO balance plus pending rewards
     * Adding proportional rewards to pendingNGORewards based on NGO shares ratio
2. Reward Distribution
   * Handled by oracle through handleNGOShareDistribution
     * Calculate pending rewards for specific token
     * Take platform fee (5% - SFI\_FEE)
     * Transfer fee to platform address
     * Transfer remaining rewards to rewardsOwner
     * Update lastNGOBalance and reset pending rewards

### Withdrawal System

1. **Request Process**
   * Users initiate withdrawals through `withdraw`
   * Amount constraints:
     * Minimum: 100 wei (MIN\_WITHDRAWAL\_AMOUNT)
     * Maximum: User's total balance (user shares + NGO shares)
     * If remaining balance < WITHDRAW\_GAP (100 wei), withdraw full amount
2. **Withdrawal Methods**
   * Direct token withdrawal from Aave pool
     * Withdraw in original token
     * No queue or waiting period
     * Minimum withdrawal: 100 wei
3. **Asset Recalculation**
   * Withdrawals trigger proportional reduction of:
     * User's shares
     * NGO shares
     * Total shares and NGO shares
     * Last NGO balance

### Inheritance Structure

```solidity
AaveImpact is
    Initializable,
    ERC721HolderUpgradeable,
    ReentrancyGuardUpgradeable,
    UUPSUpgradeable,
    OwnableUpgradeable
```

### Contract Storage Structure

#### State Variables

```solidity
uint256 private _depositId;                // Deposit ID counter
address private _lis;                      // Platform token address (fee recipient)
IAavePool public aavePool;                 // Aave pool interface
IAaveImpactFactory public factory;         // Factory interface for valid tokens
address public rewardsOwner;               // Rewards recipient
bool public isFinish;                      // NGO status flag
```

#### Key Storage Mappings

```solidity
mapping(address => uint256) private _balanceBeforeDeposit;  // Balance before deposit per token
mapping(address => uint256) private _totalShares;          // Total shares per token
mapping(address => bool) private _oracles;                 // Oracle addresses
mapping(address => bool) private _isBanned;                // Banned users
mapping(address => mapping(address => mapping(uint256 => uint256))) private _ngoShares;  // NGO shares per user per token per ID
mapping(address => mapping(address => mapping(uint256 => uint256))) private _userShares;  // User shares per user per token per ID
mapping(address => mapping(address => mapping(uint256 => uint256))) private _assets;     // User assets per user per token per ID
mapping(address => uint256) private _pendingNGORewards;    // Pending rewards per token
mapping(uint256 => UserDepositInfo) public userDepositInfo;  // Deposit info per ID
mapping(address => uint256) private _totalNGOShares;       // Total NGO shares per token
mapping(address => uint256) private _lastNGOBalance;       // Last NGO balance per token
```

#### Important Constants

```solidity
uint8 constant MIN_SHARE_PERCENT = 100;    // 1%
uint16 constant MAX_SHARE_PERCENT = 10000;  // 100%
uint16 constant PERCENT_DIVIDER = 10000;      // Base for percentage calculations
uint256 constant DIVIDER = 10 * 10 ** 18;      // Precision divider (10 ether)
uint16 constant SFI_FEE = 500;                // 5% platform fee
uint8 constant MIN_WITHDRAWAL_AMOUNT = 100;   // minimum withdrawal amount
uint16 constant MIN_AMOUNT = 1000;            // minimum amount to deposit
uint8 constant WITHDRAW_GAP = 100;           //If during withdrawal user's balance < WITHDRAW_GAP
```

### Data Structures

#### Structs

```solidity
struct UserDepositInfo {
    address tokenAddress;  // Token address
    uint256 amount;        // Deposited amount
    uint256 startDate;     // Timestamp
    uint16 percent;        // Share percentage
}
```

Struct representing initial deposit information for a user.

### Function Documentation

### `constructor`

```solidity
constructor() {
    _disableInitializers();
}
```

Disables initializers at deployment.

### `initialize`

```solidity
function initialize(
    address _aavePoolAddress,
    address _rewardOwnerAddress,
    address _owner,
    address _oracle,
    address _factoryAddress
) public initializer
```

Initializes the NGO contract.

* **Parameters**
  * `_aavePoolAddress` : Aave pool contract
  * `_rewardOwnerAddress` : Rewards recipient
  * `owner` : NGO owner address
  * `oracle` : Oracle address
  * `_factoryAddress`  : Factory contract address
* **Validation**
  * No zero addresses allowed
* **Effects**
  * Initializes base contracts
  * Sets up initial configuration
  * Sets deposit ID to 1

### `deposit`

```solidity
function deposit(
    address _tokenAddress,
    uint256 _tokenAmount,
    uint16 _ngoPercent
) public
```

Deposits ERC20 tokens to the NGO contract via Aave.

* **Parameters**
  * `_tokenAddress` : Token to deposit
  * `_tokenAmount` :  Amount to deposit (in wei)
  * `_ngoPercent`: NGO share percentage (100 = 1%, 10000 = 100%)
* **Constraints**
  * Must not be banned
  * NGO must not be finished
  * Token must be valid via factory
  * Percentage must be between MIN\_SHARE\_PERCENT and MAX\_SHARE\_PERCENT

### `withdraw`

```solidity
function withdraw(
    uint256 _amount,
    uint256 _id,
    address _tokenAddress
) public
```

Withdraws tokens from the NGO contract via Aave.

* **Parameters**
  * `amount`: Amount to withdraw (in wei)
  * `_id` : Deposit identifier
  * `_tokenAddress` : Token to withdraw
* **Constraints**
  * Amount >= MIN\_WITHDRAWAL\_AMOUNT
  * Amount <= user balance
  * Token must be valid via factory

### `withdrawCalculation`

```solidity
function withdrawCalculation(
    uint256 _amount,
    uint256 _id,
    uint256 _userBalance,
    address _tokenAddress
) private
```

Internal function for processing withdrawal mathematics.

* **Parameters**
  * `_amount`: Amount to withdraw in wei
  * `_id`: Deposit identifier
  * `_userBalance` : User's current balance
  * `_tokenAddress` : Token address

**Calculation Steps With Explanation**

1. **Calculate Ratio**

   ```solidity
   _ratio = _amount.mulDiv(DIVIDER, _userBalance)
   ```

   * Determines what fraction of user's total balance is being withdrawn
   * DIVIDER used for precision
2. **Calculate Shares to Withdraw**
   * Compute user shares and NGO shares to withdraw based on ratio
   * Formula: `user_ngo_share * total_ngo_assets / total_ngo_shares`
3. **State Updates**
   * Reduce user's user shares and NGO shares
   * Reduce total shares and total NGO shares
   * Update last NGO balance

**Example Calculation** Let's say:

* User balance: 150 tokens
* User wants to withdraw 30 tokens
* Calculate ratio: 30 \* DIVIDER / 150 = 0.2 \* DIVIDER
* Reduce shares and userAssets proportionally

1. Final balance reduced by 20%

**Important Considerations**

1. All calculations maintain proportional relationships
2. Precision is maintained using DIVIDER
3. Both user assets and NGO shares are reduced proportionally

This function is critical for maintaining correct balances and proportions during withdrawals while ensuring both user assets and NGO shares are properly accounted for.

### Internal Calculation Functions

### pendingRewardsCalculation

```solidity
function pendingRewardsCalculation(address _tokenAddress) private
```

Calculates and updates pending rewards for the NGO based on balance changes for a token.

* **Process**
  * Compares current balance with last NGO balance plus pending rewards
  * If current balance is higher:
    * Calculates reward difference
    * Adds proportional amount (based on NGO shares ratio) to pending NGO rewards
    * Updates last NGO balance
* **State Changes**
  * Updates \_pendingNGORewards
  * Modifies \_totalNGOAssets
* **Usage**
  * Called before deposit asset calculations
  * Called during withdrawal processing
  * Called during reward distribution
* **Dependencies**:
  * Relies on \_balanceBeforeDeposit for current balance snapshot

### assetsCalculation

```solidity
function assetsCalculation(
    uint256 _amount,
    uint16 _percent,
    address _tokenAddress
) private
```

Calculates and distributes deposited assets between user and NGO portions.

* **Parameters**:
  * \_amount: Amount deposited in tokens
  * \_percent: NGO share percentage (100-10000)
  * \_tokenAddress: Token address
* **Process**:
  1. NGO Asset Calculation
     * Calculates NGO portion using percentage
     * Assigns remaining amount to user's direct assets
  2. Share Distribution
     * Creates deposit information record
     * Calculates NGO and user shares based on total shares and last NGO balance
  3. State Updates
     * Updates user's asset and share records
     * Increments total shares and NGO assets
     * Updates lastNGOBalance
* **State Changes**:
  * Updates \_assets, \_userShares, \_ngoShares
  * Modifies \_totalShares, \_totalNGOShares
  * Updates \_lastNGOBalance
* **Usage**:
  * Called by deposit()

### Administrative Functions

### `handleNGOShareDistribution`

```solidity
function handleNGOShareDistribution(address _tokenAddress) public onlyOracle
```

Manages the distribution of NGO rewards for a specific token

* **Access Control**
  * Only callable by oracle
* **Calculations**
  * Calculates pending rewards
  * Takes SFI platform fee (5%)
* **Effects**
  * Updates NGO asset totals
  * Transfers fees to platform
  * Transfers remaining rewards to NGO
  * Updates last balance tracking

### `setOracle`

```solidity
function setOracle(address _newOracle, bool _state) public onlyOwner
```

Manages oracle permissions.

* **Parameters**
  * `_newOracle`: Address to modify oracle status
  * `_state`: True to grant oracle role, false to revoke

### `setRewardsOwner`

```solidity
function setRewardsOwner(address _newRewOwner) public onlyOwner
```

Updates rewards recipient.

* **Parameters**
  * `_newRewOwner`: New recipient address

### `endNGO`

```solidity
function endNGO() public notFinished onlyOwner
```

Terminates the NGO contract.

* **Effects**
  * Sets `isFinish` to true
  * Prevents new deposits
  * Allows existing withdrawals

### `setUserBan`

```solidity
function setUserBan(address userAddress, bool isBan) public onlyOwner
```

Controls user access to supply functionality.

* **Parameters**
  * `userAddress`: Address to ban/unban
  * `isBan`: True to ban, false to unban
* **Access Control**
  * Only callable by owner
* **Effects**
  * Updates user's ban status
  * Banned users can withdraw but cannot deposit

### `emitEvent`

```solidity
function emitEvent(
    string memory _name,
    string calldata _imageLink,
    string calldata _description,
    string calldata _link,
    string calldata _location
) public onlyOwner
```

Emits NGO metadata for indexing.

* **Parameters**
  * `_name`: NGO name
  * `_imageLink`: NGO image URL
  * `_description`: NGO description
  * `_link`: NGO website/resource link
  * `_location`: NGO location
* **Access Control**
  * Only callable by owner
* **Usage**
  * Used for updating NGO information in external systems
  * Enables graph indexing of NGO details

### View Functions

#### `getUserBalance`

```solidity
function getUserBalance(address _user, uint256 _id, address _tokenAddress) public view returns (uint256)
```

Returns user's total balance for a specific token and deposit ID.

* **Parameters**
  * `_user`: User address
  * `_id`: Deposit identifier
  * `_tokenAddress` : Token address
* **Returns**
  * Total balance in ERC 20 Token \[USDT/USDT/DAI]

#### `getUserDepositInfo`

```solidity
function getUserDepositInfo(uint256 _id) public view returns (UserDepositInfo memory)
```

Returns deposit details for given user and ID.

* **Parameters**
  * `_id`: Deposit identifier
* **Returns**
  * Struct containing:
    * `tokenAddress` : Token address
    * `percent`: NGO share percentage
    * `amount`: Original deposit amount
    * `startDate`: Deposit timestamp

### Modifiers

**`onlyOracle`**

```solidity
modifier onlyOracle() {
        if (!_oracles[msg.sender]) {
            revert OnlyOracle(msg.sender);
        }
        _;
    }
```

Modifier to restrict access to only oracle.

**`notFinished`**

```solidity
modifier notFinished() {
        if (isFinish) {
            revert NgoFinished();
        }
        _;
    }
```

Modifier to restrict access to only oracle.

**`validDeposit`**

```solidity
modifier validDeposit(uint16 _ngoPercent) {
        if (
            _ngoPercent < MIN_SHARE_PERCENT || _ngoPercent > MAX_SHARE_PERCENT
        ) {
            revert InvalidPercent();
        }
        _;
    }
```

Modifier to check valid deposit info.

**`notBanned`**

```solidity
modifier notBanned() {
        if (_isBanned[msg.sender]) {
            revert UserBanned();
        }
        _;
    }
```

Modifier to check is user is banned.

**`validAmount`**

```solidity
modifier validAmount(uint256 _amount) {
        if (_amount < MIN_AMOUNT) {
            revert InvalidDepositAmount();
        }
        _;
    }
```

Modifier to check valid minimum amount.

**`validWithdrawalAmount`**

```solidity
modifier validWithdrawalAmount(uint256 _amount) {
        if (_amount < MIN_WITHDRAWAL_AMOUNT) {
            revert InvalidWithdrawalAmount();
        }
        _;
    }
```

Modifier to check valid minimum amount.

### Events&#x20;

#### Supply Events

**`Deposit`**

```solidity
event Deposit(
    uint256 _depositId,
    address _depositor,
    uint256 _amountDeposited,
    uint16 _percentShare,
    address _ngo,
    uint256 _timestamp,
    uint256 _blockNumber,
    address _tokenAddress
);
```

Emitted when a user deposits funds in the NGO.

* **Parameters**
  * `_depositId`: Unique identifier for the deposit
  * `_depositor`: Address of the depositing user
  * `_amounDeposited`: Amount of tokens deposited
  * `_percentShare`: Percentage shared with NGO (100-10000)
  * `_ngo`: Address of the NGO contract
  * `_timestamp`: Block timestamp of deposit
  * `_blockNumber`: Block number of deposit
  * `_tokenAddress`: Token address
* **Tracks** : deposit ID, depositor address, amount, NGO share percentage, timestamp
* **Usage** : Track new deposits and token used

#### Reward Events

**`RewardsUpdated`**

```solidity
event RewardsUpdated(
    uint256 _totalNGOAssets,
    uint256 _timestamp,
    uint256 _blockNumber
);
```

Emitted when NGO rewards are distributed.

* **Parameters**
  * `totalNGOAssets`: Amount of tokens in the NGO pool.
  * `_timestamp`: Block timestamp of distribution
  * `_blockNumber`: Block number of distribution
* **Tracks**: total tokens in NGO pool, share distribution timestamp and block number.
* **Usage**: Monitor reward distributions and track NGO earnings

#### Withdrawal Events

**`Withdraw`**

```solidity
event Withdraw(
    address _claimer,
    address _ngo,
    uint256 _amount,
    uint256 _timestamp,
    uint256 _blockNumber,
    uint256 _depositId,
    address _tokenAddress
);
```

Emitted when a user withdraws funds.

* **Parameters**
  * `_claimer` : The address of the user claiming withdrawal
  * `_ngo`: The address of the NGO contract
  * `_amount` : The amount withdrawn
  * `_timestamp`: The block timestamp when withdraw was claimed
  * `_blockNumber`: The block number when withdraw was claimed
  * `_depositId`: The id of the deposit
  * `_tokenAddress` : The address of the token being withdrawn
* **Tracks**: claimer, amount, deposit ID, token
* **Usage**: Track completed withdrawals

### Administrative Events

**`GraphEvent`**

```solidity
event GraphEvent(
    string _name,
    string _imageLink,
    string _description,
    string _link,
    string _location,
    address _ngo,
    uint256 _timestamp
);
```

Emitted when NGO metadata is updated.

* **Parameters**
  * `_name`: The name of the NGO
  * `_imageLink`: The link to the image associated with the NGO
  * `_description`: A description of the NGO
  * `_link`: A link associated with the NGO
  * `_location`: Physical location of NGO
  * `_ngo`: The address of the NGO contract
  * `_timestamp`: The block timestamp when withdraw was claimed
* **Tracks**: NGO details and location
* **Usage**: Track NGO metadata updates for indexing

**`NGOFinished`**

```solidity
event NGOFinished(
    address _ngo,
    uint256 _timestamp,
    uint256 _blockNumber
);
```

Emitted when NGO operations are terminated.

* **Parameters**
  * `_ngo`: The address of the NGO contract
  * `_timestamp`: The timestamp when the NGO was finished
  * `_blockNumber`: The block number when the NGO was finished
* **Tracks**: termination timestamp and block number and address of NGO Contract.
* **Usage**: Signal end of NGO contract.

**`OracleChanged`**

```solidity
event OracleChanged(
    address _newOracle,
    bool _state
);
```

Emitted when the oracle was added or status was changed.

* **Parameters**

  * `_newOracle`: New oracle address
  * `_state`:Current oracle state

  **Note:** If state = true - current address active. If state = false - current address inactive.
* **Tracks**: New oracle address and current oracle state.
* **Usage**: Signals change of an Oracle.

**`RewardsOwnerChanged`**

```solidity
event RewardsOwnerChanged(
    address _newRewOwner
);
```

Emitted when the rewards owner was changed.

* **Parameters**
  * `_newRewOwner`: New reward owner address
* **Tracks**: New Reward Owner address.
* **Usage**: Signals change of Reward Owner.

**`BannedUser`**

```solidity
event BannedUser(
    address _userAddress, 
    bool _isBan
);
```

Emitted when the state of user access is changed.

* **Parameters**
  * `_userAddress`: User address
  * `_isBan`: Current user state
* **Tracks**: User address and access state of user.
* **Usage**: Signals change of User access status.

### Error Conditions

#### Validation Errors

**`InvalidPercent`**

```solidity
error InvalidPercent();
```

* **Trigger**: Share percentage outside valid range (100-10000)
* **Prevention**: Validate percentage before depositing
* **Impact**: Prevents invalid share calculations

**`InvalidDepositAmount`**

```solidity
error InvalidDepositAmount();
```

* **Trigger**: Invalid deposit amount
* **Prevention**: Ensure deposit amount is valid
* **Impact**: Ensures economic viability of deposits

**`InvalidWithdrawalAmount`**

```solidity
error InvalidWithdrawalAmount();
```

* **Trigger**: Withdrawal request below minimum limit 100 wei
* **Prevention**: Make sure the withdrawal amount >= 100 wei
* **Impact**: Ensures economic viability of withdrawals

**`InvalidWithdrawAmount`**

```solidity
error InvalidWithdrawAmount();
```

* **Trigger**: Withdrawal ratio calculates to zero (very small relative to balance)
* **Prevention**: Withdraw larger amounts
* **Impact**: Prevents micro-withdrawals

**`RequestAmountTooSmall`**

```solidity
error RequestAmountTooSmall(uint256 _amount);
```

* **Trigger**: Withdrawal request below minimum limit
* **Parameter**: `_amount` - Requested amount
* **Prevention**: Check minimum withdrawal amount
* **Impact**: Ensures economic viability of withdrawals

**`RequestAmountTooLarge`**

```solidity
error RequestAmountTooLarge(uint256 _amount);
```

* **Trigger**: Withdrawal request above user balance
* **Parameter**: `_amount` - Requested amount
* **Prevention**: Check user balance
* **Impact**: Prevents overdraw attempts

**`TokenNotAllowed`**

```solidity
error TokenNotAllowed();
```

* **Trigger** : Token address not allowed for deposit (though not used; see NotExist)
* **Prevention**: Use valid tokens from factory
* **Impact**: Ensures only supported tokens

**`NotExist`**

```solidity
error NotExist();
```

* **Trigger**: Token does not exist in factory's validDepositTokenAddresses
* **Prevention**: Check factory for valid tokens
* **Impact**: Prevents invalid token operations

**`AaveWithdrawnAmountMismatch`**

```solidity
error AaveWithdrawnAmountMismatch(uint256 expected, uint256 actual);
```

* **Trigger**: Aave withdraw returns different amount than requested
* **Parameters** : expected, actual amounts
* **Prevention**: Ensure Aave pool consistency
* **Impact**: Protects against protocol mismatches

#### Access Control Errors

**`OnlyOracle`**

```solidity
error OnlyOracle(address _sender);
```

* **Trigger**: Non-oracle address calling oracle-restricted function
* **Parameter**: `_sender` - Unauthorized caller address
* **Prevention**: Use correct oracle address
* **Impact**: Protects reward distribution mechanism

**`UserBanned`**

```solidity
error UserBanned();
```

* **Trigger**: Banned user attempting to supply
* **Prevention**: Check ban status before supply
* **Impact**: Enforces user restrictions

#### State Errors

**`NgoFinished`**

```solidity
error NgoFinished();
```

* **Trigger**: Attempting operations after NGO termination
* **Prevention**: Check NGO status before operations
* **Impact**: Prevents post-termination activities

**`NotFinalizedStatus`**

```solidity
error NotFinalizedStatus();
```

* **Trigger**: Claiming withdrawal before finalization
* **Prevention**: Wait for withdrawal finalization
* **Impact**: Ensures proper withdrawal sequence

**`RewardError`**

```solidity
error RewardError();
```

* **Trigger**: Attempting reward distribution with no rewards
* **Prevention**: Check reward balance before distribution
* **Impact**: Prevents empty reward distributions

#### Technical Errors

**`NullAddress`**

```solidity
error NullAddress();
```

* **Trigger**: Providing zero address for critical parameters
* **Prevention**: Validate addresses before use
* **Impact**: Prevents contract initialization with invalid addresses

**`InvalidRequestIdForUser`**

```solidity
error InvalidRequestIdForUser(address _claimer, uint256 _requestId);
```

* **Trigger**: Claiming withdrawal for wrong request ID
* **Parameters**:
  * `_claimer`: Address attempting claim
  * `_requestId`: Invalid request ID
* **Prevention**: Verify request ownership
* **Impact**: Protects withdrawal ownership

**`ZeroAmount`**

```solidity
error ZeroAmount();
```

* **Trigger**: Attempting operation with zero amount
* **Prevention**: Validate amount before operation
* **Impact**: Prevents meaningless transactions

**`FeeError`**

```solidity
error FeeError();
```

* **Trigger**: Attempting to transfer zero fee
* **Prevention**: Ensure fee is not zero
* **Impact**: Handles failed fee transfers

### Security Features

1. **Administrative Controls**
   * Owner-only administrative functions
     * Contract upgrades (\_authorizeUpgrade)
     * Oracle management (setOracle)
     * Rewards owner management (setRewardsOwner)
     * User banning (setUserBan)
     * NGO termination (endNGO)
   * Oracle-only functions
     * Reward distribution (handleNGOShareDistribution)
2. **User Restrictions**
   * Ban system for malicious users
   * Banned users can withdraw but cannot deposit
3. **Safety Checks**
   * Reentrancy protection on withdrawals
   * Amount validation
   * Balance verification
   * Null address checks
4. **Upgradability**
   * UUPS proxy pattern
   * Owner-controlled upgrades
   * State preservation during upgrades


---

# Agent Instructions: 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://launchnodes.gitbook.io/stablecoin-for-impact-sfi/contracts/aaveimpact.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.
