Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ERC721C capability to ERC721Items #18

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,6 @@
[submodule "lib/openzeppelin-contracts-upgradeable"]
path = lib/openzeppelin-contracts-upgradeable
url = https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable
[submodule "lib/creator-token-standards"]
path = lib/creator-token-standards
url = https://github.com/limitbreakinc/creator-token-standards
5 changes: 3 additions & 2 deletions foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@
src = 'src'
out = 'out'
libs = ['lib']
solc = "0.8.19"
solc-version = "0.8.19"
solc = "0.8.24"
solc-version = "0.8.24"
evm_version = "cancun"
via_ir = true
optimizer-runs = 20_000

Expand Down
1 change: 1 addition & 0 deletions lib/creator-token-standards
1 change: 1 addition & 0 deletions remappings.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ erc721a-upgradeable/=lib/chiru-labs/erc721a-upgradeable/
@openzeppelin/=lib/openzeppelin/
@openzeppelin-upgradeable/=lib/openzeppelin-contracts-upgradeable/
solady/=lib/solady/src/
@limitbreak/creator-token-standards/=lib/creator-token-standards/src/
2 changes: 2 additions & 0 deletions scripts/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ export const BUILD_DIR = 'build'
export const DEPLOYABLE_CONTRACT_NAMES = [
'ERC20ItemsFactory',
'ERC721ItemsFactory',
'ERC721CItemsFactory',
'ERC721SaleFactory',
'ERC1155ItemsFactory',
'ERC1155SaleFactory',
Expand All @@ -10,6 +11,7 @@ export const DEPLOYABLE_CONTRACT_NAMES = [
export const TOKEN_CONTRACT_NAMES = [
'ERC20Items',
'ERC721Items',
'ERC721CItems',
'ERC721Sale',
'ERC1155Items',
'ERC1155Sale',
Expand Down
86 changes: 86 additions & 0 deletions src/tokens/ERC721/presets/c_items/ERC721CItems.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.19;

import {ERC721Items} from "@0xsequence/contracts-library/tokens/ERC721/presets/items/ERC721Items.sol";
import {CreatorTokenBase, ICreatorToken} from "@limitbreak/creator-token-standards/utils/CreatorTokenBase.sol";
import {TOKEN_TYPE_ERC721} from "@limitbreak/permit-c/Constants.sol";

/**
* An implementation of ERC-721 capable of minting when role provided.
*/
contract ERC721CItems is ERC721Items, CreatorTokenBase {
bytes32 internal constant _TRANSFER_ADMIN_ROLE = keccak256("TRANSFER_ADMIN_ROLE");

/// @inheritdoc ERC721Items
function initialize(
address owner,
string memory tokenName,
string memory tokenSymbol,
string memory tokenBaseURI,
string memory tokenContractURI,
address royaltyReceiver,
uint96 royaltyFeeNumerator
) public virtual override {
_grantRole(_TRANSFER_ADMIN_ROLE, owner);

super.initialize(
owner, tokenName, tokenSymbol, tokenBaseURI, tokenContractURI, royaltyReceiver, royaltyFeeNumerator
);
}

function _tokenType() internal pure override returns (uint16) {
return uint16(TOKEN_TYPE_ERC721);
}

function _requireCallerIsContractOwner() internal view override {
_checkRole(_TRANSFER_ADMIN_ROLE);
}

function getTransferValidationFunction() external pure returns (bytes4 functionSignature, bool isViewFunction) {
functionSignature = bytes4(keccak256("validateTransfer(address,address,address,uint256)"));
isViewFunction = true;
}

/* FIXME
/// @inheritdoc CreatorTokenBase
function getTransferValidator() public view override returns (address validator) {
validator = transferValidator;
// Do not use the default validator
}
*/

function _beforeTokenTransfers(
address from,
address to,
uint256 startTokenId,
uint256 quantity) internal virtual override {
for (uint256 i = 0; i < quantity;) {
_validateBeforeTransfer(from, to, startTokenId + i);
unchecked {
++i;
}
}
}

function _afterTokenTransfers(
address from,
address to,
uint256 startTokenId,
uint256 quantity) internal virtual override {
for (uint256 i = 0; i < quantity;) {
_validateAfterTransfer(from, to, startTokenId + i);
unchecked {
++i;
}
}
}

/**
* Check interface support.
* @param interfaceId Interface id
* @return True if supported
*/
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return type(ICreatorToken).interfaceId == interfaceId || super.supportsInterface(interfaceId);
}
}
60 changes: 60 additions & 0 deletions src/tokens/ERC721/presets/c_items/ERC721CItemsFactory.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.19;

import {IERC721CItemsFactory, IERC721CItemsFactoryFunctions} from
"@0xsequence/contracts-library/tokens/ERC721/presets/c_items/IERC721CItemsFactory.sol";
import {ERC721CItems} from "@0xsequence/contracts-library/tokens/ERC721/presets/c_items/ERC721CItems.sol";
import {SequenceProxyFactory} from "@0xsequence/contracts-library/proxies/SequenceProxyFactory.sol";

/**
* Deployer of ERC-721C Items proxies.
*/
contract ERC721CItemsFactory is IERC721CItemsFactory, SequenceProxyFactory {
/**
* Creates an ERC-721C Items Factory.
* @param factoryOwner The owner of the ERC-721C Items Factory
*/
constructor(address factoryOwner) {
ERC721CItems impl = new ERC721CItems();
SequenceProxyFactory._initialize(address(impl), factoryOwner);
}

/// @inheritdoc IERC721CItemsFactoryFunctions
function deploy(
address proxyOwner,
address tokenOwner,
string memory name,
string memory symbol,
string memory baseURI,
string memory contractURI,
address royaltyReceiver,
uint96 royaltyFeeNumerator
)
external
returns (address proxyAddr)
{
bytes32 salt =
keccak256(abi.encode(tokenOwner, name, symbol, baseURI, contractURI, royaltyReceiver, royaltyFeeNumerator));
proxyAddr = _createProxy(salt, proxyOwner, "");
ERC721CItems(proxyAddr).initialize(tokenOwner, name, symbol, baseURI, contractURI, royaltyReceiver, royaltyFeeNumerator);
emit ERC721CItemsDeployed(proxyAddr);
return proxyAddr;
}

/// @inheritdoc IERC721CItemsFactoryFunctions
function determineAddress(
address proxyOwner,
address tokenOwner,
string memory name,
string memory symbol,
string memory baseURI,
string memory contractURI,
address royaltyReceiver,
uint96 royaltyFeeNumerator
) external view returns (address proxyAddr)
{
bytes32 salt =
keccak256(abi.encode(tokenOwner, name, symbol, baseURI, contractURI, royaltyReceiver, royaltyFeeNumerator));
return _computeProxyAddress(salt, proxyOwner, "");
}
}
64 changes: 64 additions & 0 deletions src/tokens/ERC721/presets/c_items/IERC721CItemsFactory.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.19;

interface IERC721CItemsFactoryFunctions {
/**
* Creates an ERC-721C Items proxy.
* @param proxyOwner The owner of the ERC-721C Items proxy
* @param tokenOwner The owner of the ERC-721C Items implementation
* @param name The name of the ERC-721C Items proxy
* @param symbol The symbol of the ERC-721C Items proxy
* @param baseURI The base URI of the ERC-721C Items proxy
* @param contractURI The contract URI of the ERC-721C Items proxy
* @param royaltyReceiver Address of who should be sent the royalty payment
* @param royaltyFeeNumerator The royalty fee numerator in basis points (e.g. 15% would be 1500)
* @return proxyAddr The address of the ERC-721C Items Proxy
*/
function deploy(
address proxyOwner,
address tokenOwner,
string memory name,
string memory symbol,
string memory baseURI,
string memory contractURI,
address royaltyReceiver,
uint96 royaltyFeeNumerator
)
external
returns (address proxyAddr);

/**
* Computes the address of a proxy instance.
* @param proxyOwner The owner of the ERC-721C Items proxy
* @param tokenOwner The owner of the ERC-721C Items implementation
* @param name The name of the ERC-721C Items proxy
* @param symbol The symbol of the ERC-721C Items proxy
* @param baseURI The base URI of the ERC-721C Items proxy
* @param contractURI The contract URI of the ERC-721C Items proxy
* @param royaltyReceiver Address of who should be sent the royalty payment
* @param royaltyFeeNumerator The royalty fee numerator in basis points (e.g. 15% would be 1500)
* @return proxyAddr The address of the ERC-721C Items Proxy
*/
function determineAddress(
address proxyOwner,
address tokenOwner,
string memory name,
string memory symbol,
string memory baseURI,
string memory contractURI,
address royaltyReceiver,
uint96 royaltyFeeNumerator
)
external
returns (address proxyAddr);
}

interface IERC721CItemsFactorySignals {
/**
* Event emitted when a new ERC-721C Items proxy contract is deployed.
* @param proxyAddr The address of the deployed proxy.
*/
event ERC721CItemsDeployed(address proxyAddr);
}

interface IERC721CItemsFactory is IERC721CItemsFactoryFunctions, IERC721CItemsFactorySignals {}
9 changes: 9 additions & 0 deletions test/_mocks/WalletMock.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.19;

contract WalletMock {
function execute(address to, uint256 value, bytes memory data) external returns (bool, bytes memory) {
(bool success, bytes memory result) = to.call{value: value}(data);
return (success, result);
}
}
Loading
Loading