Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[MEX-580] add readme for permissions hub SC + onBehalf features #989

Merged
merged 2 commits into from
Jan 10, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 69 additions & 0 deletions dex/farm-with-locked-rewards/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,3 +110,72 @@ The interaction scripts for this contract are located in the dex subdirectory of
## Deployment

The deployment of this contract is done using interaction scripts and it is managed by its admin.

# Farm With Locked Rewards OnBehalf Operations

## Abstract

The Farm With Locked Rewards OnBehalf operations extend the Farm With Locked Rewards smart contract with the ability to allow whitelisted contracts to perform actions on behalf of users, enabling enhanced protocol composability while maintaining security through integration with the Permissions Hub.

## Introduction

This module allows third-party contracts to perform farm operations on behalf of users, after being explicitly whitelisted through the Permissions Hub. Users maintain full control over their assets by managing contract permissions, while protocols can build more complex DeFi interactions.

## Endpoints

### enterFarmOnBehalf

```rust
#[payable("*")]
#[endpoint(enterFarmOnBehalf)]
fn enter_farm_on_behalf(&self, user: ManagedAddress) -> EnterFarmResultType<Self::Api>
```

The enterFarmOnBehalf function allows whitelisted contracts to enter farm positions on behalf of users. It receives several arguments:

- __user__ - The address of the user for whom the operation is being performed. This address must have whitelisted the caller contract through the Permissions Hub.
- __payment__ - The tokens to be used are received as payment in the transaction.

The function performs the following steps:
1. Validates that the caller is whitelisted by the user through Permissions Hub
2. Processes the farming tokens payment
3. Claims any pending boosted rewards for the original owner
4. Performs the enter farm operation on behalf of the original owner
5. Sends the new farm token to the caller
6. Sends the locked rewards, if any, to the original owner
7. Updates energy and progress for the original owner

### claimRewardsOnBehalf

```rust
#[payable("*")]
#[endpoint(claimRewardsOnBehalf)]
fn claim_rewards_on_behalf(&self) -> ClaimRewardsResultType<Self::Api>
```

The claimRewardsOnBehalf function enables whitelisted contracts to claim rewards on behalf of the users. This function does not require any address parameter, as the original owner is read from the farm position metadata. The operation requires:

- __payment__ - The farm token must be received as payment in the transaction.

The function performs these steps:
1. Processes the farm token payment
2. Extracts the original owner from the farm token attributes
3. Validates that the caller is whitelisted by the original owner
4. Claims and sends locked rewards to the original owner
5. Sends the new farm token to the caller

## exitOnBehalf
The exit operation remains under the direct control of the position owner to ensure maximum security. When third-party contracts interact with farming positions through onBehalf operations, they receive and hold the position tokens. These tokens maintain the original owner information in their attributes, protecting the user's ownership rights. To exit their position, users must first reclaim their position tokens from the third-party contract through that protocol's specific mechanisms. Once users have regained control of their position tokens, they can perform the standard exit operation directly through the specific xExchange contract.
This design ensures users maintain ultimate control over their funds while allowing protocols to build complex DeFi interactions.

## Storage

The contract relies on the Permissions Hub for permission management, thus no additional storage, other than the one holding the Permissions Hub SC address, is required. All whitelisting data is managed through the Permissions Hub contract.

## Deployment

The onBehalf features are part of the core farm contract and require:

1. A deployed Permissions Hub contract
2. Configuration of the Permissions Hub address in the farm contract
3. User whitelisting of contracts that will perform onBehalf operations
72 changes: 72 additions & 0 deletions dex/farm/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,3 +103,75 @@ The interaction scripts for this contract are located in the dex subdirectory of
## Deployment

The deployment of this contract is done using interaction scripts and it is managed by its admin (regular wallet at the moment, yet soon to be governance smart contract).


# Farm OnBehalf Operations

## Abstract

The Farm OnBehalf operations extend the Farm smart contract with the ability to allow whitelisted contracts to perform actions on behalf of users, enabling enhanced protocol composability while maintaining security through integration with the Permissions Hub.

## Introduction

This module allows third-party contracts to perform farm operations on behalf of users, after being explicitly whitelisted through the Permissions Hub. Users maintain full control over their assets by managing contract permissions, while protocols can build more complex DeFi interactions.

## Endpoints

### enterFarmOnBehalf

```rust
#[payable("*")]
#[endpoint(enterFarmOnBehalf)]
fn enter_farm_on_behalf(&self, user: ManagedAddress) -> EnterFarmResultType<Self::Api>
```

The enterFarmOnBehalf function allows whitelisted contracts to enter farm positions on behalf of users. It receives several arguments:

- __user__ - The address of the user for whom the operation is being performed. This address must have whitelisted the caller contract through the Permissions Hub.
- __payment__ - The tokens to be used are received as payment in the transaction.

