mirror of https://github.com/crytic/slither
with tests of implementation variable/slot getter functionspull/1757/head
parent
cbbcb8c8b1
commit
bff30a3481
@ -0,0 +1,5 @@ |
||||
pragma solidity ^0.5.0; |
||||
|
||||
import "./src/EIP1822Proxy.sol"; |
||||
import "./src/ZosProxy.sol"; |
||||
import "./src/MasterCopyProxy.sol"; |
@ -0,0 +1,47 @@ |
||||
pragma solidity ^0.5.0; |
||||
|
||||
contract EIP1822Proxy { |
||||
// Code position in storage is keccak256("PROXIABLE") = "0xc5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf7" |
||||
constructor(bytes memory constructData, address contractLogic) public { |
||||
// save the code address |
||||
assembly { // solium-disable-line |
||||
sstore(0xc5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf7, contractLogic) |
||||
} |
||||
(bool success, bytes memory _ ) = contractLogic.delegatecall(constructData); // solium-disable-line |
||||
require(success, "Construction failed"); |
||||
} |
||||
|
||||
function() external payable { |
||||
assembly { // solium-disable-line |
||||
let contractLogic := sload(0xc5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf7) |
||||
calldatacopy(0x0, 0x0, calldatasize) |
||||
let success := delegatecall(sub(gas, 10000), contractLogic, 0x0, calldatasize, 0, 0) |
||||
let retSz := returndatasize |
||||
returndatacopy(0, 0, retSz) |
||||
switch success |
||||
case 0 { |
||||
revert(0, retSz) |
||||
} |
||||
default { |
||||
return(0, retSz) |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
contract EIP1822Proxiable { |
||||
// Code position in storage is keccak256("PROXIABLE") = "0xc5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf7" |
||||
|
||||
function updateCodeAddress(address newAddress) internal { |
||||
require( |
||||
bytes32(0xc5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf7) == EIP1822Proxiable(newAddress).proxiableUUID(), |
||||
"Not compatible" |
||||
); |
||||
assembly { // solium-disable-line |
||||
sstore(0xc5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf7, newAddress) |
||||
} |
||||
} |
||||
function proxiableUUID() public pure returns (bytes32) { |
||||
return 0xc5f16f0fcc639fa48a6947836d9850f504798523bf8c9a3a87d5876cf622bcf7; |
||||
} |
||||
} |
@ -0,0 +1,27 @@ |
||||
pragma solidity ^0.5.0; |
||||
|
||||
contract MasterCopyProxy { |
||||
address internal masterCopy; |
||||
|
||||
constructor(address _masterCopy) |
||||
public |
||||
{ |
||||
require(_masterCopy != address(0), "Invalid master copy address provided"); |
||||
masterCopy = _masterCopy; |
||||
} |
||||
|
||||
/// @dev Fallback function forwards all transactions and returns all received return data. |
||||
function () |
||||
external |
||||
payable |
||||
{ |
||||
// solium-disable-next-line security/no-inline-assembly |
||||
assembly { |
||||
calldatacopy(0, 0, calldatasize()) |
||||
let success := delegatecall(gas, sload(0), 0, calldatasize(), 0, 0) |
||||
returndatacopy(0, 0, returndatasize()) |
||||
if eq(success, 0) { revert(0, returndatasize()) } |
||||
return(0, returndatasize()) |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,67 @@ |
||||
pragma solidity ^0.5.0; |
||||
|
||||
contract ZosProxy { |
||||
function () payable external { |
||||
_fallback(); |
||||
} |
||||
|
||||
function _implementation() internal view returns (address); |
||||
|
||||
function _delegate(address implementation) internal { |
||||
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 _willFallback() internal { |
||||
} |
||||
|
||||
function _fallback() internal { |
||||
_willFallback(); |
||||
_delegate(_implementation()); |
||||
} |
||||
} |
||||
|
||||
library AddressUtils { |
||||
function isContract(address addr) internal view returns (bool) { |
||||
uint256 size; |
||||
assembly { size := extcodesize(addr) } |
||||
return size > 0; |
||||
} |
||||
} |
||||
|
||||
contract UpgradeabilityProxy is ZosProxy { |
||||
event Upgraded(address indexed implementation); |
||||
|
||||
bytes32 private constant IMPLEMENTATION_SLOT = 0x7050c9e0f4ca769c69bd3a8ef740bc37934f8e2c036e5a723fd8ee048ed3f8c3; |
||||
|
||||
constructor(address _implementation) public payable { |
||||
assert(IMPLEMENTATION_SLOT == keccak256("org.zeppelinos.proxy.implementation")); |
||||
_setImplementation(_implementation); |
||||
} |
||||
|
||||
function _implementation() internal view returns (address impl) { |
||||
bytes32 slot = IMPLEMENTATION_SLOT; |
||||
assembly { |
||||
impl := sload(slot) |
||||
} |
||||
} |
||||
|
||||
function _upgradeTo(address newImplementation) internal { |
||||
_setImplementation(newImplementation); |
||||
emit Upgraded(newImplementation); |
||||
} |
||||
|
||||
function _setImplementation(address newImplementation) private { |
||||
require(AddressUtils.isContract(newImplementation), "Cannot set a proxy implementation to a non-contract address"); |
||||
bytes32 slot = IMPLEMENTATION_SLOT; |
||||
assembly { |
||||
sstore(slot, newImplementation) |
||||
} |
||||
} |
||||
} |
Loading…
Reference in new issue