Skip to content

Commit

Permalink
fix: resolve comment
Browse files Browse the repository at this point in the history
Signed-off-by: MASDXI <sirawitt42@gmail.com>
  • Loading branch information
MASDXI committed Nov 27, 2024
1 parent 8dff806 commit e5e4a60
Show file tree
Hide file tree
Showing 5 changed files with 51 additions and 59 deletions.
60 changes: 30 additions & 30 deletions ERCS/erc-7818.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ This extension facilitates the development of [ERC-20](./eip-20.md) standard com

The keywords “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be interpreted as described in RFC 2119.

Implementers of this **REQUIRED** inheritance [ERC-20](./eip-20.md) interface and **MUST** have all of the following functions and all function behavior **MUST** meet the specification.
Compatible implementations MUST inherit from [ERC-20](./eip-20.md)'s interface and **MUST** have all the following functions and all function behavior **MUST** meet the specification.

```solidity
// SPDX-License-Identifier: CC0-1.0
Expand All @@ -41,21 +41,21 @@ pragma solidity >=0.8.0 <0.9.0;
* @dev Interface for creating expirable ERC20 tokens.
*/
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "./IERC20.sol";
interface IERC7818 is IERC20 {
/**
* @dev Retrieves the balance of a specific `identifier` owned by an account.
* @dev Retrieves the balance of a specific `epoch` owned by an account.
* @param account The address of the account.
* @param identifier The Identifier "MAY" represents an epoch, round, period, or token identifier.
* @return uint256 The balance of the specified `identifier`.
* @notice `identifier` "MUST" represent a unique identifier, and its meaning "SHOULD"
* @param epoch "MAY" represents an epoch, round, or period.
* @return uint256 The balance of the specified `epoch`.
* @notice `epoch` "MUST" represent a unique identifier, and its meaning "SHOULD"
* align with how contract maintain the `epoch` in the implementing contract.
*/
function balanceOf(
address account,
uint256 identifier
uint256 epoch
) external view returns (uint256);
/**
Expand All @@ -75,41 +75,41 @@ interface IERC7818 is IERC20 {
function duration() external view returns (uint256);
/**
* @dev Checks whether a specific `identifier` is expired.
* @param identifier The Identifier "MAY" represents an epoch, round, period, or token identifier.
* @dev Checks whether a specific `epoch` is expired.
* @param epoch "MAY" represents an epoch, round, or period.
* @return bool True if the token is expired, false otherwise.
* @notice Implementing contracts "MUST" define the logic for determining expiration,
* typically by comparing the current `epoch()` with the given `identifier`.
* typically by comparing the current `epoch()` with the given `epoch`.
*/
function expired(uint256 identifier) external view returns (bool);
function expired(uint256 epoch) external view returns (bool);
/**
* @dev Transfers a specific `identifier` and value to a recipient.
* @dev Transfers a specific `epoch` and value to a recipient.
* @param to The recipient address.
* @param identifier The Identifier "MAY" represents an epoch, round, period, or token identifier.
* @param epoch "MAY" represents an epoch, round, or period.
* @param value The amount to transfer.
* @return bool True if the transfer succeeded, false or reverted if give `identifier` it's expired.
* @notice The transfer "MUST" revert if the token `identifier` is expired.
* @return bool True if the transfer succeeded, false or reverted if give `epoch` it's expired.
* @notice The transfer "MUST" revert if the token `epoch` is expired.
*/
function transfer(
address to,
uint256 identifier,
uint256 epoch,
uint256 value
) external returns (bool);
/**
* @dev Transfers a specific `identifier` and value from one account to another.
* @dev Transfers a specific `epoch` and value from one account to another.
* @param from The sender's address.
* @param to The recipient's address.
* @param identifier The Identifier "MAY" represents an epoch, round, period, or token identifier.
* @param epoch "MAY" represents an epoch, round, or period.
* @param value The amount to transfer.
* @return bool True if the transfer succeeded, false or reverted if give `identifier` it's expired.
* @notice The transfer "MUST" revert if the token `identifier` is expired.
* @return bool True if the transfer succeeded, false or reverted if give `epoch` it's expired.
* @notice The transfer "MUST" revert if the token `epoch` is expired.
*/
function transferFrom(
address from,
address to,
uint256 identifier,
uint256 epoch,
uint256 value
) external returns (bool);
}
Expand All @@ -120,36 +120,36 @@ interface IERC7818 is IERC20 {
- `balanceOf` **MUST** return the total balance of tokens held by an account that are still valid (i.e., have not expired). This includes any tokens associated with specific periods, epochs, or other identifiers, provided they remain within their validity duration. Expired tokens **MUST NOT** be included in the returned balance, ensuring that only actively usable tokens are reflected in the result.
- `transfer` and `transferFrom` **MUST** exclusively transfer tokens that remain non-expired at the time of the transaction. Attempting to transfer expired tokens **MUST** revert the transaction or return false. Additionally, implementations **MAY** include logic to prioritize the automatic transfer of tokens closest to expiration, ensuring that the earliest expiring tokens are used first, provided they meet the non-expired condition.
- `totalSupply` **SHOULD** be set to `0` or `type(uint256).max` due to the challenges of tracking only valid (non-expired) tokens.
- The implementation **MAY** use a standardized revert message, such as `ERC7818TransferredExpiredToken` or `ERC7818TransferredExpiredToken(address sender, uint256 identifier)`, to clearly indicate that the operation failed due to attempting to transfer expired tokens.
- The implementation **MAY** use a standardized custom error revert message, such as `ERC7818TransferredExpiredToken` or `ERC7818TransferredExpiredToken(address sender, uint256 epoch)`, to clearly indicate that the operation failed due to attempting to transfer expired tokens.

## Rationale

The rationale for developing an expirable [ERC-20](./eip-20.md) token extension is based on several key requirements that ensure its practicality and adaptability for various applications to

### Compatibility with the existing [ERC-20](./erc-20.md) standard.
### Compatibility with the existing [ERC-20](./eip-20.md) standard.
The extension should integrate smoothly with the [ERC-20](./eip-20.md) interface, This ensures compatibility with existing token ecosystems and third-party tools like wallets and blockchain explorers.

### Flexible interface for various implementation.
The smart contract should be extensible, allowing businesses to tailor the expiration functionality to their specific needs like expiry in bulk or each token independent expire, whether it’s dynamic reward systems or time-sensitive applications.

## Backwards Compatibility

This standard is fully [ERC-20](./erc-20.md) compatible.
This standard is fully [ERC-20](./eip-20.md) compatible.

## Reference Implementation

For reference implementation can be found [here](../assets/erc-7818/README.md), But in the reference implementation, we employ a sorted list to automatically select the token that nearest expires first with a First-In-First-Out (`FIFO`) and sliding window algorithm that operates based on the `block.number` as opposed to relying on `block.timestamp`, which has been criticized for its lack of security and resilience, particularly given the increasing usage of Layer 2 (L2) networks over Layer 1 (L1) networks. Many L2 networks exhibit centralization and instability, which directly impacts asset integrity, rendering them potentially unusable during periods of network halting, as they are still reliant on the timestamp.
For reference implementation can be found [here](../assets/eip-7818/README.md), But in the reference implementation, we employ a sorted list to automatically select the token that nearest expires first with a First-In-First-Out (`FIFO`) and sliding window algorithm that operates based on the `block.number` as opposed to relying on `block.timestamp`, which has been criticized for its lack of security and resilience, particularly given the increasing usage of Layer 2 (L2) networks over Layer 1 (L1) networks. Many L2 networks exhibit centralization and instability, which directly impacts asset integrity, rendering them potentially unusable during periods of network halting, as they are still reliant on the timestamp.

## Security Considerations

### SC06: Denial Of Service
Run out of gas problem due to the operation consuming high gas used if transferring multiple groups of small tokens.
### Denial Of Service
Run out of gas problem due to the operation consuming higher gas if transferring multiple groups of small tokens or loop transfer.

### SC09: Gas Limit Vulnerabilities
### Gas Limit Vulnerabilities
Exceeds block gas limit if the blockchain has a block gas limit lower than the gas used in the transaction.

### SWC116: Block values as a proxy for time
if using `block.timestamp` for calculating `epoch()`
### Block values as a proxy for time
if using `block.timestamp` for calculating `epoch()` and In rare network halts, block production stops, freezing `block.timestamp` and disrupting time-based logic. This risks asset integrity and inconsistent states.

### Fairness Concerns
In a straightforward implementation, where all tokens within the same epoch share the same expiration (e.g., at `epoch`:`x`), bulk expiration occurs.
Expand Down
1 change: 0 additions & 1 deletion assets/erc-7818/.nvmrc

This file was deleted.

7 changes: 0 additions & 7 deletions assets/erc-7818/.solcover.js

This file was deleted.

40 changes: 20 additions & 20 deletions assets/erc-7818/contracts/IERC7818.sol
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// SPDX-License-Identifier: CC0-1.0
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0 <0.9.0;

/**
Expand All @@ -10,16 +10,16 @@ import "@openzeppelin/contracts/token/ERC20/IERC20.sol";

interface IERC7818 is IERC20 {
/**
* @dev Retrieves the balance of a specific `identifier` owned by an account.
* @dev Retrieves the balance of a specific `epoch` owned by an account.
* @param account The address of the account.
* @param identifier The Identifier "MAY" represents an epoch, round, period, or token identifier.
* @return uint256 The balance of the specified `identifier`.
* @notice `identifier` "MUST" represent a unique identifier, and its meaning "SHOULD"
* @param epoch "MAY" represents an epoch, round, or period.
* @return uint256 The balance of the specified `epoch`.
* @notice `epoch` "MUST" represent a unique identifier, and its meaning "SHOULD"
* align with how contract maintain the `epoch` in the implementing contract.
*/
function balanceOf(
address account,
uint256 identifier
uint256 epoch
) external view returns (uint256);

/**
Expand All @@ -39,41 +39,41 @@ interface IERC7818 is IERC20 {
function duration() external view returns (uint256);

/**
* @dev Checks whether a specific `identifier` is expired.
* @param identifier The Identifier "MAY" represents an epoch, round, period, or token identifier.
* @dev Checks whether a specific `epoch` is expired.
* @param epoch "MAY" represents an epoch, round, or period.
* @return bool True if the token is expired, false otherwise.
* @notice Implementing contracts "MUST" define the logic for determining expiration,
* typically by comparing the current `epoch()` with the given `identifier`.
* typically by comparing the current `epoch()` with the given `epoch`.
*/
function expired(uint256 identifier) external view returns (bool);
function expired(uint256 epoch) external view returns (bool);

/**
* @dev Transfers a specific `identifier` and value to a recipient.
* @dev Transfers a specific `epoch` and value to a recipient.
* @param to The recipient address.
* @param identifier The Identifier "MAY" represents an epoch, round, period, or token identifier.
* @param epoch "MAY" represents an epoch, round, or period.
* @param value The amount to transfer.
* @return bool True if the transfer succeeded, false or reverted if give `identifier` it's expired.
* @notice The transfer "MUST" revert if the token `identifier` is expired.
* @return bool True if the transfer succeeded, false or reverted if give `epoch` it's expired.
* @notice The transfer "MUST" revert if the token `epoch` is expired.
*/
function transfer(
address to,
uint256 identifier,
uint256 epoch,
uint256 value
) external returns (bool);

/**
* @dev Transfers a specific `identifier` and value from one account to another.
* @dev Transfers a specific `epoch` and value from one account to another.
* @param from The sender's address.
* @param to The recipient's address.
* @param identifier The Identifier "MAY" represents an epoch, round, period, or token identifier.
* @param epoch "MAY" represents an epoch, round, or period.
* @param value The amount to transfer.
* @return bool True if the transfer succeeded, false or reverted if give `identifier` it's expired.
* @notice The transfer "MUST" revert if the token `identifier` is expired.
* @return bool True if the transfer succeeded, false or reverted if give `epoch` it's expired.
* @notice The transfer "MUST" revert if the token `epoch` is expired.
*/
function transferFrom(
address from,
address to,
uint256 identifier,
uint256 epoch,
uint256 value
) external returns (bool);
}
2 changes: 1 addition & 1 deletion assets/erc-7818/contracts/MockERC20Expirable.sol
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// SPDX-License-Identifier: UNLICENSED
// SPDX-License-Identifier: MIT
pragma solidity >=0.5.0 <0.9.0;

import "../contracts/abstracts/ERC20Expirable.sol";
Expand Down

0 comments on commit e5e4a60

Please sign in to comment.