The function performs the following steps:
1. Validates that the caller is whitelisted by the user through Permissions Hub
2. Processes the farming tokens payment
3. Claims any pending boosted rewards for the original owner
4. Performs the enter farm operation on behalf of the original owner
5. Sends the new farm token to the caller
6. Sends the collected rewards, if any, to the original owner
7. Updates energy and progress for the original owner

### claimRewardsOnBehalf

```rust
#[payable("*")]
#[endpoint(claimRewardsOnBehalf)]
fn claim_rewards_on_behalf(&self) -> ClaimRewardsResultType<Self::Api>
```

The claimRewardsOnBehalf function enables whitelisted contracts to claim rewards on behalf of the users. This function does not require any address parameter, as the original owner is read from the farm position metadata. The operation requires:

- __payment__ - The farm token must be received as payment in the transaction.

The function performs these steps:
1. Processes the farm token payment
2. Extracts the original owner from the farm token attributes
3. Validates that the caller is whitelisted by the original owner
4. Claims and sends rewards to the original owner
5. Sends the new farm token to the caller

## exitOnBehalf
The exit operation remains under the direct control of the position owner to ensure maximum security. When third-party contracts interact with farming positions through onBehalf operations, they receive and hold the position tokens. These tokens maintain the original owner information in their attributes, protecting the user's ownership rights. To exit their position, users must first reclaim their position tokens from the third-party contract through that protocol's specific mechanisms. Once users have regained control of their position tokens, they can perform the standard exit operation directly through the specific xExchange contract.
This design ensures users maintain ultimate control over their funds while allowing protocols to build complex DeFi interactions.

## Storage

The contract relies on the Permissions Hub for permission management, thus no additional storage, other than the one holding the Permissions Hub SC address, is required. All whitelisting data is managed through the Permissions Hub contract.


## Deployment

The onBehalf features are part of the core farm contract and require:

1. A deployed Permissions Hub contract
2. Configuration of the Permissions Hub address in the farm contract
3. User whitelisting of contracts that will perform onBehalf operations

124 changes: 124 additions & 0 deletions dex/permissions-hub/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
# Permissions Hub Smart Contract

## Overview
The Permissions Hub is a security-focused smart contract that manages permissions for on-behalf operations across the MultiversX DeFi ecosystem. It allows users to whitelist specific contracts that can perform operations on their behalf, enabling secure contract-to-contract interactions while maintaining user control over their assets.

## Features
- User-controlled whitelisting of trusted contracts
- Administrative blacklisting for security purposes
- Granular permission management
- Efficient permission checking through optimized storage
- Integration support for other smart contracts

## Core Functionality

### User Operations

#### Whitelisting Contracts
Users can whitelist multiple contract addresses that they trust to operate on their behalf:
```rust
#[endpoint]
fn whitelist(&self, addresses_to_whitelist: MultiValueEncoded<ManagedAddress>)
```
- Allows users to add multiple trusted contracts in a single transaction
- Prevents duplicate whitelisting through built-in validation
- Each user maintains their own whitelist independently

#### Removing Whitelisted Contracts
Users can remove previously whitelisted contracts:
```rust
#[endpoint(removeWhitelist)]
fn remove_whitelist(&self, addresses_to_remove: MultiValueEncoded<ManagedAddress>)
```
- Allows batch removal of whitelisted addresses
- Validates that addresses were previously whitelisted
- Maintains user control over their permissions

### Administrative Functions

#### Blacklisting
Contract owner can blacklist potentially malicious addresses:
```rust
#[only_owner]
#[endpoint(blacklist)]
fn blacklist(&self, address_to_blacklist: ManagedAddress)
```
- Restricted to contract owner
- Global blacklist affecting all users
- Security measure against identified threats

#### Removing from Blacklist
Contract owner can remove addresses from the blacklist:
```rust
#[only_owner]
#[endpoint(removeBlacklist)]
fn remove_blacklist(&self, address_to_remove: ManagedAddress)
```

### View Functions

#### Permission Checking
Contracts can verify if they have permission to operate on behalf of a user:
```rust
#[view(isWhitelisted)]
fn is_whitelisted(&self, user: &ManagedAddress, address_to_check: &ManagedAddress) -> bool
```
- Returns true only if:
1. The address is not blacklisted
2. The address is in the user's whitelist
- Efficient for integration with other contracts

#### Blacklist Viewing
```rust
#[view(getBlacklistedAddresses)]
fn blacklisted_addresses(&self) -> UnorderedSetMapper<ManagedAddress>
```
- Public view of globally blacklisted addresses
- Useful for transparency and integration purposes

## Storage

The contract uses two main storage mappers:

1. User Whitelists:
```rust
#[storage_mapper("whitelistedAddresses")]
fn user_whitelisted_addresses(&self, user: &ManagedAddress) -> UnorderedSetMapper<ManagedAddress>
```
- Separate whitelist for each user
- Implemented as an UnorderedSetMapper for efficient operations

