-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
3f66a7d
commit 67e750f
Showing
14 changed files
with
687 additions
and
2 deletions.
There are no files selected for viewing
Submodule forge-std
updated
24 files
+193 −0 | CONTRIBUTING.md | |
+17 −1 | README.md | |
+1 −1 | package.json | |
+12 −1 | scripts/vm.py | |
+4 −0 | src/StdChains.sol | |
+3 −3 | src/StdCheats.sol | |
+104 −0 | src/StdJson.sol | |
+1 −1 | src/StdStorage.sol | |
+104 −0 | src/StdToml.sol | |
+388 −73 | src/Vm.sol | |
+471 −463 | src/console.sol | |
+2 −2 | src/interfaces/IERC4626.sol | |
+693 −4 | src/safeconsole.sol | |
+1 −1 | test/StdAssertions.t.sol | |
+14 −12 | test/StdChains.t.sol | |
+10 −10 | test/StdCheats.t.sol | |
+12 −12 | test/StdError.t.sol | |
+1 −1 | test/StdJson.t.sol | |
+4 −14 | test/StdMath.t.sol | |
+13 −5 | test/StdStorage.t.sol | |
+1 −1 | test/StdStyle.t.sol | |
+1 −1 | test/StdToml.t.sol | |
+12 −12 | test/StdUtils.t.sol | |
+9 −6 | test/Vm.t.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
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
83 changes: 83 additions & 0 deletions
83
src/tokens/ERC721/presets/operator-enforced/ERC721OperatorEnforced.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,83 @@ | ||
// SPDX-License-Identifier: Apache-2.0 | ||
pragma solidity ^0.8.19; | ||
|
||
import {ERC721Items} from "@0xsequence/contracts-library/tokens/ERC721/presets/items/ERC721Items.sol"; | ||
import {OperatorAllowlistEnforced} from | ||
"@0xsequence/contracts-library/tokens/common/immutable/OperatorAllowlistEnforced.sol"; | ||
import {ERC721A, IERC721A} from "erc721a/contracts/ERC721A.sol"; | ||
|
||
error InvalidInitialization(); | ||
|
||
/** | ||
* An implementation of ERC-721 that enforces an operator allowlist. | ||
* See {OperatorAllowlistEnforced} for more details. | ||
*/ | ||
contract ERC721OperatorEnforced is ERC721Items, OperatorAllowlistEnforced { | ||
constructor() ERC721Items() {} | ||
|
||
/** | ||
* Initialize contract. | ||
* @param owner The owner of the contract | ||
* @param tokenName Name of the token | ||
* @param tokenSymbol Symbol of the token | ||
* @param tokenBaseURI Base URI of the token | ||
* @param tokenContractURI Contract URI of the token | ||
* @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) | ||
* @param operatorAllowlist Address of the operator allowlist | ||
* @dev This should be called immediately after deployment. | ||
*/ | ||
function initialize( | ||
address owner, | ||
string memory tokenName, | ||
string memory tokenSymbol, | ||
string memory tokenBaseURI, | ||
string memory tokenContractURI, | ||
address royaltyReceiver, | ||
uint96 royaltyFeeNumerator, | ||
address operatorAllowlist | ||
) public virtual { | ||
_setOperatorAllowlistRegistry(operatorAllowlist); | ||
ERC721Items.initialize( | ||
owner, tokenName, tokenSymbol, tokenBaseURI, tokenContractURI, royaltyReceiver, royaltyFeeNumerator | ||
); | ||
} | ||
|
||
// | ||
// Operator Allowlist | ||
// | ||
|
||
/** | ||
* Set the operator allowlist registry. | ||
* @param operatorAllowlist Address of the operator allowlist | ||
*/ | ||
function setOperatorAllowlistRegistry(address operatorAllowlist) external onlyRole(DEFAULT_ADMIN_ROLE) { | ||
_setOperatorAllowlistRegistry(operatorAllowlist); | ||
} | ||
|
||
/// @inheritdoc ERC721A | ||
function _approve(address to, uint256 tokenId, bool approvalCheck) internal override validateApproval(to) { | ||
super._approve(to, tokenId, approvalCheck); | ||
} | ||
|
||
/// @inheritdoc ERC721A | ||
function setApprovalForAll(address operator, bool approved) | ||
public | ||
override(ERC721A, IERC721A) | ||
validateApproval(operator) | ||
{ | ||
super.setApprovalForAll(operator, approved); | ||
} | ||
|
||
/// @inheritdoc ERC721A | ||
function _beforeTokenTransfers(address from, address to, uint256 startTokenId, uint256 quantity) | ||
internal | ||
override | ||
{ | ||
if (from != address(0)) { | ||
// Ignore validation on minting | ||
_validateTransfer(from, to); | ||
} | ||
super._beforeTokenTransfers(from, to, startTokenId, quantity); | ||
} | ||
} |
69 changes: 69 additions & 0 deletions
69
src/tokens/ERC721/presets/operator-enforced/ERC721OperatorEnforcedFactory.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,69 @@ | ||
// SPDX-License-Identifier: Apache-2.0 | ||
pragma solidity ^0.8.19; | ||
|
||
import { | ||
IERC721OperatorEnforcedFactory, | ||
IERC721OperatorEnforcedFactoryFunctions | ||
} from "@0xsequence/contracts-library/tokens/ERC721/presets/operator-enforced/IERC721OperatorEnforcedFactory.sol"; | ||
import {ERC721OperatorEnforced} from | ||
"@0xsequence/contracts-library/tokens/ERC721/presets/operator-enforced/ERC721OperatorEnforced.sol"; | ||
import {SequenceProxyFactory} from "@0xsequence/contracts-library/proxies/SequenceProxyFactory.sol"; | ||
|
||
/** | ||
* Deployer of ERC-721 Operator Enforced proxies. | ||
*/ | ||
contract ERC721OperatorEnforcedFactory is IERC721OperatorEnforcedFactory, SequenceProxyFactory { | ||
/** | ||
* Creates an ERC-721 Operator Enforced Factory. | ||
* @param factoryOwner The owner of the ERC-721 Operator Enforced Factory | ||
*/ | ||
constructor(address factoryOwner) { | ||
ERC721OperatorEnforced impl = new ERC721OperatorEnforced(); | ||
SequenceProxyFactory._initialize(address(impl), factoryOwner); | ||
} | ||
|
||
/// @inheritdoc IERC721OperatorEnforcedFactoryFunctions | ||
function deploy( | ||
address proxyOwner, | ||
address tokenOwner, | ||
string memory name, | ||
string memory symbol, | ||
string memory baseURI, | ||
string memory contractURI, | ||
address royaltyReceiver, | ||
uint96 royaltyFeeNumerator, | ||
address operatorAllowlist | ||
) external returns (address proxyAddr) { | ||
bytes32 salt = keccak256( | ||
abi.encode( | ||
tokenOwner, name, symbol, baseURI, contractURI, royaltyReceiver, royaltyFeeNumerator, operatorAllowlist | ||
) | ||
); | ||
proxyAddr = _createProxy(salt, proxyOwner, ""); | ||
ERC721OperatorEnforced(proxyAddr).initialize( | ||
tokenOwner, name, symbol, baseURI, contractURI, royaltyReceiver, royaltyFeeNumerator, operatorAllowlist | ||
); | ||
emit ERC721OperatorEnforcedDeployed(proxyAddr); | ||
return proxyAddr; | ||
} | ||
|
||
/// @inheritdoc IERC721OperatorEnforcedFactoryFunctions | ||
function determineAddress( | ||
address proxyOwner, | ||
address tokenOwner, | ||
string memory name, | ||
string memory symbol, | ||
string memory baseURI, | ||
string memory contractURI, | ||
address royaltyReceiver, | ||
uint96 royaltyFeeNumerator, | ||
address operatorAllowlist | ||
) external view returns (address proxyAddr) { | ||
bytes32 salt = keccak256( | ||
abi.encode( | ||
tokenOwner, name, symbol, baseURI, contractURI, royaltyReceiver, royaltyFeeNumerator, operatorAllowlist | ||
) | ||
); | ||
return _computeProxyAddress(salt, proxyOwner, ""); | ||
} | ||
} |
67 changes: 67 additions & 0 deletions
67
src/tokens/ERC721/presets/operator-enforced/IERC721OperatorEnforcedFactory.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,67 @@ | ||
// SPDX-License-Identifier: Apache-2.0 | ||
pragma solidity ^0.8.19; | ||
|
||
interface IERC721OperatorEnforcedFactoryFunctions { | ||
/** | ||
* Creates an ERC-721 Operator Enforced proxy. | ||
* @param proxyOwner The owner of the ERC-721 Operator Enforced proxy | ||
* @param tokenOwner The owner of the ERC-721 Operator Enforced implementation | ||
* @param name The name of the ERC-721 Operator Enforced proxy | ||
* @param symbol The symbol of the ERC-721 Operator Enforced proxy | ||
* @param baseURI The base URI of the ERC-721 Operator Enforced proxy | ||
* @param contractURI The contract URI of the ERC-721 Operator Enforced 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) | ||
* @param operatorAllowlist Address of the operator allowlist | ||
* @return proxyAddr The address of the ERC-721 Operator Enforced Proxy | ||
*/ | ||
function deploy( | ||
address proxyOwner, | ||
address tokenOwner, | ||
string memory name, | ||
string memory symbol, | ||
string memory baseURI, | ||
string memory contractURI, | ||
address royaltyReceiver, | ||
uint96 royaltyFeeNumerator, | ||
address operatorAllowlist | ||
) external returns (address proxyAddr); | ||
|
||
/** | ||
* Computes the address of a proxy instance. | ||
* @param proxyOwner The owner of the ERC-721 Operator Enforced proxy | ||
* @param tokenOwner The owner of the ERC-721 Operator Enforced implementation | ||
* @param name The name of the ERC-721 Operator Enforced proxy | ||
* @param symbol The symbol of the ERC-721 Operator Enforced proxy | ||
* @param baseURI The base URI of the ERC-721 Operator Enforced proxy | ||
* @param contractURI The contract URI of the ERC-721 Operator Enforced 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) | ||
* @param operatorAllowlist Address of the operator allowlist | ||
* @return proxyAddr The address of the ERC-721 Operator Enforced Proxy | ||
*/ | ||
function determineAddress( | ||
address proxyOwner, | ||
address tokenOwner, | ||
string memory name, | ||
string memory symbol, | ||
string memory baseURI, | ||
string memory contractURI, | ||
address royaltyReceiver, | ||
uint96 royaltyFeeNumerator, | ||
address operatorAllowlist | ||
) external returns (address proxyAddr); | ||
} | ||
|
||
interface IERC721OperatorEnforcedFactorySignals { | ||
/** | ||
* Event emitted when a new ERC-721 Operator Enforced proxy contract is deployed. | ||
* @param proxyAddr The address of the deployed proxy. | ||
*/ | ||
event ERC721OperatorEnforcedDeployed(address proxyAddr); | ||
} | ||
|
||
interface IERC721OperatorEnforcedFactory is | ||
IERC721OperatorEnforcedFactoryFunctions, | ||
IERC721OperatorEnforcedFactorySignals | ||
{} |
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,14 @@ | ||
// Copyright Immutable Pty Ltd 2018 - 2023 | ||
// SPDX-License-Identifier: Apache 2.0 | ||
pragma solidity 0.8.19; | ||
|
||
/** | ||
* @notice Required interface of an OperatorAllowlist compliant contract | ||
*/ | ||
interface IOperatorAllowlist { | ||
/** | ||
* @notice Returns true if an address is Allowlisted false otherwise | ||
* @param target the address to be checked against the Allowlist | ||
*/ | ||
function isAllowlisted(address target) external view returns (bool); | ||
} |
122 changes: 122 additions & 0 deletions
122
src/tokens/common/immutable/OperatorAllowlistEnforced.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,122 @@ | ||
// Copyright Immutable Pty Ltd 2018 - 2023 | ||
// SPDX-License-Identifier: Apache 2.0 | ||
// slither-disable-start calls-loop | ||
pragma solidity 0.8.19; | ||
|
||
// Allowlist Registry | ||
import {IOperatorAllowlist} from "./IOperatorAllowlist.sol"; | ||
|
||
// Interface | ||
import {IERC165} from "@openzeppelin/contracts/utils/introspection/ERC165.sol"; | ||
|
||
// Errors | ||
import {OperatorAllowlistEnforcementErrors} from "./OperatorAllowlistEnforcementErrors.sol"; | ||
|
||
/* | ||
OperatorAllowlistEnforced is an abstract contract that token contracts can inherit in order to set the | ||
address of the OperatorAllowlist registry that it will interface with, so that the token contract may | ||
enable the restriction of approvals and transfers to allowlisted users. | ||
OperatorAllowlistEnforced is not designed to be upgradeable or extended. | ||
*/ | ||
|
||
abstract contract OperatorAllowlistEnforced is OperatorAllowlistEnforcementErrors { | ||
/// ===== State Variables ===== | ||
|
||
/// @notice Interface that implements the `IOperatorAllowlist` interface | ||
IOperatorAllowlist public operatorAllowlist; | ||
|
||
/// ===== Events ===== | ||
|
||
/// @notice Emitted whenever the transfer Allowlist registry is updated | ||
event OperatorAllowlistRegistryUpdated(address oldRegistry, address newRegistry); | ||
|
||
/// ===== Modifiers ===== | ||
|
||
/** | ||
* @notice Internal function to validate an approval, according to whether the target is an EOA or Allowlisted | ||
* @param targetApproval the address of the approval target to be validated | ||
*/ | ||
modifier validateApproval(address targetApproval) { | ||
_validateApproval(targetApproval); | ||
_; | ||
} | ||
|
||
/** | ||
* @notice Internal function to validate an approval, according to whether the target is an EOA or Allowlisted | ||
* @param targetApproval the address of the approval target to be validated | ||
*/ | ||
function _validateApproval(address targetApproval) internal view { | ||
// Check for: | ||
// 1. approver is an EOA. Contract constructor is handled as transfers 'from' are blocked | ||
// 2. approver is address or bytecode is allowlisted | ||
if (msg.sender.code.length != 0 && !operatorAllowlist.isAllowlisted(msg.sender)) { | ||
revert ApproverNotInAllowlist(msg.sender); | ||
} | ||
|
||
// Check for: | ||
// 1. approval target is an EOA | ||
// 2. approval target address is Allowlisted or target address bytecode is Allowlisted | ||
if (targetApproval.code.length != 0 && !operatorAllowlist.isAllowlisted(targetApproval)) { | ||
revert ApproveTargetNotInAllowlist(targetApproval); | ||
} | ||
} | ||
|
||
/** | ||
* @notice Internal function to validate a transfer, according to whether the calling address, | ||
* from address and to address is an EOA or Allowlisted | ||
* @param from the address of the from target to be validated | ||
* @param to the address of the to target to be validated | ||
*/ | ||
modifier validateTransfer(address from, address to) { | ||
_validateTransfer(from, to); | ||
_; | ||
} | ||
|
||
/** | ||
* @notice Internal function to validate a transfer, according to whether the calling address, | ||
* from address and to address is an EOA or Allowlisted | ||
* @param from the address of the from target to be validated | ||
* @param to the address of the to target to be validated | ||
*/ | ||
function _validateTransfer(address from, address to) internal view { | ||
// Check for: | ||
// 1. caller is an EOA | ||
// 2. caller is Allowlisted or is the calling address bytecode is Allowlisted | ||
if ( | ||
msg.sender != tx.origin // solhint-disable-line avoid-tx-origin | ||
&& !operatorAllowlist.isAllowlisted(msg.sender) | ||
) { | ||
revert CallerNotInAllowlist(msg.sender); | ||
} | ||
|
||
// Check for: | ||
// 1. from is an EOA | ||
// 2. from is Allowlisted or from address bytecode is Allowlisted | ||
if (from.code.length != 0 && !operatorAllowlist.isAllowlisted(from)) { | ||
revert TransferFromNotInAllowlist(from); | ||
} | ||
|
||
// Check for: | ||
// 1. to is an EOA | ||
// 2. to is Allowlisted or to address bytecode is Allowlisted | ||
if (to.code.length != 0 && !operatorAllowlist.isAllowlisted(to)) { | ||
revert TransferToNotInAllowlist(to); | ||
} | ||
} | ||
|
||
/// ===== External functions ===== | ||
|
||
/** | ||
* @notice Internal function to set the operator allowlist the calling contract will interface with | ||
* @param _operatorAllowlist the address of the Allowlist registry | ||
*/ | ||
function _setOperatorAllowlistRegistry(address _operatorAllowlist) internal { | ||
if (!IERC165(_operatorAllowlist).supportsInterface(type(IOperatorAllowlist).interfaceId)) { | ||
revert AllowlistDoesNotImplementIOperatorAllowlist(); | ||
} | ||
|
||
emit OperatorAllowlistRegistryUpdated(address(operatorAllowlist), _operatorAllowlist); | ||
operatorAllowlist = IOperatorAllowlist(_operatorAllowlist); | ||
} | ||
} | ||
// slither-disable-end calls-loop |
Oops, something went wrong.