Skip to content

Commit

Permalink
implement diamond storage pattern
Browse files Browse the repository at this point in the history
  • Loading branch information
mdtanrikulu committed Nov 12, 2024
1 parent 4107fb4 commit 4678b4d
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 9 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ A system for deploying and verifying proxy contracts with predictable storage la

### 2. TransparentVerifiableProxy
- Transparent proxy pattern with verified storage layout
- Fixed storage slots:
- Slot 0: `salt` (uint256)
- Slot 1: `owner` (address)
- Fixed storage slots via Diamond Storage pattern:
- Slot 'proxy.verifiable.salt': `salt` (uint256)
- Slot 'proxy.verifiable.owner': `owner` (address)
- Immutable `creator` field (set in bytecode)
- Implements secure upgrade mechanism
- Initializable to prevent implementation tampering
Expand Down
45 changes: 39 additions & 6 deletions src/TransparentVerifiableProxy.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,21 @@ import {Proxy} from "@openzeppelin/contracts/proxy/Proxy.sol";
import {ERC1967Utils} from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Utils.sol";
import {Initializable} from "@openzeppelin/contracts/proxy/utils/Initializable.sol";

// EIP-2535 Diamond Storage pattern
// ref: https://eips.ethereum.org/EIPS/eip-2535#storage
library StorageSlot {
bytes32 constant SLOT_SALT = keccak256("proxy.verifiable.salt");
bytes32 constant SLOT_OWNER = keccak256("proxy.verifiable.owner");

function getSaltSlot() internal pure returns (bytes32) {
return SLOT_SALT;
}

function getOwnerSlot() internal pure returns (bytes32) {
return SLOT_OWNER;
}
}

interface ITransparentVerifiableProxy {
/// @dev See {UUPSUpgradeable-upgradeToAndCall}
function upgradeToAndCall(address newImplementation, bytes calldata data) external payable;
Expand All @@ -18,10 +33,6 @@ contract TransparentVerifiableProxy is Proxy, Initializable {
// immutable variable (in bytecode)
address public immutable creator;

// storage variables (in storage slots)
uint256 public salt; // Salt, being used creating the proxy (slot 0)
address public owner; // The owner of the proxy contract (slot 1)

// ### EVENTS
error ProxyDeniedOwnerAccess();

Expand Down Expand Up @@ -52,12 +63,34 @@ contract TransparentVerifiableProxy is Proxy, Initializable {
{
require(implementation != address(0), "New implementation cannot be the zero address");

salt = _salt;
owner = _owner;
bytes32 saltSlot = StorageSlot.getSaltSlot();
bytes32 ownerSlot = StorageSlot.getOwnerSlot();

assembly {
sstore(saltSlot, _salt)
sstore(ownerSlot, _owner)
}
ERC1967Utils.upgradeToAndCall(implementation, data);
}

function salt() public view returns (uint256) {
bytes32 slot = StorageSlot.getSaltSlot();
uint256 value;
assembly {
value := sload(slot)
}
return value;
}

function owner() public view returns (address) {
bytes32 slot = StorageSlot.getOwnerSlot();
address value;
assembly {
value := sload(slot)
}
return value;
}

/**
* @dev Returns the current implementation address.
*
Expand Down

0 comments on commit 4678b4d

Please sign in to comment.