Skip to content

Commit

Permalink
use upgradable storage
Browse files Browse the repository at this point in the history
  • Loading branch information
ryanio committed Apr 8, 2024
1 parent c425dbd commit 1e86080
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 9 deletions.
6 changes: 4 additions & 2 deletions src/transfer-validated/ERC1155ShipyardTransferValidated.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@ pragma solidity ^0.8.17;
import {Ownable} from "solady/src/auth/Ownable.sol";
import {ERC1155} from "solady/src/tokens/ERC1155.sol";
import {ERC1155ConduitPreapproved_Solady} from "../tokens/erc1155/ERC1155ConduitPreapproved_Solady.sol";
import {TokenTransferValidator} from "./lib/TokenTransferValidator.sol";
import {TokenTransferValidator, TokenTransferValidatorStorage} from "./lib/TokenTransferValidator.sol";
import {ICreatorToken} from "../interfaces/transfer-validated/ICreatorToken.sol";
import {ITransferValidator1155} from "../interfaces/transfer-validated/ITransferValidator.sol";

contract ERC1155ShipyardTransferValidated is ERC1155ConduitPreapproved_Solady, TokenTransferValidator, Ownable {
using TokenTransferValidatorStorage for TokenTransferValidatorStorage.Layout;

constructor(address initialTransferValidator) ERC1155ConduitPreapproved_Solady() {
// Set the initial contract owner.
_initializeOwner(msg.sender);
Expand Down Expand Up @@ -46,7 +48,7 @@ contract ERC1155ShipyardTransferValidated is ERC1155ConduitPreapproved_Solady, T
) internal virtual override {
if (from != address(0) && to != address(0)) {
// Call the transfer validator if one is set.
address transferValidator = _transferValidator;
address transferValidator = TokenTransferValidatorStorage.layout()._transferValidator;
if (transferValidator != address(0)) {
for (uint256 i = 0; i < ids.length; i++) {
ITransferValidator1155(transferValidator).validateTransfer(msg.sender, from, to, ids[i], amounts[i]);
Expand Down
6 changes: 4 additions & 2 deletions src/transfer-validated/ERC721ShipyardTransferValidated.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@ pragma solidity ^0.8.17;
import {Ownable} from "solady/src/auth/Ownable.sol";
import {ERC721} from "solady/src/tokens/ERC721.sol";
import {ERC721ConduitPreapproved_Solady} from "../tokens/erc721/ERC721ConduitPreapproved_Solady.sol";
import {TokenTransferValidator} from "./lib/TokenTransferValidator.sol";
import {TokenTransferValidator, TokenTransferValidatorStorage} from "./lib/TokenTransferValidator.sol";
import {ICreatorToken} from "../interfaces/transfer-validated/ICreatorToken.sol";
import {ITransferValidator721} from "../interfaces/transfer-validated/ITransferValidator.sol";

contract ERC721ShipyardTransferValidated is ERC721ConduitPreapproved_Solady, TokenTransferValidator, Ownable {
using TokenTransferValidatorStorage for TokenTransferValidatorStorage.Layout;

constructor(address initialTransferValidator) ERC721ConduitPreapproved_Solady() {
// Set the initial contract owner.
_initializeOwner(msg.sender);
Expand All @@ -35,7 +37,7 @@ contract ERC721ShipyardTransferValidated is ERC721ConduitPreapproved_Solady, Tok
function _beforeTokenTransfer(address from, address to, uint256 id) internal virtual override {
if (from != address(0) && to != address(0)) {
// Call the transfer validator if one is set.
address transferValidator = _transferValidator;
address transferValidator = TokenTransferValidatorStorage.layout()._transferValidator;
if (transferValidator != address(0)) {
ITransferValidator721(transferValidator).validateTransfer(msg.sender, from, to, id);
}
Expand Down
25 changes: 20 additions & 5 deletions src/transfer-validated/lib/TokenTransferValidator.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,31 +3,46 @@ pragma solidity ^0.8.17;

import {ICreatorToken} from "../../interfaces/transfer-validated/ICreatorToken.sol";

library TokenTransferValidatorStorage {
struct Layout {
/// @dev Store the transfer validator. The null address means no transfer validator is set.
address _transferValidator;
}

bytes32 internal constant STORAGE_SLOT = keccak256("contracts.storage.tokenTransferValidator");

function layout() internal pure returns (Layout storage l) {
bytes32 slot = STORAGE_SLOT;
assembly {
l.slot := slot
}
}
}

/**
* @title TokenTransferValidator
* @notice Functionality to use a transfer validator.
*/
abstract contract TokenTransferValidator is ICreatorToken {
/// @dev Store the transfer validator. The null address means no transfer validator is set.
address internal _transferValidator;
using TokenTransferValidatorStorage for TokenTransferValidatorStorage.Layout;

/// @notice Revert with an error if the transfer validator is being set to the same address.
error SameTransferValidator();

/// @notice Returns the currently active transfer validator.
/// The null address means no transfer validator is set.
function getTransferValidator() external view returns (address) {
return _transferValidator;
return TokenTransferValidatorStorage.layout()._transferValidator;
}

/// @notice Set the transfer validator.
/// The external method that uses this must include access control.
function _setTransferValidator(address newValidator) internal {
address oldValidator = _transferValidator;
address oldValidator = TokenTransferValidatorStorage.layout()._transferValidator;
if (oldValidator == newValidator) {
revert SameTransferValidator();
}
_transferValidator = newValidator;
TokenTransferValidatorStorage.layout()._transferValidator = newValidator;
emit TransferValidatorUpdated(oldValidator, newValidator);
}
}

0 comments on commit 1e86080

Please sign in to comment.