Skip to content

Commit

Permalink
BqETHSubscription: handling yellow period
Browse files Browse the repository at this point in the history
  • Loading branch information
vzotova committed Jun 7, 2024
1 parent 3c1d5be commit ec840c2
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 3 deletions.
17 changes: 15 additions & 2 deletions contracts/contracts/coordination/BqETHSubscription.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@ 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 {
using SafeERC20 for IERC20;

Coordinator public immutable coordinator;
IERC20 public immutable feeToken;

Expand Down Expand Up @@ -207,4 +207,17 @@ contract BqETHSubscription is IFeeModel {
) external view override onlyAccessController onlyActiveRitual(ritualId) {
require(block.timestamp <= endOfSubscription, "Subscription has expired");
}

/**
* @dev This function is called before the isAuthorized function
* @param ritualId The ID of the ritual
*/
function beforeIsAuthorized(
uint32 ritualId
) external view override onlyAccessController onlyActiveRitual(ritualId) {
require(
block.timestamp <= endOfSubscription + yellowPeriodDuration,
"Yellow period has expired"
);
}
}
8 changes: 8 additions & 0 deletions contracts/contracts/coordination/FlatRateFeeModel.sol
Original file line number Diff line number Diff line change
Expand Up @@ -130,4 +130,12 @@ contract FlatRateFeeModel is IFeeModel, Ownable {
) external view {
// solhint-disable-previous-line no-empty-blocks
}

/**
* @dev This function is called before the isAuthorized function
* @param ritualId The ID of the ritual
*/
function beforeIsAuthorized(uint32 ritualId) external view {
// solhint-disable-previous-line no-empty-blocks
}
}
4 changes: 3 additions & 1 deletion contracts/contracts/coordination/GlobalAllowList.sol
Original file line number Diff line number Diff line change
Expand Up @@ -83,10 +83,12 @@ contract GlobalAllowList is IEncryptionAuthorizer {
*/
function _beforeIsAuthorized(
uint32 ritualId,
// solhint-disable-next-line no-unused-vars
bytes memory evidence,
// solhint-disable-next-line no-unused-vars
bytes memory ciphertextHeader
) internal view virtual {
// solhint-disable-previous-line no-empty-blocks
feeModel.beforeIsAuthorized(ritualId);
}

/**
Expand Down
6 changes: 6 additions & 0 deletions contracts/contracts/coordination/IFeeModel.sol
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,10 @@ interface IFeeModel {
address[] calldata addresses,
bool value
) external;

/**
* @dev This function is called before the isAuthorized function
* @param ritualId The ID of the ritual
*/
function beforeIsAuthorized(uint32 ritualId) external view;
}
45 changes: 45 additions & 0 deletions tests/test_bqeth_subscription.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,13 @@
You should have received a copy of the GNU Affero General Public License
along with nucypher. If not, see <https://www.gnu.org/licenses/>.
"""
import os
from enum import IntEnum

import ape
import pytest
from eth_account.messages import encode_defunct
from web3 import Web3

FEE_RATE = 42
MAX_NODES = 10
Expand Down Expand Up @@ -363,3 +366,45 @@ def test_before_set_authorization(

subscription.paySubscriptionFor(sender=adopter)
global_allow_list.authorize(ritual_id, [creator.address], sender=adopter)


def test_before_is_authorized(
erc20, subscription, coordinator, adopter, global_allow_list, treasury, creator, chain
):
ritual_id = 6

w3 = Web3()
data = os.urandom(32)
digest = Web3.keccak(data)
signable_message = encode_defunct(digest)
signed_digest = w3.eth.account.sign_message(signable_message, private_key=adopter.private_key)
signature = signed_digest.signature

assert subscription.address == global_allow_list.feeModel()

with ape.reverts("Only Access Controller can call this method"):
subscription.beforeIsAuthorized(0, sender=adopter)

with ape.reverts("Ritual must be active"):
global_allow_list.isAuthorized(0, bytes(signature), bytes(data))

erc20.approve(subscription.address, 10 * FEE, sender=adopter)
subscription.paySubscriptionFor(sender=adopter)
coordinator.setRitual(
ritual_id, RitualState.ACTIVE, 0, global_allow_list.address, sender=treasury
)
coordinator.processRitualPayment(adopter, ritual_id, MAX_NODES, DURATION, sender=treasury)
global_allow_list.authorize(ritual_id, [adopter.address], sender=adopter)

with ape.reverts("Ritual must be active"):
global_allow_list.isAuthorized(0, bytes(signature), bytes(data))
assert global_allow_list.isAuthorized(ritual_id, bytes(signature), bytes(data))

end_subscription = subscription.endOfSubscription()
chain.pending_timestamp = end_subscription + YELLOW_PERIOD + 2

with ape.reverts("Yellow period has expired"):
global_allow_list.isAuthorized(ritual_id, bytes(signature), bytes(data))

subscription.paySubscriptionFor(sender=adopter)
assert global_allow_list.isAuthorized(ritual_id, bytes(signature), bytes(data))

0 comments on commit ec840c2

Please sign in to comment.