-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Initial commit with BqETHSubscription contract
- Loading branch information
Showing
2 changed files
with
152 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,151 @@ | ||
// SPDX-License-Identifier: AGPL-3.0-or-later | ||
|
||
pragma solidity ^0.8.0; | ||
|
||
import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; | ||
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; | ||
import "./Coordinator.sol"; | ||
import "./IFeeModel.sol"; | ||
|
||
using SafeERC20 for IERC20; | ||
|
||
/** | ||
* @title BqETH Subscription | ||
* @notice Manages the subscription information for rituals. | ||
*/ | ||
contract BqETHSubscription is IFeeModel { | ||
Coordinator public immutable coordinator; | ||
IERC20 public immutable feeToken; | ||
|
||
// TODO: DAO Treasury | ||
// TODO: Should it be updatable? | ||
address public immutable beneficiary; | ||
address public immutable adopter; | ||
|
||
uint256 public immutable feeRate; | ||
uint256 public immutable maxNodes; | ||
uint32 public immutable maxDuration; | ||
|
||
uint32 public endOfSubscription; | ||
uint32 public acttiveRitualId; | ||
|
||
/** | ||
* @notice Emitted when a subscription is spent | ||
* @param beneficiary The address of the beneficiary | ||
* @param amount The amount withdrawn | ||
*/ | ||
event WithdrawalToBeneficiary(address indexed beneficiary, uint256 amount); | ||
|
||
/** | ||
* @notice Emitted when a subscription is paid | ||
* @param subscriber The address of the subscriber | ||
* @param amount The amount paid | ||
*/ | ||
event SubscriptionPaid(address indexed subscriber, uint256 amount); | ||
|
||
/** | ||
* @notice Sets the coordinator and fee token contracts | ||
* @dev The coordinator and fee token contracts cannot be zero addresses | ||
* @param _coordinator The address of the coordinator contract | ||
* @param _feeToken The address of the fee token contract | ||
* @param _beneficiary The address of the beneficiary | ||
* @param _adopter The address of the adopter | ||
* @param _feeRate Fee rate per node per second | ||
* @param _maxNodes Maximum nodes in the package | ||
* @param _maxDuration Maximum duration of ritual | ||
*/ | ||
constructor( | ||
Coordinator _coordinator, | ||
IERC20 _feeToken, | ||
address _beneficiary, | ||
address _adopter, | ||
uint256 _feeRate, | ||
uint256 _maxNodes, | ||
uint32 _maxDuration | ||
) { | ||
require(address(_coordinator) != address(0), "Coordinator cannot be the zero address"); | ||
require(address(_feeToken) != address(0), "Fee token cannot be the zero address"); | ||
require(_beneficiary != address(0), "Beneficiary cannot be the zero address"); | ||
require(_adopter != address(0), "Adopter cannot be the zero address"); | ||
coordinator = _coordinator; | ||
feeToken = _feeToken; | ||
beneficiary = _beneficiary; | ||
adopter = _adopter; | ||
feeRate = _feeRate; | ||
maxNodes = _maxNodes; | ||
maxDuration = _maxDuration; | ||
} | ||
|
||
modifier onlyBeneficiary() { | ||
require(msg.sender == beneficiary, "Only the beneficiary can call this method"); | ||
_; | ||
} | ||
|
||
modifier onlyAdopter() { | ||
require(msg.sender == beneficiary, "Only the adopter can call this method"); | ||
_; | ||
} | ||
|
||
function packageFees() public view returns (uint256) { | ||
return feeRate * maxDuration * maxNodes; | ||
} | ||
|
||
/** | ||
* @notice Pays for a subscription | ||
*/ | ||
function paySubscriptionFor() external { | ||
require(endOfSubscription == 0, "Subscription already payed"); | ||
uint256 amount = packageFees(); | ||
endOfSubscription = uint32(block.timestamp + maxDuration); | ||
|
||
feeToken.safeTransferFrom(msg.sender, address(this), amount); | ||
emit SubscriptionPaid(msg.sender, amount); | ||
} | ||
|
||
/** | ||
* @notice Withdraws the contract balance to the beneficiary | ||
* @param amount The amount to withdraw | ||
*/ | ||
function withdrawToBeneficiary(uint256 amount) external onlyBeneficiary { | ||
require(amount <= feeToken.balanceOf(address(this)), "Insufficient available amount"); | ||
feeToken.safeTransfer(beneficiary, amount); | ||
emit WithdrawalToBeneficiary(beneficiary, amount); | ||
} | ||
|
||
function processRitualPayment( | ||
address initiator, | ||
uint32 ritualId, | ||
uint256 numberOfProviders, | ||
uint32 duration | ||
) external override { | ||
require(initiator == adopter, "Only adopter can initiate ritual"); | ||
require(endOfSubscription != 0, "Subscription has to be payed first"); | ||
require( | ||
endOfSubscription >= block.timestamp + duration && numberOfProviders <= maxNodes, | ||
"Ritual parameters exceed available in package" | ||
); | ||
if (acttiveRitualId != 0) { | ||
Coordinator.RitualState state = coordinator.getRitualState(ritualId); | ||
require( | ||
state == Coordinator.RitualState.DKG_INVALID || | ||
state == Coordinator.RitualState.DKG_TIMEOUT, | ||
"Only failed rituals allowed to be reinitiate" | ||
); | ||
} | ||
acttiveRitualId = ritualId; | ||
} | ||
|
||
/** | ||
* @dev This function is called before the setAuthorizations function | ||
* @param ritualId The ID of the ritual | ||
* @param addresses The addresses to be authorized | ||
* @param value The authorization status | ||
*/ | ||
function beforeSetAuthorization( | ||
uint32 ritualId, | ||
address[] calldata addresses, | ||
bool value | ||
) external override { | ||
// solhint-disable-previous-line no-empty-blocks | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters