Skip to content

Commit

Permalink
Merge pull request #12 from blocto/feature/upgradable
Browse files Browse the repository at this point in the history
feat: remove beacon; add transparent upgradeable proxy
  • Loading branch information
scottphc authored Jan 22, 2025
2 parents c47f36e + 398561a commit 87d2a0a
Show file tree
Hide file tree
Showing 10 changed files with 29 additions and 140 deletions.
7 changes: 2 additions & 5 deletions remappings.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/
ds-test/=lib/openzeppelin-contracts/lib/forge-std/lib/ds-test/src/
erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/
forge-std/=lib/forge-std/src/
halmos-cheatcodes/=lib/openzeppelin-contracts/lib/halmos-cheatcodes/src/
openzeppelin-contracts/=lib/openzeppelin-contracts/
@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/
@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/
solady/=lib/solady/src/
19 changes: 5 additions & 14 deletions script/Deploy.s.sol → script/DeployTokenFactory.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,11 @@
pragma solidity ^0.8.13;

import "../lib/forge-std/src/Script.sol";
import {TransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol";
import {SpotlightTokenFactory} from "../src/spotlight-token-factory/SpotlightTokenFactory.sol";
import {SpotlightTokenIPCollection} from "../src/spotlight-token-collection/SpotlightTokenIPCollection.sol";
import {SpotlightNativeBondingCurve} from "../src/spotlight-bonding-curve/SpotlightNativeBondingCurve.sol";
import {UpgradeableBeacon} from "@openzeppelin/contracts/proxy/beacon/UpgradeableBeacon.sol";
import {SpotlightToken} from "../src/spotlight-token/SpotlightToken.sol";
import {BeaconProxy} from "../src/beacon-proxy/BeaconProxy.sol";
import {SpotlightProtocolRewards} from "../src/spotlight-protocol-rewards/SpotlightProtocolRewards.sol";

contract Deploy is Script {
Expand All @@ -17,7 +16,7 @@ contract Deploy is Script {
*/

/* Deploy and verify with the following command:
forge script script/Deploy.s.sol:Deploy --broadcast \
forge script script/DeployTokenFactory.s.sol:Deploy --broadcast \
--chain-id 1516 \
--rpc-url https://odyssey.storyrpc.io \
--verify \
Expand All @@ -39,8 +38,6 @@ contract Deploy is Script {
src/{CONTRACT_PATH}.sol:{CONTRACT_NAME}
*/

//@notice The address of the SUSDCToken contract on Odyssey.(https://odyssey.storyscan.xyz/address/0x40fCa9cB1AB15eD9B5bDA19A52ac00A78AE08e1D?tab=contract)
address private _SUSDCTokenAddr = 0x40fCa9cB1AB15eD9B5bDA19A52ac00A78AE08e1D;
address private _STORY_DERIVATIVE_WORKFLOWS_ADDRESS = 0xa8815CEB96857FFb8f5F8ce920b1Ae6D70254C7B;
address private _SPOTLIGHT_TOKEN_FACTORY_OWNER = 0x582d6944a8EA7e4ACD385D18DC95CF5915510289;

Expand All @@ -65,26 +62,20 @@ contract Deploy is Script {
// @dev deploy spotlight token implementation contract
SpotlightToken spotlightTokenImpl = new SpotlightToken();

// @dev deploy spotlight token beacon contract
UpgradeableBeacon spotlightTokenBeacon =
new UpgradeableBeacon(address(spotlightTokenImpl), _SPOTLIGHT_TOKEN_FACTORY_OWNER);

// @dev deploy spotlight token factory implementation contract
SpotlightTokenFactory factoryImpl = new SpotlightTokenFactory();

// @dev deploy spotlight token factory beacon contract
UpgradeableBeacon factoryBeacon = new UpgradeableBeacon(address(factoryImpl), _SPOTLIGHT_TOKEN_FACTORY_OWNER);

// @dev deploy spotlight protocol rewards contract
SpotlightProtocolRewards protocolRewards = new SpotlightProtocolRewards();

// @dev deploy spotlight token factory proxy contract
BeaconProxy factoryProxy = new BeaconProxy(address(factoryBeacon));
TransparentUpgradeableProxy factoryProxy =
new TransparentUpgradeableProxy(address(factoryImpl), _SPOTLIGHT_TOKEN_FACTORY_OWNER, "");
SpotlightTokenFactory(address(factoryProxy)).initialize(
_SPOTLIGHT_TOKEN_FACTORY_OWNER, // owner_
0.1 ether, // creationFee: 0.1 ether
address(tokenIpCollection), // tokenIpCollection_
address(spotlightTokenBeacon), // tokenBeacon_
address(spotlightTokenImpl), // tokenImplementation_
address(bondingCurve), // bondingCurve_
WRAPPER_IP,
_STORY_DERIVATIVE_WORKFLOWS_ADDRESS, // storyDerivativeWorkflows_
Expand Down
66 changes: 0 additions & 66 deletions src/beacon-proxy/BeaconProxy.sol

This file was deleted.

9 changes: 0 additions & 9 deletions src/beacon-proxy/BeaconProxyStorage.sol

This file was deleted.

12 changes: 6 additions & 6 deletions src/spotlight-token-factory/ISpotlightTokenFactory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ interface ISpotlightTokenFactory {
* @param owner_ The address of the token factory owner.
* @param creationFee_ The fee to create a token.
* @param tokenIpCollection_ The address of the token IP collection contract.
* @param tokenBeacon_ The address of the token beacon contract.
* @param tokenImplementation_ The address of the token implementation contract.
* @param bondingCurve_ The address of the bonding curve contract.
* @param baseToken_ The address of the base token.
* @param storyDerivativeWorkflows_ The address of the story derivative workflows contract.
Expand All @@ -78,7 +78,7 @@ interface ISpotlightTokenFactory {
address owner_,
uint256 creationFee_,
address tokenIpCollection_,
address tokenBeacon_,
address tokenImplementation_,
address bondingCurve_,
address baseToken_,
address storyDerivativeWorkflows_,
Expand All @@ -105,14 +105,14 @@ interface ISpotlightTokenFactory {
function setTokenIpCollection(address newTokenIpCollection) external;

/**
* @dev Returns the address of the token beacon contract
* @dev Returns the address of the token implementation contract
*/
function tokenBeacon() external view returns (address);
function tokenImplementation() external view returns (address);

/**
* @dev Sets the address of the token beacon contract
* @dev Sets the address of the token implementation contract
*/
function setTokenBeacon(address newTokenBeacon) external;
function setTokenImplementation(address newTokenImplementation) external;

/**
* @dev Returns the fee amount required to create a token (in native token)
Expand Down
35 changes: 12 additions & 23 deletions src/spotlight-token-factory/SpotlightTokenFactory.sol
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.13;

import {BeaconProxyStorage} from "../beacon-proxy/BeaconProxyStorage.sol";
import {BeaconProxy} from "../beacon-proxy/BeaconProxy.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {IERC20Metadata} from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
import {Clones} from "@openzeppelin/contracts/proxy/Clones.sol";
import {ISpotlightTokenFactory} from "./ISpotlightTokenFactory.sol";
import {ISpotlightToken} from "../spotlight-token/ISpotlightToken.sol";
import {ISpotlightTokenIPCollection} from "../spotlight-token-collection/ISpotlightTokenIPCollection.sol";
Expand All @@ -14,7 +13,7 @@ import {SpotlightTokenFactoryStorage} from "./SpotlightTokenFactoryStorage.sol";
import {ISpotlightBondingCurve} from "../spotlight-bonding-curve/ISpotlightBondingCurve.sol";
import {MarketType} from "../spotlight-token/ISpotlightToken.sol";

contract SpotlightTokenFactory is BeaconProxyStorage, SpotlightTokenFactoryStorage, ISpotlightTokenFactory {
contract SpotlightTokenFactory is SpotlightTokenFactoryStorage, ISpotlightTokenFactory {
modifier needInitialized() {
_checkIsInitialized();
_;
Expand All @@ -39,7 +38,7 @@ contract SpotlightTokenFactory is BeaconProxyStorage, SpotlightTokenFactoryStora
address owner_,
uint256 creationFee_,
address tokenIpCollection_,
address tokenBeacon_,
address tokenImplementation_,
address bondingCurve_,
address baseToken_,
address storyDerivativeWorkflows_,
Expand All @@ -53,7 +52,7 @@ contract SpotlightTokenFactory is BeaconProxyStorage, SpotlightTokenFactoryStora
_owner = owner_;
_creationFee = creationFee_;
_tokenIpCollection = tokenIpCollection_;
_tokenBeacon = tokenBeacon_;
_tokenImplementation = tokenImplementation_;
_bondingCurve = bondingCurve_;
_baseToken = baseToken_;
_storyDerivativeWorkflows = storyDerivativeWorkflows_;
Expand Down Expand Up @@ -86,17 +85,17 @@ contract SpotlightTokenFactory is BeaconProxyStorage, SpotlightTokenFactoryStora
}

/**
* @dev See {ISpotlightTokenFactory-bondingCurve}.
* @dev See {ISpotlightTokenFactory-tokenImplementation}.
*/
function tokenBeacon() public view needInitialized returns (address) {
return _tokenBeacon;
function tokenImplementation() public view needInitialized returns (address) {
return _tokenImplementation;
}

/**
* @dev See {ISpotlightTokenFactory-setTokenBeacon}.
* @dev See {ISpotlightTokenFactory-setTokenImplementation}.
*/
function setTokenBeacon(address newTokenBeacon) external needInitialized onlyOwner {
_tokenBeacon = newTokenBeacon;
function setTokenImplementation(address newTokenImplementation) external needInitialized onlyOwner {
_tokenImplementation = newTokenImplementation;
}

/**
Expand Down Expand Up @@ -159,11 +158,8 @@ contract SpotlightTokenFactory is BeaconProxyStorage, SpotlightTokenFactoryStora
* @dev See {ISpotlightTokenFactory-calculateTokenAddress}.
*/
function calculateTokenAddress(address tokenCreator) external view needInitialized returns (address) {
bytes memory bytecode = _tokenCreateBytecode();
bytes32 salt = _salt(tokenCreator);
bytes32 calculatedHash = keccak256(abi.encodePacked(bytes1(0xff), address(this), salt, keccak256(bytecode)));

return address(uint160(uint256(calculatedHash)));
return Clones.predictDeterministicAddress(_tokenImplementation, salt, address(this));
}

/**
Expand Down Expand Up @@ -237,12 +233,6 @@ contract SpotlightTokenFactory is BeaconProxyStorage, SpotlightTokenFactoryStora
require(msg.sender == _owner, "SpotlightTokenFactory: Not owner");
}

function _tokenCreateBytecode() internal view returns (bytes memory) {
bytes memory creationCode = type(BeaconProxy).creationCode;
bytes memory bytecode = abi.encodePacked(creationCode, abi.encode(_tokenBeacon));
return bytecode;
}

function _salt(address account) internal view returns (bytes32) {
return keccak256(abi.encodePacked(account, numberOfTokensCreated(account)));
}
Expand All @@ -251,8 +241,7 @@ contract SpotlightTokenFactory is BeaconProxyStorage, SpotlightTokenFactoryStora
internal
returns (address)
{
BeaconProxy tokenProxy = new BeaconProxy{salt: _salt(creator)}(_tokenBeacon);
address tokenAddress = address(tokenProxy);
address tokenAddress = Clones.cloneDeterministic(_tokenImplementation, _salt(creator));
ISpotlightToken(tokenAddress).initialize(
owner(),
creator,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ abstract contract SpotlightTokenFactoryStorage {
address internal _owner;
uint256 internal _creationFee;
address internal _creationFeeToken; //deprecated
address internal _tokenBeacon;
address internal _tokenImplementation;
address internal _bondingCurve;
address internal _baseToken;
address internal _tokenIpCollection;
Expand Down
9 changes: 1 addition & 8 deletions src/spotlight-token/SpotlightToken.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {InitializableERC20} from "./InitializableERC20.sol";
import {ISpotlightToken} from "./ISpotlightToken.sol";
import {SpotlightTokenStorage} from "./SpotlightTokenStorage.sol";
import {BeaconProxyStorage} from "../beacon-proxy/BeaconProxyStorage.sol";
import {ISpotlightBondingCurve} from "../spotlight-bonding-curve/ISpotlightBondingCurve.sol";
import {IWETH} from "../interfaces/IWETH.sol";
import {IUniswapV2Router02} from "../interfaces/IUniswapV2Router02.sol";
Expand All @@ -14,13 +13,7 @@ import {MarketType, MarketState} from "./ISpotlightToken.sol";
import {ReentrancyGuard} from "./ReentrancyGuard.sol";
import {ISpotlightProtocolRewards} from "../spotlight-protocol-rewards/ISpotlightProtocolRewards.sol";

contract SpotlightToken is
BeaconProxyStorage,
InitializableERC20,
ReentrancyGuard,
SpotlightTokenStorage,
ISpotlightToken
{
contract SpotlightToken is InitializableERC20, ReentrancyGuard, SpotlightTokenStorage, ISpotlightToken {
constructor() InitializableERC20() {}

modifier needInitialized() {
Expand Down
5 changes: 1 addition & 4 deletions test/SpotlightTokenFactoryTest.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import {MockStoryDerivativeWorkflows} from "./mocks/MockStoryDerivativeWorkflows
import {ISpotlightTokenFactory} from "../src/spotlight-token-factory/ISpotlightTokenFactory.sol";
import {StoryWorkflowStructs} from "../src/spotlight-token-factory/story-workflow-interfaces/StoryWorkflowStructs.sol";
import {SpotlightNativeBondingCurve} from "../src/spotlight-bonding-curve/SpotlightNativeBondingCurve.sol";
import {UpgradeableBeacon} from "@openzeppelin/contracts/proxy/beacon/UpgradeableBeacon.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {SpotlightProtocolRewards} from "../src/spotlight-protocol-rewards/SpotlightProtocolRewards.sol";

Expand All @@ -23,7 +22,6 @@ contract SpotlightTokenFactoryTest is Test {

SpotlightTokenIPCollection private _tokenIpCollection;
SpotlightNativeBondingCurve private _bondingCurve;
UpgradeableBeacon private _spotlightTokenBeacon;
SpotlightProtocolRewards private _protocolRewards;
address private constant Wrapper_IP = 0xe8CabF9d1FFB6CE23cF0a86641849543ec7BD7d5;

Expand All @@ -37,14 +35,13 @@ contract SpotlightTokenFactoryTest is Test {
_factoryAddress = address(_factory);
_tokenIpCollection = new SpotlightTokenIPCollection(_factoryAddress);
_bondingCurve = new SpotlightNativeBondingCurve(1060848709, 4379701787);
_spotlightTokenBeacon = new UpgradeableBeacon(address(spotlightTokenImpl), _factoryOwner);
_protocolRewards = new SpotlightProtocolRewards();

_factory.initialize(
_factoryOwner,
DEFAULT_CREATION_FEE,
address(_tokenIpCollection),
address(_spotlightTokenBeacon),
address(spotlightTokenImpl),
address(_bondingCurve),
Wrapper_IP,
address(_mockStoryWorkflows),
Expand Down
5 changes: 1 addition & 4 deletions test/SpotlightTokenTest.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import {MockStoryDerivativeWorkflows} from "./mocks/MockStoryDerivativeWorkflows
import {ISpotlightTokenFactory} from "../src/spotlight-token-factory/ISpotlightTokenFactory.sol";
import {StoryWorkflowStructs} from "../src/spotlight-token-factory/story-workflow-interfaces/StoryWorkflowStructs.sol";
import {SpotlightNativeBondingCurve} from "../src/spotlight-bonding-curve/SpotlightNativeBondingCurve.sol";
import {UpgradeableBeacon} from "@openzeppelin/contracts/proxy/beacon/UpgradeableBeacon.sol";
import {IUniswapV2Router02} from "../src/interfaces/IUniswapV2Router02.sol";
import {ISpotlightToken} from "../src/spotlight-token/ISpotlightToken.sol";
import {SpotlightProtocolRewards} from "../src/spotlight-protocol-rewards/SpotlightProtocolRewards.sol";
Expand All @@ -33,7 +32,6 @@ contract SpotlightTokenTest is Test {
SpotlightTokenFactory private _factory;
SpotlightTokenIPCollection private _tokenIpCollection;
SpotlightNativeBondingCurve private _bondingCurve;
UpgradeableBeacon private _spotlightTokenBeacon;
SpotlightToken private _token;
SpotlightToken private _tokenCreatedWithSpecificAddress;
MockStoryDerivativeWorkflows private _mockStoryWorkflows;
Expand All @@ -53,14 +51,13 @@ contract SpotlightTokenTest is Test {
_factory = new SpotlightTokenFactory();
_tokenIpCollection = new SpotlightTokenIPCollection(address(_factory));
_bondingCurve = new SpotlightNativeBondingCurve(690_000_000, 2_878_200_000);
_spotlightTokenBeacon = new UpgradeableBeacon(address(spotlightTokenImpl), _factoryOwner);
_protocolRewards = new SpotlightProtocolRewards();

_factory.initialize(
_factoryOwner,
DEFAULT_CREATION_FEE,
address(_tokenIpCollection),
address(_spotlightTokenBeacon),
address(spotlightTokenImpl),
address(_bondingCurve),
WRAPPER_IP,
address(_mockStoryWorkflows),
Expand Down

0 comments on commit 87d2a0a

Please sign in to comment.