Skip to content

Commit

Permalink
feat: implement Allocation extension
Browse files Browse the repository at this point in the history
  • Loading branch information
0xAustrian committed Sep 10, 2024
1 parent 6e69b3e commit 41d3a3b
Show file tree
Hide file tree
Showing 4 changed files with 23 additions and 105 deletions.
106 changes: 12 additions & 94 deletions contracts/strategies/examples/sqf-superfluid/SQFSuperfluid.sol
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,13 @@ import {ReentrancyGuard} from "@openzeppelin/contracts/security/ReentrancyGuard.

// Core Contracts
import {RecipientsExtension} from "contracts/strategies/extensions/register/RecipientsExtension.sol";
import {AllocationExtension} from "strategies/extensions/allocate/AllocationExtension.sol";
import {BaseStrategy} from "contracts/strategies/BaseStrategy.sol";

// Internal Libraries
import {Transfer} from "contracts/core/libraries/Transfer.sol";

contract SQFSuperfluid is BaseStrategy, RecipientsExtension, ReentrancyGuard {
contract SQFSuperfluid is BaseStrategy, RecipientsExtension, AllocationExtension, ReentrancyGuard {
using SuperTokenV1Library for ISuperToken;
using FixedPointMathLib for uint256;
using Transfer for address;
Expand Down Expand Up @@ -54,12 +55,6 @@ contract SQFSuperfluid is BaseStrategy, RecipientsExtension, ReentrancyGuard {
/// ======= Events =======
/// ======================

/// @notice Emitted when the pool timestamps are updated
/// @param allocationStartTime The start time for the allocation
/// @param allocationEndTime The end time for the allocation
/// @param sender The sender of the transaction
event AllocationTimestampsUpdated(uint64 allocationStartTime, uint64 allocationEndTime, address sender);

/// @notice Emitted when a recipient is canceled
/// @param recipientId ID of the recipient
/// @param sender The sender of the transaction
Expand All @@ -75,13 +70,6 @@ contract SQFSuperfluid is BaseStrategy, RecipientsExtension, ReentrancyGuard {
/// @param totalUnits The total units
event TotalUnitsUpdated(address indexed recipientId, uint256 totalUnits);

/// ======================
/// ======= Errors =======
/// ======================

/// @notice Thrown when the timestamps being set or updated don't meet the contracts requirements.
error INVALID_TIMESTAMPS();

/// ================================
/// ========== Storage =============
/// ================================
Expand Down Expand Up @@ -111,12 +99,6 @@ contract SQFSuperfluid is BaseStrategy, RecipientsExtension, ReentrancyGuard {
/// @notice The minimum passport score required to be an allocator
uint256 public minPassportScore;

/// @notice The start time for allocation
uint64 public allocationStartTime;

/// @notice The end time for allocation
uint64 public allocationEndTime;

/// @notice stores the superApp of each recipientId
mapping(address => address) public recipientIdSuperApps;

Expand All @@ -131,24 +113,6 @@ contract SQFSuperfluid is BaseStrategy, RecipientsExtension, ReentrancyGuard {
/// @dev recipientId => flowRate
mapping(address => uint256) public recipientFlowRate;

/// ================================
/// ========== Modifier ============
/// ================================

/// @notice Modifier to check if the allocation is active
/// @dev Reverts if the allocation is not active
modifier onlyActiveAllocation() {
_checkOnlyActiveAllocation();
_;
}

/// @notice Modifier to check if the allocation has ended
/// @dev This will revert if the allocation has ended.
modifier onlyBeforeAllocationEnds() {
_checkOnlyBeforeAllocationEnds();
_;
}

/// ===============================
/// ======== Constructor ==========
/// ===============================
Expand Down Expand Up @@ -177,6 +141,14 @@ contract SQFSuperfluid is BaseStrategy, RecipientsExtension, ReentrancyGuard {
// Initialize the RecipientsExtension
__RecipientsExtension_init(_recipientExtensionInitializeData);

// Initialize the AllocationExtension
__AllocationExtension_init(
new address[](0),
_sqfSuperfluidInitializeParams.allocationStartTime,
_sqfSuperfluidInitializeParams.allocationEndTime,
true
);

if (
_sqfSuperfluidInitializeParams.superfluidHost == address(0)
|| _sqfSuperfluidInitializeParams.allocationSuperToken == address(0)
Expand All @@ -186,11 +158,6 @@ contract SQFSuperfluid is BaseStrategy, RecipientsExtension, ReentrancyGuard {

if (_sqfSuperfluidInitializeParams.initialSuperAppBalance == 0) revert INVALID();

// validate the timestamps for this strategy
if (_sqfSuperfluidInitializeParams.allocationStartTime > _sqfSuperfluidInitializeParams.allocationEndTime) {
revert INVALID_TIMESTAMPS();
}

superfluidHost = _sqfSuperfluidInitializeParams.superfluidHost;
minPassportScore = _sqfSuperfluidInitializeParams.minPassportScore;
recipientSuperAppFactory = IRecipientSuperAppFactory(_sqfSuperfluidInitializeParams.recipientSuperAppFactory);
Expand All @@ -210,45 +177,12 @@ contract SQFSuperfluid is BaseStrategy, RecipientsExtension, ReentrancyGuard {
true
)
);

// Set the new values
allocationStartTime = _sqfSuperfluidInitializeParams.allocationStartTime;
allocationEndTime = _sqfSuperfluidInitializeParams.allocationEndTime;

emit AllocationTimestampsUpdated(
_sqfSuperfluidInitializeParams.allocationStartTime,
_sqfSuperfluidInitializeParams.allocationEndTime,
msg.sender
);
}

/// ====================================
/// ============= External =============
/// ====================================

/// @notice Set the start and end dates for the pool
/// @param _registrationStartTime The start time for the registration
/// @param _registrationEndTime The end time for the registration
/// @param _allocationStartTime The start time for the allocation
/// @param _allocationEndTime The end time for the allocation
function updatePoolTimestamps(
uint64 _registrationStartTime,
uint64 _registrationEndTime,
uint64 _allocationStartTime,
uint64 _allocationEndTime
) external onlyPoolManager(msg.sender) {
// validate the timestamps for this strategy
if (_allocationStartTime > _allocationEndTime) revert INVALID_TIMESTAMPS();

// Set the new values
allocationStartTime = _allocationStartTime;
allocationEndTime = _allocationEndTime;

emit AllocationTimestampsUpdated(allocationStartTime, allocationEndTime, msg.sender);

_updatePoolTimestamps(_registrationStartTime, _registrationEndTime);
}

/// @notice Update the min passport score
/// @param _minPassportScore The new min passport score
function updateMinPassportScore(uint256 _minPassportScore) external onlyPoolManager(msg.sender) {
Expand All @@ -263,7 +197,7 @@ contract SQFSuperfluid is BaseStrategy, RecipientsExtension, ReentrancyGuard {
function cancelRecipients(address[] calldata _recipientIds)
external
onlyPoolManager(msg.sender)
onlyBeforeAllocationEnds
onlyActiveAllocation
nonReentrant
{
uint256 recipientLength = _recipientIds.length;
Expand Down Expand Up @@ -378,7 +312,7 @@ contract SQFSuperfluid is BaseStrategy, RecipientsExtension, ReentrancyGuard {
/// @notice Checks if the allocator is valid
/// @param _allocator The allocator address
/// @return 'true' if the allocator is valid, otherwise 'false'
function _isValidAllocator(address _allocator) internal view returns (bool) {
function _isValidAllocator(address _allocator) internal view override returns (bool) {
uint256 allocatorScore = passportDecoder.getScore(_allocator);
if (allocatorScore >= minPassportScore) {
return true;
Expand Down Expand Up @@ -483,22 +417,6 @@ contract SQFSuperfluid is BaseStrategy, RecipientsExtension, ReentrancyGuard {
}
}

/// @notice Check if the allocation is active
/// @dev Reverts if the allocation is not active
function _checkOnlyActiveAllocation() internal view {
if (allocationStartTime > block.timestamp || block.timestamp > allocationEndTime) {
revert ALLOCATION_NOT_ACTIVE();
}
}

/// @notice Checks if the allocation has not ended and reverts if it has.
/// @dev This will revert if the allocation has ended.
function _checkOnlyBeforeAllocationEnds() internal view {
if (block.timestamp > allocationEndTime) {
revert ALLOCATION_NOT_ACTIVE();
}
}

/// @notice Update the total units for a recipient
/// @param _recipientId ID of the recipient
/// @param _recipientAddress Address of the recipient
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,18 +111,18 @@ abstract contract AllocationExtension is BaseStrategy, IAllocationExtension {

/// @dev Ensure the function is called before allocation start time
function _checkBeforeAllocation() internal virtual {
if (block.timestamp >= allocationStartTime) revert ALLOCATION_HAS_STARTED();
if (block.timestamp >= allocationStartTime) revert ALLOCATION_HAS_ALREADY_STARTED();
}

/// @dev Ensure the function is called during allocation times
function _checkOnlyActiveAllocation() internal virtual {
if (block.timestamp < allocationStartTime) revert ALLOCATION_NOT_ACTIVE();
if (block.timestamp > allocationEndTime) revert ALLOCATION_NOT_ACTIVE();
if (block.timestamp < allocationStartTime) revert ALLOCATION_IS_NOT_ACTIVE();
if (block.timestamp > allocationEndTime) revert ALLOCATION_IS_NOT_ACTIVE();
}

/// @dev Ensure the function is called after allocation start time
function _checkOnlyAfterAllocation() internal virtual {
if (block.timestamp <= allocationEndTime) revert ALLOCATION_NOT_ENDED();
if (block.timestamp <= allocationEndTime) revert ALLOCATION_IS_NOT_ENDED();
}

// ====================================
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@ interface IAllocationExtension {
error INVALID_ALLOCATION_TIMESTAMPS();

/// @dev Error thrown when trying to call the function when the allocation has started
error ALLOCATION_HAS_STARTED();
error ALLOCATION_HAS_ALREADY_STARTED();

/// @dev Error thrown when trying to call the function when the allocation is not active
error ALLOCATION_NOT_ACTIVE();
error ALLOCATION_IS_NOT_ACTIVE();

/// @dev Error thrown when trying to call the function when the allocation has ended
error ALLOCATION_NOT_ENDED();
error ALLOCATION_IS_NOT_ENDED();

/// @notice Emitted when the allocation timestamps are updated
/// @param allocationStartTime The start time for the allocation period
Expand Down
8 changes: 4 additions & 4 deletions test/unit/strategies/extensions/AllocationExtensionUnit.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ contract AllocationExtension is Test {
vm.warp(_timestamp);

// It should revert
vm.expectRevert(IAllocationExtension.ALLOCATION_HAS_STARTED.selector);
vm.expectRevert(IAllocationExtension.ALLOCATION_HAS_ALREADY_STARTED.selector);

extension.call__checkBeforeAllocation();
}
Expand All @@ -144,7 +144,7 @@ contract AllocationExtension is Test {
vm.warp(_timestamp);

// It should revert
vm.expectRevert(IAllocationExtension.ALLOCATION_NOT_ACTIVE.selector);
vm.expectRevert(IAllocationExtension.ALLOCATION_IS_NOT_ACTIVE.selector);

extension.call__checkOnlyActiveAllocation();
}
Expand All @@ -159,7 +159,7 @@ contract AllocationExtension is Test {
vm.warp(_timestamp);

// It should revert
vm.expectRevert(IAllocationExtension.ALLOCATION_NOT_ACTIVE.selector);
vm.expectRevert(IAllocationExtension.ALLOCATION_IS_NOT_ACTIVE.selector);

extension.call__checkOnlyActiveAllocation();
}
Expand All @@ -174,7 +174,7 @@ contract AllocationExtension is Test {
vm.warp(_timestamp);

// It should revert
vm.expectRevert(IAllocationExtension.ALLOCATION_NOT_ENDED.selector);
vm.expectRevert(IAllocationExtension.ALLOCATION_IS_NOT_ENDED.selector);

extension.call__checkOnlyAfterAllocation();
}
Expand Down

0 comments on commit 41d3a3b

Please sign in to comment.