Skip to content

Commit

Permalink
review fixes, add the deregister process
Browse files Browse the repository at this point in the history
  • Loading branch information
FedokDL committed Dec 13, 2024
1 parent 149310a commit 8c69bfa
Show file tree
Hide file tree
Showing 7 changed files with 327 additions and 123 deletions.
42 changes: 24 additions & 18 deletions smart-contracts/contracts/delegate/DelegatorFactory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,28 +9,26 @@ import {UpgradeableBeacon} from "@openzeppelin/contracts/proxy/beacon/Upgradeabl
import {BeaconProxy} from "@openzeppelin/contracts/proxy/beacon/BeaconProxy.sol";

import {IProvidersDelegator} from "../interfaces/delegate/IProvidersDelegator.sol";
import {IDelegatorFactory} from "../interfaces/delegate/IDelegatorFactory.sol";
import {IOwnable} from "../interfaces/utils/IOwnable.sol";

contract DelegatorFactory is OwnableUpgradeable, PausableUpgradeable, UUPSUpgradeable {
contract DelegatorFactory is IDelegatorFactory, OwnableUpgradeable, PausableUpgradeable, UUPSUpgradeable {
address public lumerinDiamond;
address public beacon;
mapping(address => address[]) public proxies;

event ProxyDeployed(address indexed proxyAddress);
event ImplementationUpdated(address indexed newImplementation);

constructor() {
_disableInitializers();
}

function DelegatorFactory_init(address _lumerinDiamond, address _implementation) external initializer {
function DelegatorFactory_init(address lumerinDiamond_, address implementation_) external initializer {
__Pausable_init();
__Ownable_init();
__UUPSUpgradeable_init();

lumerinDiamond = _lumerinDiamond;
lumerinDiamond = lumerinDiamond_;

beacon = address(new UpgradeableBeacon(_implementation));
beacon = address(new UpgradeableBeacon(implementation_));
}

function pause() external onlyOwner {
Expand All @@ -45,23 +43,33 @@ contract DelegatorFactory is OwnableUpgradeable, PausableUpgradeable, UUPSUpgrad
address feeTreasury_,
uint256 fee_,
string memory name_,
string memory endpoint_
string memory endpoint_,
uint128 deregistrationTimeout_,
uint128 deregistrationNonFeePeriod_
) external whenNotPaused returns (address) {
bytes32 salt_ = _calculatePoolSalt(_msgSender());
address proxy_ = address(new BeaconProxy{salt: salt_}(beacon, bytes("")));

proxies[_msgSender()].push(address(proxy_));
proxies[_msgSender()].push(proxy_);

IProvidersDelegator(proxy_).ProvidersDelegator_init(lumerinDiamond, feeTreasury_, fee_, name_, endpoint_);
IProvidersDelegator(proxy_).ProvidersDelegator_init(
lumerinDiamond,
feeTreasury_,
fee_,
name_,
endpoint_,
deregistrationTimeout_,
deregistrationNonFeePeriod_
);
IOwnable(proxy_).transferOwnership(_msgSender());

emit ProxyDeployed(address(proxy_));
emit ProxyDeployed(proxy_);

return address(proxy_);
return proxy_;
}

function predictProxyAddress(address _deployer) external view returns (address) {
bytes32 salt_ = _calculatePoolSalt(_deployer);
function predictProxyAddress(address deployer_) external view returns (address) {
bytes32 salt_ = _calculatePoolSalt(deployer_);

bytes32 bytecodeHash_ = keccak256(
abi.encodePacked(type(BeaconProxy).creationCode, abi.encode(address(beacon), bytes("")))
Expand All @@ -70,10 +78,8 @@ contract DelegatorFactory is OwnableUpgradeable, PausableUpgradeable, UUPSUpgrad
return Create2.computeAddress(salt_, bytecodeHash_);
}

function updateImplementation(address _newImplementation) external onlyOwner {
UpgradeableBeacon(beacon).upgradeTo(_newImplementation);

emit ImplementationUpdated(_newImplementation);
function updateImplementation(address newImplementation_) external onlyOwner {
UpgradeableBeacon(beacon).upgradeTo(newImplementation_);
}

function version() external pure returns (uint256) {
Expand Down
85 changes: 52 additions & 33 deletions smart-contracts/contracts/delegate/ProvidersDelegator.sol
Original file line number Diff line number Diff line change
Expand Up @@ -16,34 +16,26 @@ contract ProvidersDelegator is IProvidersDelegator, OwnableUpgradeable {
using SafeERC20 for IERC20;
using Math for uint256;

/**
* @dev The Lumerin protocol data
*/
address public lumerinDiamond;
address public token;

/**
* @dev The fee data
*/
address public feeTreasury;
uint256 public fee;

/**
* @dev Provider metadata
*/
string public name;
string public endpoint;


/**
* @dev The main contract logic data
*/
uint256 public totalStaked;
uint256 public totalRate;
uint256 public lastContractBalance;
bool public isStakeClosed;
mapping(address => Staker) public stakers;

uint128 public deregistrationOpenAt;
uint128 public deregistrationTimeout;
uint128 public deregistrationNonFeeOpened;
uint128 public deregistrationNonFeePeriod;

constructor() {
_disableInitializers();
}
Expand All @@ -53,7 +45,9 @@ contract ProvidersDelegator is IProvidersDelegator, OwnableUpgradeable {
address feeTreasury_,
uint256 fee_,
string memory name_,
string memory endpoint_
string memory endpoint_,
uint128 deregistrationTimeout_,
uint128 deregistrationNonFeePeriod_
) external initializer {
__Ownable_init();

Expand All @@ -62,9 +56,18 @@ contract ProvidersDelegator is IProvidersDelegator, OwnableUpgradeable {

setName(name_);
setEndpoint(endpoint_);
setFee(feeTreasury_, fee_);
setFeeTreasury(feeTreasury_);

if (fee_ > PRECISION) {
revert InvalidFee(fee_, PRECISION);
}
fee = fee_;

IERC20(token).approve(lumerinDiamond_, type(uint256).max);

deregistrationTimeout = deregistrationTimeout_;
deregistrationOpenAt = uint128(block.timestamp) + deregistrationTimeout_;
deregistrationNonFeePeriod = deregistrationNonFeePeriod_;
}

function setName(string memory name_) public onlyOwner {
Expand All @@ -87,18 +90,14 @@ contract ProvidersDelegator is IProvidersDelegator, OwnableUpgradeable {
emit EndpointUpdated(endpoint_);
}

function setFee(address feeTreasury_, uint256 fee_) public onlyOwner {
function setFeeTreasury(address feeTreasury_) public onlyOwner {
if (feeTreasury_ == address(0)) {
revert InvalidFeeTreasuryAddress();
}
if (fee_ > PRECISION) {
revert InvalidFee(fee_, PRECISION);
}

fee = fee_;
feeTreasury = feeTreasury_;

emit FeeUpdated(fee_, feeTreasury_);
emit FeeTreasuryUpdated(feeTreasury_);
}

function setIsStakeClosed(bool isStakeClosed_) public onlyOwner {
Expand All @@ -117,10 +116,11 @@ contract ProvidersDelegator is IProvidersDelegator, OwnableUpgradeable {
if (isStakeClosed) {
revert StakeClosed();
}

if (amount_ == 0) {
revert InsufficientAmount();
}

address user_ = _msgSender();
Staker storage staker = stakers[user_];

Expand Down Expand Up @@ -168,6 +168,7 @@ contract ProvidersDelegator is IProvidersDelegator, OwnableUpgradeable {

staker.rate = currentRate_;
staker.staked += amount_;
staker.claimed += amount_;
staker.pendingRewards = pendingRewards_ - amount_;

IProviderRegistry(lumerinDiamond).providerRegister(address(this), amount_, endpoint);
Expand All @@ -192,9 +193,10 @@ contract ProvidersDelegator is IProvidersDelegator, OwnableUpgradeable {

staker.rate = currentRate_;
staker.pendingRewards = pendingRewards_ - amount_;
staker.claimed += amount_;

uint256 feeAmount_ = (amount_ * fee) / PRECISION;
if (feeAmount_ != 0) {
if (feeAmount_ != 0 && block.timestamp > deregistrationNonFeeOpened + deregistrationNonFeePeriod) {
IERC20(token).safeTransfer(feeTreasury, feeAmount_);

amount_ -= feeAmount_;
Expand All @@ -221,25 +223,42 @@ contract ProvidersDelegator is IProvidersDelegator, OwnableUpgradeable {
}

function getCurrentStakerRewards(address staker_) public view returns (uint256) {
Staker memory staker = stakers[staker_];
(uint256 currentRate_,) = getCurrentRate();
(uint256 currentRate_, ) = getCurrentRate();

return _getCurrentStakerRewards(currentRate_, staker);
return _getCurrentStakerRewards(currentRate_, stakers[staker_]);
}

function providerDeregister() external onlyOwner {
function providerDeregister(bytes32[] calldata bidIds_) external {
if (block.timestamp < deregistrationOpenAt) {
_checkOwner();
} else {
deregistrationOpenAt = uint128(block.timestamp) + deregistrationTimeout;
}

_deleteModelBids(bidIds_);
IProviderRegistry(lumerinDiamond).providerDeregister(address(this));

deregistrationNonFeeOpened = uint128(block.timestamp);
}

function postModelBid(
bytes32 modelId_,
uint256 pricePerSecond_
) external onlyOwner returns (bytes32) {
function postModelBid(bytes32 modelId_, uint256 pricePerSecond_) external onlyOwner returns (bytes32) {
return IMarketplace(lumerinDiamond).postModelBid(address(this), modelId_, pricePerSecond_);
}

function deleteModelBid(bytes32 bidId_) external onlyOwner {
return IMarketplace(lumerinDiamond).deleteModelBid(bidId_);
function deleteModelBids(bytes32[] calldata bidIds_) external {
if (block.timestamp < deregistrationOpenAt) {
_checkOwner();
}

_deleteModelBids(bidIds_);
}

function _deleteModelBids(bytes32[] calldata bidIds_) private {
address lumerinDiamond_ = lumerinDiamond;

for (uint256 i = 0; i < bidIds_.length; i++) {
IMarketplace(lumerinDiamond_).deleteModelBid(bidIds_[i]);
}
}

function _getCurrentStakerRewards(uint256 delegatorRate_, Staker memory staker_) private pure returns (uint256) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

interface IDelegatorFactory {
event ProxyDeployed(address indexed proxyAddress);
event ImplementationUpdated(address indexed newImplementation);

/**
* The function to initialize the contract.
* @param lumerinDiamond_ The Lumerin protocol address.
* @param implementation_ The implementation address.
*/
function DelegatorFactory_init(address lumerinDiamond_, address implementation_) external;

/**
* Triggers stopped state.
*/
function pause() external;

/**
* Returns to normal state.
*/
function unpause() external;

/**
* The function to deploy the new proxy contract.
* @param feeTreasury_ The subnet fee treasury.
* @param fee_ The fee percent where 100% = 10^25.
* @param name_ The Subnet name.
* @param endpoint_ The subnet endpoint.
* @param deregistrationTimeout_ Provider deregistration will be available after this timeout.
* @param deregistrationNonFeePeriod_ Period after deregistration when Stakers can claim rewards without fee.
*/
function deployProxy(
address feeTreasury_,
uint256 fee_,
string memory name_,
string memory endpoint_,
uint128 deregistrationTimeout_,
uint128 deregistrationNonFeePeriod_
) external returns (address);

/**
* The function to predict new proxy address.
* @param _deployer The deployer address.
*/
function predictProxyAddress(address _deployer) external view returns (address);

/**
* The function to upgrade the implementation.
* @param _newImplementation The new implementation address.
*/
function updateImplementation(address _newImplementation) external;

/**
* The function to get contract version.
*/
function version() external pure returns (uint256);
}
Loading

0 comments on commit 8c69bfa

Please sign in to comment.