Skip to content

Commit

Permalink
feat(transferFTIns): add a new way to manage fungible tokens
Browse files Browse the repository at this point in the history
  • Loading branch information
ins-evm committed Feb 27, 2024
1 parent d237cad commit 1b85ae3
Show file tree
Hide file tree
Showing 3 changed files with 108 additions and 37 deletions.
50 changes: 38 additions & 12 deletions ERCS/erc-7583.md
Expand Up @@ -45,17 +45,17 @@ interface IERC7583 /* is IERC20, IERC165 */{
*/
event TransferInsToIns(uint256 indexed fromIns, uint256 indexed toIns, uint256 value);
/**
/**
* @dev Emitted when `inscriptionId` inscription is transferred from `from` to `to`.
*/
event TransferIns(address indexed from, address indexed to, uint256 indexed inscriptionId);
/**
/**
* @dev Emitted when `owner` enables `approved` to manage the `insId` inscription.
*/
event ApprovalIns(address indexed owner, address indexed approved, uint256 indexed insId);
/**
/**
* @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its inscriptions.
*/
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
Expand All @@ -65,12 +65,12 @@ interface IERC7583 /* is IERC20, IERC165 */{
*/
function insBalance(address account) external view returns (uint256);
/**
/**
* @dev Returns the value of fungible tokens in the inscription(`indId`).
*/
function balanceOfIns(uint256 insId) external view returns (uint256);
/**
/**
* @dev Returns the owner of the `insId` inscription.
*
* Requirements:
Expand All @@ -79,7 +79,7 @@ interface IERC7583 /* is IERC20, IERC165 */{
*/
function ownerOf(uint256 insId) external view returns (address owner);
/**
/**
* @dev Gives permission to `to` to transfer `insId` inscription to another account.
* The approval is cleared when the inscription is transferred.
*
Expand All @@ -94,7 +94,7 @@ interface IERC7583 /* is IERC20, IERC165 */{
*/
function approveIns(address to, uint256 insId) external returns (bool);
/**
/**
* @dev Approve or remove `operator` as an operator for the caller.
* Operators can call {transferInsFrom} or {safeTransferFrom} for any inscription owned by the caller.
*
Expand All @@ -106,7 +106,7 @@ interface IERC7583 /* is IERC20, IERC165 */{
*/
function setApprovalForAll(address operator, bool approved) external;
/**
/**
* @dev Returns the account approved for `insId` inscription.
*
* Requirements:
Expand All @@ -115,14 +115,14 @@ interface IERC7583 /* is IERC20, IERC165 */{
*/
function getApproved(uint256 insId) external view returns (address operator);
/**
/**
* @dev Returns if the `operator` is allowed to manage all of the inscriptions of `owner`.
*
* See {setApprovalForAll}
*/
function isApprovedForAll(address owner, address operator) external view returns (bool);
/**
/**
* @dev Transfers `insId` inscription from `from` to `to`.
*
* WARNING: Note that the caller MUST confirm that the recipient is capable of receiving inscription
Expand All @@ -140,6 +140,32 @@ interface IERC7583 /* is IERC20, IERC165 */{
*/
function transferInsFrom(address from, address to, uint256 insId) external;
/**
* @dev Transfers `amount` FTs from inscription `from` to address `to`.
*
* Requirements:
*
* - msg.sender MUST be the owner of inscription `from`.
* - `to` cannot be the zero address.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {TransferInsToIns} event.
*/
function transferFTIns(uint256 from, address to, uint256 amount) external returns (bool);
/**
* @dev Moves a `value` amount of FTs from inscription `from` to address `to`
*
* Requirements:
*
* - If the caller is not the owner of inscription `from`, it must have been allowed to move this inscription by either {approveIns} or {setApprovalForAll}.
* - `to` cannot be the zero address.
*
* Emits a {TransferInsToIns} event.
*/
function transferFTInsFrom(uint256 from, address to, uint256 amount) external returns (bool);
/**
* @dev Safely transfers `insId` inscription from `from` to `to`, checking first that contract recipients
* are aware of the ERC-7583 protocol to prevent tokens from being forever locked.
Expand Down Expand Up @@ -196,12 +222,12 @@ pragma solidity ^0.8.0;
* Note: the ERC-165 identifier for this interface is 0xe45d67f9.
*/
interface IERC7583Metadata /* is IERC7583 */ {
/**
/**
* @dev Embed the inscription data corresponding to the insId into Ethereum through events.
*/
event Inscribe(uint256 indexed id, bytes data);
/**
/**
* @dev Returns the name of the inscription token.
*/
function name() external view returns (string memory);
Expand Down
66 changes: 43 additions & 23 deletions assets/erc-7583/contracts/ERC7583.sol
Expand Up @@ -241,8 +241,8 @@ contract ERC7583 is IERC7583Metadata {
function mint(uint256 insId) external recordSlot(address(0), msg.sender, insId) {
require(_totalSupply < maxSupply, "Exceeded mint limit");

_mint(msg.sender, tickNumber);
tickNumber++;
_mint(msg.sender, tickNumber);
_totalSupply+=mintLimit;

emit Transfer(address(0), msg.sender, mintLimit);
Expand Down Expand Up @@ -328,9 +328,9 @@ contract ERC7583 is IERC7583Metadata {

// Slots can be minted.
if (slotFT[to] == 0) {
tickNumber++;
_mint(to, tickNumber);
slotFT[to] = tickNumber;
tickNumber++;
}

uint256 fromBalance = _balancesOfIns[slotFT[from]];
Expand All @@ -345,7 +345,48 @@ contract ERC7583 is IERC7583Metadata {
emit TransferInsToIns(slotFT[from], slotFT[to], value);
}

/// @notice Transfers FTs from only one inscritpions to others.
/// @param from The inscription of sending FTs
/// @param to Receiver address
/// @return value The amount of FTs sent
function transferFTIns(uint256 from, address to, uint256 value) external returns (bool){
require(ownerOf(from) == msg.sender, "ERC7583: caller is not token owner");

return _transferFTIns(from, to, value);
}

function _transferFTIns(uint256 from, address to, uint256 value) internal returns (bool){
// Slots can be minted.
if (slotFT[to] == 0) {
tickNumber++;
_mint(to, tickNumber);
slotFT[to] = tickNumber;
}

uint256 fromBalance = _balancesOfIns[from];
require(fromBalance >= value, "Insufficient balance");

unchecked {
_balancesOfIns[from] = fromBalance - value;
}
_balancesOfIns[slotFT[to]] += value;

emit TransferInsToIns(from, slotFT[to], value);
return true;
}

/// @notice Transfers FTs from only one inscritpions to others.
/// @param from The inscription of sending FTs
/// @param to Receiver address
/// @return value The amount of FTs sent
function transferFTInsFrom(uint256 from, address to, uint256 value) external returns (bool){
require(_isApprovedOrOwner(msg.sender, from), "ERC7583: caller is not token owner nor approved");

return _transferFTIns(from, to, value);
}

/// @notice You can freely transfer the balances of multiple inscriptions into one, including slots.
/// @notice The inspiration comes from the first miracle of Jesus as described in John 2:1-12.
/// @param froms Multiple inscriptions with a decreased balance
/// @param to Inscription with a increased balance
function waterToWine(WTW[] calldata froms, uint256 to) public {
Expand All @@ -370,27 +411,6 @@ contract ERC7583 is IERC7583Metadata {
_balancesOfIns[to] += increment;
}

/// @notice You can freely transfer the balances between any two of your inscriptions, including slots.
/// @notice The inspiration comes from the first miracle of Jesus as described in John 2:1-12.
/// @param from Inscription with a decreased balance
/// @param to Inscription with a increased balance
/// @param amount The value you gonna transfer
function waterToWine(uint256 from, uint256 to, uint256 amount) public {
require(
ownerOf(from) == msg.sender && ownerOf(to) == msg.sender,
"Is not yours"
);

uint256 fromBalance = _balancesOfIns[from];
require(fromBalance >= amount, "Insufficient balance");
unchecked {
_balancesOfIns[from] = fromBalance - amount;
}
_balancesOfIns[to] += amount;

emit TransferInsToIns(from, to, amount);
}

/// @notice Only the balance in the slot can be transferred using this function.
/// @dev Embed Inscribe event into Transfer of ERC7583
function transferFrom(
Expand Down
29 changes: 27 additions & 2 deletions assets/erc-7583/contracts/IERC7583.sol
Expand Up @@ -109,6 +109,32 @@ interface IERC7583 is IERC20, IERC165 {
*/
function transferInsFrom(address from, address to, uint256 insId) external;

/**
* @dev Transfers `amount` FTs from inscription `from` to address `to`.
*
* Requirements:
*
* - msg.sender MUST be the owner of inscription `from`.
* - `to` cannot be the zero address.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {TransferInsToIns} event.
*/
function transferFTIns(uint256 from, address to, uint256 amount) external returns (bool);

/**
* @dev Moves a `value` amount of FTs from inscription `from` to address `to`
*
* Requirements:
*
* - If the caller is not the owner of inscription `from`, it must have been allowed to move this inscription by either {approveIns} or {setApprovalForAll}.
* - `to` cannot be the zero address.
*
* Emits a {TransferInsToIns} event.
*/
function transferFTInsFrom(uint256 from, address to, uint256 amount) external returns (bool);

/**
* @dev Safely transfers `insId` token from `from` to `to`, checking first that contract recipients
* are aware of the ERC7583 protocol to prevent tokens from being forever locked.
Expand All @@ -118,8 +144,7 @@ interface IERC7583 is IERC20, IERC165 {
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `insId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must have been allowed to move this token by either {approveIns} or
* {setApprovalForAll}.
* - If the caller is not `from`, it must have been allowed to move this token by either {approveIns} or {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC7583Receiver-onERC7583Received}, which is called upon
* a safe transfer.
*
Expand Down

0 comments on commit 1b85ae3

Please sign in to comment.