-
Notifications
You must be signed in to change notification settings - Fork 527
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Contractkit upgradeable smart contracts #269
Conversation
function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) { | ||
/// @solidity memory-safe-assembly | ||
assembly { | ||
r.slot := slot | ||
} | ||
} |
Check warning
Code scanning / Slither
Assembly usage
function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) { | ||
/// @solidity memory-safe-assembly | ||
assembly { | ||
r.slot := slot | ||
} | ||
} |
Check warning
Code scanning / Slither
Assembly usage
function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) { | ||
/// @solidity memory-safe-assembly | ||
assembly { | ||
r.slot := slot | ||
} | ||
} |
Check warning
Code scanning / Slither
Assembly usage
function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) { | ||
/// @solidity memory-safe-assembly | ||
assembly { | ||
r.slot := slot | ||
} | ||
} |
Check warning
Code scanning / Slither
Assembly usage
function _delegate(address implementation) internal virtual { | ||
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()) | ||
} | ||
} | ||
} |
Check warning
Code scanning / Slither
Assembly usage
abstract contract Upgradeable is IERC1822Proxiable, ERC1967Upgrade { | ||
/// @custom:oz-upgrades-unsafe-allow state-variable-immutable state-variable-assignment | ||
address private immutable __self = address(this); | ||
|
||
/** | ||
* @dev Check that the execution is being performed through a delegatecall call and that the execution context is | ||
* a proxy contract with an implementation (as defined in ERC1967) pointing to self. This should only be the case | ||
* for UUPS and transparent proxies that are using the current contract as their implementation. Execution of a | ||
* function through ERC1167 minimal proxies (clones) would not normally pass this test, but is not guaranteed to | ||
* fail. | ||
*/ | ||
modifier onlyProxy() { | ||
require(address(this) != __self, "Function must be called through delegatecall"); | ||
require(_getImplementation() == __self, "Function must be called through active proxy"); | ||
_; | ||
} | ||
|
||
/** | ||
* @dev Check that the execution is not being performed through a delegate call. This allows a function to be | ||
* callable on the implementing contract but not through proxies. | ||
*/ | ||
modifier notDelegated() { | ||
require(address(this) == __self, "UUPSUpgradeable: must not be called through delegatecall"); | ||
_; | ||
} | ||
|
||
/** | ||
* @dev Implementation of the ERC1822 {proxiableUUID} function. This returns the storage slot used by the | ||
* implementation. It is used to validate that the this implementation remains valid after an upgrade. | ||
* | ||
* IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks | ||
* bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this | ||
* function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier. | ||
*/ | ||
function proxiableUUID() external view virtual override notDelegated returns (bytes32) { | ||
return _IMPLEMENTATION_SLOT; | ||
} | ||
|
||
/** | ||
* @dev Upgrade the implementation of the proxy to `newImplementation`. | ||
* | ||
* Calls {_authorizeUpgrade}. | ||
* | ||
* Emits an {Upgraded} event. | ||
*/ | ||
function upgradeTo(address newImplementation) external virtual onlyProxy { | ||
_authorizeUpgrade(newImplementation); | ||
_upgradeToAndCallUUPS(newImplementation, new bytes(0), false); | ||
} | ||
|
||
/** | ||
* @dev Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call | ||
* encoded in `data`. | ||
* | ||
* Calls {_authorizeUpgrade}. | ||
* | ||
* Emits an {Upgraded} event. | ||
*/ | ||
function upgradeToAndCall(address newImplementation, bytes memory data) external payable virtual onlyProxy { | ||
_authorizeUpgrade(newImplementation); | ||
_upgradeToAndCallUUPS(newImplementation, data, true); | ||
} | ||
|
||
/** | ||
* @dev Function that should revert when `msg.sender` is not authorized to upgrade the contract. Called by | ||
* {upgradeTo} and {upgradeToAndCall}. | ||
* | ||
* Normally, this function will use an xref:access.adoc[access control] modifier such as {Ownable-onlyOwner}. | ||
* | ||
* ```solidity | ||
* function _authorizeUpgrade(address) internal override onlyOwner {} | ||
* ``` | ||
*/ | ||
function _authorizeUpgrade(address newImplementation) internal virtual; | ||
} |
Check warning
Code scanning / Slither
Unimplemented functions
No description provided.