Skip to content

Commit

Permalink
Merge pull request #44 from soramitsu/feature/refactor
Browse files Browse the repository at this point in the history
Feature/refactor
  • Loading branch information
SergeyPoslavskiy authored Jul 10, 2024
2 parents 1e33dc8 + ada8318 commit 3a25f21
Show file tree
Hide file tree
Showing 20 changed files with 1,846 additions and 1,781 deletions.
102 changes: 102 additions & 0 deletions contracts/RequestManager.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
/*
ERC20LockUpFactory
SPDX-License-Identifier: MIT
*/

pragma solidity 0.8.25;

import {IRequestManager} from "./interfaces/IRequestManager.sol";
import {IBaseFactory} from "./interfaces/IFactories/IBaseFactory.sol";
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";

/// @title RequestManager
contract RequestManager is Ownable, IRequestManager {
using SafeERC20 for IERC20;

address[] public stakingPools;
Request[] public requests;
mapping(address factory => bool whitelisted) public whitelistFactory;
mapping(uint256 id => address pool) public poolById;

constructor() Ownable(msg.sender) {}

function addFactory(address factory) onlyOwner external {
if (factory == address(0)) revert InvalidAddress();
whitelistFactory[factory] = true;
emit FactoryRegistered(factory);
}

function removeFactory(address factory) onlyOwner external {
if (whitelistFactory[factory] != true) revert UnregisteredFactory();
whitelistFactory[factory] = false;
emit FactoryUnregistered(factory);
}

/// @notice Function allows users to deploy the staking pool with specified parameters
function deploy(uint256 id) external returns (address newPoolAddress) {
if (requests.length <= id) revert InvalidId();
Request memory req = requests[id];
if (req.requestStatus != Status.APPROVED) revert InvalidRequestStatus();
if (msg.sender != req.data.deployer) revert InvalidCaller();
requests[id].requestStatus = Status.DEPLOYED;
newPoolAddress = IBaseFactory(req.data.factory).deploy(
req.data.deployer,
req.data.stakingData
);
stakingPools.push(newPoolAddress);
poolById[id] = newPoolAddress;
emit RequestFullfilled(id, newPoolAddress);
}

function requestDeployment(RequestPayload calldata data) external {
if (data.deployer == address(0) || data.factory == address(0))
revert InvalidAddress();
if (data.ipfsHash == bytes32(0)) revert InvalidIpfsHash();
if (data.stakingData.length == 0) revert InvalidPayload();
if (whitelistFactory[data.factory] != true)
revert UnregisteredFactory();
requests.push(Request({requestStatus: Status.CREATED, data: data}));
emit RequestSubmitted(
requests.length - 1,
data
);
}

function approveRequest(uint256 id) external onlyOwner {
if (requests.length <= id) revert InvalidId();
Request storage req = requests[id];
if (req.requestStatus != Status.CREATED) revert InvalidRequestStatus();
req.requestStatus = Status.APPROVED;
emit RequestStatusChanged(id, req.requestStatus);
}

function denyRequest(uint256 id) external onlyOwner {
if (requests.length <= id) revert InvalidId();
Request storage req = requests[id];
if (req.requestStatus != Status.CREATED) revert InvalidRequestStatus();
req.requestStatus = Status.DENIED;
emit RequestStatusChanged(id, req.requestStatus);
}

function cancelRequest(uint256 id) external {
if (requests.length <= id) revert InvalidId();
Request storage req = requests[id];
if (msg.sender != req.data.deployer) revert InvalidCaller();
if (
req.requestStatus != Status.CREATED &&
req.requestStatus != Status.APPROVED
) revert InvalidRequestStatus();
req.requestStatus = Status.CANCELED;
emit RequestStatusChanged(id, req.requestStatus);
}

function getRequests() external view returns (Request[] memory reqs) {
reqs = requests;
}

function getPools() external view returns (address[] memory pools) {
pools = stakingPools;
}
}
114 changes: 27 additions & 87 deletions contracts/factories/ERC20LockUpFactory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -12,114 +12,54 @@ import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol

