-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Add manifold marketplace API interfaces - Create a new version of nftc spec checker just for manifold stuff, and implement tests.
- Loading branch information
Showing
8 changed files
with
195 additions
and
2 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
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,41 @@ | ||
// SPDX-License-Identifier: MIT | ||
// Lifted from: https://github.com/delegatecash/delegation-registry/blob/main/src/IDelegationRegistry.sol | ||
pragma solidity ^0.8.11; | ||
|
||
interface ILazyDelivery { | ||
/** | ||
* @dev Deliver an asset and deliver to the specified party | ||
* When implementing this interface, please ensure you restrict access. | ||
* If using LazyDeliver.sol, you can use authorizedDelivererRequired modifier to restrict access. | ||
* Delivery can be for an existing asset or newly minted assets. | ||
* | ||
* @param listingId The listingId associated with this delivery. Useful for permissioning. | ||
* @param to The address to deliver the asset to | ||
* @param assetId The assetId to deliver | ||
* @param payableCount The number of assets to deliver | ||
* @param payableAmount The amount seller will receive upon delivery of asset | ||
* @param payableERC20 The erc20 token address of the amount (0x0 if ETH) | ||
* @param index (Optional): Index value for certain sales methods | ||
* | ||
* Suggestion: If determining a refund amount based on total sales data, do not enable this function | ||
* until the sales data is finalized and recorded in contract | ||
* | ||
* Exploit Prevention for dynamic/random assignment | ||
* 1. Ensure attributes are not assigned until AFTER underlying mint if using _safeMint. | ||
* This is to ensure a receiver cannot check attribute values on receive and revert transaction. | ||
* However, even if this is the case, the recipient can wrap its mint in a contract that checks | ||
* post mint completion and reverts if unsuccessful. | ||
* 2. Ensure that "to" is not a contract address. This prevents a contract from doing the lazy | ||
* mint, which could exploit random assignment by reverting if they do not receive the desired | ||
* item post mint. | ||
*/ | ||
function deliver( | ||
uint40 listingId, | ||
address to, | ||
uint256 assetId, | ||
uint24 payableCount, | ||
uint256 payableAmount, | ||
address payableERC20, | ||
uint256 index | ||
) external; | ||
} |
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,9 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.11; | ||
|
||
/** | ||
* Metadata for lazy delivery tokens | ||
*/ | ||
interface ILazyDeliveryMetadata { | ||
function assetURI(uint256 assetId) external view returns (string memory); | ||
} |
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,10 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.11; | ||
|
||
interface IPriceEngine { | ||
/** | ||
* @dev Determine price of an asset given the number | ||
* already minted. | ||
*/ | ||
function price(uint256 assetId, uint256 alreadyMinted, uint24 count) external view returns (uint256); | ||
} |
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
81 changes: 81 additions & 0 deletions
81
contracts/utility/introspection/NFTSpecCheckerManifold.sol
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,81 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.11; | ||
|
||
// Local References | ||
import '../../interfaces/manifoldxyz/ILazyDelivery.sol'; | ||
import '../../interfaces/manifoldxyz/ILazyDeliveryMetadata.sol'; | ||
import '../../interfaces/manifoldxyz/IPriceEngine.sol'; | ||
|
||
// OZ Libraries | ||
import '@openzeppelin/contracts/utils/introspection/ERC165Checker.sol'; | ||
|
||
/** | ||
* @title NFTSpecCheckerManifold | ||
* @author @NiftyMike | @NFTCulture | ||
* @dev Functionality to check a deployed contract against a list of Manifold specs. | ||
*/ | ||
contract NFTSpecCheckerManifold { | ||
using ERC165Checker for address; | ||
|
||
/// @dev See {ERC165Checker-supportsInterface} | ||
///> 0x01ffc9a7 | ||
bytes4 constant _ERC165_CONTRACT = type(IERC165).interfaceId; | ||
|
||
/// @dev See {ERC165Checker-supportsInterface} | ||
///> 0x8fb5170e | ||
bytes4 constant _ILAZYDELIVERY_CONTRACT = type(ILazyDelivery).interfaceId; | ||
///> 0xf1c68982 | ||
bytes4 constant _ILAZYDELIVERY_METADATA_CONTRACT = type(ILazyDeliveryMetadata).interfaceId; | ||
///> 0x8e027244 | ||
bytes4 constant _IPRICEENGINE_CONTRACT = type(IPriceEngine).interfaceId; | ||
|
||
function checkLazyDelivery(address targetContract) external view returns (bool) { | ||
return _checkContract(targetContract, _ILAZYDELIVERY_CONTRACT); | ||
} | ||
|
||
function getLazyDeliveryCode() external pure returns (string memory) { | ||
return bytes4ToString(_ILAZYDELIVERY_CONTRACT); | ||
} | ||
|
||
function checkLazyDeliveryMetadata(address targetContract) external view returns (bool) { | ||
return _checkContract(targetContract, _ILAZYDELIVERY_METADATA_CONTRACT); | ||
} | ||
|
||
function getLazyDeliveryMetadataCode() external pure returns (string memory) { | ||
return bytes4ToString(_ILAZYDELIVERY_METADATA_CONTRACT); | ||
} | ||
|
||
function checkPriceEngine(address targetContract) external view returns (bool) { | ||
return _checkContract(targetContract, _IPRICEENGINE_CONTRACT); | ||
} | ||
|
||
function getPriceEngineCode() external pure returns (string memory) { | ||
return bytes4ToString(_IPRICEENGINE_CONTRACT); | ||
} | ||
|
||
function _checkContract(address _contract, bytes4 interfaceId) internal view returns (bool) { | ||
if (_contract.supportsInterface(interfaceId)) { | ||
return true; | ||
} else { | ||
return false; | ||
} | ||
} | ||
|
||
function bytes4ToString(bytes4 _bytes) internal pure returns (string memory) { | ||
bytes memory byteArray = new bytes(8); | ||
for (uint256 i = 0; i < 4; i++) { | ||
uint8 currentByte = uint8(_bytes[i]); | ||
byteArray[i * 2] = toHexChar(currentByte / 16); | ||
byteArray[i * 2 + 1] = toHexChar(currentByte % 16); | ||
} | ||
return string(abi.encodePacked('0x', byteArray)); | ||
} | ||
|
||
function toHexChar(uint8 _value) internal pure returns (bytes1) { | ||
if (_value < 10) { | ||
return bytes1(uint8(bytes1('0')) + _value); | ||
} else { | ||
return bytes1(uint8(bytes1('a')) + _value - 10); | ||
} | ||
} | ||
} |
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
48 changes: 48 additions & 0 deletions
48
test/contracts/utility/introspection/NFTSpecCheckerManifold.test.ts
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,48 @@ | ||
import { Contract } from '@ethersproject/contracts'; | ||
import { expect } from 'chai'; | ||
import * as dotenv from 'dotenv'; | ||
import type * as ethers from 'ethers'; | ||
import hre from 'hardhat'; | ||
|
||
import { addHardhatSignersToContext } from '../../../../src'; | ||
|
||
dotenv.config(); | ||
|
||
const TESTHARNESS_CONTRACT_NAME = 'TemplateTestHarness'; | ||
const SPEC_CHECKER_CONTRACT_NAME = 'NFTSpecCheckerManifold'; | ||
|
||
let _testHarnessContractFactory: ethers.ContractFactory; | ||
let _specCheckerContractFactory: ethers.ContractFactory; | ||
|
||
let _testHarnessInstance: Contract; | ||
let _specCheckerInstance: Contract; | ||
|
||
// Start test block | ||
describe(`File:${__filename}\nContract: ${TESTHARNESS_CONTRACT_NAME}\n`, function () { | ||
before(async function () { | ||
_testHarnessContractFactory = await hre.ethers.getContractFactory(TESTHARNESS_CONTRACT_NAME); | ||
_specCheckerContractFactory = await hre.ethers.getContractFactory(SPEC_CHECKER_CONTRACT_NAME); | ||
}); | ||
|
||
beforeEach(async function () { | ||
_testHarnessInstance = await _testHarnessContractFactory.deploy(); | ||
_specCheckerInstance = await _specCheckerContractFactory.deploy(); | ||
}); | ||
|
||
addHardhatSignersToContext(); | ||
|
||
context('NFTC Spec Checker Manifold:', function () { | ||
it('uses valid interface codes', async function () { | ||
const lazyDeliveryCode = await _specCheckerInstance.connect(this.owner).getLazyDeliveryCode(); | ||
expect(lazyDeliveryCode).to.equal('0x8fb5170e'); | ||
|
||
const lazyDeliveryMetadataCode = await _specCheckerInstance | ||
.connect(this.owner) | ||
.getLazyDeliveryMetadataCode(); | ||
expect(lazyDeliveryMetadataCode).to.equal('0xf1c68982'); | ||
|
||
const priceEngineCode = await _specCheckerInstance.connect(this.owner).getPriceEngineCode(); | ||
expect(priceEngineCode).to.equal('0x8e027244'); | ||
}); | ||
}); | ||
}); |