Create a ERC1363Utils helper similar to existing ERC721Utils and ERC1155Utils (#5133)
Co-authored-by: Ernesto García <ernestognw@gmail.com> Co-authored-by: cairo <cairoeth@protonmail.com>pull/5140/head
parent
e3786e63e6
commit
aec36ddd6a
@ -0,0 +1,5 @@ |
||||
--- |
||||
'openzeppelin-solidity': minor |
||||
--- |
||||
|
||||
`ERC1363Utils`: Add helper similar to the existing `ERC721Utils` and `ERC1155Utils` |
@ -0,0 +1,96 @@ |
||||
// SPDX-License-Identifier: MIT |
||||
|
||||
pragma solidity ^0.8.20; |
||||
|
||||
import {IERC1363Receiver} from "../../../interfaces/IERC1363Receiver.sol"; |
||||
import {IERC1363Spender} from "../../../interfaces/IERC1363Spender.sol"; |
||||
|
||||
/** |
||||
* @dev Library that provides common ERC-1363 utility functions. |
||||
* |
||||
* See https://eips.ethereum.org/EIPS/eip-1363[ERC-1363]. |
||||
*/ |
||||
library ERC1363Utils { |
||||
/** |
||||
* @dev Indicates a failure with the token `receiver`. Used in transfers. |
||||
* @param receiver Address to which tokens are being transferred. |
||||
*/ |
||||
error ERC1363InvalidReceiver(address receiver); |
||||
|
||||
/** |
||||
* @dev Indicates a failure with the token `spender`. Used in approvals. |
||||
* @param spender Address that may be allowed to operate on tokens without being their owner. |
||||
*/ |
||||
error ERC1363InvalidSpender(address spender); |
||||
|
||||
/** |
||||
* @dev Performs a call to {IERC1363Receiver-onTransferReceived} on a target address. |
||||
* |
||||
* Requirements: |
||||
* |
||||
* - The target has code (i.e. is a contract). |
||||
* - The target `to` must implement the {IERC1363Receiver} interface. |
||||
* - The target must return the {IERC1363Receiver-onTransferReceived} selector to accept the transfer. |
||||
*/ |
||||
function checkOnERC1363TransferReceived( |
||||
address operator, |
||||
address from, |
||||
address to, |
||||
uint256 value, |
||||
bytes memory data |
||||
) internal { |
||||
if (to.code.length == 0) { |
||||
revert ERC1363InvalidReceiver(to); |
||||
} |
||||
|
||||
try IERC1363Receiver(to).onTransferReceived(operator, from, value, data) returns (bytes4 retval) { |
||||
if (retval != IERC1363Receiver.onTransferReceived.selector) { |
||||
revert ERC1363InvalidReceiver(to); |
||||
} |
||||
} catch (bytes memory reason) { |
||||
if (reason.length == 0) { |
||||
revert ERC1363InvalidReceiver(to); |
||||
} else { |
||||
/// @solidity memory-safe-assembly |
||||
assembly { |
||||
revert(add(32, reason), mload(reason)) |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* @dev Performs a call to {IERC1363Spender-onApprovalReceived} on a target address. |
||||
* |
||||
* Requirements: |
||||
* |
||||
* - The target has code (i.e. is a contract). |
||||
* - The target `spender` must implement the {IERC1363Spender} interface. |
||||
* - The target must return the {IERC1363Spender-onApprovalReceived} selector to accept the approval. |
||||
*/ |
||||
function checkOnERC1363ApprovalReceived( |
||||
address operator, |
||||
address spender, |
||||
uint256 value, |
||||
bytes memory data |
||||
) internal { |
||||
if (spender.code.length == 0) { |
||||
revert ERC1363InvalidSpender(spender); |
||||
} |
||||
|
||||
try IERC1363Spender(spender).onApprovalReceived(operator, value, data) returns (bytes4 retval) { |
||||
if (retval != IERC1363Spender.onApprovalReceived.selector) { |
||||
revert ERC1363InvalidSpender(spender); |
||||
} |
||||
} catch (bytes memory reason) { |
||||
if (reason.length == 0) { |
||||
revert ERC1363InvalidSpender(spender); |
||||
} else { |
||||
/// @solidity memory-safe-assembly |
||||
assembly { |
||||
revert(add(32, reason), mload(reason)) |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
Loading…
Reference in new issue