Skip to content

Commit

Permalink
chore: update contract interface and reference implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
gabrielstoica committed May 9, 2024
1 parent 6e8b373 commit 7235659
Showing 1 changed file with 56 additions and 100 deletions.
156 changes: 56 additions & 100 deletions ERCS/erc-7578.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,16 +60,14 @@ pragma solidity ^0.8.21;
/**
* @notice A struct containing data for redemption properties
* @param tokenId Set when properties are created
* @param tokenIssuer The network or entity minting the tokens
* @param legalOwner The legal owner of the physical asset
* @param assetHolder The legal owner of the physical asset
* @param storedLocation The physical storage location
* @param terms Link to IPFS contract, agreement or terms
* @param terms Link to IPFS contract, agreement or terms
* @param jurisdiction The legal justification set out in the terms
* @param declaredValue The declared value at time of token minting
*/
struct Properties {
uint256 tokenId;
string tokenIssuer;
string assetHolder;
string storedLocation;
Expand All @@ -92,74 +90,48 @@ struct Amount {
* @notice Interface for the PhysicalAssetRedemption contract
*/
interface IPhysicalAssetRedemption {
/**
* @notice Emitted when properties are set
* @param tokenId The ID of the token
* @param properties The properties of the token
*/
event PropertiesSet(Properties properties);
event PropertiesSet(uint256 indexed tokenId, Properties properties);
/**
* @notice Emitted when properties are removed
* @param tokenId The ID of the token
* @param properties The properties of the token
*/
event PropertiesRemoved(Properties properties);
event PropertiesRemoved(uint256 indexed tokenId, Properties properties);
/**
* @notice function to get the properties of a token
* @param tokenId The token id of the minted token
* @notice Retrieves all the properties of a token
* @param tokenId The token ID of the minted token
*/
function properties(
uint256 id
)
external
view
returns (
uint256 tokenId,
string memory tokenIssuer,
string memory assetHolder,
string memory storedLocation,
string memory terms,
string memory jurisdiction,
Amount memory declaredValue
);
function getProperties(uint256 tokenId) external view returns (Properties memory properties);
/**
* @notice Properties required to be set when minting a token
* @param id The token id of the minted token
* @param tokenIssuer The network or entity minting the tokens
* @param assetHolder The legal owner of the physical asset
* @param storedLocation The physical storage location
* @param terms HTTP Link to IPFS contract, agreement or terms
* @param jurisdiction The legal justification set out in the terms
* @param declaredValueCurrency The declared value currency at time of token minting
* @param declaredValueAmount The declared value amount at time of token minting
* @param tokenId The token ID of the minted token
* @param properties The properties of the token
*/
function setProperties(
uint256 id,
string memory tokenIssuer,
string memory assetHolder,
string memory storedLocation,
string memory terms,
string memory jurisdiction,
string memory declaredValueCurrency,
uint256 declaredValueAmount
) external;
function setProperties(uint256 tokenId, Properties calldata properties) external;
}
```

The `setProperties(uint256 id, string memory tokenIssuer, string memory assetHolder, string memory storedLocation, string memory terms, string memory jurisdiction, string memory declaredValueCurrency, uint256 declaredValueAmount)` function is called before minting a token.
The `setProperties(uint256 tokenId, Properties calldata properties)` function is called before minting a token.

The `properties(uint256 id)` function MUST return the unique `properties` for a token.
The `getProperties(uint256 tokenId)` function MUST return the unique `properties` for a token.

When `properties` are set, the `PropertiesSet(Properties properties)` event is emitted.
When `properties` are set, the `PropertiesSet(uint256 indexed tokenId, Properties properties)` event is emitted.

When `properties` are removed, the `PropertiesRemoved(Properties properties)` event is emitted.
When `properties` are removed, the `PropertiesRemoved(uint256 indexed tokenId, Properties properties)` event is emitted.

## Rationale

The `tokenId` must be greater than 0 so the `properties` can be checked before minting.

The mint function is overridden to check if the `properties` are set before minting.
The `_update` function is overridden to check if the `properties` are set before minting and removed after burning.

The `terms` parameter is a HTTP link to a document that is stored on IPFS. This is to ensure that the document is immutable and can be verified by the NFT holder.

Expand All @@ -171,14 +143,17 @@ This standard is compatible with ERC-721.

## Reference Implementation

An example of an ERC-721 that includes the Physical Asset Redemption:
An example of an ERC-721 that includes the Physical Asset Redemption using the OpenZeppelin ERC721 v5 library:

```solidity
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "./IPhysicalAssetRedemption.sol";
pragma solidity ^0.8.21;
import { ERC721 } from "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import { IPhysicalAssetRedemption, Properties, Amount } from "./interfaces/IPhysicalAssetRedemption.sol";
/**
* @title Physical Asset Redemption Contract
* @author DESAT
* @notice Contract for Physical Asset Redemption Standard
**/
contract PhysicalAssetRedemption is IPhysicalAssetRedemption, ERC721 {
Expand All @@ -187,77 +162,58 @@ contract PhysicalAssetRedemption is IPhysicalAssetRedemption, ERC721 {
* @param _name The name of the token
* @param _symbol The symbol of the token
*/
constructor(
string memory _name,
string memory _symbol
) ERC721(_name, _symbol) {}
constructor(string memory _name, string memory _symbol) ERC721(_name, _symbol) {}
mapping(uint256 => Properties) public properties;
mapping(uint256 tokenId => Properties) private _properties;
/**
* @notice Properties required to be set when minting a token
* @param id The token id of the initialized token. Should be greater than 0.
* @param tokenIssuer The network or entity minting the tokens
* @param assetHolder The legal owner of the physical asset
* @param storedLocation The physical storage location
* @param terms Link to IPFS contract, agreement or terms
* @param jurisdiction The legal justification set out in the terms
* @param declaredValueCurrency The declared value currency at time of token minting
* @param declaredValueAmount The declared value amount at time of token minting
* @inheritdoc IPhysicalAssetRedemption
*/
function setProperties(
uint256 id,
string memory tokenIssuer,
string memory assetHolder,
string memory storedLocation,
string memory terms,
string memory jurisdiction,
string memory declaredValueCurrency,
uint256 declaredValueAmount
) public {
require(id > 0, "Token id must be greater than 0");
properties[id] = Properties({
tokenId: id,
tokenIssuer: tokenIssuer,
assetHolder: assetHolder,
storedLocation: storedLocation,
terms: terms,
jurisdiction: jurisdiction,
function setProperties(uint256 tokenId, Properties calldata properties) public {
_properties[tokenId] = Properties({
tokenIssuer: properties.tokenIssuer,
assetHolder: properties.assetHolder,
storedLocation: properties.storedLocation,
terms: properties.terms,
jurisdiction: properties.jurisdiction,
declaredValue: Amount({
currency: declaredValueCurrency,
value: declaredValueAmount
currency: properties.declaredValue.currency,
value: properties.declaredValue.value
})
});
emit PropertiesSet(properties[id]);
emit PropertiesSet(tokenId, _properties[tokenId]);
}
/**
* @notice internal function to remove the properties of a token
* @param _tokenId The token id of the minted token
* @inheritdoc IPhysicalAssetRedemption
*/
function _removeProperties(uint256 _tokenId) internal {
delete properties[_tokenId];
emit PropertiesRemoved(properties[_tokenId]);
function getProperties(uint256 tokenId) public view override returns (Properties memory properties) {
properties = _properties[tokenId];
}
/**
* @notice override of the _safeMint function to check if properties are set
* @param to The address to mint the token to
* @param id The token id of the token to mint
* @notice Internal function to remove the properties of a token
* @param tokenId The token ID of the minted token
*/
function _safeMint(address to, uint256 id) internal virtual override {
require(properties[id].tokenId > 0, "Properties not initialized");
super._safeMint(to, id);
function _removeProperties(uint256 tokenId) internal {
delete _properties[tokenId];
emit PropertiesRemoved(tokenId, _properties[tokenId]);
}
/**
* @notice override of the _burn function to remove properties
* @param id The token id of the minted token
* @notice Override of the {_update} function to remove the properties of a token or check if they are set before minting
* @param tokenId The token ID of the minted or burned token
*/
function _burn(uint256 id) internal virtual override {
_removeProperties(id);
super._burn(id);
function _update(address to, uint256 tokenId, address auth) internal override returns (address) {
address from = _ownerOf(tokenId);
if (to == address(0)) {
_removeProperties(tokenId);
} else if (from == address(0)) {
require(bytes(_properties[tokenId].tokenIssuer).length != 0, "Properties not initialized");
}
return super._update(to, tokenId, auth);
}
}
```
Expand Down

0 comments on commit 7235659

Please sign in to comment.