2. Global Blacklist:
```rust
#[storage_mapper("blacklistedAddresses")]
fn blacklisted_addresses(&self) -> UnorderedSetMapper<ManagedAddress>
```
- Single global blacklist
- Managed by contract owner

## Integration Guide

### For Smart Contracts
To integrate with the Permissions Hub:

1. Add the Permissions Hub address as a configurable parameter in your contract
2. Before performing operations on behalf of a user, check permissions:
```rust
let is_allowed = permissions_hub_proxy.is_whitelisted(user_address, caller_address);
require!(is_allowed, "Not authorized to perform operations on behalf of user");
```

### For Users
To enable contracts to operate on your behalf:

1. Call the `whitelist` endpoint with the contract address(es) you want to authorize
2. Monitor your active whitelisted addresses
3. Remove permissions using `removeWhitelist` when they're no longer needed

## Security Considerations

- Users should carefully verify contract addresses before whitelisting
- Regular auditing of whitelisted addresses is recommended
- The blacklist provides an additional security layer managed by the contract owner
- All permission changes are permanent until explicitly modified
- Users maintain full control over their whitelist
81 changes: 81 additions & 0 deletions farm-staking/farm-staking-proxy/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,3 +98,84 @@ One thing to note here is that between claiming rewards in the farming contract

To unstake his current position, a user must send the desired amount of dual yield tokens to the proxy contract. At this moment, the proxy contract knows, based on the sent dual yield token, both the farm token position and staking token position. The first step is for the proxy contract to withdraw the LP tokens from the farms and the liquidity from the pair contract. After that all the harvested rewards, the resulting eGLD from removing the LP token and the unstake position of the staking token are all sent to the user. The unstaking process is ended with the burning of the dual yield tokens.
It is important to note that because of the user’s unstaked position, an unbonding period is not needed.

# Farm Staking Proxy OnBehalf Operations

## Abstract

The Farm Staking Proxy contract enables complex yield strategies by managing dual yield positions. The OnBehalf operations allow whitelisted contracts to manage these positions for users, combining LP farming and staking rewards while maintaining proper ownership and security through the Permissions Hub.

## Introduction

This feature extends the dual yield functionality with delegated operations, allowing third-party contracts to manage composite farming positions. It maintains the security of underlying positions, proper reward distribution, and ownership tracking while enabling more complex DeFi integrations through the Permissions Hub.

## Endpoints

### stakeFarmOnBehalf

```rust
#[payable("*")]
#[endpoint(stakeFarmOnBehalf)]
fn stake_farm_on_behalf(&self, original_owner: ManagedAddress) -> StakeProxyResult<Self::Api>
```

The stakeFarmOnBehalf function enables whitelisted contracts to create dual yield positions. It receives:

- __original_owner__ - The address of the user for whom the position is being created
- __payments__ - Multiple token payments required for the dual yield position:
- First payment must be an LP farm token
- Additional payments must belong to the same original owner

The function performs these operations:
1. Validates caller's whitelist status through Permissions Hub
2. Verifies ownership of all provided tokens
3. Creates the dual yield position
4. Distributes the results:
- LP farm boosted rewards to original owner
- Staking boosted rewards to original owner
- Dual yield tokens to caller

### claimDualYieldOnBehalf

```rust
#[payable("*")]
#[endpoint(claimDualYieldOnBehalf)]
fn claim_dual_yield_on_behalf(&self) -> ClaimDualYieldResult<Self::Api>
```

The claimDualYieldOnBehalf function allows whitelisted contracts to claim rewards from dual yield positions. It requires:

- __payment__ - A dual yield token payment

The function performs these steps:
1. Extracts original owner from underlying farm position
2. Validates caller's whitelist status for the token owner
3. Claims both LP farming and staking rewards
4. Distributes rewards:
- LP farm rewards to original owner
- Staking farm rewards to original owner
- New dual yield tokens to caller

## exitOnBehalf
The exit operation remains under the direct control of the position owner to ensure maximum security. When third-party contracts interact with farming or staking positions through onBehalf operations, they receive and hold the position tokens. These tokens maintain the original owner information in their attributes, protecting the user's ownership rights. To exit their position, users must first reclaim their position tokens from the third-party contract through that protocol's specific mechanisms. Once users have regained control of their position tokens, they can perform the standard exit operation directly through the specific xExchange contract.
This design ensures users maintain ultimate control over their funds while allowing protocols to build complex DeFi interactions.

## Storage

The contract maintains its standard dual yield token storage and relies on underlying contracts and the Permissions Hub for any additional data.

## Deployment

The onBehalf features require:

1. Proper configuration of:
- Permissions Hub address
- LP Farm contract address
- Staking Farm contract address
- Token IDs and roles

2. Required external contracts:
- Active Permissions Hub
- Active LP Farm contract
- Active Staking Farm contract

Loading