You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
137 lines
5.5 KiB
137 lines
5.5 KiB
// SPDX-License-Identifier: MIT
|
|
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/extensions/ERC1363.sol)
|
|
|
|
pragma solidity ^0.8.20;
|
|
|
|
import {ERC20} from "../ERC20.sol";
|
|
import {IERC165, ERC165} from "../../../utils/introspection/ERC165.sol";
|
|
import {IERC1363} from "../../../interfaces/IERC1363.sol";
|
|
import {ERC1363Utils} from "../utils/ERC1363Utils.sol";
|
|
|
|
/**
|
|
* @title ERC1363
|
|
* @dev Extension of {ERC20} tokens that adds support for code execution after transfers and approvals
|
|
* on recipient contracts. Calls after transfers are enabled through the {ERC1363-transferAndCall} and
|
|
* {ERC1363-transferFromAndCall} methods while calls after approvals can be made with {ERC1363-approveAndCall}
|
|
*
|
|
* _Available since v5.1._
|
|
*/
|
|
abstract contract ERC1363 is ERC20, ERC165, IERC1363 {
|
|
/**
|
|
* @dev Indicates a failure within the {transfer} part of a transferAndCall operation.
|
|
* @param receiver Address to which tokens are being transferred.
|
|
* @param value Amount of tokens to be transferred.
|
|
*/
|
|
error ERC1363TransferFailed(address receiver, uint256 value);
|
|
|
|
/**
|
|
* @dev Indicates a failure within the {transferFrom} part of a transferFromAndCall operation.
|
|
* @param sender Address from which to send tokens.
|
|
* @param receiver Address to which tokens are being transferred.
|
|
* @param value Amount of tokens to be transferred.
|
|
*/
|
|
error ERC1363TransferFromFailed(address sender, address receiver, uint256 value);
|
|
|
|
/**
|
|
* @dev Indicates a failure within the {approve} part of a approveAndCall operation.
|
|
* @param spender Address which will spend the funds.
|
|
* @param value Amount of tokens to be spent.
|
|
*/
|
|
error ERC1363ApproveFailed(address spender, uint256 value);
|
|
|
|
/**
|
|
* @inheritdoc IERC165
|
|
*/
|
|
function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {
|
|
return interfaceId == type(IERC1363).interfaceId || super.supportsInterface(interfaceId);
|
|
}
|
|
|
|
/**
|
|
* @dev Moves a `value` amount of tokens from the caller's account to `to`
|
|
* and then calls {IERC1363Receiver-onTransferReceived} on `to`. Returns a flag that indicates
|
|
* if the call succeeded.
|
|
*
|
|
* 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.
|
|
* - The internal {transfer} must succeed (returned `true`).
|
|
*/
|
|
function transferAndCall(address to, uint256 value) public returns (bool) {
|
|
return transferAndCall(to, value, "");
|
|
}
|
|
|
|
/**
|
|
* @dev Variant of {transferAndCall} that accepts an additional `data` parameter with
|
|
* no specified format.
|
|
*/
|
|
function transferAndCall(address to, uint256 value, bytes memory data) public virtual returns (bool) {
|
|
if (!transfer(to, value)) {
|
|
revert ERC1363TransferFailed(to, value);
|
|
}
|
|
ERC1363Utils.checkOnERC1363TransferReceived(_msgSender(), _msgSender(), to, value, data);
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism
|
|
* and then calls {IERC1363Receiver-onTransferReceived} on `to`. Returns a flag that indicates
|
|
* if the call succeeded.
|
|
*
|
|
* 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.
|
|
* - The internal {transferFrom} must succeed (returned `true`).
|
|
*/
|
|
function transferFromAndCall(address from, address to, uint256 value) public returns (bool) {
|
|
return transferFromAndCall(from, to, value, "");
|
|
}
|
|
|
|
/**
|
|
* @dev Variant of {transferFromAndCall} that accepts an additional `data` parameter with
|
|
* no specified format.
|
|
*/
|
|
function transferFromAndCall(
|
|
address from,
|
|
address to,
|
|
uint256 value,
|
|
bytes memory data
|
|
) public virtual returns (bool) {
|
|
if (!transferFrom(from, to, value)) {
|
|
revert ERC1363TransferFromFailed(from, to, value);
|
|
}
|
|
ERC1363Utils.checkOnERC1363TransferReceived(_msgSender(), from, to, value, data);
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* @dev Sets a `value` amount of tokens as the allowance of `spender` over the
|
|
* caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.
|
|
* Returns a flag that indicates if the call succeeded.
|
|
*
|
|
* 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.
|
|
* - The internal {approve} must succeed (returned `true`).
|
|
*/
|
|
function approveAndCall(address spender, uint256 value) public returns (bool) {
|
|
return approveAndCall(spender, value, "");
|
|
}
|
|
|
|
/**
|
|
* @dev Variant of {approveAndCall} that accepts an additional `data` parameter with
|
|
* no specified format.
|
|
*/
|
|
function approveAndCall(address spender, uint256 value, bytes memory data) public virtual returns (bool) {
|
|
if (!approve(spender, value)) {
|
|
revert ERC1363ApproveFailed(spender, value);
|
|
}
|
|
ERC1363Utils.checkOnERC1363ApprovalReceived(_msgSender(), spender, value, data);
|
|
return true;
|
|
}
|
|
}
|
|
|