-
Notifications
You must be signed in to change notification settings - Fork 143
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
docs: Provide Design document for HIP-904 System Contracts flows (#15435
- Loading branch information
1 parent
c8ec96b
commit a0cc065
Showing
1 changed file
with
175 additions
and
0 deletions.
There are no files selected for viewing
175 changes: 175 additions & 0 deletions
175
...esign/services/smart-contract-service/frictionless-airdrops-system-contracts.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,175 @@ | ||
# Frictionless Airdrops via System Contracts | ||
|
||
## Purpose | ||
|
||
[HIP-904](https://hips.hedera.com/hip/hip-904) introduced the Frictionless Airdrops feature for fungible and non-fungible tokens. | ||
This document will define the architecture and implementation of the `airdropToken`, `claimAirdrops`, `cancelAirdrops` and `rejectTokens` smart contract functions | ||
and their respective redirect function calls (`cancelAirdropFT`, `cancelAirdropNFT`, `claimAirdropFT`, `claimAirdropNFT`, `rejectTokenFT`, `rejectTokenNFTs`, `setUnlimitedAutomaticAssociations`) that will extend the capabilities of the Hedera Smart Contract Service (HSCS) to support frictionless airdrops. | ||
|
||
## References | ||
|
||
[HIP-904](https://hips.hedera.com/hip/hip-904) - HIP that introduces the frictionless airdrops. | ||
|
||
## Goals | ||
|
||
- Expose `airdropToken`, `claimAirdrops`, `cancelAirdrops` and `rejectTokens` as new functions in the Hedera Token Service Smart Contract. | ||
- Expose `cancelAirdropFT`, `cancelAirdropNFT`, `claimAirdropFT`, `claimAirdropNFT`, `rejectTokenFt`, `rejectTokenNFTs`, `setUnlimitedAutomaticAssociations` as new functions in a new proxy redirect token facade contract IHRC904. | ||
- Implement the needed HTS system contract classes to support the new functions. | ||
|
||
## Non Goals | ||
|
||
- The implementation of the HAPI operation, as it is already an existing feature. | ||
|
||
## Architecture | ||
|
||
The architecture for the frictionless airdrops follows the existing framework defined for handling all calls to the HederaTokenService system contract in the modularization services and is described in more detail in the Implementation section below. | ||
|
||
## Implementation | ||
|
||
### New Solidity Structures | ||
|
||
We will introduce the following new structures to support the new functionality: | ||
|
||
`PendingAirdrop` - A struct that represents a pending airdrop request. | ||
|
||
```solidity | ||
struct PendingAirdrop { | ||
address sender; | ||
address receiver; | ||
address token; | ||
int64 serial; | ||
} | ||
``` | ||
|
||
`NftID` - A struct that represents the Nft serial to be rejected. | ||
|
||
```solidity | ||
struct NftID { | ||
address nft; | ||
int64 serial; | ||
} | ||
``` | ||
|
||
### New Solidity Functions | ||
|
||
New system contract functions must be added to the `IHederaTokenService` interface to support airdropping tokens. | ||
|
||
| Function Selector Hash | Function Signature | HAPI Transaction | Response | | | ||
|------------------------|---------------------------------------------------------------------------------------------------------------------|------------------|----------------|---------------------------------| | ||
| `0x2f348119` | `function airdropTokens(TokenTransferList[] memory tokenTransfers) external returns (int64 responseCode)` | TokenAirdrop | `ResponseCode` | The response code from the call | | ||
| `0x012ebcaf` | `function cancelAirdrops(PendingAirdrop[] memory pendingAirdrops) external returns (int64 responseCode)` | TokenCancel | `ResponseCode` | The response code from the call | | ||
| `0x05961641` | `function claimAirdrops(PendingAirdrop[] memory pendingAirdrops) external returns (int64 responseCode)` | TokenClaim | `ResponseCode` | The response code from the call | | ||
| `0x179300d7` | `function rejectTokens(address[] memory ftAddresses, NftID[] memory nftIDs) external returns (int64 responseCode)` | TokenReject | `ResponseCode` | The response code from the call | | ||
|
||
New system contract functions must be added to a new `IHRC904` interface to support airdropping tokens. | ||
|
||
| Function Selector Hash | Function Signature | HAPI Transaction | Responsible service | Response | | | ||
|------------------------|----------------------------------------------------------------------------------------------------------------------|------------------|---------------------|----------------|---------------------------------| | ||
| `0xcef5b705` | `function cancelAirdropFT(address receiverAddress) external returns (uint256 responseCode)` | TokenCancel | HTS | `ResponseCode` | The response code from the call | | ||
| `0xad4917cf` | `function cancelAirdropNFT(address receiverAddress, int64 serialNumber) external returns (uint256 responseCode)` | TokenCancel | HTS | `ResponseCode` | The response code from the call | | ||
| `0xa83bc5b2` | `function claimAirdropFT(address senderAddress) external returns (uint256 responseCode)` | TokenClaim | HTS | `ResponseCode` | The response code from the call | | ||
| `0x63ada5d7` | `function claimAirdropNFT(address senderAddress, int64 serialNumber) external returns (uint256 responseCode)` | TokenClaim | HTS | `ResponseCode` | The response code from the call | | ||
| `0x76c6b391` | `function rejectTokenFT() external returns (uint256 responseCode)` | TokenReject | HTS | `ResponseCode` | The response code from the call | | ||
| `0xa869c78a` | `function rejectTokenNFTs(int64[] memory serialNumbers) external returns (uint256 responseCode)` | TokenReject | HTS | `ResponseCode` | The response code from the call | | ||
| `0x966884d4` | `function setUnlimitedAutomaticAssociations(boolean enableAutoAssociations) external returns (uint256 responseCode)` | CryptoUpdate | HAS | `ResponseCode` | The response code from the call | | ||
|
||
#### Input limitations | ||
|
||
- The `airdropTokens` function will accept an array of `TokenTransferList` with a maximum of 10 elements by default managed by `tokens.maxAllowedAirdropTransfersPerTx` configuration. | ||
- The `cancelAirdrops` function will accept an array of `PendingAirdrop` with a maximum of 10 elements by default managed by `tokens.maxAllowedPendingAirdropsToCancel` configuration. | ||
- The `claimAirdrops` function will accept an array of `PendingAirdrop` with a maximum of 10 elements by default managed by `tokens.maxAllowedPendingAirdropsToClaim` configuration. | ||
- The `rejectTokens` function will accept array of `address` and `NftID` with a maximum of 10 elements combined by default managed by `ledger.tokenRejects.maxLen` configuration. Same limitation applies to `rejectTokenNFTs` function. | ||
- The `setAutomaticAssociations` function will accept a boolean value to set the automatic associations to -1 if true and 0 for false. | ||
|
||
### System Contract Module | ||
|
||
- `AirdropTokensTranslator` - This class will be responsible for handling the `airdropTokens` selector and dispatching it to the corresponding HAPI calls. | ||
- `AirdropTokensDecoder` - This class provides methods and constants for decoding the given `HtsCallAttempt` into a `TokenTransferList` for `TokenAirdrop` call. | ||
- `CancelAirdropsTranslator` - This class will be responsible for handling the `cancelAirdrops`, `cancelAirdropFT` and `cancelAirdropNFT` selectors and dispatching them to the corresponding HAPI calls. | ||
- `CancelAirdropsDecoder` - This class provides methods and constants for decoding the given `HtsCallAttempt` into a `PendingAirdropId` list for `TokenCancelAirdrop` call. | ||
- `ClaimAirdropsTranslator` - This class will be responsible for handling the `claimAirdrops`, `claimAirdropFT` and `claimAirdropNFT` selectors and dispatching them to the corresponding HAPI calls. | ||
- `ClaimAirdropsDecoder` - This class provides methods and constants for decoding the given `HtsCallAttempt` into a `PendingAirdropId` list for `TokenClaimAirdrop` call. | ||
- `RejectTokensTranslator` - This class will be responsible for handling the `rejectTokens`, `rejectTokenFT` and `rejectTokenNFT` selectors and dispatching them to the corresponding HAPI calls. | ||
- `RejectTokensDecoder` - This class provides methods and constants for decoding the given `HtsCallAttempt` into `TokenReference` list for `TokenReject` call. | ||
- `SetAutomaticAssociationsTranslator` - This class will be responsible for handling the `setAutomaticAssociations` selector and dispatching it to the corresponding HAPI calls. | ||
- `SetAutomaticAssociationsCall` - This class provides methods for preparing and executing the given `HasCallAttempt`. | ||
|
||
### Feature Flags | ||
|
||
In order to gate the newly introduced system contract calls, we will introduce the following feature flags: | ||
- `contracts.systemContract.airdropTokens.enabled` - Enable/Disable the `airdropTokens` system contract call. | ||
- `contracts.systemContract.cancelAirdrops.enabled` - Enable/Disable the `cancelAirdrops`, `cancelAirdropFT` and `cancelAirdropNFT` system contract calls. | ||
- `contracts.systemContract.claimAirdrops.enabled` - Enable/Disable the `claimAirdrops`, `claimAirdropFT` and `claimAirdropNFT` system contract calls. | ||
- `contracts.systemContract.rejectTokens.enabled` - Enable/Disable the `rejectTokens`, `rejectTokenFT` and `rejectTokenNFTs` system contract calls. | ||
- `contracts.systemContract.setUnlimitedAutoAssociations.enabled` - Enable/Disable the `setUnlimitedAutomaticAssociations` system contract call. | ||
|
||
## Security Implications | ||
|
||
The newly added flows will adopt the HAPI authorization logic and the security V2 model. | ||
We will apply the `TokenReject`, `TokenAirdrop`, `TokenClaimAirdrop`, `TokenCancelAirdrop` throttle mechanisms. | ||
|
||
## Acceptance Tests | ||
|
||
### BDD Tests | ||
|
||
#### Positive Tests | ||
|
||
- Verify that the `airdropTokens` function airdrops multiple tokens both ft and nft to multiple accounts. | ||
- Verify that the `airdropTokens` function airdrops 10 tokens both ft and nft to multiple accounts. | ||
- Verify that the `airdropTokens` function airdrops a fungible token to an account. | ||
- Verify that the `airdropTokens` function airdrops a nft token to an account. | ||
- Verify that the `cancelAirdrops` function cancels multiple pending airdrops. | ||
- Verify that the `cancelAirdrops` function cancels 10 pending airdrops. | ||
- Verify that the `cancelAirdrops` function cancels single pending airdrop. | ||
- Verify that the `claimAirdrops` function claims multiple pending airdrops. | ||
- Verify that the `claimAirdrops` function claims 10 pending airdrops. | ||
- Verify that the `claimAirdrops` function claims a single pending airdrop. | ||
- Verify that the `rejectTokens` function rejects tokens for multiple accounts. | ||
- Verify that the `cancelAirdropFT` function cancels a pending airdrop of the redirected token. | ||
- Verify that the `cancelAirdropNFT` function cancels a pending airdrop of the redirected nft serial. | ||
- Verify that the `claimAirdropFT` function claims a pending airdrop of the redirected token. | ||
- Verify that the `claimAirdropNFT` function claims a pending airdrop of the redirected nft serial number. | ||
- Verify that the `rejectTokenFT` function rejects tokens for a given account. | ||
- Verify that the `rejectTokenNFTs` function rejects tokens for a given account and serial number. | ||
- Verify that the `rejectTokenNFTs` function rejects 10 tokens for a given account and serial number. | ||
- Verify that the `setUnlimitedAutomaticAssociations` function enables the automatic associations to unlimited (-1) for a given account. | ||
- Verify that the `setUnlimitedAutomaticAssociations` function disables the automatic associations to zero for a given account. | ||
|
||
#### Negative Tests | ||
|
||
- Verify that the `airdropTokens` function fails when the sender does not have enough balance. | ||
- Verify that the `airdropTokens` function fails when the receiver does not have a valid account. | ||
- Verify that the `airdropTokens` function fails when the token does not exist. | ||
- Verify that the `airdropTokens` function fails when the airdrop amounts are out of bounds. | ||
- Verify that the `airdropTokens` function fails when 11 or more airdrops are provided. | ||
- Verify that the `cancelAirdrops` function fails when the sender does not have any pending airdrops. | ||
- Verify that the `cancelAirdrops` function fails when the sender does not have a valid account. | ||
- Verify that the `cancelAirdrops` function fails when the receiver does not have a valid account. | ||
- Verify that the `cancelAirdrops` function fails when the token does not exist. | ||
- Verify that the `cancelAirdrops` function fails when the nft does not exist. | ||
- Verify that the `cancelAirdrops` function fails when 11 or more pending airdrops are provided. | ||
- Verify that the `cancelAirdrops` function fails when the nft serial number does not exist. | ||
- Verify that the `claimAirdrops` function fails when the sender does not have any pending airdrops. | ||
- Verify that the `claimAirdrops` function fails when the sender does not have a valid account. | ||
- Verify that the `claimAirdrops` function fails when 11 or more pending airdrops are provided. | ||
- Verify that the `claimAirdrops` function fails when the receiver does not have a valid account. | ||
- Verify that the `claimAirdrops` function fails when the token does not exist. | ||
- Verify that the `claimAirdrops` function fails when the nft does not exist. | ||
- Verify that the `claimAirdrops` function fails when the nft serial number does not exist. | ||
- Verify that the `rejectTokens` function fails when the sender does not have any associated tokens. | ||
- Verify that the `rejectTokens` function fails when the sender does not have a pending airdrop. | ||
- Verify that the `rejectTokens` function fails when the provided fungible token is invalid. | ||
- Verify that the `rejectTokens` function fails when the provided nft is invalid. | ||
- Verify that the `cancelAirdropFT` function fails when the sender does not have any pending airdrops. | ||
- Verify that the `cancelAirdropFT` function fails when the sender does not have a valid account. | ||
- Verify that the `cancelAirdropNFT` function fails when the sender does not have any pending airdrops. | ||
- Verify that the `cancelAirdropNFT` function fails when the sender does not have a valid account. | ||
- Verify that the `claimAirdropFT` function fails when the sender does not have any pending airdrops. | ||
- Verify that the `claimAirdropFT` function fails when the sender does not have a valid account. | ||
- Verify that the `claimAirdropNFT` function fails when the sender does not have any pending airdrops. | ||
- Verify that the `claimAirdropNFT` function fails when the sender does not have a valid account. | ||
- Verify that the `rejectTokenFT` function fails when the sender does not have any tokens. | ||
- Verify that the `rejectTokenFT` function fails when the sender does not have a valid account. | ||
- Verify that the `rejectTokensNFT` function fails when the sender does not have any tokens. | ||
- Verify that the `rejectTokensNFT` function fails when 11 or more serials are provided. |