forked from ethereum/go-ethereum
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #2 from SangIlMo/research/eip-7291-pbm-2
EIPs: add erc-7291.md
- Loading branch information
Showing
1 changed file
with
392 additions
and
0 deletions.
There are no files selected for viewing
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,392 @@ | ||
# PBM Technical Whitepaper | ||
|
||
## Background | ||
|
||
CDBC는 새로운 디지털 자산 생태계의 교환 매체(medium of exchange)로써 사용되어질 수 있다. | ||
|
||
CBDC와 같은 digital money의 가장 큰 장점은 Programmability Feature를 지원한다는 것이다. | ||
|
||
그러나, 이 Programmability로 인해 교환 매체\*로서의 기능을 잃어버려서는 안된다. 화폐의 단일 목적(Singleness)이 보존되어야 하며, Programmability가 화폐의 분배를 제한하거나 시스템의 유동성 조각화를 야기해서는 안된다. | ||
|
||
- 교환 매체 | ||
In economics, a **medium of exchange** is any item that is widely acceptable in exchange for goods and services. | ||
현대시대에서 대표적인 교환 매체는 법정 화폐 라고 볼 수 있다. | ||
|
||
PBM - Purpose Bound Money: 화폐 자체가 Program될 필요 없이, 구체적인 목적을 위해 만들어진 화폐 | ||
|
||
다른 원장 기술과 화폐 형태에도 동작할 수 있도록 Common Protocol을 활용한다. 표준화된 포멧을 통해서, 사용자는 원하는 Wallet Provider로 Digital Money에 접근할 수 있다. | ||
|
||
## Motivation | ||
|
||
- Proliferation of markets and their fragmentation (시장 증식과 조각화) | ||
|
||
- 서로 다른 결제 채널과 방식을 사용함으로써, 상인이나 소비자들이 이에 적응하기위해 소비하는 노력과 자원이 발생함 | ||
- ApplePay와 같은 페이먼트 시스템을 제공하기 위해서 해당 스펙의 프로토콜을 지원하는 포스단말기, 인앱서비스, 카드사 결제 시스템 등에 업데이트가 필요하다. | ||
- 독립적이고 개별화된 시스템들을 하나의 플랫폼으로 구성하면 더 나은 UX와 디지털화의 잠재력을 발휘할 수 있음 | ||
- 이에 여러 payment 시스템들에 대한 상호작용을 필요로 하게 되며 기업 및 소비자들에게 높은 유연성을 제공해야함 | ||
|
||
- Programmability and fungibility of money (자산의 프로그래밍 가능성과 대체 가능성) | ||
- digital money의 Prgrammability는 큰 차별점이지만, **교환 매체로써의 역할을 상실할 위험**이 있음 | ||
- 서비스에 따라 필요한 디지털 자산들이 많아지면서 모든 UseCase에 맞는 단일화된 Digital Money를 생성하기는 어려움 | ||
- 새로운 UseCase를 얻기 위해 의존성에 의해 다시 programming 해야 함 | ||
- Fungibility 또한 토큰 간의 거래가 자유롭게 이루어질 수 있는 목적에서 중요 | ||
- 개별 서비스 별 digital money를 만드는 경우, Fungibility 상실 및 유동성이 축소될 수 있음 | ||
|
||
## Models of Programmability | ||
|
||
<img width="50%" alt="models-figure" src="https://github.com/SangIlMo/EIP_opensource/assets/156392700/1de60dfd-b374-477b-b92f-471aed40a3ad"> | ||
|
||
### Programmable payment | ||
|
||
- 미리 설정된 조건을 만족한 경우 결제를 자동화하는 모델 | ||
- API Gateway 형태나 DB Trigger 형태로 구현되며 accounting ledger ↔ client application의 상호작용으로 발생함 | ||
- 자동이체, 자동납부 등 | ||
- 여러 형태의 화폐에 Programming Logic이나 조건을 적용할 수 있음 | ||
|
||
### Programmable money | ||
|
||
- 자산 자체에 정해진 규칙을 설정하고 사용을 제한하는 모델 | ||
- 포인트, 쿠폰, 상품권 등 | ||
- 토큰화된 은행 부채, CBDC | ||
- Programming Logic을 화폐에 적용한 채로 전송됨 | ||
|
||
→ Programmble payment는 자산과 Programming Logic이 분리되어 있지만, money의 경우 하나로 묶여 자산 자체를 제한한다고 볼 수 있다. | ||
|
||
→ 각 국가별 중앙은행, 시중 은행, 서비스 제공자 들에 대해 각각의 CBDC, 부채, stablecoin 이 발생한다면, 더욱 복잡하고 다양한 금융 landsape이 형성됨 따라서, 하나로 통함할 수 있는 Framework의 필요성이 매우 중요 (서로 다른 digital money간의 상호작용과 현존하는 금융 인프라와 호환성을 가능하게 해야함) | ||
|
||
### Purpose Bound Money (PBM) | ||
|
||
- 자산이 사용되는 조건을 구체화 할 수 있는 모델 | ||
- 따라서, payment와 money의 각 특징을 모두 구현 가능 | ||
- digital money로서 내재 가치(intrinsic value)와 Programming Logic 을 포함할 수 있음 | ||
- condition이 성립되면 digital money는 내재 가치가 보존되고, progrmming 조건에서 벗어나게 됨 | ||
- 예시) 디지털 쿠폰 | ||
- 상품이나 서비스와 교환할 수 있음 (Programmable Payment) | ||
- 약관에 따라 양도가 가능함 (Programmable Money) | ||
- 다른 점은, Payee가 지불받은 후 digital money로 전환되어 다른 목적으로 사용 가능 | ||
|
||
<img width="50%" alt="models-compare-table" src="https://github.com/SangIlMo/EIP_opensource/assets/156392700/1418aa35-8f24-4405-b40d-d427ec1b8136"> | ||
|
||
## System Architecture | ||
|
||
|Layer|Examples| | ||
| --- | --- | | ||
| Access Layer | Wallets, Applications, Portals | | ||
| Service Layer | Lending, Borrowing, Derivatives, Purpose Bound Money | | ||
| Asset Layer | CBDC, Stablecoin, Tokenised Bank Liability, Digital Money | | ||
| Platform Layer | Execution, Storage, Addressing, Consensus | | ||
|
||
→ PBM 디자인은 다른 유형의 블록체인과 자산에서도 작동하며, 비 원장 시스템에서도 사용 가능하다. | ||
|
||
### PBM 요소 | ||
|
||
- Wrapper: 의도한 목적에 따른 역할 수행 | ||
- 정해진 조건에 따라서 수행함 | ||
- 조건 만족시 digital money로 전환되고 recipient에게 전송됨 | ||
- ERC-1155로 구현 가능함 | ||
- Store of Value: 내재가치를 지속적으로 보유 | ||
- digital money로서의 가치를 저장함 | ||
- 상품 가치, 계좌, 환전 매개체 | ||
- CBDC 가능 | ||
|
||
<img width="394" alt="pbm-component" src="https://github.com/SangIlMo/EIP_opensource/assets/156392700/b882c587-dd4d-43ae-b295-2a545bb7b907"> | ||
|
||
### 역할과 상호작용 | ||
|
||
- PBM Creator | ||
→ PBM 로직을 정의하고, 발행 및 분배를 담당함 | ||
- PBM Holder | ||
→ PBM token을 사용하며, 기한이 만료되기 전 PBM 토큰을 상환 가능 | ||
- PBM Redeemer | ||
→ PBM token의 역할이 완료된 후, digital money를 수령함 | ||
|
||
### Lifecycle | ||
|
||
<img width="691" alt="pbm-lifecycle" src="https://github.com/SangIlMo/EIP_opensource/assets/156392700/f3397baf-79ad-4da5-bd5f-583adf24e793"> | ||
|
||
예시) | ||
|
||
1. Issue Stage | ||
- PBM 초기화 | ||
- PBM Token 생성 | ||
- PBM Token 발행 | ||
2. Distribute | Transfer | ||
- PBM 분배 및 거래(전송) | ||
3. Redemption Stage | ||
- PBM 상환 | ||
4. Expired Stage | ||
- Redeem expired PBM Token - 만기로 인한, PBM 사용(전송)불가 | ||
- Revoke PBM - 만기로 인한, PBM 상환 | ||
|
||
### components | ||
|
||
- PBM Wrapper (Actions) | ||
- Mint | Burn | Transfer PBM | ||
- Interact with PBM Logic and PBM Token Manager | ||
- PBM Logic → create complex business conditions | ||
- add or remove from whitelist / blacklist | ||
- check if PBM can be transferred / unwrapped | ||
- PBM Token Manager (Type and Balance Management) | ||
- create PBM token types | ||
- get details of each PBM token type | ||
- increase/decrease supply balance | ||
- validate PBM token expiry | ||
|
||
<img width="521" alt="pbm-smart-contract" src="https://github.com/SangIlMo/EIP_opensource/assets/156392700/ee02f5aa-254f-4bd2-9a92-8e0e040e3983"> | ||
|
||
## Interface | ||
|
||
ERC-1155를 기반으로 PBM-Wrapper를 통해 PBM Token을 생성한다. | ||
|
||
ERC-1155는 multiple tokens를 지원하고 각 토큰에 ID 부여가 가능하여 Token Type을 구체적으로 설정할 수 있다. | ||
|
||
### PBM Token Details (PBM Token Manager) | ||
|
||
- 모든 필수 비즈니스 로직이 TokenType 별로 반드시 기재되어야 함 | ||
|
||
PBMToken structure에서 다음 요소를 필수로 지정하고 있다. (**MUST**) | ||
|
||
- name - token name | ||
- faceValue - value of underlying token | ||
- Wrapping한 Token 수량을 기록 | ||
- expiry - 만료기간 | ||
- uri - metadata uri (display purpose) | ||
- 이외 모두 Optional이며 필요한 사항은 추가 가능 (**MAY**) | ||
- PBM Token이 각 서비스 목적에 따라 사용 될 수 있도록 하기 위해 자율성을 부과 | ||
- PBMToken struct | ||
|
||
```solidity | ||
abstractcontract IPBMRC1_TokenManager { | ||
/// @dev Mapping of each ERC-1155 tokenId to its corresponding PBM Token details. | ||
mapping (uint256=> PBMToken)internal tokenTypes ; | ||
/// @notice A PBM token MUST include compulsory state variables (name, faceValue, expiry, and uri) to adhere to this standard. | ||
/// @dev Represents all the details corresponding to a PBM tokenId. | ||
struct PBMToken { | ||
// Name of the token. | ||
string name; | ||
// Value of the underlying wrapped ERC20-compatible sovToken. Additional information on the `faceValue` can be specified by | ||
// adding the optional variables: `currencySymbol` or `tokenSymbol` as indicated below | ||
uint256 faceValue; | ||
// Time after which the token will be rendered useless (expressed in Unix Epoch time). | ||
uint256 expiry; | ||
// Metadata URI for ERC-1155 display purposes. | ||
string uri; | ||
// OPTIONAL: Indicates if the PBM token can be transferred to a non merchant/redeemer wallet. | ||
bool isTransferable; | ||
// OPTIONAL: Determines whether the PBM will be burned or revoked upon expiry, under certain predefined conditions, or at the owner's discretion. | ||
bool burnable; | ||
// OPTIONAL: Number of decimal places for the token. | ||
uint8 decimals; | ||
// OPTIONAL: The address of the creator of this PBM type on this smart contract. This field is optional because the creator is msg.sender by default. | ||
address creator; | ||
// OPTIONAL: The smart contract address of the sovToken. | ||
address tokenAddress; | ||
// OPTIONAL: The running balance of the PBM Token type that has been minted. | ||
uint256 totalSupply; | ||
// OPTIONAL: An ISO4217 three-character alphabetic code may be needed for the faceValue in multicurrency PBM use cases. | ||
string currencySymbol; | ||
// OPTIONAL: An abbreviation for the PBM token name may be assigned. | ||
string tokenSymbol; | ||
// Add other optional state variables below... | ||
} | ||
} | ||
``` | ||
|
||
PBMToken Type 생성 (**SHOULD**) | ||
|
||
- 필수 파라미터 (name, faceValue, expiry, uri) 전달 | ||
- 해당 Token 정보에 대한 Event 발생 | ||
- createPBMTokenType | ||
|
||
```solidity | ||
/// @notice Creates a new PBM Token type with the provided data. | ||
/// @dev The caller of createPBMTokenType shall be responsible for setting the creator address. | ||
/// Example of uri can be found in [`sample-uri`](/assets/eip-7291/sample-uri/stx-10-static) | ||
/// Must emit {NewPBMTypeCreated} | ||
/// @param _name Name of the token. | ||
/// @param _faceValue Value of the underlying wrapped ERC20-compatible sovToken. | ||
/// @param _tokenExpiry Time after which the token will be rendered useless (expressed in Unix Epoch time). | ||
/// @param _tokenURI Metadata URI for ERC-1155 display purposes | ||
function createPBMTokenType( | ||
string memory _name, | ||
uint256 _faceValue, | ||
uint256 _tokenExpiry, | ||
string memory _tokenURI | ||
) external virtual returns (uint256 tokenId_); | ||
/// @notice Emitted when a new Purpose-Bound Token (PBM) type is created within the contract. | ||
/// @param tokenId The unique identifier for the newly created PBM token type. | ||
/// @param tokenName A human-readable string representing the name of the newly created PBM token type. | ||
/// @param amount The initial supply of the newly created PBM token type. | ||
/// @param expiry The timestamp at which the newly created PBM token type will expire. | ||
/// @param creator The address of the account that created the new PBM token type. | ||
event NewPBMTypeCreated(uint256 tokenId, string tokenName, uint256 amount, uint256 expiry, address creator); | ||
``` | ||
|
||
PBM Token Info Details (**MUST**) | ||
|
||
- PBM 정보를 가져오기 위한 함수 | ||
- getTokenDetails | ||
```solidity | ||
/// @notice Retrieves the details of a PBM Token type given its tokenId. | ||
/// @dev This function fetches the PBMToken struct associated with the tokenId and returns it. | ||
/// @param tokenId The identifier of the PBM token type. | ||
/// @return pbmToken_ A PBMToken struct containing all the details of the specified PBM token type. | ||
function getTokenDetails(uint256 tokenId) external virtual view returns(PBMToken memory pbmToken_); | ||
``` | ||
|
||
### PBM Address List (PBM Logic) | ||
|
||
- PBM 사용 및 Release(Unwrap)이 가능한 Address 목록을 유지해야 함 | ||
- 해당 인터페이스는, 추가적인 비즈니스 로직과 함께 사용되어질 수 있음 (**MUST**) | ||
- isBlacklisted() | ||
- Blacklist - event | ||
- isMerchant() | ||
- MerchantList - event | ||
- IPBMAddressList | ||
|
||
``` | ||
pragma solidity^0.8.0; | ||
/// @title PBM Address list Interface. | ||
/// @notice The PBM address list stores and manages whitelisted merchants/redeemers and blacklisted address for the PBMs | ||
interface IPBMAddressList { | ||
/// @notice Checks if the address is one of the blacklisted addresses | ||
/// @param _address The address to query | ||
/// @return bool_ True if address is blacklisted, else false | ||
function isBlacklisted(address _address)externalreturns (bool bool_) ; | ||
/// @notice Checks if the address is one of the whitelisted merchant/redeemer addresses | ||
/// @param _address The address to query | ||
/// @return bool_ True if the address is in merchant/redeemer whitelist and is NOT a blacklisted address, otherwise false. | ||
function isMerchant(address _address)externalreturns (bool bool_) ; | ||
/// @notice Event emitted when the Merchant/Redeemer List is edited | ||
/// @param action Tags "add" or "remove" for action type | ||
/// @param addresses An array of merchant wallet addresses that was just added or removed from Merchant/Redeemer whitelist | ||
/// @param metadata Optional comments or notes about the added or removed addresses. | ||
event MerchantList(string action,address[] addresses,string metadata); | ||
/// @notice Event emitted when the Blacklist is edited | ||
/// @param action Tags "add" or "remove" for action type | ||
/// @param addresses An array of wallet addresses that was just added or removed from address blacklist | ||
/// @param metadata Optional comments or notes about the added or removed addresses. | ||
event Blacklist(string action,address[] addresses,string metadata); | ||
} | ||
``` | ||
|
||
### PBMRC - Base Interface (PBM Wrapper) | ||
|
||
- Digital Money Wrapping을 통한 PBM Token 발행 | ||
- mint | burn | transfer | revoke | unwrap PBM Lifecycle위한 Action 책임짐 | ||
- IPBMRC1 | ||
|
||
```solidity | ||
/// LIST OF EVENTS TO BE EMITTED | ||
/// A database or explorer may listen to events and be able to provide indexed and categorized searches | ||
/// @title PBM Specification interface | ||
/// @notice The PBM (purpose bound money) allows us to add logical requirements on the use of sovTokens. | ||
/// The PBM acts as wrapper around the sovTokens and implements the necessary business logic. | ||
/// @dev PBM deployer must assign an overall owner to the smart contract. If fine grain access controls are required, EIP-5982 can be used on top of ERC173 | ||
interface IPBMRC1 is IERC173, IERC5679Ext1155 { | ||
// underlying ERC20 토큰의 정보와, Business Logic 컨트랙트 정보 등을 얻어 | ||
// PBM Token으로 Wrapping하는 함수 | ||
function initialise(address _sovToken, uint256 _expiry, address _pbmWrapperLogic) external; | ||
/// @notice Returns the uri metadata information for the PBM with the corresponding tokenId | ||
function uri(uint256 tokenId) external view returns (string memory); | ||
function safeMint(address receiver, uint256 tokenId, uint256 amount, bytes calldata data) external; | ||
function safeMintBatch(address receiver, uint256[] calldata tokenIds, uint256[] calldata amounts, bytes calldata data) external; | ||
function burn(address from, uint256 tokenId, uint256 amount, bytes calldata data) external; | ||
function burnBatch(address from, uint256[] calldata tokenIds, uint256[] calldata amounts, bytes calldata data) external; | ||
// 1. buisiness logic check | ||
// 2. unwrap function may be called within this function | ||
// buisiness logic 조건 만족하는 경우, PBM Token 간 자유롭게 전송 가능해야 하며 | ||
// 조건 만족시 underlying ERC20 토큰 release를 위해 unwrap 호출 해야 함 | ||
function safeTransferFrom(address from, address to, uint256 id, uint256 amount, bytes memory data) external; | ||
function safeBatchTransferFrom(address from, address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data) external; | ||
function unwrap(address from, address to, uint256 tokenId, uint256 amount, bytes memory data) internal; | ||
// PBM Token 만료시 Revoke | ||
// 전송 되지 않고, unwrap 되어 underlying ERC20 release 됨 | ||
function revokePBM(uint256 tokenId) external; | ||
event PBMrevokeWithdraw(address beneficiary, uint256 PBMTokenId, address sovToken, uint256 sovTokenValue); | ||
event TokenUnwrapForTarget(address from, address to, uint256[] tokenIds, uint256[] amounts, address sovToken, uint256 sovTokenValue); | ||
event TokenUnwrapForPBMBurn(address from, address to, uint256[] tokenIds, uint256[] amounts, address sovToken, uint256 sovTokenValue); | ||
event TokenWrap(address from, uint256[] tokenIds, uint256[] amounts,address sovToken, uint256 sovTokenValue); | ||
} | ||
``` | ||
|
||
### Extension of PBMRC1 - Token Receiver | ||
|
||
- Token Receiver의 경우, PBM Token을 전송 받고 Unwrap(release) 과정에서 추가적인 로직을 수행할 수 있도록 한다. | ||
- PBMRC1_TokenReceiver | ||
|
||
```solidity | ||
/// @notice Smart contracts MUST implement the ERC-165 `supportsInterface` function and signify support for the `PBMRC1_TokenReceiver` interface to accept callbacks. | ||
/// It is optional for a receiving smart contract to implement the `PBMRC1_TokenReceiver` interface | ||
/// @dev WARNING: Reentrancy guard procedure, Non delegate call, or the check-effects-interaction pattern must be adhere to when calling an external smart contract. | ||
/// The interface functions MUST only be called at the end of the `unwrap` function. | ||
interface PBMRC1_TokenReceiver { | ||
// PBMToken 수신 후, Unwrap 시에 추가적인 logic 호출 가능 | ||
// ex) 구입 시 10% 할인 등? | ||
function onPBMRC1Unwrap(address _operator, address _from, uint256 _id, uint256 _value, bytes calldata _data) external returns(bytes4); | ||
function onPBMRC1BatchUnwrap(address _operator, address _from, uint256[] calldata _ids, uint256[] calldata _values, bytes calldata _data) external returns(bytes4); | ||
} | ||
``` | ||
|
||
### PBMRC2 | ||
|
||
- PBMRC1과 달리, non preloaded PBM으로 underlying ERC20 amount를 처음부터 할당 하지 않고, 이후에 할당할 수 있는 방식이다. | ||
- IPBMRC1을 구현하고 있으며 추가적으로 다음 함수를 포함한다. | ||
- load() - load underlying ERC20 amount into PBMtoken | ||
- unload() - unload amount | ||
- 네이버 포인트 등으로 사용 가능할 것 같음 | ||
- PBMRC2_NonPreloadedPBM | ||
|
||
```solidity | ||
interface PBMRC2_NonPreloadedPBM is IPBMRC1 { | ||
... | ||
function load(uint256 amount) external; | ||
function unload(uint256 amount) external; | ||
event TokenLoad(address caller, address to, uint256 amount, address sovToken, uint256 sovTokenValue); | ||
event TokenUnload(address caller, address from, uint256 amount, address sovToken, uint256 sovTokenValue); | ||
} | ||
``` | ||
|
||
진행된 PoC - https://github.com/StraitsX/Orchid-PBM | ||
|
||
## reference | ||
|
||
- [ERC-7291](https://eips.ethereum.org/EIPS/eip-7291) | ||
- [PBM poc Implementation](https://github.com/StraitsX/Orchid-PBM) | ||
- [ERC-7291 Interface](https://github.com/ethereum/ERCs/tree/master/assets/erc-7291/contracts) | ||
- [ERC-7291 Proposal](https://github.com/ethereum/ERCs/blob/master/ERCS/erc-7291.md) | ||
- [PBM Technical Report](https://www.mas.gov.sg/-/media/mas-media-library/development/fintech/pbm/pbm-technical-whitepaper.pdf) | ||
- [Ethereum Magician Discussion](https://ethereum-magicians.org/t/eip-7291-purpose-bound-money/14973) | ||
- [RFC2119](https://datatracker.ietf.org/doc/html/rfc2119) |