文件 1 的 11: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) {
uint256 size;
assembly {
size := extcodesize(account)
}
return size > 0;
}
function sendValue(address payable account, uint256 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,
uint256 value
) internal returns (bytes memory) {
return
functionCallWithValue(
target,
data,
value,
'AddressUtils: failed low-level call with value'
);
}
function functionCallWithValue(
address target,
bytes memory data,
uint256 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,
uint256 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 的 11: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;
}
文件 3 的 11: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() public view virtual override returns (address) {
return OwnableStorage.layout().owner;
}
function transferOwnership(address account)
public
virtual
override
onlyOwner
{
OwnableStorage.layout().setOwner(account);
emit OwnershipTransferred(msg.sender, account);
}
}
文件 4 的 11: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'
);
_;
}
}
文件 5 的 11: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;
}
}
文件 6 的 11:Proxy.sol
pragma solidity ^0.8.0;
import { AddressUtils } from '../utils/AddressUtils.sol';
abstract contract Proxy {
using AddressUtils for address;
fallback() external payable virtual {
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() internal virtual returns (address);
}
文件 7 的 11:ProxyUpgradeableOwnable.sol
pragma solidity ^0.8.0;
import {Proxy} from "@solidstate/contracts/proxy/Proxy.sol";
import {SafeOwnable, OwnableStorage} from "@solidstate/contracts/access/SafeOwnable.sol";
import {ProxyUpgradeableOwnableStorage} from "./ProxyUpgradeableOwnableStorage.sol";
contract ProxyUpgradeableOwnable is Proxy, SafeOwnable {
using ProxyUpgradeableOwnableStorage for ProxyUpgradeableOwnableStorage.Layout;
using OwnableStorage for OwnableStorage.Layout;
constructor(address implementation) {
OwnableStorage.layout().setOwner(msg.sender);
ProxyUpgradeableOwnableStorage.layout().implementation = implementation;
}
receive() external payable {}
function _getImplementation() internal view override returns (address) {
return ProxyUpgradeableOwnableStorage.layout().implementation;
}
function getImplementation() external view returns (address) {
return _getImplementation();
}
function setImplementation(address implementation) external onlyOwner {
ProxyUpgradeableOwnableStorage.layout().implementation = implementation;
}
}
文件 8 的 11:ProxyUpgradeableOwnableStorage.sol
pragma solidity ^0.8.0;
library ProxyUpgradeableOwnableStorage {
bytes32 internal constant STORAGE_SLOT =
keccak256("premia.contracts.storage.ProxyUpgradeableOwnable");
struct Layout {
address implementation;
}
function layout() internal pure returns (Layout storage l) {
bytes32 slot = STORAGE_SLOT;
assembly {
l.slot := slot
}
}
}
文件 9 的 11: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() public view virtual returns (address) {
return SafeOwnableStorage.layout().nomineeOwner;
}
function transferOwnership(address account)
public
virtual
override
onlyOwner
{
SafeOwnableStorage.layout().setNomineeOwner(account);
}
function acceptOwnership() public virtual onlyNomineeOwner {
OwnableStorage.Layout storage l = OwnableStorage.layout();
emit OwnershipTransferred(l.owner, msg.sender);
l.setOwner(msg.sender);
SafeOwnableStorage.layout().setNomineeOwner(address(0));
}
}
文件 10 的 11: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'
);
_;
}
}
文件 11 的 11: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/ProxyUpgradeableOwnable.sol": "ProxyUpgradeableOwnable"
},
"evmVersion": "london",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"address","name":"implementation","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"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":[],"name":"getImplementation","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":"implementation","type":"address"}],"name":"setImplementation","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]