Transaction Hash:
Block:
18674395 at Nov-29-2023 02:49:11 AM +UTC
Transaction Fee:
0.001620292082342362 ETH
$3.48
Gas Used:
49,486 Gas / 32.742433867 Gwei
Emitted Events:
| 275 |
TransferManager.ApprovalsGranted( user=[Sender] 0x10dc1d2f35992b28c5160c2f9fc9582735298d78, operators=[0xe7baC7d798D66D353b9e50EbFC6859950fE13Ce4] )
|
Account State Difference:
| Address | Before | After | State Difference | ||
|---|---|---|---|---|---|
| 0x00000000...4AdD29e1d | |||||
| 0x10DC1d2f...735298d78 |
3.827956423675458248 Eth
Nonce: 1366
|
3.826336131593115886 Eth
Nonce: 1367
| 0.001620292082342362 | ||
|
0x95222290...5CC4BAfe5
Miner
| (beaverbuild) | 9.982113811060067585 Eth | 9.982118759660067585 Eth | 0.0000049486 |
Execution Trace
TransferManager.grantApprovals( operators=[0xe7baC7d798D66D353b9e50EbFC6859950fE13Ce4] )
grantApprovals[TransferManager (ln:208)]
LengthsInvalid[TransferManager (ln:211)]OperatorNotAllowed[TransferManager (ln:216)]OperatorAlreadyApprovedByUser[TransferManager (ln:219)]ApprovalsGranted[TransferManager (ln:226)]
// SPDX-License-Identifier: MIT
pragma solidity 0.8.20;
// LooksRare unopinionated libraries
import {OwnableTwoSteps} from "@looksrare/contracts-libs/contracts/OwnableTwoSteps.sol";
import {LowLevelERC20Transfer} from "@looksrare/contracts-libs/contracts/lowLevelCallers/LowLevelERC20Transfer.sol";
import {LowLevelERC721Transfer} from "@looksrare/contracts-libs/contracts/lowLevelCallers/LowLevelERC721Transfer.sol";
import {LowLevelERC1155Transfer} from "@looksrare/contracts-libs/contracts/lowLevelCallers/LowLevelERC1155Transfer.sol";
// Interfaces and errors
import {ITransferManager} from "./interfaces/ITransferManager.sol";
import {AmountInvalid, LengthsInvalid} from "./errors/SharedErrors.sol";
// Enums
import {TokenType} from "./enums/TokenType.sol";
/**
* @title TransferManager
* @notice This contract provides the transfer functions for ERC20/ERC721/ERC1155 for contracts that require them.
* Token type "0" refers to ERC20 transfer functions.
* Token type "1" refers to ERC721 transfer functions.
* Token type "2" refers to ERC1155 transfer functions.
* @dev "Safe" transfer functions for ERC721 are not implemented since they come with added gas costs
* to verify if the recipient is a contract as it requires verifying the receiver interface is valid.
* @author LooksRare protocol team (👀,💎)
*/
contract TransferManager is
ITransferManager,
LowLevelERC20Transfer,
LowLevelERC721Transfer,
LowLevelERC1155Transfer,
OwnableTwoSteps
{
/**
* @notice This returns whether the user has approved the operator address.
* The first address is the user and the second address is the operator.
*/
mapping(address => mapping(address => bool)) public hasUserApprovedOperator;
/**
* @notice This returns whether the operator address is allowed by this contract's owner.
*/
mapping(address => bool) public isOperatorAllowed;
/**
* @notice Constructor
* @param _owner Owner address
*/
constructor(address _owner) OwnableTwoSteps(_owner) {}
/**
* @inheritdoc ITransferManager
*/
function transferERC20(
address tokenAddress,
address from,
address to,
uint256 amount
) external {
_isOperatorValidForTransfer(from, msg.sender);
if (amount == 0) {
revert AmountInvalid();
}
_executeERC20TransferFrom(tokenAddress, from, to, amount);
}
/**
* @inheritdoc ITransferManager
*/
function transferItemERC721(
address tokenAddress,
address from,
address to,
uint256 itemId
) external {
_isOperatorValidForTransfer(from, msg.sender);
_executeERC721TransferFrom(tokenAddress, from, to, itemId);
}
/**
* @inheritdoc ITransferManager
*/
function transferItemsERC721(
address tokenAddress,
address from,
address to,
uint256[] calldata itemIds,
uint256[] calldata amounts
) external {
uint256 length = itemIds.length;
if (length == 0 || amounts.length != length) {
revert LengthsInvalid();
}
_isOperatorValidForTransfer(from, msg.sender);
for (uint256 i; i < length; ) {
if (amounts[i] != 1) {
revert AmountInvalid();
}
_executeERC721TransferFrom(tokenAddress, from, to, itemIds[i]);
unchecked {
++i;
}
}
}
/**
* @inheritdoc ITransferManager
*/
function transferItemERC1155(
address tokenAddress,
address from,
address to,
uint256 itemId,
uint256 amount
) external {
_isOperatorValidForTransfer(from, msg.sender);
if (amount == 0) {
revert AmountInvalid();
}
_executeERC1155SafeTransferFrom(tokenAddress, from, to, itemId, amount);
}
/**
* @inheritdoc ITransferManager
*/
function transferItemsERC1155(
address tokenAddress,
address from,
address to,
uint256[] calldata itemIds,
uint256[] calldata amounts
) external {
uint256 length = itemIds.length;
if (length == 0 || amounts.length != length) {
revert LengthsInvalid();
}
_isOperatorValidForTransfer(from, msg.sender);
if (length == 1) {
if (amounts[0] == 0) {
revert AmountInvalid();
}
_executeERC1155SafeTransferFrom(tokenAddress, from, to, itemIds[0], amounts[0]);
} else {
for (uint256 i; i < length; ) {
if (amounts[i] == 0) {
revert AmountInvalid();
}
unchecked {
++i;
}
}
_executeERC1155SafeBatchTransferFrom(tokenAddress, from, to, itemIds, amounts);
}
}
/**
* @inheritdoc ITransferManager
*/
function transferBatchItemsAcrossCollections(
BatchTransferItem[] calldata items,
address from,
address to
) external {
uint256 itemsLength = items.length;
if (itemsLength == 0) {
revert LengthsInvalid();
}
if (from != msg.sender) {
_isOperatorValidForTransfer(from, msg.sender);
}
for (uint256 i; i < itemsLength; ) {
uint256[] calldata itemIds = items[i].itemIds;
uint256 itemIdsLengthForSingleCollection = itemIds.length;
uint256[] calldata amounts = items[i].amounts;
TokenType tokenType = items[i].tokenType;
if (tokenType == TokenType.ERC20) {
if (itemIdsLengthForSingleCollection != 0 || amounts.length != 1) {
revert LengthsInvalid();
}
} else {
if (itemIdsLengthForSingleCollection == 0 || amounts.length != itemIdsLengthForSingleCollection) {
revert LengthsInvalid();
}
}
if (tokenType == TokenType.ERC20) {
uint256 amount = amounts[0];
if (amount == 0) {
revert AmountInvalid();
}
_executeERC20TransferFrom(items[i].tokenAddress, from, to, amount);
} else if (tokenType == TokenType.ERC721) {
for (uint256 j; j < itemIdsLengthForSingleCollection; ) {
if (amounts[j] != 1) {
revert AmountInvalid();
}
_executeERC721TransferFrom(items[i].tokenAddress, from, to, itemIds[j]);
unchecked {
++j;
}
}
} else if (tokenType == TokenType.ERC1155) {
for (uint256 j; j < itemIdsLengthForSingleCollection; ) {
if (amounts[j] == 0) {
revert AmountInvalid();
}
unchecked {
++j;
}
}
_executeERC1155SafeBatchTransferFrom(items[i].tokenAddress, from, to, itemIds, amounts);
}
unchecked {
++i;
}
}
}
/**
* @inheritdoc ITransferManager
*/
function grantApprovals(address[] calldata operators) external {
uint256 length = operators.length;
if (length == 0) {
revert LengthsInvalid();
}
for (uint256 i; i < length; ) {
address operator = operators[i];
if (!isOperatorAllowed[operator]) {
revert OperatorNotAllowed();
}
if (hasUserApprovedOperator[msg.sender][operator]) {
revert OperatorAlreadyApprovedByUser();
}
hasUserApprovedOperator[msg.sender][operator] = true;
unchecked {
++i;
}
}
emit ApprovalsGranted(msg.sender, operators);
}
/**
* @inheritdoc ITransferManager
*/
function revokeApprovals(address[] calldata operators) external {
uint256 length = operators.length;
if (length == 0) {
revert LengthsInvalid();
}
for (uint256 i; i < length; ) {
address operator = operators[i];
if (!hasUserApprovedOperator[msg.sender][operator]) {
revert OperatorNotApprovedByUser();
}
delete hasUserApprovedOperator[msg.sender][operator];
unchecked {
++i;
}
}
emit ApprovalsRemoved(msg.sender, operators);
}
/**
* @inheritdoc ITransferManager
*/
function allowOperator(address operator) external onlyOwner {
if (isOperatorAllowed[operator]) {
revert OperatorAlreadyAllowed();
}
isOperatorAllowed[operator] = true;
emit OperatorAllowed(operator);
}
/**
* @inheritdoc ITransferManager
*/
function removeOperator(address operator) external onlyOwner {
if (!isOperatorAllowed[operator]) {
revert OperatorNotAllowed();
}
delete isOperatorAllowed[operator];
emit OperatorRemoved(operator);
}
/**
* @notice This function is internal and verifies whether the transfer
* (by an operator on behalf of a user) is valid. If not, it reverts.
* @param user User address
* @param operator Operator address
*/
function _isOperatorValidForTransfer(address user, address operator) private view {
if (isOperatorAllowed[operator] && hasUserApprovedOperator[user][operator]) {
return;
}
revert TransferCallerInvalid();
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
// Interfaces
import {IOwnableTwoSteps} from "./interfaces/IOwnableTwoSteps.sol";
/**
* @title OwnableTwoSteps
* @notice This contract offers transfer of ownership in two steps with potential owner
* having to confirm the transaction to become the owner.
* Renouncement of the ownership is also a two-step process since the next potential owner is the address(0).
* @author LooksRare protocol team (👀,💎)
*/
abstract contract OwnableTwoSteps is IOwnableTwoSteps {
/**
* @notice Address of the current owner.
*/
address public owner;
/**
* @notice Address of the potential owner.
*/
address public potentialOwner;
/**
* @notice Ownership status.
*/
Status public ownershipStatus;
/**
* @notice Modifier to wrap functions for contracts that inherit this contract.
*/
modifier onlyOwner() {
_onlyOwner();
_;
}
/**
* @notice Constructor
* @param _owner The contract's owner
*/
constructor(address _owner) {
owner = _owner;
emit NewOwner(_owner);
}
/**
* @notice This function is used to cancel the ownership transfer.
* @dev This function can be used for both cancelling a transfer to a new owner and
* cancelling the renouncement of the ownership.
*/
function cancelOwnershipTransfer() external onlyOwner {
Status _ownershipStatus = ownershipStatus;
if (_ownershipStatus == Status.NoOngoingTransfer) {
revert NoOngoingTransferInProgress();
}
if (_ownershipStatus == Status.TransferInProgress) {
delete potentialOwner;
}
delete ownershipStatus;
emit CancelOwnershipTransfer();
}
/**
* @notice This function is used to confirm the ownership renouncement.
*/
function confirmOwnershipRenouncement() external onlyOwner {
if (ownershipStatus != Status.RenouncementInProgress) {
revert RenouncementNotInProgress();
}
delete owner;
delete ownershipStatus;
emit NewOwner(address(0));
}
/**
* @notice This function is used to confirm the ownership transfer.
* @dev This function can only be called by the current potential owner.
*/
function confirmOwnershipTransfer() external {
if (ownershipStatus != Status.TransferInProgress) {
revert TransferNotInProgress();
}
if (msg.sender != potentialOwner) {
revert WrongPotentialOwner();
}
owner = msg.sender;
delete ownershipStatus;
delete potentialOwner;
emit NewOwner(msg.sender);
}
/**
* @notice This function is used to initiate the transfer of ownership to a new owner.
* @param newPotentialOwner New potential owner address
*/
function initiateOwnershipTransfer(address newPotentialOwner) external onlyOwner {
if (ownershipStatus != Status.NoOngoingTransfer) {
revert TransferAlreadyInProgress();
}
ownershipStatus = Status.TransferInProgress;
potentialOwner = newPotentialOwner;
/**
* @dev This function can only be called by the owner, so msg.sender is the owner.
* We don't have to SLOAD the owner again.
*/
emit InitiateOwnershipTransfer(msg.sender, newPotentialOwner);
}
/**
* @notice This function is used to initiate the ownership renouncement.
*/
function initiateOwnershipRenouncement() external onlyOwner {
if (ownershipStatus != Status.NoOngoingTransfer) {
revert TransferAlreadyInProgress();
}
ownershipStatus = Status.RenouncementInProgress;
emit InitiateOwnershipRenouncement();
}
function _onlyOwner() private view {
if (msg.sender != owner) revert NotOwner();
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
// Interfaces
import {IERC20} from "../interfaces/generic/IERC20.sol";
// Errors
import {ERC20TransferFail, ERC20TransferFromFail} from "../errors/LowLevelErrors.sol";
import {NotAContract} from "../errors/GenericErrors.sol";
/**
* @title LowLevelERC20Transfer
* @notice This contract contains low-level calls to transfer ERC20 tokens.
* @author LooksRare protocol team (👀,💎)
*/
contract LowLevelERC20Transfer {
/**
* @notice Execute ERC20 transferFrom
* @param currency Currency address
* @param from Sender address
* @param to Recipient address
* @param amount Amount to transfer
*/
function _executeERC20TransferFrom(address currency, address from, address to, uint256 amount) internal {
if (currency.code.length == 0) {
revert NotAContract();
}
(bool status, bytes memory data) = currency.call(abi.encodeCall(IERC20.transferFrom, (from, to, amount)));
if (!status) {
revert ERC20TransferFromFail();
}
if (data.length > 0) {
if (!abi.decode(data, (bool))) {
revert ERC20TransferFromFail();
}
}
}
/**
* @notice Execute ERC20 (direct) transfer
* @param currency Currency address
* @param to Recipient address
* @param amount Amount to transfer
*/
function _executeERC20DirectTransfer(address currency, address to, uint256 amount) internal {
if (currency.code.length == 0) {
revert NotAContract();
}
(bool status, bytes memory data) = currency.call(abi.encodeCall(IERC20.transfer, (to, amount)));
if (!status) {
revert ERC20TransferFail();
}
if (data.length > 0) {
if (!abi.decode(data, (bool))) {
revert ERC20TransferFail();
}
}
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
// Interfaces
import {IERC721} from "../interfaces/generic/IERC721.sol";
// Errors
import {ERC721TransferFromFail} from "../errors/LowLevelErrors.sol";
import {NotAContract} from "../errors/GenericErrors.sol";
/**
* @title LowLevelERC721Transfer
* @notice This contract contains low-level calls to transfer ERC721 tokens.
* @author LooksRare protocol team (👀,💎)
*/
contract LowLevelERC721Transfer {
/**
* @notice Execute ERC721 transferFrom
* @param collection Address of the collection
* @param from Address of the sender
* @param to Address of the recipient
* @param tokenId tokenId to transfer
*/
function _executeERC721TransferFrom(address collection, address from, address to, uint256 tokenId) internal {
if (collection.code.length == 0) {
revert NotAContract();
}
(bool status, ) = collection.call(abi.encodeCall(IERC721.transferFrom, (from, to, tokenId)));
if (!status) {
revert ERC721TransferFromFail();
}
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
// Interfaces
import {IERC1155} from "../interfaces/generic/IERC1155.sol";
// Errors
import {ERC1155SafeTransferFromFail, ERC1155SafeBatchTransferFromFail} from "../errors/LowLevelErrors.sol";
import {NotAContract} from "../errors/GenericErrors.sol";
/**
* @title LowLevelERC1155Transfer
* @notice This contract contains low-level calls to transfer ERC1155 tokens.
* @author LooksRare protocol team (👀,💎)
*/
contract LowLevelERC1155Transfer {
/**
* @notice Execute ERC1155 safeTransferFrom
* @param collection Address of the collection
* @param from Address of the sender
* @param to Address of the recipient
* @param tokenId tokenId to transfer
* @param amount Amount to transfer
*/
function _executeERC1155SafeTransferFrom(
address collection,
address from,
address to,
uint256 tokenId,
uint256 amount
) internal {
if (collection.code.length == 0) {
revert NotAContract();
}
(bool status, ) = collection.call(abi.encodeCall(IERC1155.safeTransferFrom, (from, to, tokenId, amount, "")));
if (!status) {
revert ERC1155SafeTransferFromFail();
}
}
/**
* @notice Execute ERC1155 safeBatchTransferFrom
* @param collection Address of the collection
* @param from Address of the sender
* @param to Address of the recipient
* @param tokenIds Array of tokenIds to transfer
* @param amounts Array of amounts to transfer
*/
function _executeERC1155SafeBatchTransferFrom(
address collection,
address from,
address to,
uint256[] calldata tokenIds,
uint256[] calldata amounts
) internal {
if (collection.code.length == 0) {
revert NotAContract();
}
(bool status, ) = collection.call(
abi.encodeCall(IERC1155.safeBatchTransferFrom, (from, to, tokenIds, amounts, ""))
);
if (!status) {
revert ERC1155SafeBatchTransferFromFail();
}
}
}
// SPDX-License-Identifier: MIT
pragma solidity 0.8.20;
// Enums
import {TokenType} from "../enums/TokenType.sol";
/**
* @title ITransferManager
* @author LooksRare protocol team (👀,💎)
*/
interface ITransferManager {
/**
* @notice This struct is only used for transferBatchItemsAcrossCollections.
* @param tokenAddress Token address
* @param tokenType 0 for ERC721, 1 for ERC1155
* @param itemIds Array of item ids to transfer
* @param amounts Array of amounts to transfer
*/
struct BatchTransferItem {
address tokenAddress;
TokenType tokenType;
uint256[] itemIds;
uint256[] amounts;
}
/**
* @notice It is emitted if operators' approvals to transfer NFTs are granted by a user.
* @param user Address of the user
* @param operators Array of operator addresses
*/
event ApprovalsGranted(address user, address[] operators);
/**
* @notice It is emitted if operators' approvals to transfer NFTs are revoked by a user.
* @param user Address of the user
* @param operators Array of operator addresses
*/
event ApprovalsRemoved(address user, address[] operators);
/**
* @notice It is emitted if a new operator is added to the global allowlist.
* @param operator Operator address
*/
event OperatorAllowed(address operator);
/**
* @notice It is emitted if an operator is removed from the global allowlist.
* @param operator Operator address
*/
event OperatorRemoved(address operator);
/**
* @notice It is returned if the operator to approve has already been approved by the user.
*/
error OperatorAlreadyApprovedByUser();
/**
* @notice It is returned if the operator to revoke has not been previously approved by the user.
*/
error OperatorNotApprovedByUser();
/**
* @notice It is returned if the transfer caller is already allowed by the owner.
* @dev This error can only be returned for owner operations.
*/
error OperatorAlreadyAllowed();
/**
* @notice It is returned if the operator to approve is not in the global allowlist defined by the owner.
* @dev This error can be returned if the user tries to grant approval to an operator address not in the
* allowlist or if the owner tries to remove the operator from the global allowlist.
*/
error OperatorNotAllowed();
/**
* @notice It is returned if the transfer caller is invalid.
* For a transfer called to be valid, the operator must be in the global allowlist and
* approved by the 'from' user.
*/
error TransferCallerInvalid();
/**
* @notice This function transfers ERC20 tokens.
* @param tokenAddress Token address
* @param from Sender address
* @param to Recipient address
* @param amount amount
*/
function transferERC20(
address tokenAddress,
address from,
address to,
uint256 amount
) external;
/**
* @notice This function transfers a single item for a single ERC721 collection.
* @param tokenAddress Token address
* @param from Sender address
* @param to Recipient address
* @param itemId Item ID
*/
function transferItemERC721(
address tokenAddress,
address from,
address to,
uint256 itemId
) external;
/**
* @notice This function transfers items for a single ERC721 collection.
* @param tokenAddress Token address
* @param from Sender address
* @param to Recipient address
* @param itemIds Array of itemIds
* @param amounts Array of amounts
*/
function transferItemsERC721(
address tokenAddress,
address from,
address to,
uint256[] calldata itemIds,
uint256[] calldata amounts
) external;
/**
* @notice This function transfers a single item for a single ERC1155 collection.
* @param tokenAddress Token address
* @param from Sender address
* @param to Recipient address
* @param itemId Item ID
* @param amount Amount
*/
function transferItemERC1155(
address tokenAddress,
address from,
address to,
uint256 itemId,
uint256 amount
) external;
/**
* @notice This function transfers items for a single ERC1155 collection.
* @param tokenAddress Token address
* @param from Sender address
* @param to Recipient address
* @param itemIds Array of itemIds
* @param amounts Array of amounts
* @dev It does not allow batch transferring if from = msg.sender since native function should be used.
*/
function transferItemsERC1155(
address tokenAddress,
address from,
address to,
uint256[] calldata itemIds,
uint256[] calldata amounts
) external;
/**
* @notice This function transfers items across an array of tokens that can be ERC20, ERC721 and ERC1155.
* @param items Array of BatchTransferItem
* @param from Sender address
* @param to Recipient address
*/
function transferBatchItemsAcrossCollections(
BatchTransferItem[] calldata items,
address from,
address to
) external;
/**
* @notice This function allows a user to grant approvals for an array of operators.
* Users cannot grant approvals if the operator is not allowed by this contract's owner.
* @param operators Array of operator addresses
* @dev Each operator address must be globally allowed to be approved.
*/
function grantApprovals(address[] calldata operators) external;
/**
* @notice This function allows a user to revoke existing approvals for an array of operators.
* @param operators Array of operator addresses
* @dev Each operator address must be approved at the user level to be revoked.
*/
function revokeApprovals(address[] calldata operators) external;
/**
* @notice This function allows an operator to be added for the shared transfer system.
* Once the operator is allowed, users can grant NFT approvals to this operator.
* @param operator Operator address to allow
* @dev Only callable by owner.
*/
function allowOperator(address operator) external;
/**
* @notice This function allows the user to remove an operator for the shared transfer system.
* @param operator Operator address to remove
* @dev Only callable by owner.
*/
function removeOperator(address operator) external;
}
// SPDX-License-Identifier: MIT
pragma solidity 0.8.20;
/**
* @notice It is returned if the amount is invalid.
* For ERC20, if amount is 0.
* For ERC721, any number that is not 1.
* For ERC1155, if amount is 0.
*/
error AmountInvalid();
/**
* @notice It is returned if there is either a mismatch or an error in the length of the array(s).
*/
error LengthsInvalid();
// SPDX-License-Identifier: MIT
pragma solidity 0.8.20;
enum TokenType {
ERC20,
ERC721,
ERC1155
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
/**
* @title IOwnableTwoSteps
* @author LooksRare protocol team (👀,💎)
*/
interface IOwnableTwoSteps {
/**
* @notice This enum keeps track of the ownership status.
* @param NoOngoingTransfer The default status when the owner is set
* @param TransferInProgress The status when a transfer to a new owner is initialized
* @param RenouncementInProgress The status when a transfer to address(0) is initialized
*/
enum Status {
NoOngoingTransfer,
TransferInProgress,
RenouncementInProgress
}
/**
* @notice This is returned when there is no transfer of ownership in progress.
*/
error NoOngoingTransferInProgress();
/**
* @notice This is returned when the caller is not the owner.
*/
error NotOwner();
/**
* @notice This is returned when there is no renouncement in progress but
* the owner tries to validate the ownership renouncement.
*/
error RenouncementNotInProgress();
/**
* @notice This is returned when the transfer is already in progress but the owner tries
* initiate a new ownership transfer.
*/
error TransferAlreadyInProgress();
/**
* @notice This is returned when there is no ownership transfer in progress but the
* ownership change tries to be approved.
*/
error TransferNotInProgress();
/**
* @notice This is returned when the ownership transfer is attempted to be validated by the
* a caller that is not the potential owner.
*/
error WrongPotentialOwner();
/**
* @notice This is emitted if the ownership transfer is cancelled.
*/
event CancelOwnershipTransfer();
/**
* @notice This is emitted if the ownership renouncement is initiated.
*/
event InitiateOwnershipRenouncement();
/**
* @notice This is emitted if the ownership transfer is initiated.
* @param previousOwner Previous/current owner
* @param potentialOwner Potential/future owner
*/
event InitiateOwnershipTransfer(address previousOwner, address potentialOwner);
/**
* @notice This is emitted when there is a new owner.
*/
event NewOwner(address newOwner);
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
interface IERC20 {
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address to, uint256 amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(address from, address to, uint256 amount) external returns (bool);
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
/**
* @notice It is emitted if the ETH transfer fails.
*/
error ETHTransferFail();
/**
* @notice It is emitted if the ERC20 approval fails.
*/
error ERC20ApprovalFail();
/**
* @notice It is emitted if the ERC20 transfer fails.
*/
error ERC20TransferFail();
/**
* @notice It is emitted if the ERC20 transferFrom fails.
*/
error ERC20TransferFromFail();
/**
* @notice It is emitted if the ERC721 transferFrom fails.
*/
error ERC721TransferFromFail();
/**
* @notice It is emitted if the ERC1155 safeTransferFrom fails.
*/
error ERC1155SafeTransferFromFail();
/**
* @notice It is emitted if the ERC1155 safeBatchTransferFrom fails.
*/
error ERC1155SafeBatchTransferFromFail();
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
/**
* @notice It is emitted if the call recipient is not a contract.
*/
error NotAContract();
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
interface IERC721 {
event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
function balanceOf(address owner) external view returns (uint256 balance);
function ownerOf(uint256 tokenId) external view returns (address owner);
function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;
function safeTransferFrom(address from, address to, uint256 tokenId) external;
function transferFrom(address from, address to, uint256 tokenId) external;
function approve(address to, uint256 tokenId) external;
function setApprovalForAll(address operator, bool _approved) external;
function getApproved(uint256 tokenId) external view returns (address operator);
function isApprovedForAll(address owner, address operator) external view returns (bool);
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
interface IERC1155 {
event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);
event TransferBatch(
address indexed operator,
address indexed from,
address indexed to,
uint256[] ids,
uint256[] values
);
event ApprovalForAll(address indexed account, address indexed operator, bool approved);
event URI(string value, uint256 indexed id);
function balanceOf(address account, uint256 id) external view returns (uint256);
function balanceOfBatch(
address[] calldata accounts,
uint256[] calldata ids
) external view returns (uint256[] memory);
function setApprovalForAll(address operator, bool approved) external;
function isApprovedForAll(address account, address operator) external view returns (bool);
function safeTransferFrom(address from, address to, uint256 id, uint256 amount, bytes calldata data) external;
function safeBatchTransferFrom(
address from,
address to,
uint256[] calldata ids,
uint256[] calldata amounts,
bytes calldata data
) external;
}