编译器
0.8.25+commit.b61c2a91
文件 1 的 5:Diamond.sol
pragma solidity ^0.8.0;
import {LibDiamond} from "./libraries/LibDiamond.sol";
import {IDiamondCutFacet} from "./interfaces/IDiamondCutFacet.sol";
contract Diamond {
error FunctionDoesNotExist(bytes4);
constructor(
address _contractOwner,
IDiamondCutFacet.FacetCut[] memory _cuts,
IDiamondCutFacet.Initializer memory _init
) payable {
LibDiamond.setContractOwner(_contractOwner);
LibDiamond.diamondCut(_cuts, _init.initializer, _init.data);
}
fallback() external payable {
LibDiamond.DiamondStorage storage ds;
bytes32 position = LibDiamond.DIAMOND_STORAGE_POSITION;
assembly {
ds.slot := position
}
address facet = ds.selectorToFacetAndPosition[msg.sig].facetAddress;
if (facet == address(0)) revert FunctionDoesNotExist(msg.sig);
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 {}
}
文件 2 的 5:EnumerableMap.sol
pragma solidity ^0.8.18;
library EnumerableMap {
error EnumerableMap__IndexOutOfBounds();
error EnumerableMap__NonExistentKey();
struct MapEntry {
bytes32 _key;
bytes32 _value;
}
struct Map {
MapEntry[] _entries;
mapping(bytes32 => uint256) _indexes;
}
struct AddressToAddressMap {
Map _inner;
}
struct UintToAddressMap {
Map _inner;
}
function at(
AddressToAddressMap storage map,
uint256 index
) internal view returns (address, address) {
(bytes32 key, bytes32 value) = _at(map._inner, index);
return (
address(uint160(uint256(key))),
address(uint160(uint256(value)))
);
}
function at(
UintToAddressMap storage map,
uint256 index
) internal view returns (uint256, address) {
(bytes32 key, bytes32 value) = _at(map._inner, index);
return (uint256(key), address(uint160(uint256(value))));
}
function contains(
AddressToAddressMap storage map,
address key
) internal view returns (bool) {
return _contains(map._inner, bytes32(uint256(uint160(key))));
}
function contains(
UintToAddressMap storage map,
uint256 key
) internal view returns (bool) {
return _contains(map._inner, bytes32(key));
}
function length(
AddressToAddressMap storage map
) internal view returns (uint256) {
return _length(map._inner);
}
function length(
UintToAddressMap storage map
) internal view returns (uint256) {
return _length(map._inner);
}
function get(
AddressToAddressMap storage map,
address key
) internal view returns (address) {
return
address(
uint160(
uint256(_get(map._inner, bytes32(uint256(uint160(key)))))
)
);
}
function get(
UintToAddressMap storage map,
uint256 key
) internal view returns (address) {
return address(uint160(uint256(_get(map._inner, bytes32(key)))));
}
function set(
AddressToAddressMap storage map,
address key,
address value
) internal returns (bool) {
return
_set(
map._inner,
bytes32(uint256(uint160(key))),
bytes32(uint256(uint160(value)))
);
}
function set(
UintToAddressMap storage map,
uint256 key,
address value
) internal returns (bool) {
return _set(map._inner, bytes32(key), bytes32(uint256(uint160(value))));
}
function remove(
AddressToAddressMap storage map,
address key
) internal returns (bool) {
return _remove(map._inner, bytes32(uint256(uint160(key))));
}
function remove(
UintToAddressMap storage map,
uint256 key
) internal returns (bool) {
return _remove(map._inner, bytes32(key));
}
function toArray(
AddressToAddressMap storage map
)
internal
view
returns (address[] memory keysOut, address[] memory valuesOut)
{
uint256 len = map._inner._entries.length;
keysOut = new address[](len);
valuesOut = new address[](len);
unchecked {
for (uint256 i; i < len; ++i) {
keysOut[i] = address(
uint160(uint256(map._inner._entries[i]._key))
);
valuesOut[i] = address(
uint160(uint256(map._inner._entries[i]._value))
);
}
}
}
function toArray(
UintToAddressMap storage map
)
internal
view
returns (uint256[] memory keysOut, address[] memory valuesOut)
{
uint256 len = map._inner._entries.length;
keysOut = new uint256[](len);
valuesOut = new address[](len);
unchecked {
for (uint256 i; i < len; ++i) {
keysOut[i] = uint256(map._inner._entries[i]._key);
valuesOut[i] = address(
uint160(uint256(map._inner._entries[i]._value))
);
}
}
}
function keys(
AddressToAddressMap storage map
) internal view returns (address[] memory keysOut) {
uint256 len = map._inner._entries.length;
keysOut = new address[](len);
unchecked {
for (uint256 i; i < len; ++i) {
keysOut[i] = address(
uint160(uint256(map._inner._entries[i]._key))
);
}
}
}
function keys(
UintToAddressMap storage map
) internal view returns (uint256[] memory keysOut) {
uint256 len = map._inner._entries.length;
keysOut = new uint256[](len);
unchecked {
for (uint256 i; i < len; ++i) {
keysOut[i] = uint256(map._inner._entries[i]._key);
}
}
}
function values(
AddressToAddressMap storage map
) internal view returns (address[] memory valuesOut) {
uint256 len = map._inner._entries.length;
valuesOut = new address[](len);
unchecked {
for (uint256 i; i < len; ++i) {
valuesOut[i] = address(
uint160(uint256(map._inner._entries[i]._value))
);
}
}
}
function values(
UintToAddressMap storage map
) internal view returns (address[] memory valuesOut) {
uint256 len = map._inner._entries.length;
valuesOut = new address[](len);
unchecked {
for (uint256 i; i < len; ++i) {
valuesOut[i] = address(
uint160(uint256(map._inner._entries[i]._value))
);
}
}
}
function _at(
Map storage map,
uint256 index
) private view returns (bytes32, bytes32) {
if (index >= map._entries.length)
revert EnumerableMap__IndexOutOfBounds();
MapEntry storage entry = map._entries[index];
return (entry._key, entry._value);
}
function _contains(
Map storage map,
bytes32 key
) private view returns (bool) {
return map._indexes[key] != 0;
}
function _length(Map storage map) private view returns (uint256) {
return map._entries.length;
}
function _get(Map storage map, bytes32 key) private view returns (bytes32) {
uint256 keyIndex = map._indexes[key];
if (keyIndex == 0) revert EnumerableMap__NonExistentKey();
unchecked {
return map._entries[keyIndex - 1]._value;
}
}
function _set(
Map storage map,
bytes32 key,
bytes32 value
) private returns (bool) {
uint256 keyIndex = map._indexes[key];
if (keyIndex == 0) {
map._entries.push(MapEntry({ _key: key, _value: value }));
map._indexes[key] = map._entries.length;
return true;
} else {
unchecked {
map._entries[keyIndex - 1]._value = value;
}
return false;
}
}
function _remove(Map storage map, bytes32 key) private returns (bool) {
uint256 keyIndex = map._indexes[key];
if (keyIndex != 0) {
unchecked {
MapEntry storage last = map._entries[map._entries.length - 1];
map._entries[keyIndex - 1] = last;
map._indexes[last._key] = keyIndex;
}
map._entries.pop();
delete map._indexes[key];
return true;
} else {
return false;
}
}
}
文件 3 的 5:EnumerableSet.sol
pragma solidity ^0.8.18;
library EnumerableSet {
error EnumerableSet__IndexOutOfBounds();
struct Set {
bytes32[] _values;
mapping(bytes32 => uint256) _indexes;
}
struct Bytes32Set {
Set _inner;
}
struct AddressSet {
Set _inner;
}
struct UintSet {
Set _inner;
}
function at(
Bytes32Set storage set,
uint256 index
) internal view returns (bytes32) {
return _at(set._inner, index);
}
function at(
AddressSet storage set,
uint256 index
) internal view returns (address) {
return address(uint160(uint256(_at(set._inner, index))));
}
function at(
UintSet storage set,
uint256 index
) internal view returns (uint256) {
return uint256(_at(set._inner, index));
}
function contains(
Bytes32Set storage set,
bytes32 value
) internal view returns (bool) {
return _contains(set._inner, value);
}
function contains(
AddressSet storage set,
address value
) internal view returns (bool) {
return _contains(set._inner, bytes32(uint256(uint160(value))));
}
function contains(
UintSet storage set,
uint256 value
) internal view returns (bool) {
return _contains(set._inner, bytes32(value));
}
function indexOf(
Bytes32Set storage set,
bytes32 value
) internal view returns (uint256) {
return _indexOf(set._inner, value);
}
function indexOf(
AddressSet storage set,
address value
) internal view returns (uint256) {
return _indexOf(set._inner, bytes32(uint256(uint160(value))));
}
function indexOf(
UintSet storage set,
uint256 value
) internal view returns (uint256) {
return _indexOf(set._inner, bytes32(value));
}
function length(Bytes32Set storage set) internal view returns (uint256) {
return _length(set._inner);
}
function length(AddressSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
function length(UintSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
function add(
Bytes32Set storage set,
bytes32 value
) internal returns (bool) {
return _add(set._inner, value);
}
function add(
AddressSet storage set,
address value
) internal returns (bool) {
return _add(set._inner, bytes32(uint256(uint160(value))));
}
function add(UintSet storage set, uint256 value) internal returns (bool) {
return _add(set._inner, bytes32(value));
}
function remove(
Bytes32Set storage set,
bytes32 value
) internal returns (bool) {
return _remove(set._inner, value);
}
function remove(
AddressSet storage set,
address value
) internal returns (bool) {
return _remove(set._inner, bytes32(uint256(uint160(value))));
}
function remove(
UintSet storage set,
uint256 value
) internal returns (bool) {
return _remove(set._inner, bytes32(value));
}
function toArray(
Bytes32Set storage set
) internal view returns (bytes32[] memory) {
return set._inner._values;
}
function toArray(
AddressSet storage set
) internal view returns (address[] memory) {
bytes32[] storage values = set._inner._values;
address[] storage array;
assembly {
array.slot := values.slot
}
return array;
}
function toArray(
UintSet storage set
) internal view returns (uint256[] memory) {
bytes32[] storage values = set._inner._values;
uint256[] storage array;
assembly {
array.slot := values.slot
}
return array;
}
function _at(
Set storage set,
uint256 index
) private view returns (bytes32) {
if (index >= set._values.length)
revert EnumerableSet__IndexOutOfBounds();
return set._values[index];
}
function _contains(
Set storage set,
bytes32 value
) private view returns (bool) {
return set._indexes[value] != 0;
}
function _indexOf(
Set storage set,
bytes32 value
) private view returns (uint256) {
unchecked {
return set._indexes[value] - 1;
}
}
function _length(Set storage set) private view returns (uint256) {
return set._values.length;
}
function _add(
Set storage set,
bytes32 value
) private returns (bool status) {
if (!_contains(set, value)) {
set._values.push(value);
set._indexes[value] = set._values.length;
status = true;
}
}
function _remove(
Set storage set,
bytes32 value
) private returns (bool status) {
uint256 valueIndex = set._indexes[value];
if (valueIndex != 0) {
unchecked {
bytes32 last = set._values[set._values.length - 1];
set._values[valueIndex - 1] = last;
set._indexes[last] = valueIndex;
}
set._values.pop();
delete set._indexes[value];
status = true;
}
}
}
文件 4 的 5:IDiamondCutFacet.sol
pragma solidity ^0.8.0;
interface IDiamondCutFacet {
struct Initializer {
address initializer;
bytes data;
}
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);
}
interface IExtendedDiamondCutFacet is IDiamondCutFacet {
function executeInitializer(Initializer calldata _init) external;
}
文件 5 的 5:LibDiamond.sol
pragma solidity ^0.8.0;
import {IDiamondCutFacet} from "../interfaces/IDiamondCutFacet.sol";
import {EnumerableMap} from "lib/solidstate/contracts/data/EnumerableMap.sol";
import {EnumerableSet} from "lib/solidstate/contracts/data/EnumerableSet.sol";
error InitializationFunctionReverted(
address _initializationContractAddress,
bytes _calldata
);
library LibDiamond {
using EnumerableSet for EnumerableSet.UintSet;
using EnumerableMap for EnumerableMap.UintToAddressMap;
bytes32 constant DIAMOND_STORAGE_POSITION =
keccak256("diamond.standard.diamond.storage");
struct FacetAddressAndPosition {
address facetAddress;
uint96 functionSelectorPosition;
}
struct FacetFunctionSelectors {
bytes4[] functionSelectors;
uint256 facetAddressPosition;
}
struct DiamondStorage {
mapping(bytes4 => FacetAddressAndPosition) selectorToFacetAndPosition;
mapping(address => FacetFunctionSelectors) facetFunctionSelectors;
address[] facetAddresses;
mapping(bytes4 => bool) supportedInterfaces;
address contractOwner;
EnumerableMap.UintToAddressMap tokenOwners;
mapping(address => EnumerableSet.UintSet) holderTokens;
mapping(uint256 => address) tokenApprovals;
mapping(address => mapping(address => bool)) operatorApprovals;
}
function diamondStorage()
internal
pure
returns (DiamondStorage storage ds)
{
bytes32 position = DIAMOND_STORAGE_POSITION;
assembly {
ds.slot := position
}
}
event OwnershipTransferred(
address indexed previousOwner,
address indexed newOwner
);
function setContractOwner(address _newOwner) internal {
DiamondStorage storage ds = diamondStorage();
address previousOwner = ds.contractOwner;
ds.contractOwner = _newOwner;
emit OwnershipTransferred(previousOwner, _newOwner);
}
function contractOwner() internal view returns (address contractOwner_) {
contractOwner_ = diamondStorage().contractOwner;
}
event DiamondCut(
IDiamondCutFacet.FacetCut[] _diamondCut,
address _init,
bytes _calldata
);
function diamondCut(
IDiamondCutFacet.FacetCut[] memory _diamondCut,
address _init,
bytes memory _calldata
) internal {
for (
uint256 facetIndex;
facetIndex < _diamondCut.length;
facetIndex++
) {
IDiamondCutFacet.FacetCutAction action = _diamondCut[facetIndex]
.action;
if (action == IDiamondCutFacet.FacetCutAction.Add) {
addFunctions(
_diamondCut[facetIndex].facetAddress,
_diamondCut[facetIndex].functionSelectors
);
} else if (action == IDiamondCutFacet.FacetCutAction.Replace) {
replaceFunctions(
_diamondCut[facetIndex].facetAddress,
_diamondCut[facetIndex].functionSelectors
);
} else if (action == IDiamondCutFacet.FacetCutAction.Remove) {
removeFunctions(
_diamondCut[facetIndex].facetAddress,
_diamondCut[facetIndex].functionSelectors
);
} else {
revert("LibDiamondCut: Incorrect FacetCutAction");
}
}
emit DiamondCut(_diamondCut, _init, _calldata);
initializeDiamondCut(_init, _calldata);
}
function addFunctions(
address _facetAddress,
bytes4[] memory _functionSelectors
) internal {
require(
_functionSelectors.length > 0,
"LibDiamondCut: No selectors in facet to cut"
);
DiamondStorage storage ds = diamondStorage();
require(
_facetAddress != address(0),
"LibDiamondCut: Add facet can't be address(0)"
);
uint96 selectorPosition = uint96(
ds.facetFunctionSelectors[_facetAddress].functionSelectors.length
);
if (selectorPosition == 0) {
addFacet(ds, _facetAddress);
}
for (
uint256 selectorIndex;
selectorIndex < _functionSelectors.length;
selectorIndex++
) {
bytes4 selector = _functionSelectors[selectorIndex];
address oldFacetAddress = ds
.selectorToFacetAndPosition[selector]
.facetAddress;
require(
oldFacetAddress == address(0),
"LibDiamondCut: Can't add function that already exists"
);
addFunction(ds, selector, selectorPosition, _facetAddress);
selectorPosition++;
}
}
function replaceFunctions(
address _facetAddress,
bytes4[] memory _functionSelectors
) internal {
require(
_functionSelectors.length > 0,
"LibDiamondCut: No selectors in facet to cut"
);
DiamondStorage storage ds = diamondStorage();
require(
_facetAddress != address(0),
"LibDiamondCut: Add facet can't be address(0)"
);
uint96 selectorPosition = uint96(
ds.facetFunctionSelectors[_facetAddress].functionSelectors.length
);
if (selectorPosition == 0) {
addFacet(ds, _facetAddress);
}
for (
uint256 selectorIndex;
selectorIndex < _functionSelectors.length;
selectorIndex++
) {
bytes4 selector = _functionSelectors[selectorIndex];
address oldFacetAddress = ds
.selectorToFacetAndPosition[selector]
.facetAddress;
require(
oldFacetAddress != _facetAddress,
"LibDiamondCut: Can't replace function with same function"
);
removeFunction(ds, oldFacetAddress, selector);
addFunction(ds, selector, selectorPosition, _facetAddress);
selectorPosition++;
}
}
function removeFunctions(
address _facetAddress,
bytes4[] memory _functionSelectors
) internal {
require(
_functionSelectors.length > 0,
"LibDiamondCut: No selectors in facet to cut"
);
DiamondStorage storage ds = diamondStorage();
require(
_facetAddress == address(0),
"LibDiamondCut: Remove facet address must be address(0)"
);
for (
uint256 selectorIndex;
selectorIndex < _functionSelectors.length;
selectorIndex++
) {
bytes4 selector = _functionSelectors[selectorIndex];
address oldFacetAddress = ds
.selectorToFacetAndPosition[selector]
.facetAddress;
removeFunction(ds, oldFacetAddress, selector);
}
}
function addFacet(
DiamondStorage storage ds,
address _facetAddress
) internal {
enforceHasContractCode(
_facetAddress,
"LibDiamondCut: New facet has no code"
);
ds.facetFunctionSelectors[_facetAddress].facetAddressPosition = ds
.facetAddresses
.length;
ds.facetAddresses.push(_facetAddress);
}
function addFunction(
DiamondStorage storage ds,
bytes4 _selector,
uint96 _selectorPosition,
address _facetAddress
) internal {
ds
.selectorToFacetAndPosition[_selector]
.functionSelectorPosition = _selectorPosition;
ds.facetFunctionSelectors[_facetAddress].functionSelectors.push(
_selector
);
ds.selectorToFacetAndPosition[_selector].facetAddress = _facetAddress;
}
function removeFunction(
DiamondStorage storage ds,
address _facetAddress,
bytes4 _selector
) internal {
require(
_facetAddress != address(0),
"LibDiamondCut: Can't remove function that doesn't exist"
);
require(
_facetAddress != address(this),
"LibDiamondCut: Can't remove immutable function"
);
uint256 selectorPosition = ds
.selectorToFacetAndPosition[_selector]
.functionSelectorPosition;
uint256 lastSelectorPosition = ds
.facetFunctionSelectors[_facetAddress]
.functionSelectors
.length - 1;
if (selectorPosition != lastSelectorPosition) {
bytes4 lastSelector = ds
.facetFunctionSelectors[_facetAddress]
.functionSelectors[lastSelectorPosition];
ds.facetFunctionSelectors[_facetAddress].functionSelectors[
selectorPosition
] = lastSelector;
ds
.selectorToFacetAndPosition[lastSelector]
.functionSelectorPosition = uint96(selectorPosition);
}
ds.facetFunctionSelectors[_facetAddress].functionSelectors.pop();
delete ds.selectorToFacetAndPosition[_selector];
if (lastSelectorPosition == 0) {
uint256 lastFacetAddressPosition = ds.facetAddresses.length - 1;
uint256 facetAddressPosition = ds
.facetFunctionSelectors[_facetAddress]
.facetAddressPosition;
if (facetAddressPosition != lastFacetAddressPosition) {
address lastFacetAddress = ds.facetAddresses[
lastFacetAddressPosition
];
ds.facetAddresses[facetAddressPosition] = lastFacetAddress;
ds
.facetFunctionSelectors[lastFacetAddress]
.facetAddressPosition = facetAddressPosition;
}
ds.facetAddresses.pop();
delete ds
.facetFunctionSelectors[_facetAddress]
.facetAddressPosition;
}
}
function initializeDiamondCut(
address _init,
bytes memory _calldata
) internal {
if (_init == address(0)) {
return;
}
enforceHasContractCode(
_init,
"LibDiamondCut: _init address has no code"
);
(bool success, bytes memory error) = _init.delegatecall(_calldata);
if (!success) {
if (error.length > 0) {
assembly {
let returndata_size := mload(error)
revert(add(32, error), returndata_size)
}
} else {
revert InitializationFunctionReverted(_init, _calldata);
}
}
}
function enforceHasContractCode(
address _contract,
string memory _errorMessage
) internal view {
uint256 contractSize;
assembly {
contractSize := extcodesize(_contract)
}
require(contractSize > 0, _errorMessage);
}
}
{
"compilationTarget": {
"src/diamond/Diamond.sol": "Diamond"
},
"evmVersion": "paris",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": [
":@openzeppelin/=lib/openzeppelin/",
":@openzeppelin/contracts-upgradeable/=lib/kresko-foundry-helpers/lib/openzeppelin-contracts-upgradeable/contracts/",
":@openzeppelin/contracts/=lib/openzeppelin/contracts/",
":@oz-upgradeable/=lib/kresko-foundry-helpers/lib/openzeppelin-contracts-upgradeable/contracts/",
":@oz/=lib/kresko-foundry-helpers/lib/openzeppelin-contracts/contracts/",
":core/=src/core/",
":ds-test/=lib/openzeppelin/lib/forge-std/lib/ds-test/src/",
":erc4626-tests/=lib/openzeppelin/lib/erc4626-tests/",
":forge-std/=lib/forge-std/src/",
":kresko-foundry-helpers/=lib/kresko-foundry-helpers/",
":kresko-lib/=lib/kresko-foundry-helpers/src/",
":lib/=lib/",
":openzeppelin-contracts-upgradeable/=lib/kresko-foundry-helpers/lib/openzeppelin-contracts-upgradeable/",
":openzeppelin-contracts/=lib/kresko-foundry-helpers/lib/openzeppelin-contracts/",
":openzeppelin/=lib/openzeppelin/",
":script/=script/",
":solidstate/=lib/solidstate/contracts/",
":src/=src/",
":test/=test/"
]
}
[{"inputs":[{"internalType":"address","name":"_contractOwner","type":"address"},{"components":[{"internalType":"address","name":"facetAddress","type":"address"},{"internalType":"enum IDiamondCutFacet.FacetCutAction","name":"action","type":"uint8"},{"internalType":"bytes4[]","name":"functionSelectors","type":"bytes4[]"}],"internalType":"struct IDiamondCutFacet.FacetCut[]","name":"_cuts","type":"tuple[]"},{"components":[{"internalType":"address","name":"initializer","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct IDiamondCutFacet.Initializer","name":"_init","type":"tuple"}],"stateMutability":"payable","type":"constructor"},{"inputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"name":"FunctionDoesNotExist","type":"error"},{"inputs":[{"internalType":"address","name":"_initializationContractAddress","type":"address"},{"internalType":"bytes","name":"_calldata","type":"bytes"}],"name":"InitializationFunctionReverted","type":"error"},{"anonymous":false,"inputs":[{"components":[{"internalType":"address","name":"facetAddress","type":"address"},{"internalType":"enum IDiamondCutFacet.FacetCutAction","name":"action","type":"uint8"},{"internalType":"bytes4[]","name":"functionSelectors","type":"bytes4[]"}],"indexed":false,"internalType":"struct IDiamondCutFacet.FacetCut[]","name":"_diamondCut","type":"tuple[]"},{"indexed":false,"internalType":"address","name":"_init","type":"address"},{"indexed":false,"internalType":"bytes","name":"_calldata","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"},{"stateMutability":"payable","type":"receive"}]