# SPA Buyback

[Git Source](https://github.com/Sperax/USDs-v2/blob/ff71faf9d7e40d2b2764e5e8f2acc631f31489aa/contracts/buyback/SPABuyback.sol)

**Inherits:** Initializable, OwnableUpgradeable, ReentrancyGuardUpgradeable

**Author:** Sperax Foundation

This contract allows users to exchange SPA tokens for USDs tokens.

*Users can provide SPA tokens and receive USDs tokens in return based on the current exchange rate.*

*A percentage of the provided SPA tokens are distributed as rewards, and the rest are burned.*

## **State Variables**

### **veSpaRewarder**

```solidity
address public veSpaRewarder;

```

### **rewardPercentage**

```solidity
uint256 public rewardPercentage;

```

### **oracle**

```solidity
address public oracle;

```

## **Functions**

### **constructor**

```solidity
constructor();

```

### **initialize**

*Contract initializer*

```solidity
function initialize(address _veSpaRewarder, uint256 _rewardPercentage) external initializer;

```

**Parameters**

| Name               | Type    | Description                      |
| ------------------ | ------- | -------------------------------- |
| \_veSpaRewarder    | address | Rewarder's address               |
| \_rewardPercentage | uint256 | Percentage of SPA to be rewarded |

### **withdraw**

Emergency withdrawal function for unexpected situations

*Can only be called by the owner*

```solidity
function withdraw(address _token, address _receiver, uint256 _amount) external onlyOwner;

```

**Parameters**

| Name       | Type    | Description                          |
| ---------- | ------- | ------------------------------------ |
| \_token    | address | Address of the asset to be withdrawn |
| \_receiver | address | Address of the receiver of tokens    |
| \_amount   | uint256 | Amount of tokens to be withdrawn     |

### **updateRewardPercentage**

Changes the reward percentage

*Example value for \_newRewardPercentage = 5000 for 50%*

```solidity
function updateRewardPercentage(uint256 _newRewardPercentage) external onlyOwner;

```

**Parameters**

| Name                  | Type    | Description           |
| --------------------- | ------- | --------------------- |
| \_newRewardPercentage | uint256 | New Reward Percentage |

### **updateVeSpaRewarder**

Update veSpaRewarder address

```solidity
function updateVeSpaRewarder(address _newVeSpaRewarder) external onlyOwner;

```

**Parameters**

| Name               | Type    | Description                             |
| ------------------ | ------- | --------------------------------------- |
| \_newVeSpaRewarder | address | is the address of desired veSpaRewarder |

### **updateOracle**

Update oracle address

```solidity
function updateOracle(address _newOracle) external onlyOwner;

```

**Parameters**

| Name        | Type    | Description                      |
| ----------- | ------- | -------------------------------- |
| \_newOracle | address | is the address of desired oracle |

### **buyUSDs**

Function to buy USDs for SPA for frontend

```solidity
function buyUSDs(uint256 _spaIn, uint256 _minUSDsOut) external;

```

**Parameters**

| Name         | Type    | Description                |
| ------------ | ------- | -------------------------- |
| \_spaIn      | uint256 | Amount of SPA tokens       |
| \_minUSDsOut | uint256 | Minimum amount out in USDs |

### **getSPAReqdForUSDs**

Calculates and returns SPA amount required for \_usdsAmount

```solidity
function getSPAReqdForUSDs(uint256 _usdsAmount) external view returns (uint256);

```

**Parameters**

| Name         | Type    | Description                |
| ------------ | ------- | -------------------------- |
| \_usdsAmount | uint256 | USDs amount the user wants |

**Returns**

| Name | Type    | Description            |
| ---- | ------- | ---------------------- |
|      | uint256 | Amount of SPA required |

### **buyUSDs**

Buy USDs for SPA if you want a different receiver

```solidity
function buyUSDs(address _receiver, uint256 _spaIn, uint256 _minUSDsOut) public nonReentrant;

```

**Parameters**

| Name         | Type    | Description                |
| ------------ | ------- | -------------------------- |
| \_receiver   | address | Receiver of USDs           |
| \_spaIn      | uint256 | Amount of SPA tokens       |
| \_minUSDsOut | uint256 | Minimum amount out in USDs |

### **distributeAndBurnSPA**

Sends available SPA in this contract to rewarder based on rewardPercentage and burns the rest

```solidity
function distributeAndBurnSPA() public;

```

### **getUsdsOutForSpa**

Returns the amount of USDS for SPA amount in

```solidity
function getUsdsOutForSpa(uint256 _spaIn) public view returns (uint256);

```

**Parameters**

| Name    | Type    | Description          |
| ------- | ------- | -------------------- |
| \_spaIn | uint256 | Amount of SPA tokens |

**Returns**

| Name | Type    | Description                  |
| ---- | ------- | ---------------------------- |
|      | uint256 | Amount of USDs user will get |

### **\_getUsdsOutForSpa**

Returns the amount of USDS for SPA amount in

```solidity
function _getUsdsOutForSpa(uint256 _spaIn) private view returns (uint256, uint256);

```

**Parameters**

| Name    | Type    | Description          |
| ------- | ------- | -------------------- |
| \_spaIn | uint256 | Amount of SPA tokens |

**Returns**

| Name | Type    | Description                  |
| ---- | ------- | ---------------------------- |
|      | uint256 | Amount of USDs user will get |
|      | uint256 |                              |

### **\_getOracleData**

*Retrieves price data from the oracle contract for SPA and USDS tokens.*

```solidity
function _getOracleData() private view returns (uint256, uint256, uint256, uint256);

```

**Returns**

| Name | Type    | Description                                                                          |
| ---- | ------- | ------------------------------------------------------------------------------------ |
|      | uint256 | The price of USDS in SPA, the price of SPA in USDS, and their respective precisions. |
|      | uint256 |                                                                                      |
|      | uint256 |                                                                                      |
|      | uint256 |                                                                                      |

### **\_isValidRewardPercentage**

*Checks if the provided reward percentage is valid.*

*The reward percentage must be a non-zero value and should not exceed the maximum percentage value.*

```solidity
function _isValidRewardPercentage(uint256 _rewardPercentage) private pure;

```

**Parameters**

| Name               | Type    | Description                        |
| ------------------ | ------- | ---------------------------------- |
| \_rewardPercentage | uint256 | The reward percentage to validate. |

## **Events**

### **BoughtBack**

```solidity
event BoughtBack(
    address indexed receiverOfUSDs, address indexed senderOfSPA, uint256 spaPrice, uint256 spaAmount, uint256 usdsAmount
);

```

### **Withdrawn**

```solidity
event Withdrawn(address indexed token, address indexed receiver, uint256 amount);

```

### **SPARewarded**

```solidity
event SPARewarded(uint256 spaAmount);

```

### **SPABurned**

```solidity
event SPABurned(uint256 spaAmount);

```

### **RewardPercentageUpdated**

```solidity
event RewardPercentageUpdated(uint256 newRewardPercentage);

```

### **VeSpaRewarderUpdated**

```solidity
event VeSpaRewarderUpdated(address newVeSpaRewarder);

```

### **OracleUpdated**

```solidity
event OracleUpdated(address newOracle);

```

## **Errors**

### **CannotWithdrawSPA**

```solidity
error CannotWithdrawSPA();

```

### **InsufficientUSDsBalance**

```solidity
error InsufficientUSDsBalance(uint256 toSend, uint256 bal);
```


---

# 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://docs.sperax.io/master/technical-documents/smart-contracts/spa-buyback.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.
