文件 1 的 1:ZeroEx_.sol
pragma solidity ^0.8.0;
pragma experimental ABIEncoderV2;
library LibRichErrors {
bytes4 internal constant STANDARD_ERROR_SELECTOR = bytes4(keccak256("Error(string)"));
function StandardError(string memory message)
internal
pure
returns (bytes memory encodedError)
{
return abi.encodeWithSelector(
STANDARD_ERROR_SELECTOR,
bytes(message)
);
}
function rrevert(bytes memory encodedError)
internal
pure
{
assembly {
revert(add(encodedError, 0x20), mload(encodedError))
}
}
}
library LibProxyRichErrors {
function NotImplementedError(bytes4 selector)
internal
pure
returns (bytes memory encodedError)
{
return abi.encodeWithSelector(
bytes4(keccak256("NotImplementedError(bytes4)")),
selector
);
}
function InvalidBootstrapCallerError(address actual, address expected)
internal
pure
returns (bytes memory encodedError)
{
return abi.encodeWithSelector(
bytes4(keccak256("InvalidBootstrapCallerError(address,address)")),
actual,
expected
);
}
function InvalidDieCallerError(address actual, address expected)
internal
pure
returns (bytes memory encodedError)
{
return abi.encodeWithSelector(
bytes4(keccak256("InvalidDieCallerError(address,address)")),
actual,
expected
);
}
function BootstrapCallFailedError(address target, bytes memory resultData)
internal
pure
returns (bytes memory encodedError)
{
return abi.encodeWithSelector(
bytes4(keccak256("BootstrapCallFailedError(address,bytes)")),
target,
resultData
);
}
}
library LibBootstrap {
bytes4 internal constant BOOTSTRAP_SUCCESS = bytes4(keccak256("BOOTSTRAP_SUCCESS"));
using LibRichErrors for bytes;
function delegatecallBootstrapFunction(
address target,
bytes memory data
)
internal
{
(bool success, bytes memory resultData) = target.delegatecall(data);
if (!success ||
resultData.length != 32 ||
abi.decode(resultData, (bytes4)) != BOOTSTRAP_SUCCESS)
{
LibProxyRichErrors.BootstrapCallFailedError(target, resultData).rrevert();
}
}
}
library LibStorage {
uint256 private constant STORAGE_SLOT_EXP = 128;
enum StorageId {
Proxy,
SimpleFunctionRegistry,
Ownable,
ERC20,
AccessControl,
ERC20AccessControl,
Test
}
function getStorageSlot(StorageId storageId)
internal
pure
returns (uint256 slot)
{
return (uint256(storageId) + 1) << STORAGE_SLOT_EXP;
}
}
library LibProxyStorage {
struct Storage {
mapping(bytes4 => address) impls;
}
function getStorage() internal pure returns (Storage storage stor) {
uint256 storageSlot = LibStorage.getStorageSlot(
LibStorage.StorageId.Proxy
);
assembly {
stor.slot := storageSlot
}
}
}
interface IBootstrapFeature {
function bootstrap(address target, bytes calldata callData) external;
}
contract BootstrapFeature is
IBootstrapFeature
{
address immutable private _deployer;
address immutable private _implementation;
address immutable private _bootstrapCaller;
using LibRichErrors for bytes;
constructor(address bootstrapCaller) {
_deployer = msg.sender;
_implementation = address(this);
_bootstrapCaller = bootstrapCaller;
}
modifier onlyBootstrapCaller() {
if (msg.sender != _bootstrapCaller) {
LibProxyRichErrors.InvalidBootstrapCallerError(msg.sender, _bootstrapCaller).rrevert();
}
_;
}
modifier onlyDeployer() {
if (msg.sender != _deployer) {
LibProxyRichErrors.InvalidDieCallerError(msg.sender, _deployer).rrevert();
}
_;
}
function bootstrap(address target, bytes calldata callData) external override onlyBootstrapCaller {
LibProxyStorage.getStorage().impls[this.bootstrap.selector] = address(0);
BootstrapFeature(_implementation).die();
LibBootstrap.delegatecallBootstrapFunction(target, callData);
}
function die() external onlyDeployer {
assert(address(this) == _implementation);
selfdestruct(payable(msg.sender));
}
}
contract ZeroEx_ {
constructor(address bootstrapper) {
BootstrapFeature bootstrap = new BootstrapFeature(bootstrapper);
LibProxyStorage.getStorage().impls[bootstrap.bootstrap.selector] = address(bootstrap);
}
function getFunctionImplementation(bytes4 selector)
public
view
returns (address impl)
{
return LibProxyStorage.getStorage().impls[selector];
}
fallback() external payable {
mapping(bytes4 => address) storage impls =
LibProxyStorage.getStorage().impls;
assembly {
let cdlen := calldatasize()
if iszero(cdlen) {
return(0, 0)
}
calldatacopy(0x40, 0, cdlen)
let selector := and(mload(0x40), 0xFFFFFFFF00000000000000000000000000000000000000000000000000000000)
mstore(0, selector)
mstore(0x20, impls.slot)
let slot := keccak256(0, 0x40)
let delegate := sload(slot)
if iszero(delegate) {
mstore(0, 0x734e6e1c00000000000000000000000000000000000000000000000000000000)
mstore(4, selector)
revert(0, 0x24)
}
let success := delegatecall(
gas(),
delegate,
0x40, cdlen,
0, 0
)
let rdlen := returndatasize()
returndatacopy(0, 0, rdlen)
if success {
return(0, rdlen)
}
revert(0, rdlen)
}
}
}
{
"compilationTarget": {
"ZeroEx_.sol": "ZeroEx_"
},
"evmVersion": "istanbul",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}