文件 1 的 21:AddressUtils.sol
pragma solidity ^0.8.0;
library AddressUtils {
function toString (address account) internal pure returns (string memory) {
bytes32 value = bytes32(uint256(uint160(account)));
bytes memory alphabet = '0123456789abcdef';
bytes memory chars = new bytes(42);
chars[0] = '0';
chars[1] = 'x';
for (uint256 i = 0; i < 20; i++) {
chars[2 + i * 2] = alphabet[uint8(value[i + 12] >> 4)];
chars[3 + i * 2] = alphabet[uint8(value[i + 12] & 0x0f)];
}
return string(chars);
}
function isContract (address account) internal view returns (bool) {
uint size;
assembly { size := extcodesize(account) }
return size > 0;
}
function sendValue (address payable account, uint amount) internal {
(bool success, ) = account.call{ value: amount }('');
require(success, 'AddressUtils: failed to send value');
}
function functionCall (address target, bytes memory data) internal returns (bytes memory) {
return functionCall(target, data, 'AddressUtils: failed low-level call');
}
function functionCall (address target, bytes memory data, string memory error) internal returns (bytes memory) {
return _functionCallWithValue(target, data, 0, error);
}
function functionCallWithValue (address target, bytes memory data, uint value) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, 'AddressUtils: failed low-level call with value');
}
function functionCallWithValue (address target, bytes memory data, uint value, string memory error) internal returns (bytes memory) {
require(address(this).balance >= value, 'AddressUtils: insufficient balance for call');
return _functionCallWithValue(target, data, value, error);
}
function _functionCallWithValue (address target, bytes memory data, uint value, string memory error) private returns (bytes memory) {
require(isContract(target), 'AddressUtils: function call to non-contract');
(bool success, bytes memory returnData) = target.call{ value: value }(data);
if (success) {
return returnData;
} else if (returnData.length > 0) {
assembly {
let returnData_size := mload(returnData)
revert(add(32, returnData), returnData_size)
}
} else {
revert(error);
}
}
}
文件 2 的 21:Diamond.sol
pragma solidity ^0.8.0;
import {SafeOwnable, OwnableStorage, Ownable} from '../../access/SafeOwnable.sol';
import {IERC173} from '../../access/IERC173.sol';
import {ERC165, IERC165, ERC165Storage} from '../../introspection/ERC165.sol';
import {DiamondBase, DiamondBaseStorage} from './DiamondBase.sol';
import {DiamondCuttable, IDiamondCuttable} from './DiamondCuttable.sol';
import {DiamondLoupe, IDiamondLoupe} from './DiamondLoupe.sol';
abstract contract Diamond is DiamondBase, DiamondCuttable, DiamondLoupe, SafeOwnable, ERC165 {
using DiamondBaseStorage for DiamondBaseStorage.Layout;
using ERC165Storage for ERC165Storage.Layout;
using OwnableStorage for OwnableStorage.Layout;
constructor () {
ERC165Storage.Layout storage erc165 = ERC165Storage.layout();
bytes4[] memory selectors = new bytes4[](12);
selectors[0] = IDiamondCuttable.diamondCut.selector;
erc165.setSupportedInterface(type(IDiamondCuttable).interfaceId, true);
selectors[1] = IDiamondLoupe.facets.selector;
selectors[2] = IDiamondLoupe.facetFunctionSelectors.selector;
selectors[3] = IDiamondLoupe.facetAddresses.selector;
selectors[4] = IDiamondLoupe.facetAddress.selector;
erc165.setSupportedInterface(type(IDiamondLoupe).interfaceId, true);
selectors[5] = IERC165.supportsInterface.selector;
erc165.setSupportedInterface(type(IERC165).interfaceId, true);
selectors[6] = Ownable.owner.selector;
selectors[7] = SafeOwnable.nomineeOwner.selector;
selectors[8] = SafeOwnable.transferOwnership.selector;
selectors[9] = SafeOwnable.acceptOwnership.selector;
erc165.setSupportedInterface(type(IERC173).interfaceId, true);
selectors[10] = Diamond.getFallbackAddress.selector;
selectors[11] = Diamond.setFallbackAddress.selector;
FacetCut[] memory facetCuts = new FacetCut[](1);
facetCuts[0] = FacetCut({
target: address(this),
action: IDiamondCuttable.FacetCutAction.ADD,
selectors: selectors
});
DiamondBaseStorage.layout().diamondCut(facetCuts, address(0), '');
OwnableStorage.layout().setOwner(msg.sender);
}
receive () external payable {}
function getFallbackAddress () external view returns (address) {
return DiamondBaseStorage.layout().fallbackAddress;
}
function setFallbackAddress (
address fallbackAddress
) external onlyOwner {
DiamondBaseStorage.layout().fallbackAddress = fallbackAddress;
}
}
文件 3 的 21:DiamondBase.sol
pragma solidity ^0.8.0;
import {Proxy} from '../Proxy.sol';
import {DiamondBaseStorage} from './DiamondBaseStorage.sol';
import {IDiamondLoupe} from './IDiamondLoupe.sol';
import {IDiamondCuttable} from './IDiamondCuttable.sol';
abstract contract DiamondBase is Proxy {
function _getImplementation () override internal view returns (address) {
DiamondBaseStorage.Layout storage l;
bytes32 slot = DiamondBaseStorage.STORAGE_SLOT;
assembly { l.slot := slot }
address implementation = address(bytes20(l.facets[msg.sig]));
if (implementation == address(0)) {
implementation = l.fallbackAddress;
require(
implementation != address(0),
'DiamondBase: no facet found for function signature'
);
}
return implementation;
}
}
文件 4 的 21:DiamondBaseStorage.sol
pragma solidity ^0.8.0;
import {AddressUtils} from '../../utils/AddressUtils.sol';
import {IDiamondCuttable} from './IDiamondCuttable.sol';
library DiamondBaseStorage {
using AddressUtils for address;
using DiamondBaseStorage for DiamondBaseStorage.Layout;
struct Layout {
mapping (bytes4 => bytes32) facets;
uint16 selectorCount;
mapping (uint256 => bytes32) selectorSlots;
address fallbackAddress;
}
bytes32 constant CLEAR_ADDRESS_MASK = bytes32(uint256(0xffffffffffffffffffffffff));
bytes32 constant CLEAR_SELECTOR_MASK = bytes32(uint256(0xffffffff << 224));
bytes32 internal constant STORAGE_SLOT = keccak256(
'solidstate.contracts.storage.DiamondBase'
);
event DiamondCut (IDiamondCuttable.FacetCut[] facetCuts, address target, bytes data);
function layout () internal pure returns (Layout storage l) {
bytes32 slot = STORAGE_SLOT;
assembly { l.slot := slot }
}
function diamondCut(
Layout storage l,
IDiamondCuttable.FacetCut[] memory facetCuts,
address target,
bytes memory data
) internal {
unchecked {
uint256 originalSelectorCount = l.selectorCount;
uint256 selectorCount = originalSelectorCount;
bytes32 selectorSlot;
if (selectorCount & 7 > 0) {
selectorSlot = l.selectorSlots[selectorCount >> 3];
}
for (uint256 i; i < facetCuts.length; i++) {
IDiamondCuttable.FacetCut memory facetCut = facetCuts[i];
IDiamondCuttable.FacetCutAction action = facetCut.action;
require(
facetCut.selectors.length > 0,
'DiamondBase: no selectors specified'
);
if (action == IDiamondCuttable.FacetCutAction.ADD) {
(selectorCount, selectorSlot) = l.addFacetSelectors(
selectorCount,
selectorSlot,
facetCut
);
} else if (action == IDiamondCuttable.FacetCutAction.REMOVE) {
(selectorCount, selectorSlot) = l.removeFacetSelectors(
selectorCount,
selectorSlot,
facetCut
);
} else if (action == IDiamondCuttable.FacetCutAction.REPLACE) {
l.replaceFacetSelectors(facetCut);
}
}
if (selectorCount != originalSelectorCount) {
l.selectorCount = uint16(selectorCount);
}
if (selectorCount & 7 > 0) {
l.selectorSlots[selectorCount >> 3] = selectorSlot;
}
emit DiamondCut(facetCuts, target, data);
initialize(target, data);
}
}
function addFacetSelectors (
Layout storage l,
uint256 selectorCount,
bytes32 selectorSlot,
IDiamondCuttable.FacetCut memory facetCut
) internal returns (uint256, bytes32) {
unchecked {
require(
facetCut.target == address(this) || facetCut.target.isContract(),
'DiamondBase: ADD target has no code'
);
for (uint256 i; i < facetCut.selectors.length; i++) {
bytes4 selector = facetCut.selectors[i];
bytes32 oldFacet = l.facets[selector];
require(
address(bytes20(oldFacet)) == address(0),
'DiamondBase: selector already added'
);
l.facets[selector] = bytes20(facetCut.target) | bytes32(selectorCount);
uint256 selectorInSlotPosition = (selectorCount & 7) << 5;
selectorSlot = (
selectorSlot & ~(CLEAR_SELECTOR_MASK >> selectorInSlotPosition)
) | (bytes32(selector) >> selectorInSlotPosition);
if (selectorInSlotPosition == 224) {
l.selectorSlots[selectorCount >> 3] = selectorSlot;
selectorSlot = 0;
}
selectorCount++;
}
return (selectorCount, selectorSlot);
}
}
function removeFacetSelectors (
Layout storage l,
uint256 selectorCount,
bytes32 selectorSlot,
IDiamondCuttable.FacetCut memory facetCut
) internal returns (uint256, bytes32) {
unchecked {
require(
facetCut.target == address(0),
'DiamondBase: REMOVE target must be zero address'
);
uint256 selectorSlotCount = selectorCount >> 3;
uint256 selectorInSlotIndex = selectorCount & 7;
for (uint256 i; i < facetCut.selectors.length; i++) {
bytes4 selector = facetCut.selectors[i];
bytes32 oldFacet = l.facets[selector];
require(
address(bytes20(oldFacet)) != address(0),
'DiamondBase: selector not found'
);
require(
address(bytes20(oldFacet)) != address(this),
'DiamondBase: selector is immutable'
);
if (selectorSlot == 0) {
selectorSlotCount--;
selectorSlot = l.selectorSlots[selectorSlotCount];
selectorInSlotIndex = 7;
} else {
selectorInSlotIndex--;
}
bytes4 lastSelector;
uint256 oldSelectorsSlotCount;
uint256 oldSelectorInSlotPosition;
{
lastSelector = bytes4(selectorSlot << (selectorInSlotIndex << 5));
if (lastSelector != selector) {
l.facets[lastSelector] = (
oldFacet & CLEAR_ADDRESS_MASK
) | bytes20(l.facets[lastSelector]);
}
delete l.facets[selector];
uint256 oldSelectorCount = uint16(uint256(oldFacet));
oldSelectorsSlotCount = oldSelectorCount >> 3;
oldSelectorInSlotPosition = (oldSelectorCount & 7) << 5;
}
if (oldSelectorsSlotCount != selectorSlotCount) {
bytes32 oldSelectorSlot = l.selectorSlots[oldSelectorsSlotCount];
oldSelectorSlot = (
oldSelectorSlot & ~(CLEAR_SELECTOR_MASK >> oldSelectorInSlotPosition)
) | (bytes32(lastSelector) >> oldSelectorInSlotPosition);
l.selectorSlots[oldSelectorsSlotCount] = oldSelectorSlot;
} else {
selectorSlot = (
selectorSlot & ~(CLEAR_SELECTOR_MASK >> oldSelectorInSlotPosition)
) | (bytes32(lastSelector) >> oldSelectorInSlotPosition);
}
if (selectorInSlotIndex == 0) {
delete l.selectorSlots[selectorSlotCount];
selectorSlot = 0;
}
}
selectorCount = (selectorSlotCount << 3) | selectorInSlotIndex;
return (selectorCount, selectorSlot);
}
}
function replaceFacetSelectors (
Layout storage l,
IDiamondCuttable.FacetCut memory facetCut
) internal {
unchecked {
require(
facetCut.target.isContract(),
'DiamondBase: REPLACE target has no code'
);
for (uint256 i; i < facetCut.selectors.length; i++) {
bytes4 selector = facetCut.selectors[i];
bytes32 oldFacet = l.facets[selector];
address oldFacetAddress = address(bytes20(oldFacet));
require(
oldFacetAddress != address(0),
'DiamondBase: selector not found'
);
require(
oldFacetAddress != address(this),
'DiamondBase: selector is immutable'
);
require(
oldFacetAddress != facetCut.target,
'DiamondBase: REPLACE target is identical'
);
l.facets[selector] = (oldFacet & CLEAR_ADDRESS_MASK) | bytes20(facetCut.target);
}
}
}
function initialize (
address target,
bytes memory data
) private {
require(
(target == address(0)) == (data.length == 0),
'DiamondBase: invalid initialization parameters'
);
if (target != address(0)) {
if (target != address(this)) {
require(
target.isContract(),
'DiamondBase: initialization target has no code'
);
}
(bool success, ) = target.delegatecall(data);
if (!success) {
assembly {
returndatacopy(0, 0, returndatasize())
revert(0, returndatasize())
}
}
}
}
}
文件 5 的 21:DiamondCuttable.sol
pragma solidity ^0.8.0;
import {OwnableInternal} from '../../access/OwnableInternal.sol';
import {IDiamondCuttable} from './IDiamondCuttable.sol';
import {DiamondBaseStorage} from './DiamondBaseStorage.sol';
abstract contract DiamondCuttable is IDiamondCuttable, OwnableInternal {
using DiamondBaseStorage for DiamondBaseStorage.Layout;
function diamondCut (
FacetCut[] calldata facetCuts,
address target,
bytes calldata data
) external override onlyOwner {
DiamondBaseStorage.layout().diamondCut(facetCuts, target, data);
}
}
文件 6 的 21:DiamondLoupe.sol
pragma solidity ^0.8.0;
import {DiamondBaseStorage} from './DiamondBaseStorage.sol';
import {IDiamondLoupe} from './IDiamondLoupe.sol';
abstract contract DiamondLoupe is IDiamondLoupe {
function facets () external override view returns (Facet[] memory diamondFacets) {
DiamondBaseStorage.Layout storage l = DiamondBaseStorage.layout();
diamondFacets = new Facet[](l.selectorCount);
uint8[] memory numFacetSelectors = new uint8[](l.selectorCount);
uint256 numFacets;
uint256 selectorIndex;
for (uint256 slotIndex; selectorIndex < l.selectorCount; slotIndex++) {
bytes32 slot = l.selectorSlots[slotIndex];
for (uint256 selectorSlotIndex; selectorSlotIndex < 8; selectorSlotIndex++) {
selectorIndex++;
if (selectorIndex > l.selectorCount) {
break;
}
bytes4 selector = bytes4(slot << (selectorSlotIndex << 5));
address facet = address(bytes20(l.facets[selector]));
bool continueLoop;
for (uint256 facetIndex; facetIndex < numFacets; facetIndex++) {
if (diamondFacets[facetIndex].target == facet) {
diamondFacets[facetIndex].selectors[numFacetSelectors[facetIndex]] = selector;
require(numFacetSelectors[facetIndex] < 255);
numFacetSelectors[facetIndex]++;
continueLoop = true;
break;
}
}
if (continueLoop) {
continue;
}
diamondFacets[numFacets].target = facet;
diamondFacets[numFacets].selectors = new bytes4[](l.selectorCount);
diamondFacets[numFacets].selectors[0] = selector;
numFacetSelectors[numFacets] = 1;
numFacets++;
}
}
for (uint256 facetIndex; facetIndex < numFacets; facetIndex++) {
uint256 numSelectors = numFacetSelectors[facetIndex];
bytes4[] memory selectors = diamondFacets[facetIndex].selectors;
assembly { mstore(selectors, numSelectors) }
}
assembly { mstore(diamondFacets, numFacets) }
}
function facetFunctionSelectors (
address facet
) external override view returns (bytes4[] memory selectors) {
DiamondBaseStorage.Layout storage l = DiamondBaseStorage.layout();
selectors = new bytes4[](l.selectorCount);
uint256 numSelectors;
uint256 selectorIndex;
for (uint256 slotIndex; selectorIndex < l.selectorCount; slotIndex++) {
bytes32 slot = l.selectorSlots[slotIndex];
for (uint256 selectorSlotIndex; selectorSlotIndex < 8; selectorSlotIndex++) {
selectorIndex++;
if (selectorIndex > l.selectorCount) {
break;
}
bytes4 selector = bytes4(slot << (selectorSlotIndex << 5));
if (facet == address(bytes20(l.facets[selector]))) {
selectors[numSelectors] = selector;
numSelectors++;
}
}
}
assembly { mstore(selectors, numSelectors) }
}
function facetAddresses () external override view returns (address[] memory addresses) {
DiamondBaseStorage.Layout storage l = DiamondBaseStorage.layout();
addresses = new address[](l.selectorCount);
uint256 numFacets;
uint256 selectorIndex;
for (uint256 slotIndex; selectorIndex < l.selectorCount; slotIndex++) {
bytes32 slot = l.selectorSlots[slotIndex];
for (uint256 selectorSlotIndex; selectorSlotIndex < 8; selectorSlotIndex++) {
selectorIndex++;
if (selectorIndex > l.selectorCount) {
break;
}
bytes4 selector = bytes4(slot << (selectorSlotIndex << 5));
address facet = address(bytes20(l.facets[selector]));
bool continueLoop;
for (uint256 facetIndex; facetIndex < numFacets; facetIndex++) {
if (facet == addresses[facetIndex]) {
continueLoop = true;
break;
}
}
if (continueLoop) {
continue;
}
addresses[numFacets] = facet;
numFacets++;
}
}
assembly { mstore(addresses, numFacets) }
}
function facetAddress (
bytes4 selector
) external override view returns (address facet) {
facet = address(bytes20(
DiamondBaseStorage.layout().facets[selector]
));
}
}
文件 7 的 21:ERC165.sol
pragma solidity ^0.8.0;
import {IERC165} from './IERC165.sol';
import {ERC165Storage} from './ERC165Storage.sol';
abstract contract ERC165 is IERC165 {
using ERC165Storage for ERC165Storage.Layout;
function supportsInterface (bytes4 interfaceId) override public view returns (bool) {
return ERC165Storage.layout().isSupportedInterface(interfaceId);
}
}
文件 8 的 21:ERC165Storage.sol
pragma solidity ^0.8.0;
library ERC165Storage {
struct Layout {
mapping (bytes4 => bool) supportedInterfaces;
}
bytes32 internal constant STORAGE_SLOT = keccak256(
'solidstate.contracts.storage.ERC165'
);
function layout () internal pure returns (Layout storage l) {
bytes32 slot = STORAGE_SLOT;
assembly { l.slot := slot }
}
function isSupportedInterface (
Layout storage l,
bytes4 interfaceId
) internal view returns (bool) {
return l.supportedInterfaces[interfaceId];
}
function setSupportedInterface (
Layout storage l,
bytes4 interfaceId,
bool status
) internal {
require(interfaceId != 0xffffffff, 'ERC165: invalid interface id');
l.supportedInterfaces[interfaceId] = status;
}
}
文件 9 的 21:ERC20MetadataStorage.sol
pragma solidity ^0.8.0;
library ERC20MetadataStorage {
struct Layout {
string name;
string symbol;
uint8 decimals;
}
bytes32 internal constant STORAGE_SLOT = keccak256(
'solidstate.contracts.storage.ERC20Metadata'
);
function layout () internal pure returns (Layout storage l) {
bytes32 slot = STORAGE_SLOT;
assembly { l.slot := slot }
}
function setName (
Layout storage l,
string memory name
) internal {
l.name = name;
}
function setSymbol (
Layout storage l,
string memory symbol
) internal {
l.symbol = symbol;
}
function setDecimals (
Layout storage l,
uint8 decimals
) internal {
l.decimals = decimals;
}
}
文件 10 的 21:IDiamondCuttable.sol
pragma solidity ^0.8.0;
interface IDiamondCuttable {
enum FacetCutAction { ADD, REPLACE, REMOVE }
event DiamondCut (FacetCut[] facetCuts, address target, bytes data);
struct FacetCut {
address target;
FacetCutAction action;
bytes4[] selectors;
}
function diamondCut (
FacetCut[] calldata facetCuts,
address target,
bytes calldata data
) external;
}
文件 11 的 21:IDiamondLoupe.sol
pragma solidity ^0.8.0;
interface IDiamondLoupe {
struct Facet {
address target;
bytes4[] selectors;
}
function facets () external view returns (Facet[] memory diamondFacets);
function facetFunctionSelectors (
address facet
) external view returns (bytes4[] memory selectors);
function facetAddresses () external view returns (address[] memory addresses);
function facetAddress (
bytes4 selector
) external view returns (address facet);
}
文件 12 的 21:IERC165.sol
pragma solidity ^0.8.0;
interface IERC165 {
function supportsInterface (
bytes4 interfaceId
) external view returns (bool);
}
文件 13 的 21:IERC173.sol
pragma solidity ^0.8.0;
interface IERC173 {
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
function owner () external view returns (address);
function transferOwnership (address account) external;
}
文件 14 的 21:MagicProxy.sol
pragma solidity ^0.8.0;
import '@solidstate/contracts/proxy/diamond/Diamond.sol';
import '@solidstate/contracts/token/ERC20/metadata/ERC20MetadataStorage.sol';
contract MagicProxy is Diamond {
constructor() {
ERC20MetadataStorage.Layout storage l = ERC20MetadataStorage.layout();
l.name = 'MAGIC';
l.symbol = 'MAGIC';
}
}
文件 15 的 21:Ownable.sol
pragma solidity ^0.8.0;
import {IERC173} from './IERC173.sol';
import {OwnableInternal} from './OwnableInternal.sol';
import {OwnableStorage} from './OwnableStorage.sol';
abstract contract Ownable is IERC173, OwnableInternal {
using OwnableStorage for OwnableStorage.Layout;
function owner () virtual override public view returns (address) {
return OwnableStorage.layout().owner;
}
function transferOwnership (
address account
) virtual override public onlyOwner {
OwnableStorage.layout().setOwner(account);
emit OwnershipTransferred(msg.sender, account);
}
}
文件 16 的 21:OwnableInternal.sol
pragma solidity ^0.8.0;
import {OwnableStorage} from './OwnableStorage.sol';
abstract contract OwnableInternal {
using OwnableStorage for OwnableStorage.Layout;
modifier onlyOwner {
require(
msg.sender == OwnableStorage.layout().owner,
'Ownable: sender must be owner'
);
_;
}
}
文件 17 的 21:OwnableStorage.sol
pragma solidity ^0.8.0;
library OwnableStorage {
struct Layout {
address owner;
}
bytes32 internal constant STORAGE_SLOT = keccak256(
'solidstate.contracts.storage.Ownable'
);
function layout () internal pure returns (Layout storage l) {
bytes32 slot = STORAGE_SLOT;
assembly { l.slot := slot }
}
function setOwner (
Layout storage l,
address owner
) internal {
l.owner = owner;
}
}
文件 18 的 21:Proxy.sol
pragma solidity ^0.8.0;
import {AddressUtils} from '../utils/AddressUtils.sol';
abstract contract Proxy {
using AddressUtils for address;
fallback () virtual external payable {
address implementation = _getImplementation();
require(
implementation.isContract(),
'Proxy: implementation must be contract'
);
assembly {
calldatacopy(0, 0, calldatasize())
let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)
returndatacopy(0, 0, returndatasize())
switch result
case 0 { revert(0, returndatasize()) }
default { return (0, returndatasize()) }
}
}
function _getImplementation () virtual internal returns (address);
}
文件 19 的 21:SafeOwnable.sol
pragma solidity ^0.8.0;
import {Ownable, OwnableStorage} from './Ownable.sol';
import {SafeOwnableInternal} from './SafeOwnableInternal.sol';
import {SafeOwnableStorage} from './SafeOwnableStorage.sol';
abstract contract SafeOwnable is Ownable, SafeOwnableInternal {
using OwnableStorage for OwnableStorage.Layout;
using SafeOwnableStorage for SafeOwnableStorage.Layout;
function nomineeOwner () virtual public view returns (address) {
return SafeOwnableStorage.layout().nomineeOwner;
}
function transferOwnership (
address account
) virtual override public onlyOwner {
SafeOwnableStorage.layout().setNomineeOwner(account);
}
function acceptOwnership () virtual public onlyNomineeOwner {
OwnableStorage.Layout storage l = OwnableStorage.layout();
emit OwnershipTransferred(l.owner, msg.sender);
l.setOwner(msg.sender);
SafeOwnableStorage.layout().setNomineeOwner(address(0));
}
}
文件 20 的 21:SafeOwnableInternal.sol
pragma solidity ^0.8.0;
import {SafeOwnableStorage} from './SafeOwnableStorage.sol';
abstract contract SafeOwnableInternal {
using SafeOwnableStorage for SafeOwnableStorage.Layout;
modifier onlyNomineeOwner () {
require(
msg.sender == SafeOwnableStorage.layout().nomineeOwner,
'SafeOwnable: sender must be nominee owner'
);
_;
}
}
文件 21 的 21:SafeOwnableStorage.sol
pragma solidity ^0.8.0;
library SafeOwnableStorage {
struct Layout {
address nomineeOwner;
}
bytes32 internal constant STORAGE_SLOT = keccak256(
'solidstate.contracts.storage.SafeOwnable'
);
function layout () internal pure returns (Layout storage l) {
bytes32 slot = STORAGE_SLOT;
assembly { l.slot := slot }
}
function setNomineeOwner (
Layout storage l,
address nomineeOwner
) internal {
l.nomineeOwner = nomineeOwner;
}
}
{
"compilationTarget": {
"contracts/token/MagicProxy.sol": "MagicProxy"
},
"evmVersion": "istanbul",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"components":[{"internalType":"address","name":"target","type":"address"},{"internalType":"enum IDiamondCuttable.FacetCutAction","name":"action","type":"uint8"},{"internalType":"bytes4[]","name":"selectors","type":"bytes4[]"}],"indexed":false,"internalType":"struct IDiamondCuttable.FacetCut[]","name":"facetCuts","type":"tuple[]"},{"indexed":false,"internalType":"address","name":"target","type":"address"},{"indexed":false,"internalType":"bytes","name":"data","type":"bytes"}],"name":"DiamondCut","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"target","type":"address"},{"internalType":"enum IDiamondCuttable.FacetCutAction","name":"action","type":"uint8"},{"internalType":"bytes4[]","name":"selectors","type":"bytes4[]"}],"internalType":"struct IDiamondCuttable.FacetCut[]","name":"facetCuts","type":"tuple[]"},{"internalType":"address","name":"target","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"diamondCut","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"selector","type":"bytes4"}],"name":"facetAddress","outputs":[{"internalType":"address","name":"facet","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"facetAddresses","outputs":[{"internalType":"address[]","name":"addresses","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"facet","type":"address"}],"name":"facetFunctionSelectors","outputs":[{"internalType":"bytes4[]","name":"selectors","type":"bytes4[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"facets","outputs":[{"components":[{"internalType":"address","name":"target","type":"address"},{"internalType":"bytes4[]","name":"selectors","type":"bytes4[]"}],"internalType":"struct IDiamondLoupe.Facet[]","name":"diamondFacets","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFallbackAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nomineeOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"fallbackAddress","type":"address"}],"name":"setFallbackAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]