From df7bfb2b25ebed60879be0614d42b1e622ac4644 Mon Sep 17 00:00:00 2001 From: didi Date: Tue, 23 Jan 2024 12:48:01 +0100 Subject: [PATCH] inline UUPSProxy with fixed license --- contracts/PureSuperToken.sol | 2 +- contracts/base/UUPSProxy.sol | 48 ++++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 1 deletion(-) create mode 100644 contracts/base/UUPSProxy.sol diff --git a/contracts/PureSuperToken.sol b/contracts/PureSuperToken.sol index a000989..e577736 100644 --- a/contracts/PureSuperToken.sol +++ b/contracts/PureSuperToken.sol @@ -6,7 +6,7 @@ pragma solidity 0.8.19; // This abstract contract provides storage padding for the proxy import { CustomSuperTokenBase } from "@superfluid-finance/ethereum-contracts/contracts/interfaces/superfluid/CustomSuperTokenBase.sol"; // Implementation of UUPSProxy (see https://eips.ethereum.org/EIPS/eip-1822) -import { UUPSProxy } from "@superfluid-finance/ethereum-contracts/contracts/upgradability/UUPSProxy.sol"; +import { UUPSProxy } from "./base/UUPSProxy.sol"; // Superfluid framework interfaces we need import { ISuperToken, ISuperTokenFactory, IERC20 } from "@superfluid-finance/ethereum-contracts/contracts/interfaces/superfluid/ISuperfluid.sol"; diff --git a/contracts/base/UUPSProxy.sol b/contracts/base/UUPSProxy.sol new file mode 100644 index 0000000..0d02a07 --- /dev/null +++ b/contracts/base/UUPSProxy.sol @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: MIT OR Apache-2.0 +pragma solidity ^0.8.0; + +import {Proxy} from "@openzeppelin/contracts/proxy/Proxy.sol"; + +/// @title UUPS Proxy implementation contract +/// @author jtriley.eth +/// @notice Stores the logic contract's address at the _IMPLEMENTATION_SLOT +/// @dev `initializeProxy(address)` is called by the Super Token Factory +/// The call to the factory should be in the same transaction to avoid being +/// front run +contract UUPSProxy is Proxy { + /// @notice Thrown when the logic contract address is zero + error ZeroAddress(); + + /// @notice Thrown when the logic contract has been set + error Initialized(); + + /// @notice Precomputed from the following for gas savings + /// bytes32(uint256(keccak256("eip1967.proxy.implementation") - 1)); + bytes32 internal constant _IMPLEMENTATION_SLOT = + 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; + + /// @notice Stores the logic contract address only once. + /// @dev Called by the SuperTokenFactory contract on upgrade + /// @param initialAddress logic contract address + function initializeProxy(address initialAddress) external { + if (initialAddress == address(0)) revert ZeroAddress(); + if (_implementation() != address(0)) revert Initialized(); + assembly { + sstore(_IMPLEMENTATION_SLOT, initialAddress) + } + } + + /// @notice Reads logic contract from precomputed slot + /// @return impl Logic contract address + function _implementation() + internal + view + virtual + override + returns (address impl) + { + assembly { + impl := sload(_IMPLEMENTATION_SLOT) + } + } +}