> For the complete documentation index, see [llms.txt](https://docs.sperax.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.sperax.io/master/technical-documents/smart-contracts/spa-buyback.md).

# 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);
```
