文件 1 的 8:IDiamondCut.sol
pragma solidity 0.7.6;
pragma experimental ABIEncoderV2;
interface IDiamondCut {
enum FacetCutAction {Add, Replace, Remove}
struct FacetCut {
address facetAddress;
FacetCutAction action;
bytes4[] functionSelectors;
}
function diamondCut(
FacetCut[] calldata _diamondCut,
address _init,
bytes calldata _calldata
) external;
event DiamondCut(FacetCut[] _diamondCut, address _init, bytes _calldata);
}
文件 2 的 8:IDiamondLoupe.sol
pragma solidity 0.7.6;
pragma experimental ABIEncoderV2;
interface IDiamondLoupe {
struct Facet {
address facetAddress;
bytes4[] functionSelectors;
}
function facets() external view returns (Facet[] memory facets_);
function facetFunctionSelectors(address _facet) external view returns (bytes4[] memory facetFunctionSelectors_);
function facetAddresses() external view returns (address[] memory facetAddresses_);
function facetAddress(bytes4 _functionSelector) external view returns (address facetAddress_);
}
文件 3 的 8:IERC165.sol
pragma solidity 0.7.6;
pragma experimental ABIEncoderV2;
interface IERC165 {
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
文件 4 的 8:IERC173.sol
pragma solidity 0.7.6;
interface IERC173 {
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
function owner() external view returns (address owner_);
function transferOwnership(address _newOwner) external;
}
文件 5 的 8:LibDiamond.sol
pragma solidity 0.7.6;
pragma experimental ABIEncoderV2;
import "../interfaces/IDiamondCut.sol";
import "./LibDiamondStorage.sol";
library LibDiamond {
event DiamondCut(IDiamondCut.FacetCut[] _diamondCut, address _init, bytes _calldata);
function diamondCut(
IDiamondCut.FacetCut[] memory _diamondCut,
address _init,
bytes memory _calldata
) internal {
uint256 selectorCount = LibDiamondStorage.diamondStorage().selectors.length;
for (uint256 facetIndex; facetIndex < _diamondCut.length; facetIndex++) {
selectorCount = executeDiamondCut(selectorCount, _diamondCut[facetIndex]);
}
emit DiamondCut(_diamondCut, _init, _calldata);
initializeDiamondCut(_init, _calldata);
}
function executeDiamondCut(uint256 selectorCount, IDiamondCut.FacetCut memory cut) internal returns (uint256) {
require(cut.functionSelectors.length > 0, "LibDiamond: No selectors in facet to cut");
if (cut.action == IDiamondCut.FacetCutAction.Add) {
require(cut.facetAddress != address(0), "LibDiamond: add facet address can't be address(0)");
enforceHasContractCode(cut.facetAddress, "LibDiamond: add facet must have code");
return _handleAddCut(selectorCount, cut);
}
if (cut.action == IDiamondCut.FacetCutAction.Replace) {
require(cut.facetAddress != address(0), "LibDiamond: remove facet address can't be address(0)");
enforceHasContractCode(cut.facetAddress, "LibDiamond: remove facet must have code");
return _handleReplaceCut(selectorCount, cut);
}
if (cut.action == IDiamondCut.FacetCutAction.Remove) {
require(cut.facetAddress == address(0), "LibDiamond: remove facet address must be address(0)");
return _handleRemoveCut(selectorCount, cut);
}
revert("LibDiamondCut: Incorrect FacetCutAction");
}
function _handleAddCut(uint256 selectorCount, IDiamondCut.FacetCut memory cut) internal returns (uint256) {
LibDiamondStorage.DiamondStorage storage ds = LibDiamondStorage.diamondStorage();
for (uint256 selectorIndex; selectorIndex < cut.functionSelectors.length; selectorIndex++) {
bytes4 selector = cut.functionSelectors[selectorIndex];
address oldFacetAddress = ds.facets[selector].facetAddress;
require(oldFacetAddress == address(0), "LibDiamondCut: Can't add function that already exists");
ds.facets[selector] = LibDiamondStorage.Facet(
cut.facetAddress,
uint16(selectorCount)
);
ds.selectors.push(selector);
selectorCount++;
}
return selectorCount;
}
function _handleReplaceCut(uint256 selectorCount, IDiamondCut.FacetCut memory cut) internal returns (uint256) {
LibDiamondStorage.DiamondStorage storage ds = LibDiamondStorage.diamondStorage();
for (uint256 selectorIndex; selectorIndex < cut.functionSelectors.length; selectorIndex++) {
bytes4 selector = cut.functionSelectors[selectorIndex];
address oldFacetAddress = ds.facets[selector].facetAddress;
require(oldFacetAddress != address(this), "LibDiamondCut: Can't replace immutable function");
require(oldFacetAddress != cut.facetAddress, "LibDiamondCut: Can't replace function with same function");
require(oldFacetAddress != address(0), "LibDiamondCut: Can't replace function that doesn't exist");
ds.facets[selector].facetAddress = cut.facetAddress;
}
return selectorCount;
}
function _handleRemoveCut(uint256 selectorCount, IDiamondCut.FacetCut memory cut) internal returns (uint256) {
LibDiamondStorage.DiamondStorage storage ds = LibDiamondStorage.diamondStorage();
for (uint256 selectorIndex; selectorIndex < cut.functionSelectors.length; selectorIndex++) {
bytes4 selector = cut.functionSelectors[selectorIndex];
LibDiamondStorage.Facet memory oldFacet = ds.facets[selector];
require(oldFacet.facetAddress != address(0), "LibDiamondCut: Can't remove function that doesn't exist");
require(oldFacet.facetAddress != address(this), "LibDiamondCut: Can't remove immutable function.");
if (oldFacet.selectorPosition != selectorCount - 1) {
bytes4 lastSelector = ds.selectors[selectorCount - 1];
ds.selectors[oldFacet.selectorPosition] = lastSelector;
ds.facets[lastSelector].selectorPosition = oldFacet.selectorPosition;
}
ds.selectors.pop();
delete ds.facets[selector];
selectorCount--;
}
return selectorCount;
}
function initializeDiamondCut(address _init, bytes memory _calldata) internal {
if (_init == address(0)) {
require(_calldata.length == 0, "LibDiamondCut: _init is address(0) but _calldata is not empty");
return;
}
require(_calldata.length > 0, "LibDiamondCut: _calldata is empty but _init is not address(0)");
if (_init != address(this)) {
enforceHasContractCode(_init, "LibDiamondCut: _init address has no code");
}
(bool success, bytes memory error) = _init.delegatecall(_calldata);
if (!success) {
if (error.length > 0) {
revert(string(error));
} else {
revert("LibDiamondCut: _init function reverted");
}
}
}
function enforceHasContractCode(address _contract, string memory _errorMessage) internal view {
uint256 contractSize;
assembly {
contractSize := extcodesize(_contract)
}
require(contractSize > 0, _errorMessage);
}
}
文件 6 的 8:LibDiamondStorage.sol
pragma solidity 0.7.6;
pragma experimental ABIEncoderV2;
library LibDiamondStorage {
bytes32 constant DIAMOND_STORAGE_POSITION = keccak256("diamond.standard.diamond.storage");
struct Facet {
address facetAddress;
uint16 selectorPosition;
}
struct DiamondStorage {
mapping(bytes4 => Facet) facets;
bytes4[] selectors;
mapping(bytes4 => bool) supportedInterfaces;
address contractOwner;
}
function diamondStorage() internal pure returns (DiamondStorage storage ds) {
bytes32 position = DIAMOND_STORAGE_POSITION;
assembly {
ds.slot := position
}
}
}
文件 7 的 8:LibOwnership.sol
pragma solidity 0.7.6;
pragma experimental ABIEncoderV2;
import "./LibDiamondStorage.sol";
library LibOwnership {
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
function setContractOwner(address _newOwner) internal {
LibDiamondStorage.DiamondStorage storage ds = LibDiamondStorage.diamondStorage();
address previousOwner = ds.contractOwner;
require(previousOwner != _newOwner, "Previous owner and new owner must be different");
ds.contractOwner = _newOwner;
emit OwnershipTransferred(previousOwner, _newOwner);
}
function contractOwner() internal view returns (address contractOwner_) {
contractOwner_ = LibDiamondStorage.diamondStorage().contractOwner;
}
function enforceIsContractOwner() view internal {
require(msg.sender == LibDiamondStorage.diamondStorage().contractOwner, "Must be contract owner");
}
modifier onlyOwner {
require(msg.sender == LibDiamondStorage.diamondStorage().contractOwner, "Must be contract owner");
_;
}
}
文件 8 的 8:Supernova.sol
pragma solidity 0.7.6;
pragma experimental ABIEncoderV2;
import "./interfaces/IDiamondCut.sol";
import "./interfaces/IDiamondLoupe.sol";
import "./libraries/LibDiamond.sol";
import "./libraries/LibOwnership.sol";
import "./libraries/LibDiamondStorage.sol";
import "./interfaces/IERC165.sol";
import "./interfaces/IERC173.sol";
contract Supernova {
constructor(IDiamondCut.FacetCut[] memory _diamondCut, address _owner) payable {
require(_owner != address(0), "owner must not be 0x0");
LibDiamond.diamondCut(_diamondCut, address(0), new bytes(0));
LibOwnership.setContractOwner(_owner);
LibDiamondStorage.DiamondStorage storage ds = LibDiamondStorage.diamondStorage();
ds.supportedInterfaces[type(IERC165).interfaceId] = true;
ds.supportedInterfaces[type(IDiamondCut).interfaceId] = true;
ds.supportedInterfaces[type(IDiamondLoupe).interfaceId] = true;
ds.supportedInterfaces[type(IERC173).interfaceId] = true;
}
fallback() external payable {
LibDiamondStorage.DiamondStorage storage ds = LibDiamondStorage.diamondStorage();
address facet = address(bytes20(ds.facets[msg.sig].facetAddress));
require(facet != address(0), "Diamond: Function does not exist");
assembly {
calldatacopy(0, 0, calldatasize())
let result := delegatecall(gas(), facet, 0, calldatasize(), 0, 0)
returndatacopy(0, 0, returndatasize())
switch result
case 0 {
revert(0, returndatasize())
}
default {
return (0, returndatasize())
}
}
}
receive() external payable {}
}
{
"compilationTarget": {
"contracts/Supernova.sol": "Supernova"
},
"evmVersion": "istanbul",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 9999
},
"remappings": []
}
[{"inputs":[{"components":[{"internalType":"address","name":"facetAddress","type":"address"},{"internalType":"enum IDiamondCut.FacetCutAction","name":"action","type":"uint8"},{"internalType":"bytes4[]","name":"functionSelectors","type":"bytes4[]"}],"internalType":"struct IDiamondCut.FacetCut[]","name":"_diamondCut","type":"tuple[]"},{"internalType":"address","name":"_owner","type":"address"}],"stateMutability":"payable","type":"constructor"},{"stateMutability":"payable","type":"fallback"},{"stateMutability":"payable","type":"receive"}]