Skip to content
Draft
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
1 change: 1 addition & 0 deletions contracts/access/MintingAccessControl.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {AccessControlEnumerable} from "@openzeppelin/contracts/access/AccessCont

abstract contract MintingAccessControl is AccessControlEnumerable {
/// @notice Role to mint tokens
// forge-lint: disable-next-line(unsafe-typecast)
bytes32 public constant MINTER_ROLE = bytes32("MINTER_ROLE");

/**
Expand Down
89 changes: 49 additions & 40 deletions contracts/allowlist/OperatorAllowlistEnforced.sol
Original file line number Diff line number Diff line change
@@ -1,42 +1,68 @@
// Copyright Immutable Pty Ltd 2018 - 2023
// Copyright Immutable Pty Ltd 2018 - 2026
// SPDX-License-Identifier: Apache 2.0
// slither-disable-start calls-loop
pragma solidity >=0.8.19 <0.8.29;

// Allowlist Registry
import {IOperatorAllowlist} from "./IOperatorAllowlist.sol";

// Interface
import {IERC165} from "@openzeppelin/contracts/utils/introspection/ERC165.sol";

// Errors
import {OperatorAllowlistEnforcementErrors} from "../errors/Errors.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.
*/

/**
* @notice 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 Emitted whenever the transfer Allowlist registry is updated
event OperatorAllowlistRegistryUpdated(address oldRegistry, address newRegistry);

/// @notice Interface that implements the `IOperatorAllowlist` interface
IOperatorAllowlist public operatorAllowlist;

/// ===== Events =====
/**
* @notice 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) {
// Note: the validity checks are in a separate function so that if the modifier is
// used for multiple functions, the check code isn't copied for each function.
_validateApproval(targetApproval);
_;
}

/// @notice Emitted whenever the transfer Allowlist registry is updated
event OperatorAllowlistRegistryUpdated(address oldRegistry, address newRegistry);
/**
* @notice 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) {
// Note: the validity checks are in a separate function so that if the modifier is
// used for multiple functions, the check code isn't copied for each function.
_validateTransfer(from, to);
_;
}

/**
* @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();
}

/// ===== Modifiers =====
emit OperatorAllowlistRegistryUpdated(address(operatorAllowlist), _operatorAllowlist);
operatorAllowlist = IOperatorAllowlist(_operatorAllowlist);
}

/**
* @notice Internal function to validate an approval, according to whether the target is an EOA or Allowlisted
* @notice 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) {
function _validateApproval(address targetApproval) private 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
Expand All @@ -50,16 +76,15 @@ abstract contract OperatorAllowlistEnforced is OperatorAllowlistEnforcementError
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
* @notice 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) {
function _validateTransfer(address from, address to) private view {
// Check for:
// 1. caller is an EOA
// 2. caller is Allowlisted or is the calling address bytecode is Allowlisted
Expand All @@ -83,22 +108,6 @@ abstract contract OperatorAllowlistEnforced is OperatorAllowlistEnforcementError
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
2 changes: 2 additions & 0 deletions contracts/allowlist/OperatorAllowlistUpgradeable.sol
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,11 @@ contract OperatorAllowlistUpgradeable is
/// ===== State Variables =====

/// @notice Only REGISTRAR_ROLE can invoke white listing registration and removal
// forge-lint: disable-next-line(unsafe-typecast)
bytes32 public constant REGISTRAR_ROLE = bytes32("REGISTRAR_ROLE");

/// @notice Only UPGRADE_ROLE can upgrade the contract
// forge-lint: disable-next-line(unsafe-typecast)
bytes32 public constant UPGRADE_ROLE = bytes32("UPGRADE_ROLE");

/// @notice Mapping of Allowlisted addresses
Expand Down
6 changes: 3 additions & 3 deletions contracts/deployer/create/OwnableCreateDeploy.sol
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ pragma solidity >=0.8.19 <0.8.29;
*/
contract OwnableCreateDeploy {
// Address that is authorised to call the deploy function.
address private immutable owner;
address private immutable OWNER;

constructor() {
owner = msg.sender;
OWNER = msg.sender;
}
/**
* @dev Deploys a new contract with the specified bytecode using the `CREATE` opcode.
Expand All @@ -24,7 +24,7 @@ contract OwnableCreateDeploy {
// slither-disable-next-line locked-ether
function deploy(bytes memory bytecode) external payable {
// solhint-disable-next-line custom-errors, reason-string
require(msg.sender == owner, "CreateDeploy: caller is not the owner");
require(msg.sender == OWNER, "CreateDeploy: caller is not the owner");
// solhint-disable no-inline-assembly
assembly {
if iszero(create(callvalue(), add(bytecode, 32), mload(bytecode))) {
Expand Down
6 changes: 3 additions & 3 deletions contracts/deployer/create3/OwnableCreate3Address.sol
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@ import {OwnableCreateDeploy} from "../create/OwnableCreateDeploy.sol";
*/
abstract contract OwnableCreate3Address {
/// @dev bytecode hash of the CreateDeploy helper contract
bytes32 internal immutable createDeployBytecodeHash;
bytes32 internal immutable CREATE_DEPLOY_BYTECODE_HASH;

constructor() {
// Slither is mistakenly seeing the expansion of type(OwnableCreateDeploy).creationCode
// as a very large number.
// slither-disable-next-line too-many-digits
createDeployBytecodeHash = keccak256(type(OwnableCreateDeploy).creationCode);
CREATE_DEPLOY_BYTECODE_HASH = keccak256(type(OwnableCreateDeploy).creationCode);
}

/**
Expand All @@ -28,7 +28,7 @@ abstract contract OwnableCreate3Address {
*/
function _create3Address(bytes32 deploySalt) internal view returns (address deployed) {
address deployer = address(
uint160(uint256(keccak256(abi.encodePacked(hex"ff", address(this), deploySalt, createDeployBytecodeHash))))
uint160(uint256(keccak256(abi.encodePacked(hex"ff", address(this), deploySalt, CREATE_DEPLOY_BYTECODE_HASH))))
);

deployed = address(uint160(uint256(keccak256(abi.encodePacked(hex"d694", deployer, hex"01")))));
Expand Down
6 changes: 3 additions & 3 deletions contracts/mocks/MockDisguisedEOA.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,17 @@ import {IERC721} from "@openzeppelin/contracts/token/ERC721/IERC721.sol";

// Used in CREATE2 vector
contract MockDisguisedEOA {
IERC721 public immutable tokenAddress;
IERC721 public immutable TOKEN_ADDRESS;

constructor(IERC721 _tokenAddress) {
tokenAddress = _tokenAddress;
TOKEN_ADDRESS = _tokenAddress;
}

/// @notice This code is only for testing purposes. Do not use similar
/// @notice constructions in production code as they are open to attack.
/// @dev For details see: https://github.com/crytic/slither/wiki/Detector-Documentation#arbitrary-from-in-transferfrom
function executeTransfer(address from, address recipient, uint256 _tokenId) external {
// slither-disable-next-line arbitrary-send-erc20
tokenAddress.transferFrom(from, recipient, _tokenId);
TOKEN_ADDRESS.transferFrom(from, recipient, _tokenId);
}
}
6 changes: 3 additions & 3 deletions contracts/mocks/MockEIP1271Wallet.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,16 @@ import {IERC1271} from "@openzeppelin/contracts/interfaces/IERC1271.sol";
import {IERC721Receiver} from "@openzeppelin/contracts/interfaces/IERC721Receiver.sol";

contract MockEIP1271Wallet is IERC1271 {
address public immutable owner;
address public immutable OWNER;

constructor(address _owner) {
// slither-disable-next-line missing-zero-check
owner = _owner;
OWNER = _owner;
}

function isValidSignature(bytes32 hash, bytes memory signature) public view override returns (bytes4) {
address recoveredAddress = ECDSA.recover(hash, signature);
if (recoveredAddress == owner) {
if (recoveredAddress == OWNER) {
return this.isValidSignature.selector;
} else {
return 0;
Expand Down
18 changes: 9 additions & 9 deletions contracts/mocks/MockMarketplace.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,28 +7,28 @@ import {IERC2981} from "@openzeppelin/contracts/interfaces/IERC2981.sol";
contract MockMarketplace {
error ZeroAddress();

IERC721 public immutable tokenAddress;
IERC2981 public immutable royaltyAddress;
IERC721 public immutable TOKEN_ADDRESS;
IERC2981 public immutable ROYALTY_ADDRESS;

constructor(address _tokenAddress) {
tokenAddress = IERC721(_tokenAddress);
royaltyAddress = IERC2981(_tokenAddress);
TOKEN_ADDRESS = IERC721(_tokenAddress);
ROYALTY_ADDRESS = IERC2981(_tokenAddress);
}

function executeTransfer(address recipient, uint256 _tokenId) public {
tokenAddress.transferFrom(msg.sender, recipient, _tokenId);
TOKEN_ADDRESS.transferFrom(msg.sender, recipient, _tokenId);
}

/// @notice This code is only for testing purposes. Do not use similar
/// @notice constructions in production code as they are open to attack.
/// @dev For details see: https://github.com/crytic/slither/wiki/Detector-Documentation#arbitrary-from-in-transferfrom
function executeTransferFrom(address from, address to, uint256 _tokenId) public {
// slither-disable-next-line arbitrary-send-erc20
tokenAddress.transferFrom(from, to, _tokenId);
TOKEN_ADDRESS.transferFrom(from, to, _tokenId);
}

function executeApproveForAll(address operator, bool approved) public {
tokenAddress.setApprovalForAll(operator, approved);
TOKEN_ADDRESS.setApprovalForAll(operator, approved);
}

/// @notice This code is only for testing purposes. Do not use similar
Expand All @@ -40,14 +40,14 @@ contract MockMarketplace {
}
// solhint-disable-next-line custom-errors
require(msg.value == price, "insufficient msg.value");
(address receiver, uint256 royaltyAmount) = royaltyAddress.royaltyInfo(_tokenId, price);
(address receiver, uint256 royaltyAmount) = ROYALTY_ADDRESS.royaltyInfo(_tokenId, price);
if (receiver == address(0)) {
revert ZeroAddress();
}
uint256 sellerAmt = msg.value - royaltyAmount;
payable(receiver).transfer(royaltyAmount);
payable(from).transfer(sellerAmt);
// slither-disable-next-line arbitrary-send-erc20
tokenAddress.transferFrom(from, recipient, _tokenId);
TOKEN_ADDRESS.transferFrom(from, recipient, _tokenId);
}
}
10 changes: 5 additions & 5 deletions contracts/mocks/MockOnReceive.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ pragma solidity >=0.8.19 <0.8.29;
import {IERC721} from "@openzeppelin/contracts/token/ERC721/IERC721.sol";

contract MockOnReceive {
IERC721 public immutable tokenAddress;
address private immutable recipient;
IERC721 public immutable TOKEN_ADDRESS;
address private immutable RECIPIENT;

// slither-disable-next-line missing-zero-check
constructor(IERC721 _tokenAddress, address _recipient) {
tokenAddress = _tokenAddress;
recipient = _recipient;
TOKEN_ADDRESS = _tokenAddress;
RECIPIENT = _recipient;
}

// Attempt to transfer token to another address on receive
Expand All @@ -20,7 +20,7 @@ contract MockOnReceive {
/* from */ uint256 tokenId,
bytes calldata /* data */
) public returns (bytes4) {
tokenAddress.transferFrom(address(this), recipient, tokenId);
TOKEN_ADDRESS.transferFrom(address(this), RECIPIENT, tokenId);
return this.onERC721Received.selector;
}
}
1 change: 1 addition & 0 deletions contracts/multicall/GuardedMulticaller2.sol
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ contract GuardedMulticaller2 is AccessControl, ReentrancyGuard, EIP712 {
mapping(bytes32 ref => bool executed) private replayProtection;

/// @dev Only those with MULTICALL_SIGNER_ROLE can generate valid signatures for execute function.
// forge-lint: disable-next-line(unsafe-typecast)
bytes32 public constant MULTICALL_SIGNER_ROLE = bytes32("MULTICALL_SIGNER_ROLE");

/// @dev EIP712 typehash for call
Expand Down
2 changes: 2 additions & 0 deletions contracts/payment-splitter/PaymentSplitter.sol
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,11 @@ contract PaymentSplitter is AccessControlEnumerable, IPaymentSplitterErrors, Ree
event PaymentReceived(address from, uint256 amount);

/// @notice Role responsible for releasing funds
// forge-lint: disable-next-line(unsafe-typecast)
bytes32 public constant RELEASE_FUNDS_ROLE = bytes32("RELEASE_FUNDS_ROLE");

/// @notice Role responsible for registering tokens
// forge-lint: disable-next-line(unsafe-typecast)
bytes32 public constant TOKEN_REGISTRAR_ROLE = bytes32("TOKEN_REGISTRAR_ROLE");

/// @notice the totalshares held by payees
Expand Down
2 changes: 2 additions & 0 deletions contracts/staking/StakeHolderBase.sol
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,11 @@ abstract contract StakeHolderBase is
ReentrancyGuardUpgradeable
{
/// @notice Only UPGRADE_ROLE can upgrade the contract
// forge-lint: disable-next-line(unsafe-typecast)
bytes32 public constant UPGRADE_ROLE = bytes32("UPGRADE_ROLE");

/// @notice Only DISTRIBUTE_ROLE can call the distribute function
// forge-lint: disable-next-line(unsafe-typecast)
bytes32 public constant DISTRIBUTE_ROLE = bytes32("DISTRIBUTE_ROLE");

/// @notice Version 0 version number
Expand Down
2 changes: 1 addition & 1 deletion contracts/staking/StakeHolderWIMXV2.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache 2
pragma solidity >=0.8.19 <0.8.29;

import {IStakeHolder, StakeHolderBase, StakeHolderBaseV2, StakeHolderNativeV2} from "./StakeHolderNativeV2.sol";
import {IStakeHolder, StakeHolderBase, StakeHolderNativeV2} from "./StakeHolderNativeV2.sol";
import {IWIMX} from "./IWIMX.sol";

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {IImmutableERC20Errors} from "./Errors.sol";
*/
contract ImmutableERC20MinterBurnerPermit is ERC20Capped, ERC20Burnable, ERC20Permit, MintingAccessControl {
/// @notice Role to mint tokens
// forge-lint: disable-next-line(unsafe-typecast)
bytes32 public constant HUB_OWNER_ROLE = bytes32("HUB_OWNER_ROLE");

/**
Expand Down
2 changes: 2 additions & 0 deletions contracts/token/erc721/abstract/ERC721Hybrid.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import {ERC721Psi, ERC721PsiBurnable} from "../erc721psi/ERC721PsiBurnable.sol";
// Errors
import {IImmutableERC721Errors} from "../../../errors/Errors.sol";

// forge-lint: disable-start(pascal-case-struct)

/*
This contract allows for minting with one of two strategies:
- ERC721: minting with specified tokenIDs (inefficient)
Expand Down
3 changes: 3 additions & 0 deletions contracts/token/erc721/abstract/ImmutableERC721Base.sol
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ import {OperatorAllowlistEnforced} from "../../../allowlist/OperatorAllowlistEnf
import {BitMaps} from "@openzeppelin/contracts/utils/structs/BitMaps.sol";
import {AccessControlEnumerable, MintingAccessControl} from "../../../access/MintingAccessControl.sol";


// forge-lint: disable-start(pascal-case-struct)

/*
ImmutableERC721Base is an abstract contract that offers minimum preset functionality without
an opinionated form of minting. This contract is intended to be inherited and implement its
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ abstract contract ImmutableERC721HybridBase is
* @notice sets the contract uri for the collection. Permissioned to only the admin role
* @param _contractURI the new baseURI to set
*/
// solhint-disable-next-line mixed-case-function
function setContractURI(string memory _contractURI) public onlyRole(DEFAULT_ADMIN_ROLE) {
contractURI = _contractURI;
}
Expand Down
Loading