-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathProxyObject.sol
53 lines (45 loc) · 1.46 KB
/
ProxyObject.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;
import { ProxyBeacon } from "./ProxyBeacon.sol";
contract ProxyObject {
// bytes32(uint256(keccak256("eip1967.proxy.beacon")) - 1)
bytes32 constant BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;
ProxyBeacon immutable immutableBeacon;
constructor(ProxyBeacon beacon, bytes memory data) {
immutableBeacon = beacon;
assembly {
sstore(BEACON_SLOT, beacon)
}
if (data.length > 0) {
(bool success, ) = beacon.implementation().delegatecall(data);
require(success, "Construction failed");
}
}
fallback() external payable {
ProxyBeacon beacon;
assembly {
beacon := sload(BEACON_SLOT)
}
if (address(beacon) == address(0)) beacon = immutableBeacon;
address implementation = beacon.implementation();
assembly {
// Copy msg.data. We take full control of memory in this inline assembly
// block because it will not return to Solidity code. We overwrite the
// Solidity scratch pad at memory position 0.
calldatacopy(0, 0, calldatasize())
// Call the implementation.
// out and outsize are 0 because we don't know the size yet.
let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)
// Copy the returned data.
returndatacopy(0, 0, returndatasize())
switch result
// delegatecall returns 0 on error.
case 0 {
revert(0, returndatasize())
}
default {
return(0, returndatasize())
}
}
}
}