Skip to content
Merged
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
37 changes: 22 additions & 15 deletions src/extension/token/transferable/TransferableERC1155.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ pragma solidity ^0.8.0;

import {ModularExtension} from "../../../ModularExtension.sol";
import {Role} from "../../../Role.sol";
import {BeforeTransferCallbackERC1155} from "../../../callback/BeforeTransferCallbackERC1155.sol";
import {BeforeBatchTransferCallbackERC1155} from "../../../callback/BeforeBatchTransferCallbackERC1155.sol";

library TransferableStorage {
/// @custom:storage-location erc7201:token.transferable
Expand All @@ -13,7 +15,7 @@ library TransferableStorage {
// token => whether transfers are enabled
mapping(address => bool) transferEnabled;
// token => from/to/operator address => bool, whether transfer is enabled
mapping(address => mapping(address => bool)) transferrerAllowed;
mapping(address => mapping(address => bool)) transferEnabledFor;
}

function data() internal pure returns (Data storage data_) {
Expand All @@ -24,7 +26,7 @@ library TransferableStorage {
}
}

contract TransferableERC1155 is ModularExtension {
contract TransferableERC1155 is ModularExtension, BeforeTransferCallbackERC1155, BeforeBatchTransferCallbackERC1155 {
/*//////////////////////////////////////////////////////////////
ERRORS
//////////////////////////////////////////////////////////////*/
Expand Down Expand Up @@ -73,29 +75,34 @@ contract TransferableERC1155 is ModularExtension {
//////////////////////////////////////////////////////////////*/

/// @notice Callback function for ERC1155.safeTransferFrom
function beforeTransferERC1155(address from, address to, uint256, uint256)
function beforeTransferERC1155(address caller, address from, address to, uint256, uint256)
external
virtual
override
returns (bytes memory)
{
address token = msg.sender;
TransferableStorage.Data storage data = _transferableStorage();
bool isOperatorAllowed = data.transferrerAllowed[token][from] || data.transferrerAllowed[token][to];
bool isOperatorAllowed = data.transferEnabledFor[token][caller] || data.transferEnabledFor[token][from]
|| data.transferEnabledFor[token][to];

if (!isOperatorAllowed && !data.transferEnabled[token]) {
revert TransferDisabled();
}
}

/// @notice Callback function for ERC1155.safeBatchTransferFrom
function beforeBatchTransferERC1155(address from, address to, uint256[] calldata, uint256[] calldata)
external
virtual
returns (bytes memory)
{
function beforeBatchTransferERC1155(
address caller,
address from,
address to,
uint256[] calldata,
uint256[] calldata
) external virtual override returns (bytes memory) {
address token = msg.sender;
TransferableStorage.Data storage data = _transferableStorage();
bool isOperatorAllowed = data.transferrerAllowed[token][from] || data.transferrerAllowed[token][to];
bool isOperatorAllowed = data.transferEnabledFor[token][caller] || data.transferEnabledFor[token][from]
|| data.transferEnabledFor[token][to];

if (!isOperatorAllowed && !data.transferEnabled[token]) {
revert TransferDisabled();
Expand All @@ -111,9 +118,9 @@ contract TransferableERC1155 is ModularExtension {
return _transferableStorage().transferEnabled[msg.sender];
}

/// @notice Returns whether transfers is enabled for the transferrer for the token.
function isTransferEnabledFor(address transferrer) external view returns (bool) {
return _transferableStorage().transferrerAllowed[msg.sender][transferrer];
/// @notice Returns whether transfers is enabled for the target for the token.
function isTransferEnabledFor(address target) external view returns (bool) {
return _transferableStorage().transferEnabledFor[msg.sender][target];
}

/// @notice Set transferability for a token.
Expand All @@ -123,9 +130,9 @@ contract TransferableERC1155 is ModularExtension {
}

/// @notice Set transferability for an operator for a token.
function setTransferableFor(address transferrer, bool enableTransfer) external {
function setTransferableFor(address target, bool enableTransfer) external {
address token = msg.sender;
_transferableStorage().transferrerAllowed[token][transferrer] = enableTransfer;
_transferableStorage().transferEnabledFor[token][target] = enableTransfer;
}

/*//////////////////////////////////////////////////////////////
Expand Down
27 changes: 17 additions & 10 deletions src/extension/token/transferable/TransferableERC20.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ pragma solidity ^0.8.0;

import {ModularExtension} from "../../../ModularExtension.sol";
import {Role} from "../../../Role.sol";
import {BeforeTransferCallbackERC20} from "../../../callback/BeforeTransferCallbackERC20.sol";

library TransferableStorage {
/// @custom:storage-location erc7201:token.transferable
Expand All @@ -13,7 +14,7 @@ library TransferableStorage {
// token => whether transfers are enabled
mapping(address => bool) transferEnabled;
// token => from/to/operator address => bool, whether transfer is enabled
mapping(address => mapping(address => bool)) transferrerAllowed;
mapping(address => mapping(address => bool)) transferEnabledFor;
}

function data() internal pure returns (Data storage data_) {
Expand All @@ -24,7 +25,7 @@ library TransferableStorage {
}
}

contract TransferableERC20 is ModularExtension {
contract TransferableERC20 is ModularExtension, BeforeTransferCallbackERC20 {
/*//////////////////////////////////////////////////////////////
ERRORS
//////////////////////////////////////////////////////////////*/
Expand Down Expand Up @@ -70,10 +71,16 @@ contract TransferableERC20 is ModularExtension {
//////////////////////////////////////////////////////////////*/

/// @notice Callback function for ERC20.transfer
function beforeTransferERC20(address from, address to, uint256) external virtual returns (bytes memory) {
function beforeTransferERC20(address caller, address from, address to, uint256)
external
virtual
override
returns (bytes memory)
{
address token = msg.sender;
TransferableStorage.Data storage data = _transferableStorage();
bool isOperatorAllowed = data.transferrerAllowed[token][from] || data.transferrerAllowed[token][to];
bool isOperatorAllowed = data.transferEnabledFor[token][caller] || data.transferEnabledFor[token][from]
|| data.transferEnabledFor[token][to];

if (!isOperatorAllowed && !data.transferEnabled[token]) {
revert TransferDisabled();
Expand All @@ -89,9 +96,9 @@ contract TransferableERC20 is ModularExtension {
return _transferableStorage().transferEnabled[msg.sender];
}

/// @notice Returns whether transfers is enabled for the transferrer for the token.
function isTransferEnabledFor(address transferrer) external view returns (bool) {
return _transferableStorage().transferrerAllowed[msg.sender][transferrer];
/// @notice Returns whether transfers is enabled for the target address for the token.
function isTransferEnabledFor(address target) external view returns (bool) {
return _transferableStorage().transferEnabledFor[msg.sender][target];
}

/// @notice Set transferability for a token.
Expand All @@ -100,10 +107,10 @@ contract TransferableERC20 is ModularExtension {
_transferableStorage().transferEnabled[token] = enableTransfer;
}

/// @notice Set transferability for an operator for a token.
function setTransferableFor(address transferrer, bool enableTransfer) external {
/// @notice Set transferability for an address for a token.
function setTransferableFor(address target, bool enableTransfer) external {
address token = msg.sender;
_transferableStorage().transferrerAllowed[token][transferrer] = enableTransfer;
_transferableStorage().transferEnabledFor[token][target] = enableTransfer;
}

/*//////////////////////////////////////////////////////////////
Expand Down
27 changes: 17 additions & 10 deletions src/extension/token/transferable/TransferableERC721.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ pragma solidity ^0.8.0;

import {ModularExtension} from "../../../ModularExtension.sol";
import {Role} from "../../../Role.sol";
import {BeforeTransferCallbackERC721} from "../../../callback/BeforeTransferCallbackERC721.sol";

library TransferableStorage {
/// @custom:storage-location erc7201:token.transferable
Expand All @@ -13,7 +14,7 @@ library TransferableStorage {
// token => whether transfer is enabled
mapping(address => bool) transferEnabled;
// token => from/to/operator address => bool, whether transfer is enabled
mapping(address => mapping(address => bool)) transferrerAllowed;
mapping(address => mapping(address => bool)) transferEnabledFor;
}

function data() internal pure returns (Data storage data_) {
Expand All @@ -24,7 +25,7 @@ library TransferableStorage {
}
}

contract TransferableERC721 is ModularExtension {
contract TransferableERC721 is ModularExtension, BeforeTransferCallbackERC721 {
/*//////////////////////////////////////////////////////////////
ERRORS
//////////////////////////////////////////////////////////////*/
Expand Down Expand Up @@ -72,10 +73,16 @@ contract TransferableERC721 is ModularExtension {
//////////////////////////////////////////////////////////////*/

/// @notice Callback function for ERC721.transferFrom/safeTransferFrom
function beforeTransferERC721(address from, address to, uint256) external virtual returns (bytes memory) {
function beforeTransferERC721(address caller, address from, address to, uint256)
external
virtual
override
returns (bytes memory)
{
address token = msg.sender;
TransferableStorage.Data storage data = _transferableStorage();
bool isOperatorAllowed = data.transferrerAllowed[token][from] || data.transferrerAllowed[token][to];
bool isOperatorAllowed = data.transferEnabledFor[token][caller] || data.transferEnabledFor[token][from]
|| data.transferEnabledFor[token][to];

if (!isOperatorAllowed && !data.transferEnabled[token]) {
revert TransferDisabled();
Expand All @@ -91,9 +98,9 @@ contract TransferableERC721 is ModularExtension {
return _transferableStorage().transferEnabled[msg.sender];
}

/// @notice Returns whether transfers is enabled for the transferrer for the token.
function isTransferEnabledFor(address transferrer) external view returns (bool) {
return _transferableStorage().transferrerAllowed[msg.sender][transferrer];
/// @notice Returns whether transfers is enabled for the target address for the token.
function isTransferEnabledFor(address target) external view returns (bool) {
return _transferableStorage().transferEnabledFor[msg.sender][target];
}

/// @notice Set transferability for a token.
Expand All @@ -102,10 +109,10 @@ contract TransferableERC721 is ModularExtension {
_transferableStorage().transferEnabled[token] = enableTransfer;
}

/// @notice Set transferability for an operator for a token.
function setTransferableFor(address transferrer, bool enableTransfer) external {
/// @notice Set transferability for an address for a token.
function setTransferableFor(address target, bool enableTransfer) external {
address token = msg.sender;
_transferableStorage().transferrerAllowed[token][transferrer] = enableTransfer;
_transferableStorage().transferEnabledFor[token][target] = enableTransfer;
}

/*//////////////////////////////////////////////////////////////
Expand Down
Loading