-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathAnchorVaultProxy.sol
118 lines (102 loc) · 3.44 KB
/
AnchorVaultProxy.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
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
// SPDX-License-Identifier: MIT
pragma solidity 0.8.4;
import "OpenZeppelin/[email protected]/contracts/proxy/ERC1967/ERC1967Proxy.sol";
import "OpenZeppelin/[email protected]/contracts/utils/Address.sol";
/**
* @dev Copied from https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.1.0/contracts/utils/StorageSlot.sol
*/
library StorageSlot {
struct AddressSlot {
address value;
}
function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {
assembly {
r.slot := slot
}
}
}
/**
* @dev An ossifiable proxy for AnchorVault contract.
*/
contract AnchorVaultProxy is ERC1967Proxy {
/**
* @dev Storage slot with the admin of the contract.
*
* Equals `bytes32(uint256(keccak256("eip1967.proxy.admin")) - 1)`.
*/
bytes32 internal constant ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;
/**
* @dev Emitted when the admin account has changed.
*/
event AdminChanged(address previousAdmin, address newAdmin);
/**
* @dev Initializes the upgradeable proxy with the initial implementation and admin.
*/
constructor(address implementation, address admin)
ERC1967Proxy(implementation, new bytes(0))
{
_setAdmin(admin);
}
/**
* @return Returns the current implementation address.
*/
function implementation() external view returns (address) {
return _implementation();
}
/**
* @dev Upgrades the proxy to a new implementation, optionally performing an additional
* setup call.
*
* Can only be called by the proxy admin until the proxy is ossified.
* Cannot be called after the proxy is ossified.
*
* Emits an {Upgraded} event.
*
* @param setupCalldata Data for the setup call. The call is skipped if data is empty.
*/
function proxy_upgradeTo(address newImplementation, bytes memory setupCalldata) external {
address admin = _getAdmin();
require(admin != address(0), "proxy: ossified");
require(msg.sender == admin, "proxy: unauthorized");
_upgradeTo(newImplementation);
if (setupCalldata.length > 0) {
Address.functionDelegateCall(newImplementation, setupCalldata, "proxy: setup failed");
}
}
/**
* @dev Returns the current admin.
*/
function _getAdmin() internal view returns (address) {
return StorageSlot.getAddressSlot(ADMIN_SLOT).value;
}
/**
* @dev Stores a new address in the EIP1967 admin slot.
*/
function _setAdmin(address newAdmin) private {
StorageSlot.getAddressSlot(ADMIN_SLOT).value = newAdmin;
}
/**
* @dev Returns the current admin of the proxy.
*/
function proxy_getAdmin() external view returns (address) {
return _getAdmin();
}
/**
* @dev Changes the admin of the proxy.
*
* Emits an {AdminChanged} event.
*/
function proxy_changeAdmin(address newAdmin) external {
address admin = _getAdmin();
require(admin != address(0), "proxy: ossified");
require(msg.sender == admin, "proxy: unauthorized");
emit AdminChanged(admin, newAdmin);
_setAdmin(newAdmin);
}
/**
* @dev Returns whether the implementation is locked forever.
*/
function proxy_getIsOssified() external view returns (bool) {
return _getAdmin() == address(0);
}
}