/// @title ERC20LockUpStakingFactory
/// @notice A smart contract for deploying ERC20 LockUp staking pools.
/// @author Ayooluwa Akindeko, Soramitsu team
contract ERC20LockUpStakingFactory is Ownable, ILockUpFactory {
using SafeERC20 for IERC20;

address public requestManager;
address[] public stakingPools;
LockUpRequest[] public requests;
mapping(uint256 id => address pool) public poolById;

constructor() Ownable(msg.sender) {}
constructor(address managerContract) Ownable(msg.sender) {
if (managerContract == address(0)) revert InvalidManagerAddress();
requestManager = managerContract;
}

/// @notice Function allows users to deploy the LockUp staking pool with specified parameters
function deploy(uint256 id) public returns (address newPoolAddress) {
if (requests.length <= id) revert InvalidId();
LockUpRequest memory req = requests[id];
if (req.info.requestStatus != Status.APPROVED)
revert InvalidRequestStatus();
if (msg.sender != req.info.deployer) revert InvalidCaller();
function deploy(address deployer, bytes calldata payload) external returns (address newPoolAddress) {
if (payload.length != 224) revert InvalidPayloadLength();
if (msg.sender != requestManager) revert InvalidCaller();
DeploymentData memory data = abi.decode(payload, (DeploymentData));
newPoolAddress = address(
new ERC20LockUpPool{
salt: keccak256(
abi.encode(
req.data.stakeToken,
req.data.rewardToken,
req.data.rewardPerSecond,
req.data.poolStartTime,
req.data.poolEndTime
data.stakeToken,
data.rewardToken,
data.rewardPerSecond,
data.poolStartTime,
data.poolEndTime
)
)
}(
req.data.stakeToken,
req.data.rewardToken,
req.data.poolStartTime,
req.data.poolEndTime,
req.data.rewardPerSecond,
req.data.unstakeLockUpTime,
req.data.claimLockUpTime
data.stakeToken,
data.rewardToken,
data.poolStartTime,
data.poolEndTime,
data.rewardPerSecond,
data.unstakeLockUpTime,
data.claimLockUpTime
)
);
stakingPools.push(newPoolAddress);
requests[id].info.requestStatus = Status.DEPLOYED;
poolById[id] = newPoolAddress;
uint256 rewardAmount = (req.data.poolEndTime - req.data.poolStartTime) *
req.data.rewardPerSecond;
ERC20LockUpPool(newPoolAddress).transferOwnership(msg.sender);
uint256 rewardAmount = (data.poolEndTime - data.poolStartTime) *
data.rewardPerSecond;
ERC20LockUpPool(newPoolAddress).transferOwnership(deployer);
// Transfer reward tokens from the owner to the contract
// slither-disable-next-line arbitrary-send-erc20
IERC20(req.data.rewardToken).safeTransferFrom(
msg.sender,
IERC20(data.rewardToken).safeTransferFrom(
deployer,
newPoolAddress,
rewardAmount
);
emit StakingPoolDeployed(newPoolAddress, id);
}

function requestDeployment(
bytes32 ipfsHash,
DeploymentData calldata data
) external {
if (data.stakeToken == address(0) || data.rewardToken == address(0))
revert InvalidTokenAddress();
requests.push(
LockUpRequest({
info: RequestInfo({
ipfsHash: ipfsHash,
deployer: msg.sender,
requestStatus: Status.CREATED
}),
data: data
})
);
emit RequestSubmitted(
requests.length - 1,
msg.sender,
Status.CREATED,
data
);
}

function approveRequest(uint256 id) external onlyOwner {
if (requests.length <= id) revert InvalidId();
LockUpRequest storage req = requests[id];
if (req.info.requestStatus != Status.CREATED) revert InvalidRequestStatus();
req.info.requestStatus = Status.APPROVED;
emit RequestStatusChanged(id, req.info.requestStatus);
}

function denyRequest(uint256 id) external onlyOwner {
if (requests.length <= id) revert InvalidId();
LockUpRequest storage req = requests[id];
if (req.info.requestStatus != Status.CREATED) revert InvalidRequestStatus();
req.info.requestStatus = Status.DENIED;
emit RequestStatusChanged(id, req.info.requestStatus);
}

function cancelRequest(uint256 id) external {
if (requests.length <= id) revert InvalidId();
LockUpRequest storage req = requests[id];
if (msg.sender != req.info.deployer) revert InvalidCaller();
if (
req.info.requestStatus != Status.CREATED &&
req.info.requestStatus != Status.APPROVED
) revert InvalidRequestStatus();
req.info.requestStatus = Status.CANCELED;
emit RequestStatusChanged(id, req.info.requestStatus);
}

function getRequests() external view returns (LockUpRequest[] memory reqs) {
reqs = requests;
emit StakingPoolDeployed(newPoolAddress);
}

function getPools() external view returns (address[] memory pools) {
Expand Down
107 changes: 26 additions & 81 deletions contracts/factories/ERC20PenaltyFeeFactory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -15,107 +15,52 @@ import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol
/// @author Ayooluwa Akindeko, Soramitsu team
contract ERC20PenaltyFeeStakingFactory is Ownable, IPenaltyFeeFactory {
using SafeERC20 for IERC20;

address public requestManager;
address[] public stakingPools;
PenaltyFeeRequest[] public requests;
mapping(uint256 id => address pool) public poolById;

constructor() Ownable(msg.sender) {}
constructor(address managerContract) Ownable(msg.sender) {
if (managerContract == address(0)) revert InvalidManagerAddress();
requestManager = managerContract;
}

/// @notice Function allows users to deploy the penaltyFee staking pool with specified parameters
function deploy(uint256 id) public returns (address newPoolAddress) {
if (requests.length < id) revert InvalidId();
PenaltyFeeRequest memory req = requests[id];
if (req.info.requestStatus != Status.APPROVED) revert InvalidRequestStatus();
if (msg.sender != req.info.deployer) revert InvalidCaller();
function deploy(address deployer, bytes calldata payload) external returns (address newPoolAddress) {
if (payload.length != 192) revert InvalidPayloadLength();
if (msg.sender != requestManager) revert InvalidCaller();
DeploymentData memory data = abi.decode(payload, (DeploymentData));
newPoolAddress = address(
new ERC20PenaltyFeePool{
salt: keccak256(
abi.encode(
req.data.stakeToken,
req.data.rewardToken,
req.data.rewardPerSecond,
req.data.poolStartTime,
req.data.poolEndTime
data.stakeToken,
data.rewardToken,
data.rewardPerSecond,
data.poolStartTime,
data.poolEndTime
)
)
}(
req.data.stakeToken,
req.data.rewardToken,
req.data.poolStartTime,
req.data.poolEndTime,
req.data.rewardPerSecond,
req.data.penaltyPeriod,
data.stakeToken,
data.rewardToken,
data.poolStartTime,
data.poolEndTime,
data.rewardPerSecond,
data.penaltyPeriod,
owner()
)
);
stakingPools.push(newPoolAddress);
requests[id].info.requestStatus = Status.DEPLOYED;
poolById[id] = newPoolAddress;
uint256 rewardAmount = (req.data.poolEndTime - req.data.poolStartTime) *
req.data.rewardPerSecond;
ERC20PenaltyFeePool(newPoolAddress).transferOwnership(msg.sender);
uint256 rewardAmount = (data.poolEndTime - data.poolStartTime) *
data.rewardPerSecond;
ERC20PenaltyFeePool(newPoolAddress).transferOwnership(deployer);
// Transfer reward tokens from the owner to the contract
// slither-disable-next-line arbitrary-send-erc20
IERC20(req.data.rewardToken).safeTransferFrom(
msg.sender,
IERC20(data.rewardToken).safeTransferFrom(
deployer,
newPoolAddress,
rewardAmount
);
emit StakingPoolDeployed(newPoolAddress, id);
}

function requestDeployment(bytes32 ipfsHash, DeploymentData calldata data) external {
if (data.stakeToken == address(0) || data.rewardToken == address(0))
revert InvalidTokenAddress();
requests.push(
PenaltyFeeRequest({
info: RequestInfo({
ipfsHash: ipfsHash,
deployer: msg.sender,
requestStatus: Status.CREATED
}),
data: data
})
);
emit RequestSubmitted(
requests.length - 1,
msg.sender,
Status.CREATED,
data
);
}

function approveRequest(uint256 id) external onlyOwner {
if (requests.length <= id) revert InvalidId();
PenaltyFeeRequest storage req = requests[id];
if (req.info.requestStatus != Status.CREATED) revert InvalidRequestStatus();
req.info.requestStatus = Status.APPROVED;
emit RequestStatusChanged(id, req.info.requestStatus);
}

function denyRequest(uint256 id) external onlyOwner {
if (requests.length <= id) revert InvalidId();
PenaltyFeeRequest storage req = requests[id];
if (req.info.requestStatus != Status.CREATED) revert InvalidRequestStatus();
req.info.requestStatus = Status.DENIED;
emit RequestStatusChanged(id, req.info.requestStatus);
}

function cancelRequest(uint256 id) external {
if (requests.length <= id) revert InvalidId();
PenaltyFeeRequest storage req = requests[id];
if (msg.sender != req.info.deployer) revert InvalidCaller();
if (
req.info.requestStatus != Status.CREATED ||
req.info.requestStatus != Status.APPROVED
) revert InvalidRequestStatus();
req.info.requestStatus = Status.CANCELED;
emit RequestStatusChanged(id, req.info.requestStatus);
}

function getRequests() external view returns (PenaltyFeeRequest[] memory reqs) {
reqs = requests;
emit StakingPoolDeployed(newPoolAddress);
}

function getPools() external view returns (address[] memory pools) {
Expand Down
Loading

0 comments on commit 3a25f21

Please sign in to comment.