diff --git a/nest/script/DeployNestContracts.s.sol b/nest/script/DeployNestContracts.s.sol index 5a68323..f7d0154 100644 --- a/nest/script/DeployNestContracts.s.sol +++ b/nest/script/DeployNestContracts.s.sol @@ -7,12 +7,15 @@ import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import { AggregateToken } from "../src/AggregateToken.sol"; import { FakeComponentToken } from "../src/FakeComponentToken.sol"; +import { NestStaking } from "../src/NestStaking.sol"; import { AggregateTokenProxy } from "../src/proxies/AggregateTokenProxy.sol"; import { FakeComponentTokenProxy } from "../src/proxies/FakeComponentTokenProxy.sol"; +import { NestStakingProxy } from "../src/proxies/NestStakingProxy.sol"; contract DeployNestContracts is Script { address private constant ARC_ADMIN_ADDRESS = 0x1c9d94FAD4ccCd522804a955103899e0D6A4405a; + address private constant NEST_ADMIN_ADDRESS = 0xb015762405De8fD24d29A6e0799c12e0Ea81c1Ff; address private constant USDC_ADDRESS = 0x849c25e6cCB03cdc23ba91d92440dA7bC8486be2; function run() external { @@ -33,7 +36,7 @@ contract DeployNestContracts is Script { abi.encodeCall( AggregateToken.initialize, ( - ARC_ADMIN_ADDRESS, + NEST_ADMIN_ADDRESS, "Apple", "AAPL", USDC_ADDRESS, @@ -46,6 +49,11 @@ contract DeployNestContracts is Script { ); console.log("AggregateTokenProxy deployed to:", address(aggregateTokenProxy)); + NestStaking nestStaking = new NestStaking(); + NestStakingProxy nestStakingProxy = + new NestStakingProxy(address(nestStaking), abi.encodeCall(NestStaking.initialize, (NEST_ADMIN_ADDRESS))); + console.log("NestStakingProxy deployed to:", address(nestStakingProxy)); + vm.stopBroadcast(); } diff --git a/nest/src/NestStaking.sol b/nest/src/NestStaking.sol new file mode 100644 index 0000000..c97ddb4 --- /dev/null +++ b/nest/src/NestStaking.sol @@ -0,0 +1,91 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.25; + +import { AccessControlUpgradeable } from "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol"; +import { Initializable } from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; +import { UUPSUpgradeable } from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; + +import { AggregateToken } from "./AggregateToken.sol"; +import { IAggregateToken } from "./interfaces/IAggregateToken.sol"; +import { AggregateTokenProxy } from "./proxies/AggregateTokenProxy.sol"; + +/** + * @title NestStaking + * @author Eugene Y. Q. Shen + * @notice Contract for creating AggregateTokens + * @custom:oz-upgrades-from NestStaking + */ +contract NestStaking is Initializable, AccessControlUpgradeable, UUPSUpgradeable { + + // Constants + + /// @notice Role for the upgrader of the AggregateToken + bytes32 public constant UPGRADER_ROLE = keccak256("UPGRADE_ROLE"); + + // Events + + /** + * @notice Emitted when a new AggregateToken is created + * @param owner Address of the owner of the AggregateToken + * @param aggregateTokenProxy Address of the proxy of the new AggregateToken + */ + event TokenCreated(address indexed owner, AggregateTokenProxy indexed aggregateTokenProxy); + + // Initializer + + /** + * @notice Initialize the AggregateToken + * @param owner Address of the owner of the AggregateToken + */ + function initialize(address owner) public initializer { + __AccessControl_init(); + __UUPSUpgradeable_init(); + + _grantRole(DEFAULT_ADMIN_ROLE, owner); + _grantRole(UPGRADER_ROLE, owner); + } + + // Override Functions + + /** + * @notice Revert when `msg.sender` is not authorized to upgrade the contract + * @param newImplementation Address of the new implementation + */ + function _authorizeUpgrade(address newImplementation) internal override onlyRole(UPGRADER_ROLE) { } + + // User Functions + + /** + * @notice Create a new AggregateToken + * @param owner Address of the owner of the AggregateToken + * @param name Name of the AggregateToken + * @param symbol Symbol of the AggregateToken + * @param currencyAddress Address of the CurrencyToken used to mint and burn the AggregateToken + * @param decimals_ Number of decimals of the AggregateToken + * @param askPrice Price at which users can buy the AggregateToken using CurrencyToken, times the base + * @param bidPrice Price at which users can sell the AggregateToken to receive CurrencyToken, times the base + * @param tokenURI URI of the AggregateToken metadata + */ + function createAggregateToken( + address owner, + string memory name, + string memory symbol, + address currencyAddress, + uint8 decimals_, + uint256 askPrice, + uint256 bidPrice, + string memory tokenURI + ) public { + AggregateToken aggregateToken = new AggregateToken(); + AggregateTokenProxy aggregateTokenProxy = new AggregateTokenProxy( + address(aggregateToken), + abi.encodeCall( + AggregateToken.initialize, + (owner, name, symbol, currencyAddress, decimals_, askPrice, bidPrice, tokenURI) + ) + ); + + emit TokenCreated(msg.sender, aggregateTokenProxy); + } + +} diff --git a/nest/src/proxies/NestStakingProxy.sol b/nest/src/proxies/NestStakingProxy.sol new file mode 100644 index 0000000..007a970 --- /dev/null +++ b/nest/src/proxies/NestStakingProxy.sol @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.25; + +import { ERC1967Proxy } from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol"; + +/** + * @title NestStakingProxy + * @author Eugene Y. Q. Shen + * @notice Proxy contract for the NestStakingProxy + */ +contract NestStakingProxy is ERC1967Proxy { + + constructor(address logic, bytes memory data) ERC1967Proxy(logic, data) { } + +}