From c4900dcc0c62647b30f1b77c41d92789073fa75c Mon Sep 17 00:00:00 2001
From: MrDeadCe11 <84342118+MrDeadCe11@users.noreply.github.com>
Date: Tue, 25 Jun 2024 14:26:08 -0500
Subject: [PATCH] updated natspec and readme (#43)
* updated natspec and readme
* Final cleanup
* author ordering
---------
Co-authored-by: Patrick Gallagher
---
README.md | 39 ++++++++++++-------
src/contracts/SIP15Zone.sol | 18 ++++++---
src/contracts/Vault721Adapter.sol | 2 +-
src/sips/SIP15Decoder.sol | 35 ++++++++++++++++-
src/sips/SIP15Encoder.sol | 24 ++++++++++--
test/e2e/SetUp.sol | 2 +-
...ansferValidationSIP15ZoneOffererTest.t.sol | 4 +-
7 files changed, 94 insertions(+), 30 deletions(-)
diff --git a/README.md b/README.md
index 6e7415d..fab2088 100644
--- a/README.md
+++ b/README.md
@@ -11,15 +11,17 @@
-# Dynamic Traits Enforcement Zone
+# Dynamic Traits Enforcement Zone
-A Seaport zone for specifying and enforcing values of ERC-7496 Dynamic Traits
+A Seaport zone which implements [ERC-7496](https://eips.ethereum.org/EIPS/eip-7496) to enforce NFT trait details.
-View the SIP-15 standard: https://github.com/open-dollar/SIPs/blob/main/SIPS/sip-15.md
+The zone was developed to align with the [SIP-15](https://github.com/open-dollar/SIPs/blob/main/SIPS/sip-15.md) standard from Seaport.
## Setup
-1. Copy the `.env.example` and update the following values:
+Use the command-line scripts to create, submit, and fulfill an order for an Open Dollar NFV, using the OpenSea API.
+
+1. Copy the `.env.example` and update the following values:
```bash
ARB_SEPOLIA_RPC=
@@ -28,26 +30,35 @@ ARB_SEPOLIA_OFFERER_PK=
ARB_SEPOLIA_BUYER_PK=
```
-2. Use the “Offerer” wallet to open a vault on Open Dollar testnet https://app.dev.opendollar.com
+2. Use the “Offerer” wallet to open a vault on Open Dollar testnet https://app.dev.opendollar.com
-2. User the “Buyer” wallet to mint the consideration token "ARB" at https://sepolia.arbiscan.io/address/0x3018EC2AD556f28d2c0665d10b55ebfa469fD749#writeContract
+3. User the “Buyer” wallet to mint the consideration token "ARB" at https://sepolia.arbiscan.io/address/0x3018EC2AD556f28d2c0665d10b55ebfa469fD749#writeContract
+## Create Listing
-## Create listing
+Use the `create-listing` scrip to create an order from the "Offerer" wallet.
```bash
-yarn
+# Install and build the contracts
+yarn
yarn build
-# Create Listing
yarn create-listing
-yarn create-listing sepolia 313 0.000001
+# eg.
+yarn create-listing sepolia 313 0.000001
+```
+
+## Fulfill Order
-# Execute listing
+Use the fulfill script to execute the order from the "Buyer" wallet.
+
+```bash
yarn fulfill
+# eg.
yarn fulfill sepolia orders/order-1-1718667016.json
```
-Notes:
-- Vaults have a 100 second cooldown on testnet before they can be transferred.
-- Order `endTime` is 24 hours
+Important Notes:
+
+- On testnet, Open Dollar NFVs have a 100 second cooldown after any modification before they can be transferred.
+- The default order `endTime` is currently 24 hours.
diff --git a/src/contracts/SIP15Zone.sol b/src/contracts/SIP15Zone.sol
index ae46312..cbb396c 100644
--- a/src/contracts/SIP15Zone.sol
+++ b/src/contracts/SIP15Zone.sol
@@ -12,10 +12,10 @@ import {SIP15ZoneEventsAndErrors} from '../interfaces/SIP15ZoneEventsAndErrors.s
import {ISIP15Zone} from '../interfaces/ISIP15Zone.sol';
/**
- * @title ODSeaportZone
- * @author MrDeadce11 & stephankmin
- * @notice SIP15Zone is an implementation of SIP-15. It verifies that the dynamic traits of an NFT
- * have not changed between the time of order creation and the time of order fulfillment.
+ * @title DynamicTraitsEnforcementZone
+ * @author MrDeadCe11, daopunk, pi0neerpat, CupOJoseph, stephankmin
+ * @notice DynamicTraitsEnforcementZone is an implementation of SIP-15 for enforcing ERC-7496 traits. It verifies the state of
+ * dynamic traits after a transfer and supports substandards 1 through 5. Substandard docs: https://github.com/open-dollar/SIPs/blob/main/SIPS/sip-15.md
*/
contract SIP15Zone is ERC165, ISIP15Zone, SIP15ZoneEventsAndErrors {
using SIP15Decoder for bytes;
@@ -25,7 +25,7 @@ contract SIP15Zone is ERC165, ISIP15Zone, SIP15ZoneEventsAndErrors {
constructor() {}
/**
- * @dev Validates an order.
+ * @dev Validates an order. called after order is fulfilled and offers and considerations have been transfered
*
* @param zoneParameters The context about the order fulfillment and any
* supplied extraData.
@@ -55,6 +55,10 @@ contract SIP15Zone is ERC165, ISIP15Zone, SIP15ZoneEventsAndErrors {
return this.validateOrder.selector;
}
+ /**
+ * @dev called before order fulfillment. no authorization is required for this zone.
+ * @return authorizedOrderMagicValue the bytes4 magic order value that authorizes the order
+ */
function authorizeOrder(ZoneParameters calldata /* zoneParameters*/ )
external
view
@@ -62,6 +66,10 @@ contract SIP15Zone is ERC165, ISIP15Zone, SIP15ZoneEventsAndErrors {
{
return this.authorizeOrder.selector;
}
+ /**
+ * @dev decodes extraData acording to the substandard and then checks the traits according to
+ * the designated comparison enum/enums. See SIP15encoder for encoding details.
+ */
function _validateSubstandard(uint8 substandardVersion, bytes calldata extraData) internal view {
address token;
diff --git a/src/contracts/Vault721Adapter.sol b/src/contracts/Vault721Adapter.sol
index ca46299..ac35ff5 100644
--- a/src/contracts/Vault721Adapter.sol
+++ b/src/contracts/Vault721Adapter.sol
@@ -7,7 +7,7 @@ import {IERC7496} from 'shipyard-core/src/dynamic-traits/interfaces/IERC7496.sol
import {IERC721} from '@openzeppelin/token/ERC721/IERC721.sol';
/**
* @title Adds support for ERC7496 to an existing ERC721
- * @author OpenFi Foundation
+ * @author daopunk, MrDeadCe11, pi0neerpat, CupOJoseph
* @notice IERC7496 events are never emitted since NFVState is tracked in Vault721
*/
diff --git a/src/sips/SIP15Decoder.sol b/src/sips/SIP15Decoder.sol
index 287e57a..b0a43c3 100644
--- a/src/sips/SIP15Decoder.sol
+++ b/src/sips/SIP15Decoder.sol
@@ -8,12 +8,18 @@ library SIP15Decoder {
/**
* @notice Read the SIP15 substandard version byte from the extraData field of a SIP15 encoded bytes array.
* @param extraData bytes calldata
+ * @return substandard the single byte substandard number 0-5
*/
function decodeSubstandardVersion(bytes calldata extraData) internal pure returns (bytes1 substandard) {
return BaseSIPDecoder.decodeSubstandardVersion(extraData);
}
+ /**
+ * @notice decodes data encoding with substandard1Efficient encoder
+ * @param extraData the encoded bytes with substandard and the extra data
+ * @return (uint8 comparisonEnum, address token, uint256 identifier, bytes32 traitValue, bytes32 traitKey)
+ */
- function decodeSubstandard1(bytes calldata extraData)
+ function decodeSubstandard1Efficient(bytes calldata extraData)
internal
pure
returns (uint8, address, uint256, bytes32, bytes32)
@@ -21,7 +27,12 @@ library SIP15Decoder {
return _decodeSingleTraitsWithOffset(extraData, 1);
}
- function decodeSubstandard1Efficient(bytes calldata extraData)
+ /**
+ * @notice decodes data encoding with substandard1 encoder
+ * @param extraData the encoded bytes with substandard and the extra data
+ * @return (uint8 comparisonEnum, address token, uint256 identifier, bytes32 traitValue, bytes32 traitKey)
+ */
+ function decodeSubstandard1(bytes calldata extraData)
internal
pure
returns (uint8, address, uint256, bytes32, bytes32)
@@ -29,6 +40,11 @@ library SIP15Decoder {
return _decodeSingleTraitsWithOffset(extraData, 1);
}
+ /**
+ * @notice decodes data encoding with substandard2 encoder
+ * @param extraData the encoded bytes with substandard and the extra data
+ * @return (uint8 comparisonEnum, address token, uint256 identifier, bytes32 traitValue, bytes32 traitKey)
+ */
function decodeSubstandard2(bytes calldata extraData)
internal
pure
@@ -37,6 +53,11 @@ library SIP15Decoder {
return _decodeSingleTraitsWithOffset(extraData, 1);
}
+ /**
+ * @notice decodes data encoding with substandard3 encoder
+ * @param extraData the encoded bytes with substandard and the extra data
+ * @return (uint8 comparisonEnum, address token, uint256 identifier, bytes32 traitValue, bytes32 traitKey)
+ */
function decodeSubstandard3(bytes calldata extraData)
internal
pure
@@ -45,6 +66,11 @@ library SIP15Decoder {
return _decodeSingleTraitsWithOffset(extraData, 1);
}
+ /**
+ * @notice decodes data encoding with substandard4 encoder
+ * @param extraData the encoded bytes with substandard and the extra data
+ * @return (uint8 comparisonEnum, address token, uint256[] identifiers, bytes32 traitValue, bytes32 traitKey)
+ */
function decodeSubstandard4(bytes calldata extraData)
internal
pure
@@ -53,6 +79,11 @@ library SIP15Decoder {
return abi.decode(extraData[1:], (uint8, address, uint256[], bytes32, bytes32));
}
+ /**
+ * @notice decodes data encoding with substandard1 encoder
+ * @param extraData the encoded bytes with substandard and the extra data
+ * @return Substandard5Comparison
+ */
function decodeSubstandard5(bytes calldata extraData) internal pure returns (Substandard5Comparison memory) {
return abi.decode(extraData[1:], (Substandard5Comparison));
}
diff --git a/src/sips/SIP15Encoder.sol b/src/sips/SIP15Encoder.sol
index a728d11..1cab67f 100644
--- a/src/sips/SIP15Encoder.sol
+++ b/src/sips/SIP15Encoder.sol
@@ -18,6 +18,7 @@ library SIP15Encoder {
/**
* @notice Generate a zone hash for an SIP15 contract,
* @param encodedData the SIP15 encoded extra data
+ * @return bytes32 hashed encoded data
*/
function generateZoneHash(bytes memory encodedData) internal pure returns (bytes32) {
return keccak256(abi.encodePacked(encodedData));
@@ -26,7 +27,9 @@ library SIP15Encoder {
/**
* @notice Encode extraData for SIP15-substandard-1 Efficient, which specifies the
* first consideration item, comparison "equal to", single trait key, zero trait value
+ * @param zoneParameters the orderParams of the order to be encoded
* @param traitKey the bytes32 encoded trait key for checking a trait on an ERC7496 token
+ * @return bytes the encoded extra data with added substandard
*/
function encodeSubstandard1Efficient(
ZoneParameters memory zoneParameters,
@@ -42,10 +45,12 @@ library SIP15Encoder {
/**
* @notice Encode extraData for SIP15-substandard-1, which specifies the
- * first offer item, token address and id from first offer item
+ * token address and id from first offer item
+ * @param zoneParameters the zone parameters with the offer to be used for the token and identifier
* @param comparisonEnum the comparison enum 0 - 5
* @param traitKey the bytes32 encoded trait key for checking a trait on an ERC7496 token
* @param traitValue the expected value of the trait.
+ * @return bytes the encoded extra data with added substandard
*/
function encodeSubstandard1(
ZoneParameters memory zoneParameters,
@@ -63,11 +68,12 @@ library SIP15Encoder {
/**
* @notice Encode extraData for SIP15-substandard-2, which specifies
- * the token and identifier from the first consideration item as well as a comparison enum, trait key and trait value
- * @param zoneParameters memory zoneParameters,
+ * the token and identifier from the first consideration item as well as a comparison enum, trait key and expected trait value
+ * @param zoneParameters the zoneParameters of the order whose first consideration will be used for the token and identifier
* @param comparisonEnum The comparison enum 0 - 5
* @param traitValue The expecta value of the trait
* @param traitKey the bytes32 encoded trait key for checking a trait on an ERC7496 token
+ * @return bytes the encoded extra data with added substandard
*/
function encodeSubstandard2(
ZoneParameters memory zoneParameters,
@@ -91,6 +97,7 @@ library SIP15Encoder {
* @param identifier the tokenId of the token to be checked
* @param traitKey the bytes32 encoded trait key for checking a trait on an ERC7496 token
* @param traitValue the expected value of the trait.
+ * @return bytes the encoded extra data with added substandard
*/
function encodeSubstandard3(
uint8 comparisonEnum,
@@ -111,6 +118,7 @@ library SIP15Encoder {
* @param identifiers the tokenId of the token to be checked
* @param traitKey the bytes32 encoded trait key for checking a trait on an ERC7496 token
* @param traitValue the expected value of the trait.
+ * @return bytes the encoded extra data with added substandard
*/
function encodeSubstandard4(
uint8 comparisonEnum,
@@ -124,7 +132,15 @@ library SIP15Encoder {
/**
* @notice Encode extraData for SIP15-substandard-5, which specifies a single tokenIdentifier
- * @param comparisonStruct the struct of comparison data
+ * @param comparisonStruct the struct of comparison data with the following values:
+ * - uint8[] comparisonEnums the array of comparison enums for each trait key and expected value, must be the same length as the trait keys and values.
+ * - address token the address of the token whose traits will be checked
+ * - address traits the address that contains the ERC7496 traits. this is useful if you have an erc712 with traits availible at a
+ * different address leave as address(0) if the traits can be retreived from the same address as the token
+ * - uint256 identifier the identifier of the token to be checked;
+ * - bytes32[] traitValues the array of expected trait values
+ * - bytes32[] traitKeys the encoded trait keys ;
+ * @return bytes the encoded extra data with added substandard
*/
function encodeSubstandard5(Substandard5Comparison memory comparisonStruct) internal pure returns (bytes memory) {
return abi.encodePacked(uint8(0x05), abi.encode(comparisonStruct));
diff --git a/test/e2e/SetUp.sol b/test/e2e/SetUp.sol
index 96dad1f..bc68bb4 100644
--- a/test/e2e/SetUp.sol
+++ b/test/e2e/SetUp.sol
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.24;
-import {DeployForTest, ODTest, COLLAT, DEBT, TKN} from '@opendollar/test/e2e/Common.t.sol';
+import {DeployForTest, ODTest, TKN} from '@opendollar/test/e2e/Common.t.sol';
import {ERC20ForTest} from '@opendollar/test/mocks/ERC20ForTest.sol';
import {ISAFEEngine} from '@opendollar/interfaces/ISAFEEngine.sol';
import {BaseOrderTest} from 'seaport/test/foundry/utils/BaseOrderTest.sol';
diff --git a/test/e2e/TestTransferValidationSIP15ZoneOffererTest.t.sol b/test/e2e/TestTransferValidationSIP15ZoneOffererTest.t.sol
index 0d2accd..06e9535 100644
--- a/test/e2e/TestTransferValidationSIP15ZoneOffererTest.t.sol
+++ b/test/e2e/TestTransferValidationSIP15ZoneOffererTest.t.sol
@@ -7,14 +7,13 @@ import {
CriteriaResolver,
Fulfillment,
FulfillmentComponent,
- OrderParameters,
ItemType,
OfferItem,
Order,
OrderComponents,
OrderType
} from 'seaport-types/src/lib/ConsiderationStructs.sol';
-import {DeployForTest, ODTest, COLLAT, DEBT, TKN} from '@opendollar/test/e2e/Common.t.sol';
+import {ODTest, COLLAT, DEBT, TKN} from '@opendollar/test/e2e/Common.t.sol';
import {UnavailableReason} from 'seaport-sol/src/SpaceEnums.sol';
import {BaseOrderTest} from 'seaport/test/foundry/utils/BaseOrderTest.sol';
@@ -49,7 +48,6 @@ import {SIP15ZoneEventsAndErrors} from '../../src/interfaces/SIP15ZoneEventsAndE
import {SIP15Zone} from '../../src/contracts/SIP15Zone.sol';
import {SIP15Encoder, Substandard5Comparison} from '../../src/sips/SIP15Encoder.sol';
import {Math, RAY, WAD} from '@opendollar/libraries/Math.sol';
-import 'forge-std/console2.sol';
contract TestTransferValidationSIP15ZoneOffererTest is SetUp {
using Math for uint256;