From 2eb4bae0746449e416c1ab7e6bf9339914df50a2 Mon Sep 17 00:00:00 2001 From: FlacoJones Date: Sat, 25 Feb 2023 14:22:41 -0700 Subject: [PATCH 1/7] removes all traces of Ongoing and TieredPercentage bounties, including the Ongoing+TieredPercentage implementations, interfaces, and methods in OpenQV1 and ClaimManagerV1 --- .../Implementations/OngoingBountyV1.sol | 242 ------------------ .../TieredPercentageBountyV1.sol | 187 -------------- contracts/Bounty/Interfaces/IBounty.sol | 9 +- .../Bounty/Interfaces/IOngoingBounty.sol | 54 ---- .../Bounty/Interfaces/ITieredFixedBounty.sol | 2 + .../Interfaces/ITieredPercentageBounty.sol | 26 -- .../Bounty/Storage/OngoingBountyStorage.sol | 32 --- .../Storage/TieredPercentageBountyStorage.sol | 12 - contracts/BountyFactory/BountyFactory.sol | 12 - .../Implementations/ClaimManagerV1.sol | 174 ------------- contracts/Library/OpenQDefinitions.sol | 2 - contracts/OpenQ/Implementations/OpenQV1.sol | 102 -------- 12 files changed, 3 insertions(+), 851 deletions(-) delete mode 100755 contracts/Bounty/Implementations/OngoingBountyV1.sol delete mode 100755 contracts/Bounty/Implementations/TieredPercentageBountyV1.sol delete mode 100755 contracts/Bounty/Interfaces/IOngoingBounty.sol delete mode 100755 contracts/Bounty/Interfaces/ITieredPercentageBounty.sol delete mode 100755 contracts/Bounty/Storage/OngoingBountyStorage.sol delete mode 100755 contracts/Bounty/Storage/TieredPercentageBountyStorage.sol diff --git a/contracts/Bounty/Implementations/OngoingBountyV1.sol b/contracts/Bounty/Implementations/OngoingBountyV1.sol deleted file mode 100755 index d78f566f..00000000 --- a/contracts/Bounty/Implementations/OngoingBountyV1.sol +++ /dev/null @@ -1,242 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.17; - -import '../Storage/OngoingBountyStorage.sol'; - -/// @title OngoingBountyV1 -/// @author FlacoJones -/// @notice Bounty implementation for multiple contributor, multiple + fixed payout scenarios (e.g. 500 USDC for every submission) -/// @dev OngoingBountyV1 -> OngoingBountyStorageV1 -> BountyCore -> BountyStorageCore -> Core Dependencies (OZ + Custom) -/// @dev Do not add any new storage variables here. Put them in a TieredPercentageBountyStorageV# and release new implementation -contract OngoingBountyV1 is OngoingBountyStorageV1 { - using SafeERC20Upgradeable for IERC20Upgradeable; - using AddressUpgradeable for address payable; - using EnumerableSetUpgradeable for EnumerableSetUpgradeable.AddressSet; - - constructor() {} - - /// @notice Initializes a bounty proxy with initial state - /// @param _bountyId The unique bounty identifier - /// @param _issuer The sender of the mint bounty transaction - /// @param _organization The organization associated with the bounty - /// @param _openQ The OpenQProxy address - /// @param _claimManager The Claim Manager proxy address - /// @param _depositManager The Deposit Manager proxy address - /// @param _operation The ABI encoded data determining the type of bounty being initialized and associated data - /// @dev see IBountyCore.initialize.(_operation) for _operation ABI encoding schema for ONGOING - function initialize( - string memory _bountyId, - address _issuer, - string memory _organization, - address _openQ, - address _claimManager, - address _depositManager, - OpenQDefinitions.InitOperation memory _operation - ) external initializer { - require(bytes(_bountyId).length != 0, Errors.NO_EMPTY_BOUNTY_ID); - require(bytes(_organization).length != 0, Errors.NO_EMPTY_ORGANIZATION); - - __ReentrancyGuard_init(); - - __OnlyOpenQ_init(_openQ); - __ClaimManagerOwnable_init(_claimManager); - __DepositManagerOwnable_init(_depositManager); - - bountyId = _bountyId; - issuer = _issuer; - organization = _organization; - bountyCreatedTime = block.timestamp; - nftDepositLimit = 5; - - ( - address _payoutTokenAddress, - uint256 _payoutVolume, - bool _hasFundingGoal, - address _fundingToken, - uint256 _fundingGoal, - bool _invoiceRequired, - bool _kycRequired, - bool _supportingDocumentsRequired, - string memory _issuerExternalUserId, - , - - ) = abi.decode( - _operation.data, - ( - address, - uint256, - bool, - address, - uint256, - bool, - bool, - bool, - string, - string, - string - ) - ); - - bountyType = OpenQDefinitions.ONGOING; - payoutTokenAddress = _payoutTokenAddress; - payoutVolume = _payoutVolume; - hasFundingGoal = _hasFundingGoal; - fundingToken = _fundingToken; - fundingGoal = _fundingGoal; - invoiceRequired = _invoiceRequired; - kycRequired = _kycRequired; - supportingDocumentsRequired = _supportingDocumentsRequired; - issuerExternalUserId = _issuerExternalUserId; - } - - /// @notice Transfers a payout amount of an ongoing bounty to claimant for claimant asset - /// @param _payoutAddress The destination address for the funds - /// @param _closerData ABI-encoded data of the claimant and claimant asset - /// @dev see IBountyCore.claimOngoingPayout.(_closerData) for _closerData ABI encoding schema - function claimOngoingPayout( - address _payoutAddress, - bytes calldata _closerData - ) external onlyClaimManager nonReentrant returns (address, uint256) { - (, string memory claimant, , string memory claimantAsset) = abi.decode( - _closerData, - (address, string, address, string) - ); - - bytes32 _claimId = generateClaimId(claimant, claimantAsset); - - claimId[_claimId] = true; - claimIds.push(_claimId); - - _transferToken(payoutTokenAddress, payoutVolume, _payoutAddress); - return (payoutTokenAddress, payoutVolume); - } - - /// @notice Similar to close() for single priced bounties. Stops all withdrawls. - /// @param _closer Address of the closer - function closeOngoing(address _closer) external onlyOpenQ { - require( - status == OpenQDefinitions.OPEN, - Errors.CONTRACT_ALREADY_CLOSED - ); - require(_closer == issuer, Errors.CALLER_NOT_ISSUER); - - status = OpenQDefinitions.CLOSED; - bountyClosedTime = block.timestamp; - } - - /// @notice Receives an NFT for this contract - /// @param _sender Sender of the NFT - /// @param _tokenAddress NFT token address - /// @param _tokenId NFT token id - /// @param _expiration How long before this deposit becomes refundable - /// @return bytes32 the deposit id - function receiveNft( - address _sender, - address _tokenAddress, - uint256 _tokenId, - uint256 _expiration, - bytes calldata - ) external onlyDepositManager nonReentrant returns (bytes32) { - require( - nftDeposits.length < nftDepositLimit, - Errors.NFT_DEPOSIT_LIMIT_REACHED - ); - require(_expiration > 0, Errors.EXPIRATION_NOT_GREATER_THAN_ZERO); - _receiveNft(_tokenAddress, _sender, _tokenId); - - bytes32 depositId = _generateDepositId(); - - funder[depositId] = _sender; - tokenAddress[depositId] = _tokenAddress; - depositTime[depositId] = block.timestamp; - tokenId[depositId] = _tokenId; - expiration[depositId] = _expiration; - isNFT[depositId] = true; - - deposits.push(depositId); - nftDeposits.push(depositId); - - return depositId; - } - - /// @notice Sets the payout for an ongoing bounty - /// @param _payoutTokenAddress Sets payout token address - /// @param _payoutVolume Sets payout token volume - function setPayout(address _payoutTokenAddress, uint256 _payoutVolume) - external - onlyOpenQ - { - payoutTokenAddress = _payoutTokenAddress; - payoutVolume = _payoutVolume; - } - - /// @notice Whether or not invoice has been completed - /// @param _data ABI encoded data - /// @dev see IBountyCore.setInvoiceComplete.(_data) for _data ABI encoding schema - function setInvoiceComplete(bytes calldata _data) external onlyOpenQ { - (bytes32 _claimId, bool _invoiceComplete) = abi.decode( - _data, - (bytes32, bool) - ); - invoiceComplete[_claimId] = _invoiceComplete; - invoiceCompleteClaimIds.push(_claimId); - } - - /// @notice Whether or not supporting documents have been completed - /// @param _data ABI encoded data - /// @dev see IBountyCore.setSupportingDocumentsComplete.(_data) for _data ABI encoding schema - function setSupportingDocumentsComplete(bytes calldata _data) - external - onlyOpenQ - { - (bytes32 _claimId, bool _supportingDocumentsComplete) = abi.decode( - _data, - (bytes32, bool) - ); - supportingDocumentsComplete[_claimId] = _supportingDocumentsComplete; - supportingDocumentsCompleteClaimIds.push(_claimId); - } - - /// @notice Returns the claimIds which have completed supporting documents - /// @return Documents the return variables of a contract’s function state variable - /// @dev We return from all IBountyCore.getSupportingDocumentsComplete() as bytes to accomodate different return types - /// @dev _data (bytes32[]) - /// @dev _data (supportingDocumentsCompleteClaimIds) - function getSupportingDocumentsComplete() - external - view - returns (bytes memory) - { - return abi.encode(supportingDocumentsCompleteClaimIds); - } - - /// @notice Returns the claimIds which have completed supporting documents - /// @return Documents the return variables of a contract’s function state variable - /// @dev We return from all IBountyCore.getInvoiceComplete() as bytes to accomodate different return types - /// @dev _data (bytes32[]) - /// @dev _data (invoiceCompleteClaimIds) - function getInvoiceComplete() external view returns (bytes memory) { - return abi.encode(invoiceCompleteClaimIds); - } - - /// @notice Returns all claimIds - /// @return Array of bytes32 claim ids - function getClaimIds() public view returns (bytes32[] memory) { - return claimIds; - } - - /// @notice Generates a unique claimant ID from user and asset - function generateClaimId( - string memory claimant, - string memory claimantAsset - ) public pure virtual returns (bytes32) { - return keccak256(abi.encode(claimant, claimantAsset)); - } - - /// @notice receive() method to accept protocol tokens - receive() external payable { - revert( - 'Cannot send Ether directly to boutny contract. Please use the BountyV1.receiveFunds() method.' - ); - } -} diff --git a/contracts/Bounty/Implementations/TieredPercentageBountyV1.sol b/contracts/Bounty/Implementations/TieredPercentageBountyV1.sol deleted file mode 100755 index 5296740e..00000000 --- a/contracts/Bounty/Implementations/TieredPercentageBountyV1.sol +++ /dev/null @@ -1,187 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.17; - -import '../Storage/TieredPercentageBountyStorage.sol'; - -/// @title TieredPercentageBountyV1 -/// @notice TieredPercentageBountyV1 is a bounty implementation contract for single contributor, single payout circumstances -/// @dev TieredPercentageBountyV1 -> TieredPercentageBountyStorageV1 -> TieredBountyCore -> TieredBountyStorageCore -> (BountyCore -> BountyStorageCore) -> (Third Party Deps + Custom ) -/// @dev Do not add any new storage variables here. Put them in a TieredPercentageBountyStorageV# and release new implementation -contract TieredPercentageBountyV1 is TieredPercentageBountyStorageV1 { - using SafeERC20Upgradeable for IERC20Upgradeable; - using AddressUpgradeable for address payable; - using EnumerableSetUpgradeable for EnumerableSetUpgradeable.AddressSet; - - constructor() {} - - /// @notice Initializes a bounty proxy with initial state - /// @param _bountyId The unique bounty identifier - /// @param _issuer The sender of the mint bounty transaction - /// @param _organization The organization associated with the bounty - /// @param _openQ The OpenQProxy address - /// @param _claimManager The Claim Manager proxy address - /// @param _depositManager The Deposit Manager proxy address - /// @param _operation The ABI encoded data determining the type of bounty being initialized and associated data - /// @dev see IBountyCore.initialize.(_operation) for _operation ABI encoding schema for TIERED PERCENTAGE - function initialize( - string memory _bountyId, - address _issuer, - string memory _organization, - address _openQ, - address _claimManager, - address _depositManager, - OpenQDefinitions.InitOperation memory _operation - ) external initializer { - require(bytes(_bountyId).length != 0, Errors.NO_EMPTY_BOUNTY_ID); - require(bytes(_organization).length != 0, Errors.NO_EMPTY_ORGANIZATION); - - __ReentrancyGuard_init(); - - __OnlyOpenQ_init(_openQ); - __ClaimManagerOwnable_init(_claimManager); - __DepositManagerOwnable_init(_depositManager); - - bountyId = _bountyId; - issuer = _issuer; - organization = _organization; - bountyCreatedTime = block.timestamp; - nftDepositLimit = 5; - - ( - uint256[] memory _payoutSchedule, - bool _hasFundingGoal, - address _fundingToken, - uint256 _fundingGoal, - bool _invoiceRequired, - bool _kycRequired, - bool _supportingDocumentsRequired, - string memory _issuerExternalUserId, - , - - ) = abi.decode( - _operation.data, - ( - uint256[], - bool, - address, - uint256, - bool, - bool, - bool, - string, - string, - string - ) - ); - - uint256 sum; - for (uint256 i = 0; i < _payoutSchedule.length; i++) { - sum += _payoutSchedule[i]; - } - require(sum == 100, Errors.PAYOUT_SCHEDULE_MUST_ADD_TO_100); - payoutSchedule = _payoutSchedule; - - bountyType = OpenQDefinitions.TIERED_PERCENTAGE; - hasFundingGoal = _hasFundingGoal; - fundingToken = _fundingToken; - fundingGoal = _fundingGoal; - invoiceRequired = _invoiceRequired; - kycRequired = _kycRequired; - supportingDocumentsRequired = _supportingDocumentsRequired; - issuerExternalUserId = _issuerExternalUserId; - - // Initialize metadata arrays to same number of tiers - tierWinners = new string[](_payoutSchedule.length); - invoiceComplete = new bool[](_payoutSchedule.length); - supportingDocumentsComplete = new bool[](_payoutSchedule.length); - } - - /// @notice Transfers the tiered percentage of the token balance of _tokenAddress from bounty to _payoutAddress - /// @param _payoutAddress The destination address for the fund - /// @param _tier The ordinal of the claimant (e.g. 1st place, 2nd place) - /// @param _tokenAddress The token address being claimed - /// @return Volume of claimed token payout - function claimTiered( - address _payoutAddress, - uint256 _tier, - address _tokenAddress - ) external onlyClaimManager nonReentrant returns (uint256) { - require( - bountyType == OpenQDefinitions.TIERED_PERCENTAGE, - Errors.NOT_A_TIERED_BOUNTY - ); - require(!tierClaimed[_tier], Errors.TIER_ALREADY_CLAIMED); - - uint256 claimedBalance = (payoutSchedule[_tier] * - fundingTotals[_tokenAddress]) / 100; - - _transferToken(_tokenAddress, claimedBalance, _payoutAddress); - return claimedBalance; - } - - /// @notice Similar to close() for single priced bounties. closeCompetition() freezes the current funds for the competition. - function closeCompetition() external onlyClaimManager { - require( - status == OpenQDefinitions.OPEN, - Errors.CONTRACT_ALREADY_CLOSED - ); - - status = OpenQDefinitions.CLOSED; - bountyClosedTime = block.timestamp; - - for (uint256 i = 0; i < getTokenAddresses().length; i++) { - address _tokenAddress = getTokenAddresses()[i]; - fundingTotals[_tokenAddress] = getTokenBalance(_tokenAddress); - } - } - - /// @notice Sets the payout schedule - /// @notice There is no tokenAddress needed here - payouts on percentage tiered bounties is a percentage of whatever is deposited on the contract - /// @param _payoutSchedule An array of payout volumes for each tier - function setPayoutSchedule(uint256[] calldata _payoutSchedule) - external - onlyOpenQ - { - require( - bountyType == OpenQDefinitions.TIERED_PERCENTAGE, - Errors.NOT_A_TIERED_BOUNTY - ); - uint256 sum; - for (uint256 i = 0; i < _payoutSchedule.length; i++) { - sum += _payoutSchedule[i]; - } - require(sum == 100, Errors.PAYOUT_SCHEDULE_MUST_ADD_TO_100); - - payoutSchedule = _payoutSchedule; - - // Resize metadata arrays and copy current members to new array - // NOTE: If resizing to fewer tiers than previously, the final indexes will be removed - string[] memory newTierWinners = new string[](payoutSchedule.length); - bool[] memory newInvoiceComplete = new bool[](payoutSchedule.length); - bool[] memory newSupportingDocumentsCompleted = new bool[]( - payoutSchedule.length - ); - - for (uint256 i = 0; i < tierWinners.length; i++) { - newTierWinners[i] = tierWinners[i]; - } - tierWinners = newTierWinners; - - for (uint256 i = 0; i < invoiceComplete.length; i++) { - newInvoiceComplete[i] = invoiceComplete[i]; - } - invoiceComplete = newInvoiceComplete; - - for (uint256 i = 0; i < supportingDocumentsComplete.length; i++) { - newSupportingDocumentsCompleted[i] = supportingDocumentsComplete[i]; - } - supportingDocumentsComplete = newSupportingDocumentsCompleted; - } - - /// @notice receive() method to accept protocol tokens - receive() external payable { - revert( - 'Cannot send Ether directly to boutny contract. Please use the BountyV1.receiveFunds() method.' - ); - } -} diff --git a/contracts/Bounty/Interfaces/IBounty.sol b/contracts/Bounty/Interfaces/IBounty.sol index 47976e62..23c6f47d 100755 --- a/contracts/Bounty/Interfaces/IBounty.sol +++ b/contracts/Bounty/Interfaces/IBounty.sol @@ -2,18 +2,11 @@ pragma solidity 0.8.17; import './IAtomicBounty.sol'; -import './IOngoingBounty.sol'; -import './ITieredPercentageBounty.sol'; import './ITieredFixedBounty.sol'; /// @title IBounty /// @author FlacoJones /// @notice Interface aggregating all bounty type interfaces for use in OpenQ, ClaimManager and DepositManager -interface IBounty is - IAtomicBounty, - IOngoingBounty, - ITieredPercentageBounty, - ITieredFixedBounty -{ +interface IBounty is IAtomicBounty, ITieredFixedBounty { } diff --git a/contracts/Bounty/Interfaces/IOngoingBounty.sol b/contracts/Bounty/Interfaces/IOngoingBounty.sol deleted file mode 100755 index 1915592a..00000000 --- a/contracts/Bounty/Interfaces/IOngoingBounty.sol +++ /dev/null @@ -1,54 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.17; - -import './IBountyCore.sol'; - -/// @title IOngoingBounty -/// @author FlacoJones -/// @notice Interface defining OngoingBounty specific methods -interface IOngoingBounty is IBountyCore { - /// @notice Sets the payout for an ongoing bounty - /// @param _payoutTokenAddress Sets payout token address - /// @param _payoutVolume Sets payout token volume - function setPayout(address _payoutTokenAddress, uint256 _payoutVolume) - external; - - /// @notice Transfers a payout amount of an ongoing bounty to claimant for claimant asset - /// @param _payoutAddress The destination address for the funds - /// @param _closerData ABI-encoded data of the claimant and claimant asset - /// @dev _closerData (address,string,address,string,uint256) - /// @dev _closerData (bountyAddress, externalUserId, closer, claimantAsset, tier) - function claimOngoingPayout( - address _payoutAddress, - bytes calldata _closerData - ) external returns (address, uint256); - - /// @notice Similar to close() for single priced bounties. Stops all withdrawls. - /// @param _closer Address of the closer - function closeOngoing(address _closer) external; - - function getClaimIds() external returns (bytes32[] memory); - - function generateClaimId( - string memory claimant, - string memory claimantAsset - ) external pure returns (bytes32); - - function invoiceComplete(bytes32) external view returns (bool); - - function supportingDocumentsComplete(bytes32) external view returns (bool); - - function supportingDocumentsCompleteClaimIds() - external - view - returns (bytes32[] memory); - - function invoiceCompleteClaimIds() external view returns (bytes32[] memory); - - // PUBLIC GETTERS - function payoutTokenAddress() external view returns (address); - - function payoutVolume() external view returns (uint256); - - function claimId(bytes32) external view returns (bool); -} diff --git a/contracts/Bounty/Interfaces/ITieredFixedBounty.sol b/contracts/Bounty/Interfaces/ITieredFixedBounty.sol index b305bbe3..938bb894 100755 --- a/contracts/Bounty/Interfaces/ITieredFixedBounty.sol +++ b/contracts/Bounty/Interfaces/ITieredFixedBounty.sol @@ -22,4 +22,6 @@ interface ITieredFixedBounty is IBountyCore, ITieredBounty { function claimTieredFixed(address _payoutAddress, uint256 _tier) external returns (uint256); + + function payoutTokenAddress() external returns (address); } diff --git a/contracts/Bounty/Interfaces/ITieredPercentageBounty.sol b/contracts/Bounty/Interfaces/ITieredPercentageBounty.sol deleted file mode 100755 index 765bf3df..00000000 --- a/contracts/Bounty/Interfaces/ITieredPercentageBounty.sol +++ /dev/null @@ -1,26 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.17; - -import './IBountyCore.sol'; -import './ITieredBounty.sol'; - -/// @title ITieredPercentageBounty -/// @author FlacoJones -/// @notice Interface defining TieredPercentageBounty specific methods -interface ITieredPercentageBounty is IBountyCore, ITieredBounty { - /// @notice Sets the payout schedule - /// @notice There is no tokenAddress needed here - payouts on percentage tiered bounties is a percentage of whatever is deposited on the contract - /// @param _payoutSchedule An array of payout volumes for each tier - function setPayoutSchedule(uint256[] calldata _payoutSchedule) external; - - /// @notice Transfers the tiered percentage of the token balance of _tokenAddress from bounty to _payoutAddress - /// @param _payoutAddress The destination address for the fund - /// @param _tier The ordinal of the claimant (e.g. 1st place, 2nd place) - /// @param _tokenAddress The token address being claimed - /// @return Volume of claimed token payout - function claimTiered( - address _payoutAddress, - uint256 _tier, - address _tokenAddress - ) external returns (uint256); -} diff --git a/contracts/Bounty/Storage/OngoingBountyStorage.sol b/contracts/Bounty/Storage/OngoingBountyStorage.sol deleted file mode 100755 index 715f5535..00000000 --- a/contracts/Bounty/Storage/OngoingBountyStorage.sol +++ /dev/null @@ -1,32 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.17; - -import '../Implementations/BountyCore.sol'; - -/// @title OngoingBountyStorageV1 -/// @author FlacoJones -/// @notice Backwards compatible, append-only chain of storage contracts inherited by all OngoingBountyStorage implementations -/// @dev Add new variables for upgrades in a new, derived abstract contract that inherits from the previous storage contract version (see: https://forum.openzeppelin.com/t/to-inherit-version1-to-version2-or-to-copy-code-inheritance-order-from-version1-to-version2/28069) -abstract contract OngoingBountyStorageV1 is BountyCore { - uint256 public constant VERSION_1 = 1; - - /// @notice Ongoing Bounties pay out the same amount set by the minter for each submission. - /// @dev Only closed once minter explicitly closes - address public payoutTokenAddress; - uint256 public payoutVolume; - - /// @dev keccak256 hash of the claimant ID (GitHub ID) with the claimant asset ID (GitHub PR ID) - mapping(bytes32 => bool) public claimId; - - // Keys of claims, can be used off-chain as an iterable to determine completed payouts - bytes32[] public claimIds; - - // Quick lookup - mapping(bytes32 => bool) public invoiceComplete; - - mapping(bytes32 => bool) public supportingDocumentsComplete; - - bytes32[] public supportingDocumentsCompleteClaimIds; - - bytes32[] public invoiceCompleteClaimIds; -} diff --git a/contracts/Bounty/Storage/TieredPercentageBountyStorage.sol b/contracts/Bounty/Storage/TieredPercentageBountyStorage.sol deleted file mode 100755 index 1fab1836..00000000 --- a/contracts/Bounty/Storage/TieredPercentageBountyStorage.sol +++ /dev/null @@ -1,12 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.17; - -import '../Implementations/TieredBountyCore.sol'; - -/// @title TieredPercentageBountyStorageV1 -/// @author FlacoJones -/// @notice Backwards compatible, append-only chain of storage contracts inherited by all TieredPercentageBountyStorage implementations -/// @dev Add new variables for upgrades in a new, derived abstract contract that inherits from the previous storage contract version (see: https://forum.openzeppelin.com/t/to-inherit-version1-to-version2-or-to-copy-code-inheritance-order-from-version1-to-version2/28069) -abstract contract TieredPercentageBountyStorageV1 is TieredBountyCore { - -} diff --git a/contracts/BountyFactory/BountyFactory.sol b/contracts/BountyFactory/BountyFactory.sol index be010fc4..574033a7 100755 --- a/contracts/BountyFactory/BountyFactory.sol +++ b/contracts/BountyFactory/BountyFactory.sol @@ -13,28 +13,20 @@ import '../Library/Errors.sol'; contract BountyFactory is OnlyOpenQ { /// @notice The address of the UpgradeableBeacon holding the current bounty implementation address public immutable atomicBountyBeacon; - address public immutable ongoingBountyBeacon; - address public immutable tieredPercentageBountyBeacon; address public immutable tieredFixedBountyBeacon; /// @notice Deploys and initializes a new BeaconProxy with implementation pulled from the appropriate BountyBeacon /// @param _openQ The OpenQProxy address, used to initialize OnlyOpenQ /// @param _atomicBountyBeacon The UpgradeableBeacon "BountyBeacon" address for Atomic contracts - /// @param _ongoingBountyBeacon The UpgradeableBeacon "BountyBeacon" address for Ongoing contracts - /// @param _tieredPercentageBountyBeacon The UpgradeableBeacon "BountyBeacon" address for Tiered contracts /// @param _tieredFixedBountyBeacon The UpgradeableBeacon "BountyBeacon" address for Tiered Fixed contracts constructor( address _openQ, address _atomicBountyBeacon, - address _ongoingBountyBeacon, - address _tieredPercentageBountyBeacon, address _tieredFixedBountyBeacon ) { __OnlyOpenQ_init(_openQ); atomicBountyBeacon = _atomicBountyBeacon; - ongoingBountyBeacon = _ongoingBountyBeacon; - tieredPercentageBountyBeacon = _tieredPercentageBountyBeacon; tieredFixedBountyBeacon = _tieredFixedBountyBeacon; } @@ -60,10 +52,6 @@ contract BountyFactory is OnlyOpenQ { if (operationType == OpenQDefinitions.ATOMIC) { beaconProxy = atomicBountyBeacon; - } else if (operationType == OpenQDefinitions.ONGOING) { - beaconProxy = ongoingBountyBeacon; - } else if (operationType == OpenQDefinitions.TIERED_PERCENTAGE) { - beaconProxy = tieredPercentageBountyBeacon; } else if (operationType == OpenQDefinitions.TIERED_FIXED) { beaconProxy = tieredFixedBountyBeacon; } else { diff --git a/contracts/ClaimManager/Implementations/ClaimManagerV1.sol b/contracts/ClaimManager/Implementations/ClaimManagerV1.sol index ea8ef1cf..11b5c28d 100755 --- a/contracts/ClaimManager/Implementations/ClaimManagerV1.sol +++ b/contracts/ClaimManager/Implementations/ClaimManagerV1.sol @@ -4,7 +4,6 @@ pragma solidity 0.8.17; import '../Storage/ClaimManagerStorage.sol'; import '../../Bounty/Interfaces/IAtomicBounty.sol'; import '../../Bounty/Interfaces/ITieredBounty.sol'; -import '../../Bounty/Interfaces/IOngoingBounty.sol'; /// @title ClaimManagerV1 /// @author FlacoJones @@ -53,10 +52,6 @@ contract ClaimManagerV1 is ClaimManagerStorageV1 { _closerData, VERSION_1 ); - } else if (_bountyType == OpenQDefinitions.ONGOING) { - _claimOngoingBounty(bounty, _closer, _closerData); - } else if (_bountyType == OpenQDefinitions.TIERED_PERCENTAGE) { - _claimTieredPercentageBounty(bounty, _closer, _closerData); } else if (_bountyType == OpenQDefinitions.TIERED_FIXED) { _claimTieredFixedBounty(bounty, _closer, _closerData); } else { @@ -101,8 +96,6 @@ contract ClaimManagerV1 is ClaimManagerStorageV1 { if (bounty.bountyType() == OpenQDefinitions.TIERED_FIXED) { _claimTieredFixedBounty(bounty, msg.sender, _closerData); - } else if (bounty.bountyType() == OpenQDefinitions.TIERED_PERCENTAGE) { - _claimTieredPercentageBounty(bounty, msg.sender, _closerData); } else { revert(Errors.NOT_A_COMPETITION_CONTRACT); } @@ -165,112 +158,6 @@ contract ClaimManagerV1 is ClaimManagerStorageV1 { } } - /// @notice Claim method for OngoingBounty - /// @param _bounty The payout address of the bounty - /// @param _closer The payout address of the claimant - /// @param _closerData ABI Encoded data associated with this claim - /// @dev see IBountyCore.claimOngoingPayout.(_closerData) for _closerData ABI encoding schema - function _claimOngoingBounty( - IOngoingBounty _bounty, - address _closer, - bytes calldata _closerData - ) internal { - _eligibleToClaimOngoingBounty(_bounty, _closer, _closerData); - - (address tokenAddress, uint256 volume) = _bounty.claimOngoingPayout( - _closer, - _closerData - ); - - emit TokenBalanceClaimed( - _bounty.bountyId(), - address(_bounty), - _bounty.organization(), - _closer, - block.timestamp, - tokenAddress, - volume, - _bounty.bountyType(), - _closerData, - VERSION_1 - ); - } - - /// @notice Claim method for TieredPercentageBounty - /// @param _bounty The payout address of the bounty - /// @param _closer The payout address of the claimant - /// @param _closerData ABI Encoded data associated with this claim - function _claimTieredPercentageBounty( - IBounty _bounty, - address _closer, - bytes calldata _closerData - ) internal { - (, , , , uint256 _tier) = abi.decode( - _closerData, - (address, string, address, string, uint256) - ); - - _eligibleToClaimTier(_bounty, _tier, _closer); - - if (_bounty.status() == 0) { - _bounty.closeCompetition(); - - emit BountyClosed( - _bounty.bountyId(), - address(_bounty), - _bounty.organization(), - address(0), - block.timestamp, - _bounty.bountyType(), - new bytes(0), - VERSION_1 - ); - } - - for (uint256 i = 0; i < _bounty.getTokenAddresses().length; i++) { - uint256 volume = _bounty.claimTiered( - _closer, - _tier, - _bounty.getTokenAddresses()[i] - ); - - emit TokenBalanceClaimed( - _bounty.bountyId(), - address(_bounty), - _bounty.organization(), - _closer, - block.timestamp, - _bounty.getTokenAddresses()[i], - volume, - _bounty.bountyType(), - _closerData, - VERSION_1 - ); - } - - for (uint256 i = 0; i < _bounty.getNftDeposits().length; i++) { - bytes32 _depositId = _bounty.nftDeposits(i); - if (_bounty.tier(_depositId) == _tier) { - _bounty.claimNft(_closer, _depositId); - - emit NFTClaimed( - _bounty.bountyId(), - address(_bounty), - _bounty.organization(), - _closer, - block.timestamp, - _bounty.tokenAddress(_depositId), - _bounty.tokenId(_depositId), - _bounty.bountyType(), - _closerData, - VERSION_1 - ); - } - } - - _bounty.setTierClaimed(_tier); - } - /// @notice Claim method for TieredFixedBounty /// @param _bounty The payout address of the bounty /// @param _closer The payout address of the claimant @@ -340,30 +227,6 @@ contract ClaimManagerV1 is ClaimManagerStorageV1 { _bounty.setTierClaimed(_tier); } - /// @notice Checks if bounty associated with _bountyId is open - /// @return bool True if _bountyId is associated with an open bounty - function bountyIsClaimable(address _bountyAddress) - public - view - returns (bool) - { - IBounty bounty = IBounty(payable(_bountyAddress)); - - uint256 status = bounty.status(); - uint256 _bountyType = bounty.bountyType(); - - if ( - _bountyType == OpenQDefinitions.ATOMIC || - _bountyType == OpenQDefinitions.ONGOING || - _bountyType == OpenQDefinitions.TIERED_PERCENTAGE || - _bountyType == OpenQDefinitions.TIERED_FIXED - ) { - return status == 0; - } else { - return status == 1; - } - } - /// @notice Override for UUPSUpgradeable._authorizeUpgrade(address newImplementation) to enforce onlyOwner upgrades function _authorizeUpgrade(address) internal override onlyOwner {} @@ -451,41 +314,4 @@ contract ClaimManagerV1 is ClaimManagerStorageV1 { require(hasKYC(_closer), Errors.ADDRESS_LACKS_KYC); } } - - /// @notice Runs all require statements to determine if the claimant can claim an ongoing bounty payout - function _eligibleToClaimOngoingBounty( - IOngoingBounty bounty, - address _closer, - bytes memory _closerData - ) internal view { - require( - bounty.status() == OpenQDefinitions.OPEN, - Errors.CONTRACT_IS_NOT_CLAIMABLE - ); - - (, string memory claimant, , string memory claimantAsset) = abi.decode( - _closerData, - (address, string, address, string) - ); - - bytes32 claimId = bounty.generateClaimId(claimant, claimantAsset); - - if (bounty.invoiceRequired()) { - require( - bounty.invoiceComplete(claimId), - Errors.INVOICE_NOT_COMPLETE - ); - } - - if (bounty.supportingDocumentsRequired()) { - require( - bounty.supportingDocumentsComplete(claimId), - Errors.SUPPORTING_DOCS_NOT_COMPLETE - ); - } - - if (bounty.kycRequired()) { - require(hasKYC(_closer), Errors.ADDRESS_LACKS_KYC); - } - } } diff --git a/contracts/Library/OpenQDefinitions.sol b/contracts/Library/OpenQDefinitions.sol index aa6dabff..8d918ba9 100755 --- a/contracts/Library/OpenQDefinitions.sol +++ b/contracts/Library/OpenQDefinitions.sol @@ -16,8 +16,6 @@ library OpenQDefinitions { /// @notice Bounty types uint32 internal constant ATOMIC = 0; - uint32 internal constant ONGOING = 1; - uint32 internal constant TIERED_PERCENTAGE = 2; uint32 internal constant TIERED_FIXED = 3; uint32 internal constant OPEN = 0; diff --git a/contracts/OpenQ/Implementations/OpenQV1.sol b/contracts/OpenQ/Implementations/OpenQV1.sol index 98686a06..2aa98936 100755 --- a/contracts/OpenQ/Implementations/OpenQV1.sol +++ b/contracts/OpenQ/Implementations/OpenQV1.sol @@ -249,55 +249,6 @@ contract OpenQV1 is OpenQStorageV1 { ); } - /// @notice Sets payout token address and volume on bounty with id _bountyId - /// @param _bountyId The id to update - /// @param _payoutToken The token address to be used for the payout - /// @param _payoutVolume The volume of token to be used for the payout - function setPayout( - string calldata _bountyId, - address _payoutToken, - uint256 _payoutVolume - ) external onlyProxy { - IBounty bounty = getBounty(_bountyId); - - require(msg.sender == bounty.issuer(), Errors.CALLER_NOT_ISSUER); - - bounty.setPayout(_payoutToken, _payoutVolume); - - emit PayoutSet( - address(bounty), - _payoutToken, - _payoutVolume, - bounty.bountyType(), - new bytes(0), - VERSION_1 - ); - } - - /// @notice Sets payout volume array on percentage tiered bounty with id _bountyId - /// @dev There is no tokenAddress needed here - payouts on percentage tiered bounties is a percentage of whatever is deposited on the contract - /// @param _bountyId The bounty to update - /// @param _payoutSchedule An array of payout volumes for each tier - function setPayoutSchedule( - string calldata _bountyId, - uint256[] calldata _payoutSchedule - ) external onlyProxy { - IBounty bounty = getBounty(_bountyId); - - require(msg.sender == bounty.issuer(), Errors.CALLER_NOT_ISSUER); - - bounty.setPayoutSchedule(_payoutSchedule); - - emit PayoutScheduleSet( - address(bounty), - address(0), - _payoutSchedule, - bounty.bountyType(), - new bytes(0), - VERSION_1 - ); - } - /// @notice Sets payout volume array on fixed tiered bounty with id _bountyId /// @param _bountyId The bounty to update /// @param _payoutSchedule An array of payout volumes for each tier @@ -323,33 +274,6 @@ contract OpenQV1 is OpenQStorageV1 { ); } - /// @notice Closes and ongoing bounty - /// @param _bountyId The ongoing bounty to close - function closeOngoing(string calldata _bountyId) external { - require(bountyIsOpen(_bountyId), Errors.CONTRACT_ALREADY_CLOSED); - require( - bountyType(_bountyId) == OpenQDefinitions.ONGOING, - Errors.NOT_AN_ONGOING_CONTRACT - ); - - IBounty bounty = IBounty(payable(bountyIdToAddress[_bountyId])); - - require(msg.sender == bounty.issuer(), Errors.CALLER_NOT_ISSUER); - - bounty.closeOngoing(msg.sender); - - emit BountyClosed( - _bountyId, - bountyIdToAddress[_bountyId], - bounty.organization(), - address(0), - block.timestamp, - bounty.bountyType(), - new bytes(0), - VERSION_1 - ); - } - /// @notice Checks if bounty associated with _bountyId is open /// @param _bountyId The bounty id /// @return True if _bountyId is associated with an open bounty, false otherwise @@ -402,16 +326,6 @@ contract OpenQV1 is OpenQStorageV1 { return _tierClaimed; } - /// @notice Determines whether or not an ongoing bounty or tiered bounty have enough funds to cover payouts - /// @param _bountyId The bounty id - /// @return True if solvent, false otherwise - function solvent(string calldata _bountyId) external view returns (bool) { - IBounty bounty = getBounty(_bountyId); - - uint256 balance = bounty.getTokenBalance(bounty.payoutTokenAddress()); - return balance >= bounty.payoutVolume(); - } - /// @notice Returns an IBounty ABI wrapped arround given bounty address /// @param _bountyId The bounty id /// @return An IBounty upon which any methods in IBounty can be called @@ -425,22 +339,6 @@ contract OpenQV1 is OpenQStorageV1 { return bounty; } - /// @notice Determines whether or not a given submission by claimant has already been used for a claim - /// @param _bountyId The bounty id - /// @param _claimant The external user id to check - /// @param _claimantAsset The external id of the claimant's asset to check - /// @return True if claimed, false otherwise - function ongoingClaimed( - string calldata _bountyId, - string calldata _claimant, - string calldata _claimantAsset - ) external view returns (bool) { - IBounty bounty = getBounty(_bountyId); - bytes32 claimId = keccak256(abi.encode(_claimant, _claimantAsset)); - bool _ongoingClaimed = bounty.claimId(claimId); - return _ongoingClaimed; - } - /// @notice Override for UUPSUpgradeable._authorizeUpgrade(address newImplementation) to enforce onlyOwner upgrades function _authorizeUpgrade(address) internal override onlyOwner {} From 5206d9a318be86f6233992dd3d2d1ecc2f4f3e1c Mon Sep 17 00:00:00 2001 From: FlacoJones Date: Sat, 25 Feb 2023 14:25:27 -0700 Subject: [PATCH 2/7] updates BountyFactory test to operate without Ongoing or TieredPercentage --- test/Bounty/OngoingBounty.test.js | 392 --------------------- test/Bounty/TieredPercentageBounty.test.js | 290 --------------- test/BountyFactory.test.js | 136 +------ 3 files changed, 1 insertion(+), 817 deletions(-) delete mode 100755 test/Bounty/OngoingBounty.test.js delete mode 100755 test/Bounty/TieredPercentageBounty.test.js diff --git a/test/Bounty/OngoingBounty.test.js b/test/Bounty/OngoingBounty.test.js deleted file mode 100755 index 93b324aa..00000000 --- a/test/Bounty/OngoingBounty.test.js +++ /dev/null @@ -1,392 +0,0 @@ -/* eslint-disable */ -const { BigNumber } = require('@ethersproject/bignumber'); -const { expect } = require('chai'); -const { ethers } = require("hardhat"); -const truffleAssert = require('truffle-assertions'); -require('@nomiclabs/hardhat-waffle'); - -const { generateDepositId, generateClaimantId } = require('../utils'); - -const { - Constants, - ongoingBountyInitOperationBuilder, - ongoingBountyInitOperationBuilder_noFundingGoal -} = require('../constants'); - -describe('OngoingBountyV1.sol', () => { - // CONTRACT FACTORIES - let OngoingBountyV1; - - // ACCOUNTS - let owner; - let claimManager; - let depositManager; - - // MOCK ASSETS - let mockLink; - let mockDai; - let mockNft; - - // UTILS - let abiCoder = new ethers.utils.AbiCoder; - - // CONSTANTS - let closerData = abiCoder.encode(['address', 'string', 'address', 'string'], [ethers.constants.AddressZero, "FlacoJones", ethers.constants.AddressZero, "https://github.com/OpenQDev/OpenQ-Frontend/pull/398"]); - - - // INITIALIZATION OPERATIONS - let ongoingContractInitOperation; - - // TEST CONTRACTS - let ongoingContract; - let ongoingContract_noFundingGoal; - - // MISC - let initializationTimestampAtomic; - let initializationTimestampOngoingNoFundingGoal; - - beforeEach(async () => { - OngoingBountyV1 = await ethers.getContractFactory('OngoingBountyV1'); - const MockLink = await ethers.getContractFactory('MockLink'); - const MockDai = await ethers.getContractFactory('MockDai'); - const MockNft = await ethers.getContractFactory('MockNft'); - - [owner, claimManager, depositManager] = await ethers.getSigners(); - - // MOCK ASSETS - mockLink = await MockLink.deploy(); - await mockLink.deployed(); - - mockDai = await MockDai.deploy(); - await mockDai.deployed(); - - mockNft = await MockNft.deploy(); - await mockNft.deployed(); - - await mockNft.safeMint(owner.address); - await mockNft.safeMint(owner.address); - await mockNft.safeMint(owner.address); - await mockNft.safeMint(owner.address); - await mockNft.safeMint(owner.address); - await mockNft.safeMint(owner.address); - - // ONGOIN CONTRACT - ongoingContract = await OngoingBountyV1.deploy(); - await ongoingContract.deployed(); - - ongoingContractInitOperation = ongoingBountyInitOperationBuilder(mockLink.address) - initializationTimestamp = await setNextBlockTimestamp(); - await ongoingContract.initialize(Constants.bountyId, owner.address, Constants.organization, owner.address, claimManager.address, depositManager.address, ongoingContractInitOperation); - - await mockNft.approve(ongoingContract.address, 0); - await mockNft.approve(ongoingContract.address, 1); - await mockNft.approve(ongoingContract.address, 2); - await mockNft.approve(ongoingContract.address, 3); - await mockNft.approve(ongoingContract.address, 4); - await mockNft.approve(ongoingContract.address, 5); - - // Pre-approve LINK and DAI for transfers during testing - await mockLink.approve(ongoingContract.address, 10000000); - await mockDai.approve(ongoingContract.address, 10000000); - - // ATOMIC CONTRACT W/ NO FUNDING GOAL - ongoingContract_noFundingGoal = await OngoingBountyV1.deploy(); - await ongoingContract_noFundingGoal.deployed(); - - const ongoingBountyNoFundingGoalInitOperation = ongoingBountyInitOperationBuilder_noFundingGoal(mockLink.address) - initializationTimestampOngoingNoFundingGoal = await setNextBlockTimestamp(); - await ongoingContract_noFundingGoal.initialize(Constants.bountyId, owner.address, Constants.organization, owner.address, claimManager.address, depositManager.address, ongoingBountyNoFundingGoalInitOperation); - }); - - describe('initializer', () => { - it(`should initialize bounty with correct metadata`, async () => { - // ARRANGE/ASSERT - await expect(await ongoingContract.bountyId()).equals(Constants.bountyId); - await expect(await ongoingContract.issuer()).equals(owner.address); - await expect(await ongoingContract.organization()).equals(Constants.organization); - await expect(await ongoingContract.status()).equals(0); - await expect(await ongoingContract.openQ()).equals(owner.address); - await expect(await ongoingContract.claimManager()).equals(claimManager.address); - await expect(await ongoingContract.depositManager()).equals(depositManager.address); - await expect(await ongoingContract.bountyCreatedTime()).equals(initializationTimestamp); - await expect(await ongoingContract.bountyType()).equals(Constants.ONGOING_CONTRACT); - await expect(await ongoingContract.hasFundingGoal()).equals(true); - await expect(await ongoingContract.fundingToken()).equals(mockLink.address); - await expect(await ongoingContract.fundingGoal()).equals(100); - await expect(await ongoingContract.issuerExternalUserId()).equals(Constants.mockOpenQId); - - await expect(await ongoingContract.invoiceRequired()).equals(false); - await expect(await ongoingContract.kycRequired()).equals(false); - await expect(await ongoingContract.supportingDocumentsRequired()).equals(false); - }); - - it('should revert if bountyId is empty', async () => { - // ARRANGE - const OngoingBountyV1 = await ethers.getContractFactory('OngoingBountyV1'); - ongoingContract = await OngoingBountyV1.deploy(); - - // ASSERT - await expect(ongoingContract.initialize("", owner.address, Constants.organization, owner.address, claimManager.address, depositManager.address, ongoingContractInitOperation)).to.be.revertedWith('NO_EMPTY_BOUNTY_ID'); - }); - - it('should revert if organization is empty', async () => { - // ARRANGE - const OngoingBountyV1 = await ethers.getContractFactory('OngoingBountyV1'); - ongoingContract = await OngoingBountyV1.deploy(); - - // ASSERT - await expect(ongoingContract.initialize(Constants.bountyId, owner.address, "", owner.address, claimManager.address, depositManager.address, ongoingContractInitOperation)).to.be.revertedWith('NO_EMPTY_ORGANIZATION'); - }); - }); - - describe('receiveNFT', () => { - - describe('REVERTS', () => { - it('should revert if too many NFT deposits', async () => { - // ASSUME - expect(await mockNft.ownerOf(0)).to.equal(owner.address); - expect(await mockNft.ownerOf(1)).to.equal(owner.address); - expect(await mockNft.ownerOf(2)).to.equal(owner.address); - expect(await mockNft.ownerOf(3)).to.equal(owner.address); - expect(await mockNft.ownerOf(4)).to.equal(owner.address); - - // ACT - await ongoingContract.connect(depositManager).receiveNft(owner.address, mockNft.address, 0, 1, []); - await ongoingContract.connect(depositManager).receiveNft(owner.address, mockNft.address, 1, 1, []); - await ongoingContract.connect(depositManager).receiveNft(owner.address, mockNft.address, 2, 1, []); - await ongoingContract.connect(depositManager).receiveNft(owner.address, mockNft.address, 3, 1, []); - await ongoingContract.connect(depositManager).receiveNft(owner.address, mockNft.address, 4, 1, []); - - // ASSERT - await expect(ongoingContract.connect(depositManager).receiveNft(owner.address, mockNft.address, 5, 1, [])).to.be.revertedWith('NFT_DEPOSIT_LIMIT_REACHED'); - }); - - it('should revert if expiration is negative', async () => { - await expect(ongoingContract.connect(depositManager).receiveNft(owner.address, mockNft.address, 0, 0, [])).to.be.revertedWith('EXPIRATION_NOT_GREATER_THAN_ZERO'); - }); - }); - - describe('DEPOSIT INITIALIZATION', () => { - it(`should initialize nft deposit data with correct metadata`, async () => { - - // ACT - const expectedTimestamp = await setNextBlockTimestamp(); - const depositId = generateDepositId(Constants.bountyId, 0); - await ongoingContract.connect(depositManager).receiveNft(owner.address, mockNft.address, 1, Constants.thirtyDays, []); - - // ASSERT - expect(await ongoingContract.funder(depositId)).to.equal(owner.address); - expect(await ongoingContract.tokenAddress(depositId)).to.equal(mockNft.address); - expect(await ongoingContract.tokenId(depositId)).to.equal(1); - expect(await ongoingContract.expiration(depositId)).to.equal(Constants.thirtyDays); - expect(await ongoingContract.isNFT(depositId)).to.equal(true); - - const depositTime = await ongoingContract.depositTime(depositId); - expect(depositTime.toString()).to.equal(expectedTimestamp.toString()); - }); - }); - - describe('transfer', () => { - it('should transfer NFT from owner to bounty contract', async () => { - // ASSUME - expect(await mockNft.ownerOf(0)).to.equal(owner.address); - - // ACT - await ongoingContract.connect(depositManager).receiveNft(owner.address, mockNft.address, 0, 1, []); - - // ASSERT - expect(await mockNft.ownerOf(0)).to.equal(ongoingContract.address); - }); - }); - }); - - describe('claimOngoingPayout', () => { - it('should transfer payoutVolume of payoutTokenAddress to claimant', async () => { - // ARRANGE - const volume = 300; - - const [, claimer] = await ethers.getSigners(); - - await ongoingContract.connect(depositManager).receiveFunds(owner.address, mockLink.address, volume, Constants.thirtyDays); - - const deposits = await ongoingContract.getDeposits(); - const linkDepositId = deposits[0]; - - // ASSUME - const bountyMockTokenBalance = (await mockLink.balanceOf(ongoingContract.address)).toString(); - expect(bountyMockTokenBalance).to.equal('300'); - - const claimerMockTokenBalance = (await mockLink.balanceOf(claimer.address)).toString(); - expect(claimerMockTokenBalance).to.equal('0'); - - // ACT - await ongoingContract.connect(claimManager).claimOngoingPayout(claimer.address, closerData); - - // ASSERT - const newClaimerMockTokenBalance = (await mockLink.balanceOf(claimer.address)).toString(); - expect(newClaimerMockTokenBalance).to.equal('100'); - - const newBountyMockLinkBalance = (await mockLink.balanceOf(ongoingContract.address)).toString(); - expect(newBountyMockLinkBalance).to.equal('200'); - - // ACT - await ongoingContract.connect(claimManager).claimOngoingPayout(claimer.address, closerData); - - // ASSERT - const newClaimerMockTokenBalance2 = (await mockLink.balanceOf(claimer.address)).toString(); - expect(newClaimerMockTokenBalance2).to.equal('200'); - - const newBountyMockLinkBalance2 = (await mockLink.balanceOf(ongoingContract.address)).toString(); - expect(newBountyMockLinkBalance2).to.equal('100'); - }); - - it('should set claimId to true for the claimant and claimant asset', async () => { - // ARRANGE - let claimId = generateClaimantId('FlacoJones', "https://github.com/OpenQDev/OpenQ-Frontend/pull/398"); - await ongoingContract.connect(depositManager).receiveFunds(owner.address, mockLink.address, 10000000, Constants.thirtyDays); - - - // ASSUME - let claimantIdClaimed = await ongoingContract.claimId(claimId); - expect(claimantIdClaimed).to.equal(false); - - // ACT - await ongoingContract.connect(claimManager).claimOngoingPayout(owner.address, closerData); - - // ASSERT - claimantIdClaimed = await ongoingContract.claimId(claimId); - expect(claimantIdClaimed).to.equal(true); - }); - - it('should revert if not called by claim manager', async () => { - // ACT/ASSERT - await expect(ongoingContract.claimOngoingPayout(owner.address, closerData)).to.be.revertedWith('ClaimManagerOwnable: caller is not the current OpenQ Claim Manager'); - }); - }); - - describe('setPayout', () => { - it('should revert if not called by OpenQ contract', async () => { - // ARRANGE - const [, notOwner] = await ethers.getSigners(); - - // ASSERT - await expect(ongoingContract.connect(notOwner).setPayout(mockLink.address, 100)).to.be.revertedWith('Method is only callable by OpenQ'); - }); - - it('should set payoutTokenAddress and payoutTokenVolume', async () => { - // ASSUME - expect(await ongoingContract.payoutTokenAddress()).to.equal(mockLink.address) - expect(await ongoingContract.payoutVolume()).to.equal(100) - - // ACT - await ongoingContract.setPayout(mockDai.address, 250); - - // ASSERT - expect(await ongoingContract.payoutTokenAddress()).to.equal(mockDai.address) - expect(await ongoingContract.payoutVolume()).to.equal(250) - }) - }) - - describe('closeOngoing', () => { - it('should revert if not called by OpenQ contract', async () => { - // ARRANGE - const [, , , , , notOpenQ] = await ethers.getSigners(); - - // ASSERT - await expect(ongoingContract.connect(notOpenQ).closeOngoing(owner.address)).to.be.revertedWith('Method is only callable by OpenQ'); - }); - - it('should revert if already closed', async () => { - // ARRANGE - ongoingContract.connect(owner).closeOngoing(owner.address); - //ACT / ASSERT - await expect(ongoingContract.connect(owner).closeOngoing(owner.address)).to.be.revertedWith('CONTRACT_ALREADY_CLOSED'); - }); - - it('should change status to CLOSED (1)', async () => { - // ASSUME - await expect(await ongoingContract.status()).equals(0); - //ACT - await ongoingContract.connect(owner).closeOngoing(owner.address); - // ASSERT - await expect(await ongoingContract.status()).equals(1); - }); - - it('should set bountyClosedTime to the block timestamp', async () => { - // ARRANGE - const expectedTimestamp = await setNextBlockTimestamp(); - // ASSUME - await expect(await ongoingContract.bountyClosedTime()).equals(0); - //ACT - await ongoingContract.connect(owner).closeOngoing(owner.address); - // ASSERT - await expect(await ongoingContract.bountyClosedTime()).equals(expectedTimestamp); - }); - }); - - describe('setInvoiceComplete', () => { - it('should revert if not called by OpenQ contract', async () => { - // ARRANGE - const [, notOwner] = await ethers.getSigners(); - - const claimId = generateClaimantId(Constants.mockOpenQId, Constants.mockClaimantAsset) - let setInvoiceCompleteData = abiCoder.encode(["bytes32", "bool"], [claimId, true]); - - // ASSERT - await expect(ongoingContract.connect(notOwner).setInvoiceComplete(setInvoiceCompleteData)).to.be.revertedWith('Method is only callable by OpenQ'); - }); - - it('should set invoiceComplete for given claimId', async () => { - const claimId = generateClaimantId(Constants.mockOpenQId, Constants.mockClaimantAsset) - let setInvoiceCompleteData = abiCoder.encode(["bytes32", "bool"], [claimId, true]); - - // ASSUME - expect(await ongoingContract.invoiceComplete(claimId)).to.equal(false) - - // ACT - await ongoingContract.setInvoiceComplete(setInvoiceCompleteData); - - // ASSERT - expect(await ongoingContract.invoiceComplete(claimId)).to.equal(true) - }) - }) - - describe('setSupportingDocumentsComplete', () => { - it('should revert if not called by OpenQ contract', async () => { - // ARRANGE - const [, notOwner] = await ethers.getSigners(); - - const claimId = generateClaimantId(Constants.mockOpenQId, Constants.mockClaimantAsset) - let setSupportingDocumentsCompleteData = abiCoder.encode(["bytes32", "bool"], [claimId, true]); - - // ASSERT - await expect(ongoingContract.connect(notOwner).setSupportingDocumentsComplete(setSupportingDocumentsCompleteData)).to.be.revertedWith('Method is only callable by OpenQ'); - }); - - it('should set supportingDocumentsComplete for given claimId', async () => { - const claimId = generateClaimantId(Constants.mockOpenQId, Constants.mockClaimantAsset) - let setSupportingDocumentsCompleteData = abiCoder.encode(["bytes32", "bool"], [claimId, true]); - - // ASSUME - expect(await ongoingContract.supportingDocumentsComplete(claimId)).to.equal(false) - - // ACT - await ongoingContract.setSupportingDocumentsComplete(setSupportingDocumentsCompleteData); - - // ASSERT - expect(await ongoingContract.supportingDocumentsComplete(claimId)).to.equal(true) - }) - }) - -}); - -async function setNextBlockTimestamp() { - return new Promise(async (resolve,) => { - const blockNumBefore = await ethers.provider.getBlockNumber(); - const blockBefore = await ethers.provider.getBlock(blockNumBefore); - const timestampBefore = blockBefore.timestamp; - const expectedTimestamp = timestampBefore + 10; - await network.provider.send("evm_setNextBlockTimestamp", [expectedTimestamp]); - resolve(expectedTimestamp); - }); -} \ No newline at end of file diff --git a/test/Bounty/TieredPercentageBounty.test.js b/test/Bounty/TieredPercentageBounty.test.js deleted file mode 100755 index df9ab96f..00000000 --- a/test/Bounty/TieredPercentageBounty.test.js +++ /dev/null @@ -1,290 +0,0 @@ -/* eslint-disable */ -const { BigNumber } = require('@ethersproject/bignumber'); -const { expect } = require('chai'); -const { ethers } = require("hardhat"); -const truffleAssert = require('truffle-assertions'); -require('@nomiclabs/hardhat-waffle'); - -const { generateDepositId, generateClaimantId } = require('../utils'); - -const { - Constants, - tieredBountyInitOperationBuilder, - tieredBountyInitOperationBuilder_noFundingGoal -} = require('../constants'); - -describe('TieredPercentageBountyV1.sol', () => { - // CONTRACT FACTORIES - let TieredPercentageBountyV1; - - // ACCOUNTS - let owner; - let claimManager; - let depositManager; - - // MOCK ASSETS - let mockLink; - let mockDai; - let mockNft; - - // UTILS - let abiCoder = new ethers.utils.AbiCoder; - - // CONSTANTS - let closerData = abiCoder.encode(['address', 'string', 'address', 'string'], [ethers.constants.AddressZero, "FlacoJones", ethers.constants.AddressZero, "https://github.com/OpenQDev/OpenQ-Frontend/pull/398"]); - - - // INITIALIZATION OPERATIONS - let tieredBountyInitOperation; - - // TEST CONTRACTS - let tieredContract; - let tieredContract_noFundingGoal; - - // MISC - let initializationTimestampTiered; - - beforeEach(async () => { - TieredPercentageBountyV1 = await ethers.getContractFactory('TieredPercentageBountyV1'); - const MockLink = await ethers.getContractFactory('MockLink'); - const MockDai = await ethers.getContractFactory('MockDai'); - const MockNft = await ethers.getContractFactory('MockNft'); - - [owner, claimManager, depositManager] = await ethers.getSigners(); - - // MOCK ASSETS - mockLink = await MockLink.deploy(); - await mockLink.deployed(); - - mockDai = await MockDai.deploy(); - await mockDai.deployed(); - - mockNft = await MockNft.deploy(); - await mockNft.deployed(); - - await mockNft.safeMint(owner.address); - await mockNft.safeMint(owner.address); - await mockNft.safeMint(owner.address); - await mockNft.safeMint(owner.address); - await mockNft.safeMint(owner.address); - await mockNft.safeMint(owner.address); - - // TIERED PERCENTAGE BOUNTY W/ FUNDING GOAL - tieredContract = await TieredPercentageBountyV1.deploy(); - await tieredContract.deployed(); - tieredBountyInitOperation = tieredBountyInitOperationBuilder(mockLink.address) - initializationTimestampTiered = await setNextBlockTimestamp(); - await tieredContract.initialize(Constants.bountyId, owner.address, Constants.organization, owner.address, claimManager.address, depositManager.address, tieredBountyInitOperation); - - // TIERED PERCENTAGE BOUNTY - NO FUNDING GOAL - tieredContract_noFundingGoal = await TieredPercentageBountyV1.deploy(); - await tieredContract_noFundingGoal.deployed(); - tieredBountyInitOperation_noFundingGoal = tieredBountyInitOperationBuilder_noFundingGoal() - await tieredContract_noFundingGoal.initialize(Constants.bountyId, owner.address, Constants.organization, owner.address, claimManager.address, depositManager.address, tieredBountyInitOperation_noFundingGoal); - - // Pre-approve LINK and DAI for transfers during testing - await mockLink.approve(tieredContract.address, 10000000); - await mockDai.approve(tieredContract.address, 10000000); - - await mockNft.approve(tieredContract.address, 0); - await mockNft.approve(tieredContract.address, 1); - await mockNft.approve(tieredContract.address, 2); - }); - - describe('initializer', () => { - it('should init with tiered correct metadata', async () => { - const actualBountyPayoutSchedule = await tieredContract.getPayoutSchedule(); - const payoutToString = actualBountyPayoutSchedule.map(thing => thing.toString()); - - await expect(await tieredContract.bountyId()).equals(Constants.bountyId); - await expect(await tieredContract.issuer()).equals(owner.address); - await expect(await tieredContract.organization()).equals(Constants.organization); - await expect(await tieredContract.status()).equals(0); - await expect(await tieredContract.openQ()).equals(owner.address); - await expect(await tieredContract.claimManager()).equals(claimManager.address); - await expect(await tieredContract.depositManager()).equals(depositManager.address); - await expect(await tieredContract.bountyCreatedTime()).equals(initializationTimestampTiered); - await expect(await tieredContract.bountyType()).equals(Constants.TIERED_PERCENTAGE_CONTRACT); - await expect(await tieredContract.hasFundingGoal()).equals(true); - await expect(await tieredContract.fundingToken()).equals(mockLink.address); - await expect(await tieredContract.fundingGoal()).equals(100); - await expect(payoutToString[0]).equals("60"); - await expect(payoutToString[1]).equals("30"); - await expect(payoutToString[2]).equals("10"); - await expect(await tieredContract.invoiceRequired()).equals(true); - await expect(await tieredContract.kycRequired()).equals(true); - await expect(await tieredContract.issuerExternalUserId()).equals(Constants.mockOpenQId); - await expect(await tieredContract.supportingDocumentsRequired()).equals(true); - - await expect(await tieredContract.invoiceComplete(0)).equals(false); - await expect(await tieredContract.supportingDocumentsComplete(0)).equals(false); - }); - - it('should revert if payoutSchedule values do not add up to 100', async () => { - // ARRANGE - tieredContract = await TieredPercentageBountyV1.deploy(); - await tieredContract.deployed(); - - const abiEncodedParamsTieredBountyNot100 = abiCoder.encode(["uint256[]", "bool", "address", "uint256", "bool", "bool", "bool", "string", "string", "string"], [[1, 2], true, mockLink.address, 100, true, true, true, Constants.mockOpenQId, "", ""]); - - tieredBountyInitOperation = [2, abiEncodedParamsTieredBountyNot100]; - - // ACT/ASSERT - await expect(tieredContract.initialize(Constants.bountyId, owner.address, Constants.organization, owner.address, claimManager.address, depositManager.address, tieredBountyInitOperation)).to.be.revertedWith('PAYOUT_SCHEDULE_MUST_ADD_TO_100'); - }); - - it('should revert if bountyId is empty', async () => { - // ARRANGE - const TieredPercentageBountyV1 = await ethers.getContractFactory('TieredPercentageBountyV1'); - tieredContract = await TieredPercentageBountyV1.deploy(); - - // ASSERT - await expect(tieredContract.initialize("", owner.address, Constants.organization, owner.address, claimManager.address, depositManager.address, tieredBountyInitOperation)).to.be.revertedWith('NO_EMPTY_BOUNTY_ID'); - }); - - it('should revert if organization is empty', async () => { - // ARRANGE - const TieredPercentageBountyV1 = await ethers.getContractFactory('TieredPercentageBountyV1'); - tieredContract = await TieredPercentageBountyV1.deploy(); - - // ASSERT - await expect(tieredContract.initialize(Constants.bountyId, owner.address, "", owner.address, claimManager.address, depositManager.address, tieredBountyInitOperation)).to.be.revertedWith('NO_EMPTY_ORGANIZATION'); - }); - }); - - describe('claimTiered', () => { - it('should transfer volume of tokenAddress balance based on payoutSchedule', async () => { - // ARRANGE - const volume = 1000; - - const [, firstPlace, secondPlace] = await ethers.getSigners(); - - await tieredContract.connect(depositManager).receiveFunds(owner.address, mockLink.address, volume, Constants.thirtyDays); - - const deposits = await tieredContract.getDeposits(); - const linkDepositId = deposits[0]; - - await tieredContract.connect(claimManager).closeCompetition(); - - // ASSUME - const bountyMockTokenBalance = (await mockLink.balanceOf(tieredContract.address)).toString(); - expect(bountyMockTokenBalance).to.equal('1000'); - - const claimerMockTokenBalance = (await mockLink.balanceOf(firstPlace.address)).toString(); - expect(claimerMockTokenBalance).to.equal('0'); - - // ACT - await tieredContract.connect(claimManager).claimTiered(firstPlace.address, 0, mockLink.address); - - // // // ASSERT - // const newClaimerMockTokenBalance = (await mockLink.balanceOf(firstPlace.address)).toString(); - // expect(newClaimerMockTokenBalance).to.equal('800'); - - // // ACT - // await tieredContract.connect(claimManager).claimTiered(secondPlace.address, 1, mockLink.address); - - // // // ASSERT - // const secondPlaceMockTokenBalance = (await mockLink.balanceOf(secondPlace.address)).toString(); - // expect(secondPlaceMockTokenBalance).to.equal('200'); - }); - - it('should revert if not called by claim manager', async () => { - // ACT/ASSERT - await expect(tieredContract.claimTiered(owner.address, 0, mockLink.address)).to.be.revertedWith('ClaimManagerOwnable: caller is not the current OpenQ Claim Manager'); - }); - }); - - describe('closeCompetition', () => { - it('should set bounty status to 1, freeze balances and set bountyClosedTime', async () => { - // ARRANGE - const volume = 1000; - - const [, firstPlace, secondPlace] = await ethers.getSigners(); - - await tieredContract.connect(depositManager).receiveFunds(owner.address, mockLink.address, volume, Constants.thirtyDays); - - // ASSUME - const bountyMockTokenBalance = (await mockLink.balanceOf(tieredContract.address)).toString(); - expect(bountyMockTokenBalance).to.equal('1000'); - - const claimerMockTokenBalance = (await mockLink.balanceOf(firstPlace.address)).toString(); - expect(claimerMockTokenBalance).to.equal('0'); - - // ASSUME - let status = await tieredContract.status(); - let mockTokenFundingTotal = await tieredContract.fundingTotals(mockLink.address); - let bountyClosedTime = await tieredContract.bountyClosedTime(); - - expect(status).to.equal(0); - expect(mockTokenFundingTotal).to.equal(0); - expect(bountyClosedTime).to.equal(0); - - const expectedTimestamp = await setNextBlockTimestamp(); - // ACT - await tieredContract.connect(claimManager).closeCompetition(); - - // ASSERT - status = await tieredContract.status(); - mockTokenFundingTotal = await tieredContract.fundingTotals(mockLink.address); - bountyClosedTime = await tieredContract.bountyClosedTime(); - - expect(status).to.equal(1); - expect(mockTokenFundingTotal).to.equal(1000); - expect(bountyClosedTime).to.equal(expectedTimestamp); - }); - - it('should revert if already closed', async () => { - await tieredContract.connect(claimManager).closeCompetition(); - await expect(tieredContract.connect(claimManager).closeCompetition()).to.be.revertedWith('CONTRACT_ALREADY_CLOSED'); - }); - }); - - describe('setPayoutSchedule', () => { - it('should revert if not called by OpenQ contract', async () => { - // ARRANGE - const [, notOwner] = await ethers.getSigners(); - - // ASSERT - await expect(tieredContract.connect(notOwner).setPayoutSchedule([80, 20])).to.be.revertedWith('Method is only callable by OpenQ'); - }); - - it('should revert if payoutschedule doesnt add to 100', async () => { - // ARRANGE - const [, notOwner] = await ethers.getSigners(); - - // ASSERT - await expect(tieredContract.connect(notOwner).setPayoutSchedule([100, 20])).to.be.revertedWith('Method is only callable by OpenQ'); - }); - - it('should set payout schedule', async () => { - // ASSUME - let initialPayoutSchedule = await tieredContract.getPayoutSchedule(); - let payoutToString = initialPayoutSchedule.map(thing => thing.toString()); - expect(payoutToString[0]).to.equal('60'); - expect(payoutToString[1]).to.equal('30'); - expect(payoutToString[2]).to.equal('10'); - - // ACT - await tieredContract.setPayoutSchedule([70, 20, 10]); - - // ASSERT - let expectedPayoutSchedule = await tieredContract.getPayoutSchedule(); - payoutToString = expectedPayoutSchedule.map(thing => thing.toString()); - expect(payoutToString[0]).to.equal('70'); - expect(payoutToString[1]).to.equal('20'); - expect(payoutToString[2]).to.equal('10'); - }); - }); - -}); - -async function setNextBlockTimestamp() { - return new Promise(async (resolve,) => { - const blockNumBefore = await ethers.provider.getBlockNumber(); - const blockBefore = await ethers.provider.getBlock(blockNumBefore); - const timestampBefore = blockBefore.timestamp; - const expectedTimestamp = timestampBefore + 10; - await network.provider.send("evm_setNextBlockTimestamp", [expectedTimestamp]); - resolve(expectedTimestamp); - }); -} \ No newline at end of file diff --git a/test/BountyFactory.test.js b/test/BountyFactory.test.js index 567b7c84..bef6b267 100755 --- a/test/BountyFactory.test.js +++ b/test/BountyFactory.test.js @@ -10,13 +10,11 @@ const { atomicBountyInitOperation_fundingGoal, atomicBountyInitOperation_noFundingGoal, atomicBountyInitOperation_permissioned, - ongoingBountyInitOperationBuilder, - tieredBountyInitOperationBuilder, tieredFixedBountyInitOperationBuilder, tieredBountyInitOperation_not100 } = require('./constants'); -describe('BountyFactory', () => { +describe.only('BountyFactory', () => { let openQImplementation; let openQProxy; let bountyFactory; @@ -27,8 +25,6 @@ describe('BountyFactory', () => { let OpenQProxy; let AtomicBountyV1; - let OngoingBountyV1; - let TieredPercentageBountyV1; let TieredFixedBountyV1; let BountyBeacon; @@ -41,8 +37,6 @@ describe('BountyFactory', () => { let depositManager; let atomicBountyInitOperation; - let ongoingBountyInitOperation; - let tieredPercentageBountyInitOperation; let tieredFixedBountyInitOperation; const mockOpenQId = "mockOpenQId" @@ -57,8 +51,6 @@ describe('BountyFactory', () => { BountyBeacon = await hre.ethers.getContractFactory('BountyBeacon'); AtomicBountyV1 = await hre.ethers.getContractFactory('AtomicBountyV1'); - OngoingBountyV1 = await hre.ethers.getContractFactory('OngoingBountyV1'); - TieredPercentageBountyV1 = await hre.ethers.getContractFactory('TieredPercentageBountyV1'); TieredFixedBountyV1 = await hre.ethers.getContractFactory('TieredFixedBountyV1'); [owner, oracle, notOpenQ, claimManager, depositManager] = await ethers.getSigners(); @@ -74,12 +66,6 @@ describe('BountyFactory', () => { atomicBountyV1 = await AtomicBountyV1.deploy(); await atomicBountyV1.deployed(); - ongoingBountyV1 = await OngoingBountyV1.deploy(); - await ongoingBountyV1.deployed(); - - tieredPercentageBountyV1 = await TieredPercentageBountyV1.deploy(); - await tieredPercentageBountyV1.deployed(); - tieredFixedBountyV1 = await TieredFixedBountyV1.deploy(); await tieredFixedBountyV1.deployed(); @@ -87,12 +73,6 @@ describe('BountyFactory', () => { atomicBountyBeacon = await BountyBeacon.deploy(atomicBountyV1.address); await atomicBountyBeacon.deployed(); - ongoingBountyBeacon = await BountyBeacon.deploy(ongoingBountyV1.address); - await ongoingBountyBeacon.deployed(); - - tieredPercentageBountyBeacon = await BountyBeacon.deploy(tieredPercentageBountyV1.address); - await tieredPercentageBountyBeacon.deployed(); - tieredFixedBountyBeacon = await BountyBeacon.deploy(tieredFixedBountyV1.address); await tieredFixedBountyBeacon.deployed(); @@ -110,8 +90,6 @@ describe('BountyFactory', () => { bountyFactory = await BountyFactory.deploy( openQProxy.address, atomicBountyBeacon.address, - ongoingBountyBeacon.address, - tieredPercentageBountyBeacon.address, tieredFixedBountyBeacon.address ); await bountyFactory.deployed(); @@ -120,8 +98,6 @@ describe('BountyFactory', () => { const abiCoder = new ethers.utils.AbiCoder; atomicBountyInitOperation = atomicBountyInitOperation_fundingGoal(mockLink.address) - ongoingBountyInitOperation = ongoingBountyInitOperationBuilder(mockLink.address) - tieredPercentageBountyInitOperation = tieredBountyInitOperationBuilder(mockLink.address) tieredFixedBountyInitOperation = tieredFixedBountyInitOperationBuilder(mockLink.address) }); @@ -129,8 +105,6 @@ describe('BountyFactory', () => { it('should initiatlize with correct OpenQ proxy address and BountyBeacon address', async () => { expect(await bountyFactory.openQ()).equals(openQProxy.address); expect(await bountyFactory.atomicBountyBeacon()).equals(atomicBountyBeacon.address); - expect(await bountyFactory.ongoingBountyBeacon()).equals(ongoingBountyBeacon.address); - expect(await bountyFactory.tieredPercentageBountyBeacon()).equals(tieredPercentageBountyBeacon.address); expect(await bountyFactory.tieredFixedBountyBeacon()).equals(tieredFixedBountyBeacon.address); }); }); @@ -147,8 +121,6 @@ describe('BountyFactory', () => { let newBountyFactory = await BountyFactory.deploy( owner.address, atomicBountyBeacon.address, - ongoingBountyBeacon.address, - tieredPercentageBountyBeacon.address, tieredFixedBountyBeacon.address ); await newBountyFactory.deployed(); @@ -189,115 +161,11 @@ describe('BountyFactory', () => { await expect(atomicContract.initialize(mockOpenQId, owner.address, organization, owner.address, claimManager.address, depositManager.address, atomicBountyInitOperation)).to.be.revertedWith('Initializable: contract is already initialized'); }); - it('should mint a bounty with expected data - ONGOING', async () => { - // Must redeploy and pretend that owner account is OpenQ in order to call BountyFactory.mintBounty - let newBountyFactory = await BountyFactory.deploy( - owner.address, - atomicBountyBeacon.address, - ongoingBountyBeacon.address, - tieredPercentageBountyBeacon.address, - tieredFixedBountyBeacon.address - ); - await newBountyFactory.deployed(); - - let initializationTimestamp = await setNextBlockTimestamp(); - - const txn = await newBountyFactory.mintBounty( - mockId, - owner.address, - organization, - claimManager.address, - depositManager.address, - ongoingBountyInitOperation - ); - - const receipt = await txn.wait(); - - const ongoingContract = await OngoingBountyV1.attach(receipt.events[0].address); - - await expect(await ongoingContract.bountyId()).equals(mockId); - await expect(await ongoingContract.issuer()).equals(owner.address); - await expect(await ongoingContract.organization()).equals(organization); - await expect(await ongoingContract.status()).equals(0); - await expect(await ongoingContract.openQ()).equals(owner.address); - await expect(await ongoingContract.claimManager()).equals(claimManager.address); - await expect(await ongoingContract.depositManager()).equals(depositManager.address); - await expect(await ongoingContract.bountyCreatedTime()).equals(initializationTimestamp); - await expect(await ongoingContract.bountyType()).equals(Constants.ONGOING_CONTRACT); - await expect(await ongoingContract.hasFundingGoal()).equals(true); - await expect(await ongoingContract.fundingToken()).equals(mockLink.address); - await expect(await ongoingContract.fundingGoal()).equals(Constants.volume); - await expect(await ongoingContract.issuerExternalUserId()).equals(mockOpenQId); - - await expect(await ongoingContract.invoiceRequired()).equals(false); - await expect(await ongoingContract.kycRequired()).equals(false); - await expect(await ongoingContract.supportingDocumentsRequired()).equals(false); - - await expect(ongoingContract.initialize('mock-id', owner.address, 'mock-organization', owner.address, claimManager.address, depositManager.address, ongoingBountyInitOperation)).to.be.revertedWith('Initializable: contract is already initialized'); - }); - - it('should mint a bounty with expected data - TIERED PERCENTAGE', async () => { - // Must redeploy and pretend that owner account is OpenQ in order to call BountyFactory.mintBounty - let newBountyFactory = await BountyFactory.deploy( - owner.address, - atomicBountyBeacon.address, - ongoingBountyBeacon.address, - tieredPercentageBountyBeacon.address, - tieredFixedBountyBeacon.address - ); - await newBountyFactory.deployed(); - - let initializationTimestamp = await setNextBlockTimestamp(); - - const txn = await newBountyFactory.mintBounty( - mockId, - owner.address, - organization, - claimManager.address, - depositManager.address, - tieredPercentageBountyInitOperation - ); - - const receipt = await txn.wait(); - - const tieredPercentageContract = await TieredPercentageBountyV1.attach(receipt.events[0].address); - - const actualBountyPayoutSchedule = await tieredPercentageContract.getPayoutSchedule(); - const payoutToString = actualBountyPayoutSchedule.map(thing => thing.toString()); - - await expect(await tieredPercentageContract.bountyId()).equals(mockId); - await expect(await tieredPercentageContract.bountyId()).equals(mockId); - await expect(await tieredPercentageContract.issuer()).equals(owner.address); - await expect(await tieredPercentageContract.organization()).equals(organization); - await expect(await tieredPercentageContract.status()).equals(0); - await expect(await tieredPercentageContract.openQ()).equals(owner.address); - await expect(await tieredPercentageContract.claimManager()).equals(claimManager.address); - await expect(await tieredPercentageContract.depositManager()).equals(depositManager.address); - await expect(await tieredPercentageContract.bountyCreatedTime()).equals(initializationTimestamp); - await expect(await tieredPercentageContract.bountyType()).equals(Constants.TIERED_PERCENTAGE_CONTRACT); - await expect(await tieredPercentageContract.hasFundingGoal()).equals(true); - await expect(await tieredPercentageContract.fundingToken()).equals(mockLink.address); - await expect(await tieredPercentageContract.fundingGoal()).equals(Constants.volume); - await expect(payoutToString[0]).equals("60"); - await expect(payoutToString[1]).equals("30"); - await expect(await tieredPercentageContract.invoiceRequired()).equals(true); - await expect(await tieredPercentageContract.kycRequired()).equals(true); - await expect(await tieredPercentageContract.issuerExternalUserId()).equals(mockOpenQId); - - await expect(await tieredPercentageContract.supportingDocumentsRequired()).equals(true); - await expect(await tieredPercentageContract.invoiceComplete(0)).equals(false); - await expect(await tieredPercentageContract.supportingDocumentsComplete(0)).equals(false); - - await expect(tieredPercentageContract.initialize(mockOpenQId, owner.address, organization, owner.address, claimManager.address, depositManager.address, tieredPercentageBountyInitOperation)).to.be.revertedWith('Initializable: contract is already initialized'); - }); - it('should mint a bounty with expected data - TIERED FIXED', async () => { // Must redeploy and pretend that owner account is OpenQ in order to call BountyFactory.mintBounty let newBountyFactory = await BountyFactory.deploy( owner.address, atomicBountyBeacon.address, - ongoingBountyBeacon.address, - tieredPercentageBountyBeacon.address, tieredFixedBountyBeacon.address ); await newBountyFactory.deployed(); @@ -348,8 +216,6 @@ describe('BountyFactory', () => { let newBountyFactory = await BountyFactory.deploy( owner.address, atomicBountyBeacon.address, - ongoingBountyBeacon.address, - tieredPercentageBountyBeacon.address, tieredFixedBountyBeacon.address ); await newBountyFactory.deployed(); From 67155c2ad52a0e1e38064a4975c1d1fb85504946 Mon Sep 17 00:00:00 2001 From: FlacoJones Date: Sat, 25 Feb 2023 14:37:35 -0700 Subject: [PATCH 3/7] updates ClaimManager tests to pass without Ongoing or TieredPercentage --- test/BountyFactory.test.js | 2 +- test/ClaimManager.test.js | 490 ++----------------------------------- test/constants.js | 4 +- 3 files changed, 17 insertions(+), 479 deletions(-) diff --git a/test/BountyFactory.test.js b/test/BountyFactory.test.js index bef6b267..24fe7453 100755 --- a/test/BountyFactory.test.js +++ b/test/BountyFactory.test.js @@ -14,7 +14,7 @@ const { tieredBountyInitOperation_not100 } = require('./constants'); -describe.only('BountyFactory', () => { +describe('BountyFactory', () => { let openQImplementation; let openQProxy; let bountyFactory; diff --git a/test/ClaimManager.test.js b/test/ClaimManager.test.js index 41be3ce4..c11c91c8 100755 --- a/test/ClaimManager.test.js +++ b/test/ClaimManager.test.js @@ -12,19 +12,15 @@ const { atomicBountyInitOperation_fundingGoal, atomicBountyInitOperation_noFundingGoal, atomicBountyInitOperation_permissioned, - ongoingBountyInitOperationBuilder, - tieredBountyInitOperationBuilder, tieredFixedBountyInitOperationBuilder, - tieredBountyInitOperation_not100, setInvoiceCompleteData_tiered, setSupportingDocumentsComplete_tiered, setInvoiceCompleteData_atomic, setSupportingDocumentsComplete_atomic, - tieredBountyInitOperationBuilder_permissionless, tieredFixedBountyInitOperationBuilder_permissionless } = require('./constants'); -describe('ClaimManager.sol', () => { +describe.only('ClaimManager.sol', () => { // MOCK ASSETS let openQProxy; let openQImplementation; @@ -53,9 +49,6 @@ describe('ClaimManager.sol', () => { // INIT OPERATIONS let atomicBountyInitOperation; - let ongoingBountyInitOperation; - let tieredPercentageBountyInitOperation_permissionless; - let tieredPercentageBountyInitOperation_permissioned let tieredFixedBountyInitOperation_permissionless; let tieredFixedBountyInitOperation_permissioned; @@ -71,8 +64,6 @@ describe('ClaimManager.sol', () => { let abiEncodedTieredCloserDataThirdPlace; let AtomicBountyV1 - let OngoingBountyV1 - let TieredPercentageBountyV1 let TieredFixedBountyV1 beforeEach(async () => { @@ -87,20 +78,12 @@ describe('ClaimManager.sol', () => { const MockKyc = await ethers.getContractFactory('MockKyc'); AtomicBountyV1 = await ethers.getContractFactory('AtomicBountyV1'); - OngoingBountyV1 = await ethers.getContractFactory('OngoingBountyV1'); - TieredPercentageBountyV1 = await ethers.getContractFactory('TieredPercentageBountyV1'); TieredFixedBountyV1 = await ethers.getContractFactory('TieredFixedBountyV1'); // BOUNTY IMPLEMENTATIONS atomicBountyV1 = await AtomicBountyV1.deploy(); await atomicBountyV1.deployed(); - ongoingBountyV1 = await OngoingBountyV1.deploy(); - await ongoingBountyV1.deployed(); - - tieredPercentageBountyV1 = await TieredPercentageBountyV1.deploy(); - await tieredPercentageBountyV1.deployed(); - tieredFixedBountyV1 = await TieredFixedBountyV1.deploy(); await tieredFixedBountyV1.deployed(); @@ -153,12 +136,6 @@ describe('ClaimManager.sol', () => { atomicBountyBeacon = await BountyBeacon.deploy(atomicBountyV1.address); await atomicBountyBeacon.deployed(); - ongoingBountyBeacon = await BountyBeacon.deploy(ongoingBountyV1.address); - await ongoingBountyBeacon.deployed(); - - tieredPercentageBountyBeacon = await BountyBeacon.deploy(tieredPercentageBountyV1.address); - await tieredPercentageBountyBeacon.deployed(); - tieredFixedBountyBeacon = await BountyBeacon.deploy(tieredFixedBountyV1.address); await tieredFixedBountyBeacon.deployed(); @@ -166,8 +143,6 @@ describe('ClaimManager.sol', () => { bountyFactory = await BountyFactory.deploy( openQProxy.address, atomicBountyBeacon.address, - ongoingBountyBeacon.address, - tieredPercentageBountyBeacon.address, tieredFixedBountyBeacon.address ); await bountyFactory.deployed(); @@ -198,10 +173,6 @@ describe('ClaimManager.sol', () => { abiCoder = new ethers.utils.AbiCoder; atomicBountyInitOperation = atomicBountyInitOperation_fundingGoal(mockLink.address) - ongoingBountyInitOperation = ongoingBountyInitOperationBuilder(mockLink.address) - - tieredPercentageBountyInitOperation_permissionless = tieredBountyInitOperationBuilder_permissionless(mockLink.address) - tieredPercentageBountyInitOperation_permissioned = tieredBountyInitOperationBuilder(mockLink.address) tieredFixedBountyInitOperation_permissionless = tieredFixedBountyInitOperationBuilder_permissionless(mockLink.address) tieredFixedBountyInitOperation_permissioned = tieredFixedBountyInitOperationBuilder(mockLink.address) @@ -250,46 +221,6 @@ describe('ClaimManager.sol', () => { }); }); - describe('bountyIsClaimable', () => { - describe('ATOMIC', () => { - it('should return TRUE if atomic bounty is open, FALSE if atomic bounty is closed', async () => { - // ARRANGE - await openQProxy.mintBounty(Constants.bountyId, Constants.organization, atomicBountyInitOperation); - const bountyAddress = await openQProxy.bountyIdToAddress(Constants.bountyId); - - // ASSUME - let bountyIsClaimable = await claimManager.bountyIsClaimable(bountyAddress); - expect(bountyIsClaimable).to.equal(true); - - // ACT - await claimManager.connect(oracle).claimBounty(bountyAddress, owner.address, abiEncodedSingleCloserData); - - // ASSERT - bountyIsClaimable = await claimManager.bountyIsClaimable(bountyAddress); - expect(bountyIsClaimable).to.equal(false); - }); - }); - - describe('ONGOING', () => { - it('should return TRUE if ongoing bounty is open, FALSE if ongoing bounty is closed', async () => { - // ARRANCE - await openQProxy.mintBounty(Constants.bountyId, Constants.organization, ongoingBountyInitOperation); - const bountyAddress = await openQProxy.bountyIdToAddress(Constants.bountyId); - - // ASSUME - let bountyIsClaimable = await claimManager.bountyIsClaimable(bountyAddress); - expect(bountyIsClaimable).to.equal(true); - - // ACT - await openQProxy.closeOngoing(Constants.bountyId); - - // ASSERT - bountyIsClaimable = await claimManager.bountyIsClaimable(bountyAddress); - expect(bountyIsClaimable).to.equal(false); - }); - }); - }); - describe('claimBounty', () => { describe('ALL', () => { @@ -505,284 +436,6 @@ describe('ClaimManager.sol', () => { }); }); - describe('ONGOING', () => { - describe('REVERTS', () => { - it('should revert if ongoing bounty is closed', async () => { - // ARRANGE - await openQProxy.mintBounty(Constants.bountyId, Constants.organization, ongoingBountyInitOperation); - const bountyAddress = await openQProxy.bountyIdToAddress(Constants.bountyId); - - await openQProxy.closeOngoing(Constants.bountyId); - - // ACT/ASSERT - await expect(claimManager.connect(oracle).claimBounty(bountyAddress, owner.address, abiEncodedSingleCloserData)).to.be.revertedWith('CONTRACT_IS_NOT_CLAIMABLE'); - }); - }); - - describe('TRANSFER', () => { - it('should transfer payoutAmount from bounty pool to claimant', async () => { - // ARRANGE - const volume = 1000; - const expectedTimestamp = await setNextBlockTimestamp(); - - await openQProxy.mintBounty(Constants.bountyId, Constants.organization, ongoingBountyInitOperation); - - const bountyIsOpen = await openQProxy.bountyIsOpen(Constants.bountyId); - const bountyAddress = await openQProxy.bountyIdToAddress(Constants.bountyId); - - const newBounty = await OngoingBountyV1.attach( - bountyAddress - ); - - await mockLink.approve(bountyAddress, 10000000); - - await depositManager.fundBountyToken(bountyAddress, mockLink.address, volume, 1, Constants.funderUuid); - - // ACT - - await claimManager.connect(oracle).claimBounty(bountyAddress, claimant.address, abiEncodedOngoingCloserData); - - // ASSERT - const newBountyMockTokenBalance = (await mockLink.balanceOf(bountyAddress)).toString(); - expect(newBountyMockTokenBalance).to.equal('900'); - - const newClaimerMockTokenBalance = (await mockLink.balanceOf(claimant.address)).toString(); - expect(newClaimerMockTokenBalance).to.equal('100'); - }); - }); - - describe('EVENTS', () => { - it('should emit a TokenBalanceClaimed event with correct parameters', async () => { - // ARRANGE - await openQProxy.mintBounty(Constants.bountyId, Constants.organization, ongoingBountyInitOperation); - const bountyAddress = await openQProxy.bountyIdToAddress(Constants.bountyId); - - const volume = 1000; - const bounty = OngoingBountyV1.attach(bountyAddress); - const payoutVolume = await bounty.payoutVolume(); - - await mockLink.approve(bountyAddress, 10000000); - await depositManager.fundBountyToken(bountyAddress, mockLink.address, volume, 1, Constants.funderUuid); - - const expectedTimestamp = await setNextBlockTimestamp(); - // ACT - // ASSERT - - await expect(claimManager.connect(oracle).claimBounty(bountyAddress, owner.address, abiEncodedOngoingCloserData)) - .to.emit(claimManager, 'TokenBalanceClaimed') - .withArgs(Constants.bountyId, bountyAddress, Constants.organization, owner.address, expectedTimestamp, mockLink.address, payoutVolume, 1, abiEncodedOngoingCloserData, Constants.VERSION_1); - }); - }); - }); - - describe('TIERED', () => { - describe('REVERTS', () => { - it('should revert if tier is claimed', async () => { - // ARRANGE - await openQProxy.mintBounty(Constants.bountyId, Constants.organization, tieredFixedBountyInitOperation_permissionless); - const bountyAddress = await openQProxy.bountyIdToAddress(Constants.bountyId); - - await mockLink.approve(bountyAddress, 10000000); - await depositManager.fundBountyToken(bountyAddress, mockLink.address, 10000000, 1, Constants.funderUuid); - - await claimManager.connect(oracle).claimBounty(bountyAddress, owner.address, abiEncodedTieredCloserData); - - // ACT/ASSERT - await expect(claimManager.connect(oracle).claimBounty(bountyAddress, owner.address, abiEncodedTieredCloserData)).to.be.revertedWith('TIER_ALREADY_CLAIMED'); - }); - }); - - describe('BOUNTY UPDATES', () => { - it('should close competition if it is the first claimant', async () => { - // ARRANGE - await openQProxy.mintBounty(Constants.bountyId, Constants.organization, tieredPercentageBountyInitOperation_permissionless); - const bountyAddress = await openQProxy.bountyIdToAddress(Constants.bountyId); - const bounty = TieredPercentageBountyV1.attach(bountyAddress); - - // ASSUME - const isOpen = await bounty.status(); - await expect(isOpen).to.equal(0); - - // ACT - await claimManager.connect(oracle).claimBounty(bountyAddress, owner.address, abiEncodedTieredCloserData); - - // ACT/ASSERT - const isClosed = await bounty.status(); - await expect(isClosed).to.equal(1); - }); - }); - - describe('TRANSFER', () => { - it('should transfer all assets from bounty contract to claimant', async () => { - // ARRANGE - const volume = 1000; - await openQProxy.mintBounty(Constants.bountyId, Constants.organization, tieredPercentageBountyInitOperation_permissionless); - - const bountyAddress = await openQProxy.bountyIdToAddress(Constants.bountyId); - - await mockLink.approve(bountyAddress, 10000000); - await mockDai.approve(bountyAddress, 10000000); - - await depositManager.fundBountyToken(bountyAddress, mockLink.address, volume, 1, Constants.funderUuid); - await depositManager.fundBountyToken(bountyAddress, mockDai.address, volume, 1, Constants.funderUuid); - await depositManager.fundBountyToken(bountyAddress, ethers.constants.AddressZero, volume, 1, Constants.funderUuid, { value: volume }); - - // ASSUME - const bountyMockLinkTokenBalance = (await mockLink.balanceOf(bountyAddress)).toString(); - const bountyDaiTokenBalance = (await mockDai.balanceOf(bountyAddress)).toString(); - const bountyProtcolTokenBalance = (await ethers.provider.getBalance(bountyAddress)).toString(); - expect(bountyMockLinkTokenBalance).to.equal('1000'); - expect(bountyDaiTokenBalance).to.equal('1000'); - expect(bountyProtcolTokenBalance).to.equal('1000'); - - const claimantMockTokenBalance = (await mockLink.balanceOf(claimant.address)).toString(); - const claimantFakeTokenBalance = (await mockDai.balanceOf(claimant.address)).toString(); - const claimantProtocolTokenBalance = (await ethers.provider.getBalance(claimant.address)).toString(); - expect(claimantMockTokenBalance).to.equal('0'); - expect(claimantFakeTokenBalance).to.equal('0'); - - // ACT - await claimManager.connect(oracle).claimBounty(bountyAddress, claimant.address, abiEncodedTieredCloserDataFirstPlace); - await claimManager.connect(oracle).claimBounty(bountyAddress, claimantSecondPlace.address, abiEncodedTieredCloserDataSecondPlace); - await claimManager.connect(oracle).claimBounty(bountyAddress, claimantThirdPlace.address, abiEncodedTieredCloserDataThirdPlace); - - // ASSERT - const newBountyMockTokenBalance = (await mockLink.balanceOf(bountyAddress)).toString(); - const newBountyFakeTokenBalance = (await mockDai.balanceOf(bountyAddress)).toString(); - const newBountyProtocolTokenBalance = (await ethers.provider.getBalance(bountyAddress)).toString(); - expect(newBountyMockTokenBalance).to.equal('0'); - expect(newBountyFakeTokenBalance).to.equal('0'); - expect(newBountyProtocolTokenBalance).to.equal('0'); - - const newClaimerMockTokenBalance = (await mockLink.balanceOf(claimant.address)).toString(); - const newClaimerFakeTokenBalance = (await mockDai.balanceOf(claimant.address)).toString(); - const newClaimerProtocolTokenBalance = (await ethers.provider.getBalance(claimant.address)).toString(); - expect(newClaimerMockTokenBalance).to.equal('600'); - expect(newClaimerFakeTokenBalance).to.equal('600'); - - const newClaimerMockTokenBalanceSecondPlace = (await mockLink.balanceOf(claimantSecondPlace.address)).toString(); - const newClaimerFakeTokenBalanceSecondPlace = (await mockDai.balanceOf(claimantSecondPlace.address)).toString(); - const newClaimerProtocolTokenBalanceSecondPlace = (await ethers.provider.getBalance(claimantSecondPlace.address)).toString(); - expect(newClaimerMockTokenBalanceSecondPlace).to.equal('300'); - expect(newClaimerFakeTokenBalanceSecondPlace).to.equal('300'); - - const newClaimerMockTokenBalanceThirdPlace = (await mockLink.balanceOf(claimantThirdPlace.address)).toString(); - const newClaimerFakeTokenBalanceThirdPlace = (await mockDai.balanceOf(claimantThirdPlace.address)).toString(); - const newClaimerProtocolTokenBalanceThirdPlace = (await ethers.provider.getBalance(claimantThirdPlace.address)).toString(); - expect(newClaimerMockTokenBalanceThirdPlace).to.equal('100'); - expect(newClaimerFakeTokenBalanceThirdPlace).to.equal('100'); - }); - - it('should transfer NFT assets with the same tier the claimant won and emit an NFTClaimed event', async () => { - const FIRST_PLACE_NFT = 1; - const SECOND_PLACE_NFT = 2; - - // ASSUME - expect(await mockNft.ownerOf(FIRST_PLACE_NFT)).to.equal(owner.address); - expect(await mockNft.ownerOf(SECOND_PLACE_NFT)).to.equal(owner.address); - - // ARRANGE - await openQProxy.mintBounty(Constants.bountyId, Constants.organization, tieredPercentageBountyInitOperation_permissionless); - const bountyAddress = await openQProxy.bountyIdToAddress(Constants.bountyId); - - // Fund with NFTs for 2nd and 3rd place - await mockNft.approve(bountyAddress, FIRST_PLACE_NFT); - await mockNft.approve(bountyAddress, SECOND_PLACE_NFT); - - await depositManager.fundBountyNFT(bountyAddress, mockNft.address, FIRST_PLACE_NFT, 1, zeroTier); - await depositManager.fundBountyNFT(bountyAddress, mockNft.address, SECOND_PLACE_NFT, 1, oneTier); - - let expectedTimestamp = await setNextBlockTimestamp(); - - // ACT - await expect(claimManager.connect(oracle).claimBounty(bountyAddress, claimant.address, abiEncodedTieredCloserDataFirstPlace)) - .to.emit(claimManager, 'NFTClaimed') - .withArgs(Constants.bountyId, bountyAddress, Constants.organization, claimant.address, expectedTimestamp, mockNft.address, 1, 2, abiEncodedTieredCloserDataFirstPlace, Constants.VERSION_1); - - - expectedTimestamp = await setNextBlockTimestamp(); - await expect(claimManager.connect(oracle).claimBounty(bountyAddress, claimantSecondPlace.address, abiEncodedTieredCloserDataSecondPlace)) - .to.emit(claimManager, 'NFTClaimed') - .withArgs(Constants.bountyId, bountyAddress, Constants.organization, claimantSecondPlace.address, expectedTimestamp, mockNft.address, 2, 2, abiEncodedTieredCloserDataSecondPlace, Constants.VERSION_1); - - // ASSERT - expect(await mockNft.ownerOf(FIRST_PLACE_NFT)).to.equal(claimant.address); - expect(await mockNft.ownerOf(SECOND_PLACE_NFT)).to.equal(claimantSecondPlace.address); - }); - }); - - describe('EVENTS', () => { - it('should emit a BountyClosed event with correct parameters', async () => { - // ARRANGE - await openQProxy.mintBounty(Constants.bountyId, Constants.organization, tieredPercentageBountyInitOperation_permissionless); - const bountyAddress = await openQProxy.bountyIdToAddress(Constants.bountyId); - - const volume = 1000; - const bounty = TieredPercentageBountyV1.attach(bountyAddress); - const payoutSchedule = await bounty.getPayoutSchedule(); - const proportion = payoutSchedule[1].toString(); - const payoutAmount = (proportion / 100) * volume; - - await mockLink.approve(bountyAddress, 10000000); - await mockDai.approve(bountyAddress, 10000000); - await depositManager.fundBountyToken(bountyAddress, mockLink.address, volume, 1, Constants.funderUuid); - await depositManager.fundBountyToken(bountyAddress, mockDai.address, volume, 1, Constants.funderUuid); - - const expectedTimestamp = await setNextBlockTimestamp(); - // ACT - // ASSERT - - await expect(claimManager.connect(oracle).claimBounty(bountyAddress, owner.address, abiEncodedTieredCloserData)) - .to.emit(claimManager, 'BountyClosed') - .withArgs(Constants.bountyId, bountyAddress, Constants.organization, ethers.constants.AddressZero, expectedTimestamp, 2, '0x', Constants.VERSION_1); - }); - - it('should emit a TokenBalanceClaimed event with correct parameters', async () => { - // ARRANGE - await openQProxy.mintBounty(Constants.bountyId, Constants.organization, tieredPercentageBountyInitOperation_permissionless); - const bountyAddress = await openQProxy.bountyIdToAddress(Constants.bountyId); - - const volume = 1000; - const bounty = TieredPercentageBountyV1.attach(bountyAddress); - const payoutSchedule = await bounty.getPayoutSchedule(); - const proportion = payoutSchedule[1].toString(); - const payoutAmount = (proportion / 100) * volume; - - await mockLink.approve(bountyAddress, 10000000); - await mockDai.approve(bountyAddress, 10000000); - await depositManager.fundBountyToken(bountyAddress, mockLink.address, volume, 1, Constants.funderUuid); - await depositManager.fundBountyToken(bountyAddress, mockDai.address, volume, 1, Constants.funderUuid); - - const expectedTimestamp = await setNextBlockTimestamp(); - // ACT - // ASSERT - - await expect(claimManager.connect(oracle).claimBounty(bountyAddress, owner.address, abiEncodedTieredCloserData)) - .to.emit(claimManager, 'TokenBalanceClaimed') - .withArgs(Constants.bountyId, bountyAddress, Constants.organization, owner.address, expectedTimestamp, mockLink.address, payoutAmount, 2, abiEncodedTieredCloserData, Constants.VERSION_1) - .withArgs(Constants.bountyId, bountyAddress, Constants.organization, owner.address, expectedTimestamp, mockDai.address, payoutAmount, 2, abiEncodedTieredCloserData, Constants.VERSION_1); - }); - - it('should emit an NftClaimed event with correct parameters', async () => { - // ARRANGE - await openQProxy.mintBounty(Constants.bountyId, Constants.organization, tieredPercentageBountyInitOperation_permissionless); - const bountyAddress = await openQProxy.bountyIdToAddress(Constants.bountyId); - - await mockNft.approve(bountyAddress, 1); - - await depositManager.fundBountyNFT(bountyAddress, mockNft.address, 1, 1, zeroTier); - - const expectedTimestamp = await setNextBlockTimestamp(); - - // ACT/ASSERT - - await expect(claimManager.connect(oracle).claimBounty(bountyAddress, owner.address, abiEncodedTieredCloserDataFirstPlace)) - .to.emit(claimManager, 'NFTClaimed') - .withArgs(Constants.bountyId, bountyAddress, Constants.organization, owner.address, expectedTimestamp, mockNft.address, 1, 2, abiEncodedTieredCloserDataFirstPlace, Constants.VERSION_1); - }); - }); - }); - describe('TIERED FIXED', () => { describe('REVERTS', () => { it('should revert if tier is already claimed', async () => { @@ -800,40 +453,6 @@ describe('ClaimManager.sol', () => { }); }); - describe('TRANSFER', () => { - it('should transfer NFT assets with tier corresponding to the tier the claimant won', async () => { - const FIRST_PLACE_NFT = 1; - const SECOND_PLACE_NFT = 2; - - // ASSUME - expect(await mockNft.ownerOf(FIRST_PLACE_NFT)).to.equal(owner.address); - expect(await mockNft.ownerOf(SECOND_PLACE_NFT)).to.equal(owner.address); - - // ARRANGE - await openQProxy.mintBounty(Constants.bountyId, Constants.organization, tieredPercentageBountyInitOperation_permissionless); - const bountyAddress = await openQProxy.bountyIdToAddress(Constants.bountyId); - - // Fund with NFTs for 2nd and 3rd place - await mockNft.approve(bountyAddress, FIRST_PLACE_NFT); - await mockNft.approve(bountyAddress, SECOND_PLACE_NFT); - await depositManager.fundBountyNFT(bountyAddress, mockNft.address, FIRST_PLACE_NFT, 1, zeroTier); - await depositManager.fundBountyNFT(bountyAddress, mockNft.address, SECOND_PLACE_NFT, 1, oneTier); - - // Closer data for 2nd and 3rd place - let abiEncodedTieredCloserDataFirstPlace = abiCoder.encode(['address', 'string', 'address', 'string', 'uint256'], [owner.address, "FlacoJones", owner.address, "https://github.com/OpenQDev/OpenQ-Frontend/pull/398", 0]); - let abiEncodedTieredCloserDataSecondPlace = abiCoder.encode(['address', 'string', 'address', 'string', 'uint256'], [owner.address, "FlacoJones", owner.address, "https://github.com/OpenQDev/OpenQ-Frontend/pull/398", 1]); - - // ACT - - await claimManager.connect(oracle).claimBounty(bountyAddress, claimant.address, abiEncodedTieredCloserDataFirstPlace); - await claimManager.connect(oracle).claimBounty(bountyAddress, claimantSecondPlace.address, abiEncodedTieredCloserDataSecondPlace); - - // ASSERT - expect(await mockNft.ownerOf(FIRST_PLACE_NFT)).to.equal(claimant.address); - expect(await mockNft.ownerOf(SECOND_PLACE_NFT)).to.equal(claimantSecondPlace.address); - }); - }); - describe('EVENTS', () => { it('should emit BountyClosed event', async () => { // ARRANGE @@ -882,9 +501,9 @@ describe('ClaimManager.sol', () => { describe('tierClaimed', () => { it('should return FALSE if tier not claimed, TRUE if already claimed', async () => { // ARRANGE - await openQProxy.mintBounty(Constants.bountyId, Constants.organization, tieredPercentageBountyInitOperation_permissionless); + await openQProxy.mintBounty(Constants.bountyId, Constants.organization, tieredFixedBountyInitOperation_permissionless); const bountyAddress = await openQProxy.bountyIdToAddress(Constants.bountyId); - const bounty = await TieredPercentageBountyV1.attach(bountyAddress); + const bounty = await TieredFixedBountyV1.attach(bountyAddress); await mockLink.approve(bountyAddress, 10000000); await depositManager.fundBountyToken(bountyAddress, mockLink.address, 10000000, 1, Constants.funderUuid); @@ -896,35 +515,9 @@ describe('ClaimManager.sol', () => { // ACT await claimManager.connect(oracle).claimBounty(bountyAddress, owner.address, abiEncodedTieredCloserData); - // // ASSERT - // tierClaimed = await openQProxy.tierClaimed(Constants.bountyId, 1); - // expect(tierClaimed).to.equal(true); - }); - }); - - describe('ongoingClaimed', () => { - it('should return FALSE if ongoing claimant is not claimed, TRUE if it is claimed', async () => { - // ARRANGE - await openQProxy.mintBounty(Constants.bountyId, Constants.organization, ongoingBountyInitOperation); - const bountyAddress = await openQProxy.bountyIdToAddress(Constants.bountyId); - const bounty = await OngoingBountyV1.attach(bountyAddress); - - await mockLink.approve(bountyAddress, 10000000); - await depositManager.fundBountyToken(bountyAddress, mockLink.address, 10000000, 1, Constants.funderUuid); - - let claimId = generateClaimantId('FlacoJones', "https://github.com/OpenQDev/OpenQ-Frontend/pull/398"); - - // ASSUME - let ongoingClaimed = await bounty.claimId(claimId); - expect(ongoingClaimed).to.equal(false); - - // ACT - - await claimManager.connect(oracle).claimBounty(bountyAddress, owner.address, abiEncodedOngoingCloserData); - - // // ASSERT - ongoingClaimed = await bounty.claimId(claimId); - expect(ongoingClaimed).to.equal(true); + // // // ASSERT + tierClaimed = await openQProxy.tierClaimed(Constants.bountyId, 1); + expect(tierClaimed).to.equal(true); }); }); @@ -947,7 +540,7 @@ describe('ClaimManager.sol', () => { it('should revert if caller lacks associated address to their uuid', async () => { // ARRANGE - await openQProxy.mintBounty(Constants.bountyId, Constants.organization, tieredPercentageBountyInitOperation_permissioned); + await openQProxy.mintBounty(Constants.bountyId, Constants.organization, tieredFixedBountyInitOperation_permissioned); const bountyAddress = await openQProxy.bountyIdToAddress(Constants.bountyId); // ASSERT @@ -956,7 +549,7 @@ describe('ClaimManager.sol', () => { it('should revert if claimant not tier winner', async () => { // ARRANGE - await openQProxy.mintBounty(Constants.bountyId, Constants.organization, tieredPercentageBountyInitOperation_permissioned); + await openQProxy.mintBounty(Constants.bountyId, Constants.organization, tieredFixedBountyInitOperation_permissioned); const bountyAddress = await openQProxy.bountyIdToAddress(Constants.bountyId); await openQProxy.connect(oracle).associateExternalIdToAddress(Constants.mockOpenQId, owner.address) @@ -967,7 +560,7 @@ describe('ClaimManager.sol', () => { it('should revert if caller lacks invoice', async () => { // ARRANGE - await openQProxy.mintBounty(Constants.bountyId, Constants.organization, tieredPercentageBountyInitOperation_permissioned); + await openQProxy.mintBounty(Constants.bountyId, Constants.organization, tieredFixedBountyInitOperation_permissioned); const bountyAddress = await openQProxy.bountyIdToAddress(Constants.bountyId); await mockKyc.setIsValid(true) @@ -979,7 +572,7 @@ describe('ClaimManager.sol', () => { it('should revert if caller lacks supporting documents', async () => { // ARRANGE - await openQProxy.mintBounty(Constants.bountyId, Constants.organization, tieredPercentageBountyInitOperation_permissioned); + await openQProxy.mintBounty(Constants.bountyId, Constants.organization, tieredFixedBountyInitOperation_permissioned); const bountyAddress = await openQProxy.bountyIdToAddress(Constants.bountyId); // Set Permissions @@ -993,7 +586,7 @@ describe('ClaimManager.sol', () => { it('should revert if caller is lacks KYC', async () => { // ARRANGE - await openQProxy.mintBounty(Constants.bountyId, Constants.organization, tieredPercentageBountyInitOperation_permissioned); + await openQProxy.mintBounty(Constants.bountyId, Constants.organization, tieredFixedBountyInitOperation_permissioned); const bountyAddress = await openQProxy.bountyIdToAddress(Constants.bountyId); await openQProxy.connect(oracle).associateExternalIdToAddress(Constants.mockOpenQId, owner.address) @@ -1005,64 +598,9 @@ describe('ClaimManager.sol', () => { await expect(claimManager.permissionedClaimTieredBounty(bountyAddress, abiEncodedTieredCloserDataFirstPlace)).to.be.revertedWith('ADDRESS_LACKS_KYC'); }); - it('should transfer tier to closer - TIERED', async () => { - // ARRANGE - await openQProxy.mintBounty(Constants.bountyId, Constants.organization, tieredPercentageBountyInitOperation_permissioned); - const bountyAddress = await openQProxy.bountyIdToAddress(Constants.bountyId); - const expectedTimestamp = await setNextBlockTimestamp(); - const volume = 100; - - const bounty = await TieredPercentageBountyV1.attach(bountyAddress); - - // ACT - await mockLink.approve(bountyAddress, 10000000); - await mockDai.approve(bountyAddress, 10000000); - - await depositManager.fundBountyToken(bountyAddress, mockLink.address, volume, 1, Constants.funderUuid); - await depositManager.fundBountyToken(bountyAddress, mockDai.address, volume, 1, Constants.funderUuid); - await depositManager.fundBountyToken(bountyAddress, ethers.constants.AddressZero, volume, 1, Constants.funderUuid, { value: volume }); - - // ASSUME - const bountyMockLinkTokenBalance = (await mockLink.balanceOf(bountyAddress)).toString(); - const bountyDaiTokenBalance = (await mockDai.balanceOf(bountyAddress)).toString(); - const bountyProtcolTokenBalance = (await ethers.provider.getBalance(bountyAddress)).toString(); - expect(bountyMockLinkTokenBalance).to.equal('100'); - expect(bountyDaiTokenBalance).to.equal('100'); - expect(bountyProtcolTokenBalance).to.equal('100'); - - const claimantMockTokenBalance = (await mockLink.balanceOf(claimant.address)).toString(); - const claimantFakeTokenBalance = (await mockDai.balanceOf(claimant.address)).toString(); - expect(claimantMockTokenBalance).to.equal('0'); - expect(claimantFakeTokenBalance).to.equal('0'); - - // ARRANGE - // Set Permissions - await mockKyc.setIsValid(true) - await openQProxy.connect(oracle).associateExternalIdToAddress(Constants.mockOpenQId, claimant.address) - await openQProxy.setTierWinner(Constants.bountyId, 0, Constants.mockOpenQId) - await openQProxy.setInvoiceComplete(Constants.bountyId, setInvoiceCompleteData_tiered(0, true)) - await openQProxy.setSupportingDocumentsComplete(Constants.bountyId, setSupportingDocumentsComplete_tiered(0, true)) - - // ACT - await claimManager.connect(claimant).permissionedClaimTieredBounty(bountyAddress, abiEncodedTieredCloserDataFirstPlace); - - // ASSERT - const newBountyMockTokenBalance = (await mockLink.balanceOf(bountyAddress)).toString(); - const newBountyFakeTokenBalance = (await mockDai.balanceOf(bountyAddress)).toString(); - const newBountyProtocolTokenBalance = (await ethers.provider.getBalance(bountyAddress)).toString(); - expect(newBountyMockTokenBalance).to.equal('40'); - expect(newBountyFakeTokenBalance).to.equal('40'); - expect(newBountyProtocolTokenBalance).to.equal('40'); - - const newClaimerMockTokenBalance = (await mockLink.balanceOf(claimant.address)).toString(); - const newClaimerFakeTokenBalance = (await mockDai.balanceOf(claimant.address)).toString(); - expect(newClaimerMockTokenBalance).to.equal('60'); - expect(newClaimerFakeTokenBalance).to.equal('60'); - }); - it('should transfer tier to closer - TIERED FIXED', async () => { // ARRANGE - await openQProxy.mintBounty(Constants.bountyId, Constants.organization, tieredPercentageBountyInitOperation_permissioned); + await openQProxy.mintBounty(Constants.bountyId, Constants.organization, tieredFixedBountyInitOperation_permissioned); const bountyAddress = await openQProxy.bountyIdToAddress(Constants.bountyId); const expectedTimestamp = await setNextBlockTimestamp(); const volume = 100; @@ -1095,10 +633,10 @@ describe('ClaimManager.sol', () => { // ASSERT const newBountyMockTokenBalance = (await mockLink.balanceOf(bountyAddress)).toString(); - expect(newBountyMockTokenBalance).to.equal('40'); + expect(newBountyMockTokenBalance).to.equal('20'); const newClaimerMockTokenBalance = (await mockLink.balanceOf(claimant.address)).toString(); - expect(newClaimerMockTokenBalance).to.equal('60'); + expect(newClaimerMockTokenBalance).to.equal('80'); }); }) diff --git a/test/constants.js b/test/constants.js index 8ad7df77..cd09f41f 100755 --- a/test/constants.js +++ b/test/constants.js @@ -115,8 +115,8 @@ const tieredFixedBountyInitOperationBuilder_permissionless = (tokenAddress) => { ['uint256[]','address','bool','bool','bool','string','string','string'], [[80, 20],tokenAddress,false,false,false,Constants.mockOpenQId,Constants.alternativeName,Constants.alternativeLogo] ); - const tieredPercentageBountyInitOperationComplete = [Constants.TIERED_FIXED_CONTRACT, abiEncodedParamsTieredFixedBounty]; - return tieredPercentageBountyInitOperationComplete; + const tieredFixedBountyInitOperationComplete = [Constants.TIERED_FIXED_CONTRACT, abiEncodedParamsTieredFixedBounty]; + return tieredFixedBountyInitOperationComplete; }; const setInvoiceCompleteData_tiered = (tier, invoiceComplete) => { From 9c56e95a6fb81fd10d3ad33516311882d839d73b Mon Sep 17 00:00:00 2001 From: FlacoJones Date: Sat, 25 Feb 2023 14:49:39 -0700 Subject: [PATCH 4/7] updates DepositManager test to run without Ongoing or TieredPercentage bounty types --- .../Implementations/DepositManagerV1.sol | 1 + test/ClaimManager.test.js | 2 +- test/DepositManager.test.js | 40 +++---------------- 3 files changed, 7 insertions(+), 36 deletions(-) diff --git a/contracts/DepositManager/Implementations/DepositManagerV1.sol b/contracts/DepositManager/Implementations/DepositManagerV1.sol index 21710a6d..93186254 100755 --- a/contracts/DepositManager/Implementations/DepositManagerV1.sol +++ b/contracts/DepositManager/Implementations/DepositManagerV1.sol @@ -2,6 +2,7 @@ pragma solidity 0.8.17; import '../Storage/DepositManagerStorage.sol'; +import 'hardhat/console.sol'; /// @title DepositManagerV1 /// @author FlacoJones diff --git a/test/ClaimManager.test.js b/test/ClaimManager.test.js index c11c91c8..37984ef3 100755 --- a/test/ClaimManager.test.js +++ b/test/ClaimManager.test.js @@ -20,7 +20,7 @@ const { tieredFixedBountyInitOperationBuilder_permissionless } = require('./constants'); -describe.only('ClaimManager.sol', () => { +describe('ClaimManager.sol', () => { // MOCK ASSETS let openQProxy; let openQImplementation; diff --git a/test/DepositManager.test.js b/test/DepositManager.test.js index 00338d3b..1dd863fd 100755 --- a/test/DepositManager.test.js +++ b/test/DepositManager.test.js @@ -12,14 +12,10 @@ const { atomicBountyInitOperation_fundingGoal, atomicBountyInitOperation_noFundingGoal, atomicBountyInitOperation_permissioned, - ongoingBountyInitOperationBuilder, - tieredBountyInitOperationBuilder, - tieredFixedBountyInitOperationBuilder, - tieredBountyInitOperation_not100, - tieredBountyInitOperationBuilder_permissionless + tieredFixedBountyInitOperationBuilder_permissionless } = require('./constants'); -describe('DepositManager.sol', () => { +describe.only('DepositManager.sol', () => { // MOCK ASSETS let openQProxy; let openQImplementation; @@ -43,21 +39,15 @@ describe('DepositManager.sol', () => { // INIT OPERATIONS let atomicBountyInitOperation; - let ongoingBountyInitOperation; - let tieredPercentageBountyInitOperation; - let tieredPercentageBountyInitOperation_permissionless; let tieredFixedBountyInitOperation; // CLOSER DATA let abiCoder; let abiEncodedSingleCloserData; - let abiEncodedOngoingCloserData; let abiEncodedTieredCloserData; let AtomicBountyV1 - let OngoingBountyV1 - let TieredPercentageBountyV1 let TieredFixedBountyV1 beforeEach(async () => { @@ -71,20 +61,12 @@ describe('DepositManager.sol', () => { const ClaimManager = await ethers.getContractFactory('ClaimManagerV1'); AtomicBountyV1 = await ethers.getContractFactory('AtomicBountyV1'); - OngoingBountyV1 = await ethers.getContractFactory('OngoingBountyV1'); - TieredPercentageBountyV1 = await ethers.getContractFactory('TieredPercentageBountyV1'); TieredFixedBountyV1 = await ethers.getContractFactory('TieredFixedBountyV1'); // BOUNTY IMPLEMENTATIONS atomicBountyV1 = await AtomicBountyV1.deploy(); await atomicBountyV1.deployed(); - ongoingBountyV1 = await OngoingBountyV1.deploy(); - await ongoingBountyV1.deployed(); - - tieredPercentageBountyV1 = await TieredPercentageBountyV1.deploy(); - await tieredPercentageBountyV1.deployed(); - tieredFixedBountyV1 = await TieredFixedBountyV1.deploy(); await tieredFixedBountyV1.deployed(); @@ -133,12 +115,6 @@ describe('DepositManager.sol', () => { atomicBountyBeacon = await BountyBeacon.deploy(atomicBountyV1.address); await atomicBountyBeacon.deployed(); - ongoingBountyBeacon = await BountyBeacon.deploy(ongoingBountyV1.address); - await ongoingBountyBeacon.deployed(); - - tieredPercentageBountyBeacon = await BountyBeacon.deploy(tieredPercentageBountyV1.address); - await tieredPercentageBountyBeacon.deployed(); - tieredFixedBountyBeacon = await BountyBeacon.deploy(tieredFixedBountyV1.address); await tieredFixedBountyBeacon.deployed(); @@ -146,8 +122,6 @@ describe('DepositManager.sol', () => { bountyFactory = await BountyFactory.deploy( openQProxy.address, atomicBountyBeacon.address, - ongoingBountyBeacon.address, - tieredPercentageBountyBeacon.address, tieredFixedBountyBeacon.address ); await bountyFactory.deployed(); @@ -180,13 +154,9 @@ describe('DepositManager.sol', () => { funderUuidEncoded = abiCoder.encode(["string"], [Constants.funderUuid]); atomicBountyInitOperation = atomicBountyInitOperation_fundingGoal(mockLink.address) - ongoingBountyInitOperation = ongoingBountyInitOperationBuilder(mockLink.address) - tieredPercentageBountyInitOperation = tieredBountyInitOperationBuilder(mockLink.address) - tieredFixedBountyInitOperation = tieredFixedBountyInitOperationBuilder(mockLink.address) - tieredPercentageBountyInitOperation_permissionless = tieredBountyInitOperationBuilder_permissionless(mockLink.address) + tieredFixedBountyInitOperation = tieredFixedBountyInitOperationBuilder_permissionless(mockLink.address) abiEncodedSingleCloserData = abiCoder.encode(['address', 'string', 'address', 'string'], [owner.address, "FlacoJones", owner.address, "https://github.com/OpenQDev/OpenQ-Frontend/pull/398"]); - abiEncodedOngoingCloserData = abiCoder.encode(['address', 'string', 'address', 'string'], [owner.address, "FlacoJones", owner.address, "https://github.com/OpenQDev/OpenQ-Frontend/pull/398"]); abiEncodedTieredCloserData = abiCoder.encode(['address', 'string', 'address', 'string', 'uint256'], [owner.address, "FlacoJones", owner.address, "https://github.com/OpenQDev/OpenQ-Frontend/pull/398", 1]); }); @@ -247,9 +217,9 @@ describe('DepositManager.sol', () => { await expect(depositManager.fundBountyToken(bountyAddress, mockLink.address, 10000000, 1, Constants.funderUuid)).to.be.revertedWith('CONTRACT_ALREADY_CLOSED'); }); - it('should revert if tiered bounty is already closed', async () => { + it.only('should revert if tiered bounty is already closed', async () => { // ARRANGE - await openQProxy.mintBounty(Constants.bountyId, Constants.organization, tieredPercentageBountyInitOperation_permissionless); + await openQProxy.mintBounty(Constants.bountyId, Constants.organization, tieredFixedBountyInitOperation); const bountyAddress = await openQProxy.bountyIdToAddress(Constants.bountyId); await claimManager.connect(oracle).claimBounty(bountyAddress, owner.address, abiEncodedTieredCloserData); From 71ed979f00fb18d0a98df4bf9bccc6901479b714 Mon Sep 17 00:00:00 2001 From: FlacoJones Date: Sat, 25 Feb 2023 14:55:41 -0700 Subject: [PATCH 5/7] updates OpenQ test to pass without Ongoing or TieredPercentage bounty types --- test/DepositManager.test.js | 4 +- test/OpenQ.test.js | 543 +----------------------------------- 2 files changed, 8 insertions(+), 539 deletions(-) diff --git a/test/DepositManager.test.js b/test/DepositManager.test.js index 1dd863fd..02e38d07 100755 --- a/test/DepositManager.test.js +++ b/test/DepositManager.test.js @@ -15,7 +15,7 @@ const { tieredFixedBountyInitOperationBuilder_permissionless } = require('./constants'); -describe.only('DepositManager.sol', () => { +describe('DepositManager.sol', () => { // MOCK ASSETS let openQProxy; let openQImplementation; @@ -217,7 +217,7 @@ describe.only('DepositManager.sol', () => { await expect(depositManager.fundBountyToken(bountyAddress, mockLink.address, 10000000, 1, Constants.funderUuid)).to.be.revertedWith('CONTRACT_ALREADY_CLOSED'); }); - it.only('should revert if tiered bounty is already closed', async () => { + it('should revert if tiered bounty is already closed', async () => { // ARRANGE await openQProxy.mintBounty(Constants.bountyId, Constants.organization, tieredFixedBountyInitOperation); const bountyAddress = await openQProxy.bountyIdToAddress(Constants.bountyId); diff --git a/test/OpenQ.test.js b/test/OpenQ.test.js index 77539439..44f95e5d 100755 --- a/test/OpenQ.test.js +++ b/test/OpenQ.test.js @@ -12,11 +12,8 @@ const { atomicBountyInitOperation_fundingGoal, atomicBountyInitOperation_noFundingGoal, atomicBountyInitOperation_permissioned, - ongoingBountyInitOperationBuilder, - tieredBountyInitOperationBuilder, tieredFixedBountyInitOperationBuilder, - tieredBountyInitOperation_not100, - tieredBountyInitOperationBuilder_permissionless + tieredFixedBountyInitOperationBuilder_permissionless, } = require('./constants'); describe('OpenQ.sol', () => { @@ -40,10 +37,6 @@ describe('OpenQ.sol', () => { // INIT OPERATIONS let atomicBountyInitOperation let atomicBountyInitOperationPermissioned - let ongoingBountyInitOperation - let tieredBountyInitOperation - let tieredBountyInitOperation_permissionless - let tieredBountyInitOperationNot100 let tieredFixedBountyInitOperation // CLOSER DATA @@ -51,12 +44,9 @@ describe('OpenQ.sol', () => { let abiEncodedSingleCloserData let abiEncodedOngoingCloserData - let abiEncodedTieredCloserData let abiEncodedTieredFixedCloserData let AtomicBountyV1 - let OngoingBountyV1 - let TieredPercentageBountyV1 let TieredFixedBountyV1 beforeEach(async () => { @@ -72,22 +62,12 @@ describe('OpenQ.sol', () => { const ClaimManager = await ethers.getContractFactory('ClaimManagerV1') AtomicBountyV1 = await ethers.getContractFactory('AtomicBountyV1') - OngoingBountyV1 = await ethers.getContractFactory('OngoingBountyV1') - TieredPercentageBountyV1 = await ethers.getContractFactory( - 'TieredPercentageBountyV1' - ) TieredFixedBountyV1 = await ethers.getContractFactory('TieredFixedBountyV1') // BOUNTY IMPLEMENTATIONS atomicBountyV1 = await AtomicBountyV1.deploy() await atomicBountyV1.deployed() - ongoingBountyV1 = await OngoingBountyV1.deploy() - await ongoingBountyV1.deployed() - - tieredPercentageBountyV1 = await TieredPercentageBountyV1.deploy() - await tieredPercentageBountyV1.deployed() - tieredFixedBountyV1 = await TieredFixedBountyV1.deploy() await tieredFixedBountyV1.deployed() @@ -164,14 +144,6 @@ describe('OpenQ.sol', () => { atomicBountyBeacon = await BountyBeacon.deploy(atomicBountyV1.address) await atomicBountyBeacon.deployed() - ongoingBountyBeacon = await BountyBeacon.deploy(ongoingBountyV1.address) - await ongoingBountyBeacon.deployed() - - tieredPercentageBountyBeacon = await BountyBeacon.deploy( - tieredPercentageBountyV1.address - ) - await tieredPercentageBountyBeacon.deployed() - tieredFixedBountyBeacon = await BountyBeacon.deploy( tieredFixedBountyV1.address ) @@ -181,8 +153,6 @@ describe('OpenQ.sol', () => { bountyFactory = await BountyFactory.deploy( openQProxy.address, atomicBountyBeacon.address, - ongoingBountyBeacon.address, - tieredPercentageBountyBeacon.address, tieredFixedBountyBeacon.address ) await bountyFactory.deployed() @@ -196,11 +166,8 @@ describe('OpenQ.sol', () => { abiCoder = new ethers.utils.AbiCoder() atomicBountyInitOperation = atomicBountyInitOperation_fundingGoal(mockLink.address) - ongoingBountyInitOperation = ongoingBountyInitOperationBuilder(mockLink.address) - tieredBountyInitOperation = tieredBountyInitOperationBuilder(mockLink.address) - tieredBountyInitOperationNot100 = tieredBountyInitOperation_not100(mockLink.address) tieredFixedBountyInitOperation = tieredFixedBountyInitOperationBuilder(mockLink.address) - tieredBountyInitOperation_permissionless = tieredBountyInitOperationBuilder_permissionless(mockLink.address) + tieredFixedBountyInitOperation_permissionless = tieredFixedBountyInitOperationBuilder_permissionless(mockLink.address) abiEncodedSingleCloserData = abiCoder.encode( ['address', 'string', 'address', 'string'], @@ -211,25 +178,7 @@ describe('OpenQ.sol', () => { 'https://github.com/OpenQDev/OpenQ-Frontend/pull/398', ] ) - abiEncodedOngoingCloserData = abiCoder.encode( - ['address', 'string', 'address', 'string'], - [ - owner.address, - 'FlacoJones', - owner.address, - 'https://github.com/OpenQDev/OpenQ-Frontend/pull/398', - ] - ) - abiEncodedTieredCloserData = abiCoder.encode( - ['address', 'string', 'address', 'string', 'uint256'], - [ - owner.address, - 'FlacoJones', - owner.address, - 'https://github.com/OpenQDev/OpenQ-Frontend/pull/398', - 1, - ] - ) + abiEncodedTieredFixedCloserData = abiCoder.encode( ['address', 'string', 'address', 'string', 'uint256'], [ @@ -376,97 +325,6 @@ describe('OpenQ.sol', () => { }) }) - describe('ONGOING', () => { - it('should deploy a new bounty contract with expected initial metadata', async () => { - // ACT - let initializationTimestamp = await setNextBlockTimestamp() - await openQProxy.mintBounty( - Constants.bountyId, - Constants.organization, - ongoingBountyInitOperation - ) - - const bountyIsOpen = await openQProxy.bountyIsOpen(Constants.bountyId) - - const bountyAddress = await openQProxy.bountyIdToAddress(Constants.bountyId) - const ongoingContract = await OngoingBountyV1.attach(bountyAddress) - - await expect(await ongoingContract.bountyId()).equals(Constants.bountyId) - await expect(await ongoingContract.issuer()).equals(owner.address) - await expect(await ongoingContract.organization()).equals(Constants.organization) - await expect(await ongoingContract.status()).equals(0) - await expect(await ongoingContract.openQ()).equals(openQProxy.address) - await expect(await ongoingContract.claimManager()).equals(claimManager.address) - await expect(await ongoingContract.depositManager()).equals(depositManager.address) - await expect(await ongoingContract.bountyCreatedTime()).equals(initializationTimestamp) - await expect(await ongoingContract.bountyType()).equals(Constants.ONGOING_CONTRACT) - await expect(await ongoingContract.hasFundingGoal()).equals(true) - await expect(await ongoingContract.fundingToken()).equals(mockLink.address) - await expect(await ongoingContract.payoutTokenAddress()).equals(mockLink.address) - await expect(await ongoingContract.payoutVolume()).equals(Constants.volume) - await expect(await ongoingContract.fundingGoal()).equals(Constants.volume) - await expect(await ongoingContract.issuerExternalUserId()).equals(Constants.mockOpenQId) - await expect(await ongoingContract.invoiceRequired()).equals(false) - await expect(await ongoingContract.kycRequired()).equals(false) - await expect(await ongoingContract.supportingDocumentsRequired()).equals(false) - }) - }) - - describe('TIERED', () => { - it('should correctly init bountyType and payout schedule', async () => { - // ARRANGE - let initializationTimestamp = await setNextBlockTimestamp() - - // ACT - await openQProxy.mintBounty( - Constants.bountyId, - Constants.organization, - tieredBountyInitOperation - ) - - const bountyIsOpen = await openQProxy.bountyIsOpen(Constants.bountyId) - const bountyAddress = await openQProxy.bountyIdToAddress(Constants.bountyId) - - const tieredPercentageContract = await TieredPercentageBountyV1.attach(bountyAddress) - - const actualBountyPayoutSchedule = await tieredPercentageContract.getPayoutSchedule() - const payoutToString = actualBountyPayoutSchedule.map((thing) => thing.toString()) - - await expect(await tieredPercentageContract.bountyId()).equals(Constants.bountyId) - await expect(await tieredPercentageContract.issuer()).equals(owner.address) - await expect(await tieredPercentageContract.organization()).equals(Constants.organization) - await expect(await tieredPercentageContract.status()).equals(0) - await expect(await tieredPercentageContract.openQ()).equals(openQProxy.address) - await expect(await tieredPercentageContract.claimManager()).equals(claimManager.address) - await expect(await tieredPercentageContract.depositManager()).equals(depositManager.address) - await expect(await tieredPercentageContract.bountyCreatedTime()).equals(initializationTimestamp) - await expect(await tieredPercentageContract.bountyType()).equals(Constants.TIERED_PERCENTAGE_CONTRACT) - await expect(await tieredPercentageContract.hasFundingGoal()).equals(true) - await expect(await tieredPercentageContract.fundingToken()).equals(mockLink.address) - await expect(await tieredPercentageContract.fundingGoal()).equals(Constants.volume) - await expect(payoutToString[0]).equals('60') - await expect(payoutToString[1]).equals('30') - await expect(await tieredPercentageContract.issuerExternalUserId()).equals(Constants.mockOpenQId) - - await expect(await tieredPercentageContract.supportingDocumentsRequired()).equals(true) - await expect(await tieredPercentageContract.invoiceRequired()).equals(true) - await expect(await tieredPercentageContract.kycRequired()).equals(true) - - await expect(await tieredPercentageContract.invoiceComplete(0)).equals(false) - await expect(await tieredPercentageContract.supportingDocumentsComplete(0)).equals(false) - }) - - it('should revert if payout schedule does not add to 100', async () => { - await expect( - openQProxy.mintBounty( - Constants.bountyId, - Constants.organization, - tieredBountyInitOperationNot100 - ) - ).to.be.revertedWith('PAYOUT_SCHEDULE_MUST_ADD_TO_100') - }) - }) - describe('TIERED FIXED', () => { it('should correctly init bountyType and payout schedule', async () => { // ARRANGE @@ -511,184 +369,18 @@ describe('OpenQ.sol', () => { }) }) - describe('solvent', () => { - it('should return TRUE for solvent ongoing contracts', async () => { - // ARRANGE - await openQProxy.mintBounty( - Constants.bountyId, - Constants.organization, - ongoingBountyInitOperation - ) - const bountyAddress = await openQProxy.bountyIdToAddress(Constants.bountyId) - const bounty = await OngoingBountyV1.attach(bountyAddress) - - await mockLink.approve(bountyAddress, 10000000) - await depositManager.fundBountyToken( - bountyAddress, - mockLink.address, - 10000000, - 1, - Constants.funderUuid - ) - - const solvent = await openQProxy.solvent(Constants.bountyId) - expect(solvent).to.equal(true) - }) - - it('should return FALSE for insolvent ongoing contracts', async () => { - // ARRANGE - await openQProxy.mintBounty( - Constants.bountyId, - Constants.organization, - ongoingBountyInitOperation - ) - const bountyAddress = await openQProxy.bountyIdToAddress( - Constants.bountyId - ) - const bounty = await OngoingBountyV1.attach(bountyAddress) - - const solvent = await openQProxy.solvent(Constants.bountyId) - expect(solvent).to.equal(false) - }) - }) - - describe('closeOngoing', () => { - it('should close ongoing', async () => { - // ARRANGE - await openQProxy.mintBounty( - Constants.bountyId, - Constants.organization, - ongoingBountyInitOperation - ) - const bountyAddress = await openQProxy.bountyIdToAddress( - Constants.bountyId - ) - const bounty = await OngoingBountyV1.attach(bountyAddress) - - // ASSUME - let status = await bounty.status() - expect(status).to.equal(0) - - // ACT - await openQProxy.closeOngoing(Constants.bountyId) - - // ASSERT - status = await bounty.status() - expect(status).to.equal(1) - }) - - it('should revert if not ongoing', async () => { - // ARRANGE - await openQProxy.mintBounty( - Constants.bountyId, - Constants.organization, - atomicBountyInitOperation - ) - const bountyAddress = await openQProxy.bountyIdToAddress( - Constants.bountyId - ) - const bounty = await AtomicBountyV1.attach(bountyAddress) - - // ASSUME - let status = await bounty.status() - expect(status).to.equal(0) - - // ASSERT - await expect( - openQProxy.closeOngoing(Constants.bountyId) - ).to.be.revertedWith('NOT_AN_ONGOING_CONTRACT') - }) - - it('should revert if already closed', async () => { - // ARRANGE - await openQProxy.mintBounty( - Constants.bountyId, - Constants.organization, - ongoingBountyInitOperation - ) - const bountyAddress = await openQProxy.bountyIdToAddress( - Constants.bountyId - ) - const bounty = await OngoingBountyV1.attach(bountyAddress) - - // ASSUME - let status = await bounty.status() - expect(status).to.equal(0) - await openQProxy.closeOngoing(Constants.bountyId) - - // ASSERT - await expect( - openQProxy.closeOngoing(Constants.bountyId) - ).to.be.revertedWith('CONTRACT_ALREADY_CLOSED') - }) - - it('should revert if caller not issuer', async () => { - // ARRANGE - await openQProxy.mintBounty( - Constants.bountyId, - Constants.organization, - ongoingBountyInitOperation - ) - const bountyAddress = await openQProxy.bountyIdToAddress( - Constants.bountyId - ) - const bounty = await OngoingBountyV1.attach(bountyAddress) - - // ASSUME - let status = await bounty.status() - expect(status).to.equal(0) - - // ASSERT - await expect( - openQProxy.connect(notIssuer).closeOngoing(Constants.bountyId) - ).to.be.revertedWith('CALLER_NOT_ISSUER') - }) - - it('should emit BountyClosed', async () => { - // ARRANGE - await openQProxy.mintBounty( - Constants.bountyId, - Constants.organization, - ongoingBountyInitOperation - ) - const bountyAddress = await openQProxy.bountyIdToAddress( - Constants.bountyId - ) - const bounty = await OngoingBountyV1.attach(bountyAddress) - - // ASSUME - let status = await bounty.status() - expect(status).to.equal(0) - - const expectedTimestamp = await setNextBlockTimestamp() - // ACT - await expect(openQProxy.closeOngoing(Constants.bountyId)) - .to.emit(openQProxy, 'BountyClosed') - .withArgs( - Constants.bountyId, - anyValue, - Constants.organization, - ethers.constants.AddressZero, - expectedTimestamp, - 1, - [], - Constants.VERSION_1 - ) - }) - }) - describe('tierClaimed', () => { it('should return FALSE if tier not claimed, TRUE if already claimed', async () => { // ARRANGE await openQProxy.mintBounty( Constants.bountyId, Constants.organization, - tieredBountyInitOperation_permissionless + tieredFixedBountyInitOperation_permissionless ) const bountyAddress = await openQProxy.bountyIdToAddress( Constants.bountyId ) - const bounty = await TieredPercentageBountyV1.attach(bountyAddress) + const bounty = await TieredFixedBountyV1.attach(bountyAddress) await mockLink.approve(bountyAddress, 10000000) await depositManager.fundBountyToken( @@ -707,7 +399,7 @@ describe('OpenQ.sol', () => { await claimManager .connect(oracle) - .claimBounty(bountyAddress, owner.address, abiEncodedTieredCloserData) + .claimBounty(bountyAddress, owner.address, abiEncodedTieredFixedCloserData) // ASSERT tierClaimed = await openQProxy.tierClaimed(Constants.bountyId, 1) @@ -715,49 +407,6 @@ describe('OpenQ.sol', () => { }) }) - describe('ongoingClaimed', () => { - it('should return FALSE if ongoing claimant is not claimed, TRUE if it is claimed', async () => { - // ARRANGE - await openQProxy.mintBounty( - Constants.bountyId, - Constants.organization, - ongoingBountyInitOperation - ) - const bountyAddress = await openQProxy.bountyIdToAddress( - Constants.bountyId - ) - const bounty = await OngoingBountyV1.attach(bountyAddress) - - await mockLink.approve(bountyAddress, 10000000) - await depositManager.fundBountyToken( - bountyAddress, - mockLink.address, - 10000000, - 1, - Constants.funderUuid - ) - - let claimId = generateClaimantId( - 'FlacoJones', - 'https://github.com/OpenQDev/OpenQ-Frontend/pull/398' - ) - - // ASSUME - let ongoingClaimed = await bounty.claimId(claimId) - expect(ongoingClaimed).to.equal(false) - - // ACT - - await claimManager - .connect(oracle) - .claimBounty(bountyAddress, owner.address, abiEncodedOngoingCloserData) - - // // ASSERT - ongoingClaimed = await bounty.claimId(claimId) - expect(ongoingClaimed).to.equal(true) - }) - }) - describe('setFundingGoal', () => { it('should set funding goal', async () => { // ARRANGE @@ -1171,46 +820,6 @@ const bountyAddress = await openQProxy.bountyIdToAddress(Constants.bountyId) ) }) }) - - describe('ONGOING', () => { - it('should emit an SupportingDocumentsCompleteSet event with a boolean of supportingDocumentsComplete', async () => { - // ARRANGE - await openQProxy.mintBounty( - Constants.bountyId, - Constants.organization, - atomicBountyInitOperation - ) - const bountyAddress = await openQProxy.bountyIdToAddress( - Constants.bountyId - ) - const bounty = await AtomicBountyV1.attach(bountyAddress) - - let setSupportingDocumentsCompleteData_1 = abiCoder.encode( - ['bool'], - [true] - ) - - const supportingDocumentsCompleteArrayData = abiCoder.encode( - ['bool'], - [true] - ) - - // ACT/ASSERT - await expect( - await openQProxy.setSupportingDocumentsComplete( - Constants.bountyId, - setSupportingDocumentsCompleteData_1 - ) - ) - .to.emit(openQProxy, 'SupportingDocumentsCompleteSet') - .withArgs( - bountyAddress, - Constants.ATOMIC_CONTRACT, - supportingDocumentsCompleteArrayData, - Constants.VERSION_1 - ) - }) - }) }) describe('setInvoiceComplete', () => { @@ -1436,146 +1045,6 @@ const bountyAddress = await openQProxy.bountyIdToAddress(Constants.bountyId) }) }) - describe('setPayout', () => { - it('should set payout', async () => { - // ARRANGE - await openQProxy.mintBounty( - Constants.bountyId, - Constants.organization, - ongoingBountyInitOperation - ) -const bountyAddress = await openQProxy.bountyIdToAddress(Constants.bountyId) - const bounty = await OngoingBountyV1.attach(bountyAddress) - - // ACT - await openQProxy.setPayout(Constants.bountyId, mockDai.address, Constants.volume) - - // ASSERT - let payoutTokenAddress = await bounty.payoutTokenAddress() - let payoutVolume = await bounty.payoutVolume() - - expect(payoutTokenAddress).to.equal(mockDai.address) - expect(payoutVolume).to.equal(Constants.volume) - }) - - it('should emit a PayoutSet event', async () => { - // ARRANGE - await openQProxy.mintBounty( - Constants.bountyId, - Constants.organization, - ongoingBountyInitOperation - ) -const bountyAddress = await openQProxy.bountyIdToAddress(Constants.bountyId) - const bounty = await OngoingBountyV1.attach(bountyAddress) - - // ACT/ASSERT - await expect( - await openQProxy.setPayout(Constants.bountyId, mockDai.address, Constants.volume) - ) - .to.emit(openQProxy, 'PayoutSet') - .withArgs( - bountyAddress, - mockDai.address, - Constants.volume, - Constants.ONGOING_CONTRACT, - [], - Constants.VERSION_1 - ) - }) - - it('should revert if not called by issuer', async () => { - // ARRANGE - await openQProxy.mintBounty( - Constants.bountyId, - Constants.organization, - ongoingBountyInitOperation - ) - const notOwnerContract = openQProxy.connect(oracle) - - // ACT/ASSERT - await expect( - notOwnerContract.setPayout(Constants.bountyId, mockDai.address, Constants.volume) - ).to.be.revertedWith('CALLER_NOT_ISSUER') - }) - }) - - describe('setPayoutSchedule', () => { - it('should revert if payout schedule does not add to 100', async () => { - // ARRANGE - await openQProxy.mintBounty( - Constants.bountyId, - Constants.organization, - tieredBountyInitOperation - ) - // ACT/ASSERT - await expect( - openQProxy.setPayoutSchedule(Constants.bountyId, [20, 23, 43]) - ).to.be.revertedWith('PAYOUT_SCHEDULE_MUST_ADD_TO_100') - }) - - it('should revert if caller is not issuer', async () => { - // ARRANGE - await openQProxy.mintBounty( - Constants.bountyId, - Constants.organization, - tieredBountyInitOperation - ) - // ACT/ASSERT - await expect( - openQProxy - .connect(notIssuer) - .setPayoutSchedule(Constants.bountyId, [20, 23, 43]) - ).to.be.revertedWith('CALLER_NOT_ISSUER') - }) - - it('should set payout schedule', async () => { - // ARRANGE - await openQProxy.mintBounty( - Constants.bountyId, - Constants.organization, - tieredBountyInitOperation - ) -const bountyAddress = await openQProxy.bountyIdToAddress(Constants.bountyId) - const bounty = await TieredPercentageBountyV1.attach(bountyAddress) - - // ACT - await openQProxy.setPayoutSchedule(Constants.bountyId, [70, 20, 10]) - - // ASSERT - const payoutSchedule = await bounty.getPayoutSchedule() - const payoutToString = payoutSchedule.map((thing) => - parseInt(thing.toString()) - ) - expect(payoutToString[0]).to.equal(70) - expect(payoutToString[1]).to.equal(20) - expect(payoutToString[2]).to.equal(10) - }) - - it('should emit PayoutScheduleSet event', async () => { - // ARRANGE - await openQProxy.mintBounty( - Constants.bountyId, - Constants.organization, - tieredBountyInitOperation - ) -const bountyAddress = await openQProxy.bountyIdToAddress(Constants.bountyId) - const bounty = await TieredPercentageBountyV1.attach(bountyAddress) - - await expect( - openQProxy.setPayoutSchedule(Constants.bountyId, [70, 20, 10]) - ) - .to.emit(openQProxy, 'PayoutScheduleSet') - .withArgs( - bountyAddress, - ethers.constants.AddressZero, - [70, 20, 10], - 2, - [], - Constants.VERSION_1 - ) - }) - }) - describe('setPayoutScheduleFixed', () => { it('should revert if caller is not issuer', async () => { // ARRANGE From 4300bae724e7528203b9a95304df69b98f5cbf97 Mon Sep 17 00:00:00 2001 From: FlacoJones Date: Sat, 25 Feb 2023 14:57:12 -0700 Subject: [PATCH 6/7] udpates TieredBountyCore tests to pass without Ongoing or TieredPercentage --- test/Bounty/TieredBountyCore.test.js | 3 --- test/DepositManager.test.js | 14 -------------- 2 files changed, 17 deletions(-) diff --git a/test/Bounty/TieredBountyCore.test.js b/test/Bounty/TieredBountyCore.test.js index 782b9fc5..06038c2d 100755 --- a/test/Bounty/TieredBountyCore.test.js +++ b/test/Bounty/TieredBountyCore.test.js @@ -9,14 +9,11 @@ const { generateDepositId, generateClaimantId } = require('../utils'); const { Constants, - tieredBountyInitOperationBuilder, tieredFixedBountyInitOperationBuilder, - tieredBountyInitOperation_not100, setInvoiceCompleteData_tiered, setSupportingDocumentsComplete_tiered, setInvoiceCompleteData_atomic, setSupportingDocumentsComplete_atomic, - tieredBountyInitOperationBuilder_permissionless, tieredFixedBountyInitOperationBuilder_permissionless } = require('../constants'); diff --git a/test/DepositManager.test.js b/test/DepositManager.test.js index 02e38d07..790b4b26 100755 --- a/test/DepositManager.test.js +++ b/test/DepositManager.test.js @@ -217,20 +217,6 @@ describe('DepositManager.sol', () => { await expect(depositManager.fundBountyToken(bountyAddress, mockLink.address, 10000000, 1, Constants.funderUuid)).to.be.revertedWith('CONTRACT_ALREADY_CLOSED'); }); - it('should revert if tiered bounty is already closed', async () => { - // ARRANGE - await openQProxy.mintBounty(Constants.bountyId, Constants.organization, tieredFixedBountyInitOperation); - const bountyAddress = await openQProxy.bountyIdToAddress(Constants.bountyId); - - await claimManager.connect(oracle).claimBounty(bountyAddress, owner.address, abiEncodedTieredCloserData); - - await mockLink.approve(bountyAddress, 10000000); - await mockDai.approve(bountyAddress, 10000000); - - // ACT + ASSERT - await expect(depositManager.fundBountyToken(bountyAddress, mockLink.address, 10000000, 1, Constants.funderUuid)).to.be.revertedWith('CONTRACT_ALREADY_CLOSED'); - }); - it('should revert if funded with a non-whitelisted token and bounty is at funded token address capacity', async () => { // ARRANGE await openQProxy.mintBounty(Constants.bountyId, Constants.organization, atomicBountyInitOperation); From 6fb823c86f643e2ffb34bc951619ace6fa09835f Mon Sep 17 00:00:00 2001 From: FlacoJones Date: Sat, 25 Feb 2023 15:03:49 -0700 Subject: [PATCH 7/7] updates deploy scripts to operate without Ongoing or TieredPercentage --- .env.contracts | 30 ++++++++++----------- deploy/deploy_bounties.js | 55 -------------------------------------- deploy/deploy_contracts.js | 34 ----------------------- 3 files changed, 14 insertions(+), 105 deletions(-) diff --git a/.env.contracts b/.env.contracts index e3a458c6..a1a45072 100755 --- a/.env.contracts +++ b/.env.contracts @@ -1,17 +1,15 @@ -OPENQ_PROXY_ADDRESS=0x5FC8d32690cc91D4c39d9d3abcBD16989F875707 -OPENQ_IMPLEMENTATION_ADDRESS=0xDc64a140Aa3E981100a9becA4E685f962f0cF6C9 -CLAIM_MANAGER_PROXY_ADDRESS=0x2279B7A0a67DB372996a5FaB50D91eAA73d2eBe6 -CLAIM_MANAGER_IMPLEMENTATION_ADDRESS=0xa513E6E4b8f2a923D98304ec87F64353C4D5C853 -DEPOSIT_MANAGER_PROXY_ADDRESS=0xB7f8BC63BbcaD18155201308C8f3540b07f84F5e -DEPOSIT_MANAGER_IMPLEMENTATION_ADDRESS=0x610178dA211FEF7D417bC0e6FeD39F05609AD788 -OPENQ_BOUNTY_FACTORY_ADDRESS=0x322813Fd9A801c5507c9de605d63CEA4f2CE6c44 -ATOMIC_BOUNTY_BEACON_ADDRESS=0x3Aa5ebB10DC797CAC828524e59A333d0A371443c -ONGOING_BOUNTY_BEACON_ADDRESS=0xc6e7DF5E7b4f2A278906862b61205850344D4e7d -TIERED_BOUNTY_BEACON_ADDRESS=0x59b670e9fA9D0A427751Af201D676719a970857b -TIERED_FIXED_BOUNTY_BEACON_ADDRESS=0x4ed7c70F96B99c776995fB64377f0d4aB3B0e1C1 -OPENQ_TOKEN_WHITELIST_ADDRESS=0x0DCd1Bf9A1b36cE34237eEaFef220932846BCD82 +OPENQ_PROXY_ADDRESS=0xE6E340D132b5f46d1e472DebcD681B2aBc16e57E +OPENQ_IMPLEMENTATION_ADDRESS=0x67d269191c92Caf3cD7723F116c85e6E9bf55933 +CLAIM_MANAGER_PROXY_ADDRESS=0x9E545E3C0baAB3E08CdfD552C960A1050f373042 +CLAIM_MANAGER_IMPLEMENTATION_ADDRESS=0x84eA74d481Ee0A5332c457a4d796187F6Ba67fEB +DEPOSIT_MANAGER_PROXY_ADDRESS=0x851356ae760d987E095750cCeb3bC6014560891C +DEPOSIT_MANAGER_IMPLEMENTATION_ADDRESS=0x1613beB3B2C4f22Ee086B2b38C1476A3cE7f78E8 +OPENQ_BOUNTY_FACTORY_ADDRESS=0x8f86403A4DE0BB5791fa46B8e795C547942fE4Cf +ATOMIC_BOUNTY_BEACON_ADDRESS=0x99bbA657f2BbC93c02D617f8bA121cB8Fc104Acf +TIERED_FIXED_BOUNTY_BEACON_ADDRESS=0x0E801D84Fa97b50751Dbf25036d067dCf18858bF +OPENQ_TOKEN_WHITELIST_ADDRESS=0x95401dc811bb5740090279Ba06cfA8fcF6113778 OPENQ_DEPLOY_BLOCK_NUMBER=1 -MOCK_LINK_TOKEN_ADDRESS=0x5FbDB2315678afecb367f032d93F642f64180aa3 -MOCK_DAI_TOKEN_ADDRESS=0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0 -MOCK_NFT_TOKEN_ADDRESS=0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512 -MOCK_DAI_BLACKLISTED_TOKEN_ADDRESS=0xCf7Ed3AccA5a467e9e704C703E8D87F634fB0Fc9 +MOCK_LINK_TOKEN_ADDRESS=0x4A679253410272dd5232B3Ff7cF5dbB88f295319 +MOCK_DAI_TOKEN_ADDRESS=0x09635F643e140090A9A8Dcd712eD6285858ceBef +MOCK_NFT_TOKEN_ADDRESS=0x7a2088a1bFc9d81c55368AE168C2C02570cB814F +MOCK_DAI_BLACKLISTED_TOKEN_ADDRESS=0xc5a5C42992dECbae36851359345FE25997F5C42d diff --git a/deploy/deploy_bounties.js b/deploy/deploy_bounties.js index a2b2a99d..300bb00b 100755 --- a/deploy/deploy_bounties.js +++ b/deploy/deploy_bounties.js @@ -23,21 +23,7 @@ async function deployBounties() { const abiEncodedParamsAtomic = abiCoder.encode(['bool', 'address', 'uint256' , 'bool' , 'bool', 'bool' , 'string', 'string' , 'string'], [true, process.env.MOCK_LINK_TOKEN_ADDRESS, 100, true, true, true, 'po', 'po', 'po']); let atomicBountyInitOperation = [0, abiEncodedParamsAtomic]; - // ONGOING - - const abiEncodedParamsOngoing = abiCoder.encode(['address', 'uint256', 'bool', 'address', 'uint256', 'bool', 'bool', 'bool', 'string', 'string', 'string'], [process.env.MOCK_LINK_TOKEN_ADDRESS, '100', true, process.env.MOCK_LINK_TOKEN_ADDRESS, '1000', true, true, true, '', '', '']); - let ongoingBountyInitOperation = [1, abiEncodedParamsOngoing]; - - const abiEncodedParamsOngoingNoFundingGoal = abiCoder.encode(['address', 'uint256', 'bool', 'address', 'uint256', 'bool', 'bool', 'bool', 'string', 'string', 'string'], [process.env.MOCK_LINK_TOKEN_ADDRESS, '100', false, ethers.constants.AddressZero, 0, true, true, true, '', '', '']); - let ongoingBountyNoFundingGoalInitOperation = [1, abiEncodedParamsOngoingNoFundingGoal]; - // CONTEST - const abiEncodedParamsContestPercentage = abiCoder.encode(['uint256[]', 'bool', 'address', 'uint256', 'bool', 'bool', 'bool', 'string', 'string', 'string'], [[70, 20, 10], true, process.env.MOCK_LINK_TOKEN_ADDRESS, 100, true, true, true, '', '', '']); - let contestPercentageInitOperation = [2, abiEncodedParamsContestPercentage]; - - const abiEncodedParamsContestPercentageNoFundingGoal = abiCoder.encode(['uint256[]', 'bool', 'address', 'uint256', 'bool', 'bool', 'bool', 'string', 'string', 'string'], [[70, 20, 10], false, ethers.constants.AddressZero, 0, true, true, true, '', '', '']); - let contestPercentageNoFundingGoalInitOperation = [2, abiEncodedParamsContestPercentageNoFundingGoal]; - const abiEncodedParamsTieredFixedBounty = abiCoder.encode(['uint256[]', 'address', 'bool', 'bool', 'bool', 'string', 'string', 'string'], [[80, 20], process.env.MOCK_LINK_TOKEN_ADDRESS, true, true, true, '', '', '']); let tieredFixedBountyInitOperation = [3, abiEncodedParamsTieredFixedBounty]; @@ -65,48 +51,7 @@ async function deployBounties() { await optionalSleep(10000); console.log('Atomic Contract with funding goal deployed!'); - // ONGOING - console.log('Minting Ongoing contract with no funding goal...'); - await openQ.mintBounty(openQIssueIds[2], 'MDEyOk9yZ2FuaXphdGlvbjc3NDAyNTM4', ongoingBountyNoFundingGoalInitOperation); - await optionalSleep(10000); - console.log('Ongoing contract with no funding goal deployed!'); - - console.log('Minting Ongoing contract with no funding goal...'); - await openQ.mintBounty(otherOrgIssueIds[2], otherOrgIssueOwners[2], ongoingBountyNoFundingGoalInitOperation); - await optionalSleep(10000); - console.log('Ongoing contract with no funding goal deployed!'); - - console.log('Minting Ongoing contract with funding goal...'); - await openQ.mintBounty(openQIssueIds[3], 'MDEyOk9yZ2FuaXphdGlvbjc3NDAyNTM4', ongoingBountyInitOperation); - await optionalSleep(10000); - console.log('Ongoing contract with funding goal deployed!'); - - console.log('Minting Ongoing contract with funding goal...'); - await openQ.mintBounty(otherOrgIssueIds[3], otherOrgIssueOwners[3], ongoingBountyInitOperation); - await optionalSleep(10000); - console.log('Ongoing contract with funding goal deployed!'); - // CONTEST - console.log('Minting Contest percentage contract with funding goal...'); - await openQ.mintBounty(openQIssueIds[4], 'MDEyOk9yZ2FuaXphdGlvbjc3NDAyNTM4', contestPercentageInitOperation); - await optionalSleep(10000); - console.log('Contest percentage contract with funding goal deployed!'); - - console.log('Minting Contest percentage contract with funding goal...'); - await openQ.mintBounty(otherOrgIssueIds[4], otherOrgIssueOwners[4], contestPercentageInitOperation); - await optionalSleep(10000); - console.log('Contest percentage contract with funding goal deployed!'); - - console.log('Minting Contest percentage contract with no funding goal...'); - await openQ.mintBounty(openQIssueIds[5], 'MDEyOk9yZ2FuaXphdGlvbjc3NDAyNTM4', contestPercentageNoFundingGoalInitOperation); - await optionalSleep(10000); - console.log('Contest percentage contract with no funding goal deployed!'); - - console.log('Minting Contest percentage contract with no funding goal...'); - await openQ.mintBounty(otherOrgIssueIds[5], otherOrgIssueOwners[5], contestPercentageNoFundingGoalInitOperation); - await optionalSleep(10000); - console.log('Contest percentage contract with no funding goal deployed!'); - console.log('Minting Contest fixed contract...'); await openQ.mintBounty(openQIssueIds[6], 'MDEyOk9yZ2FuaXphdGlvbjc3NDAyNTM4', tieredFixedBountyInitOperation); await optionalSleep(10000); diff --git a/deploy/deploy_contracts.js b/deploy/deploy_contracts.js index 8638909a..bb6a1f58 100755 --- a/deploy/deploy_contracts.js +++ b/deploy/deploy_contracts.js @@ -135,20 +135,6 @@ async function deployContracts() { await optionalSleep(10000); console.log(`AtomicBountyV1 Deployed to ${atomicBountyV1.address}\n`); - console.log('Deploying OngoingBountyV1 implementation...'); - const OngoingBountyV1 = await ethers.getContractFactory('OngoingBountyV1'); - const ongoingBountyV1 = await OngoingBountyV1.deploy(); - await ongoingBountyV1.deployed(); - await optionalSleep(10000); - console.log(`OngoingBountyV1 Deployed to ${ongoingBountyV1.address}\n`); - - console.log('Deploying TieredPercentageBountyV1 implementation...'); - const TieredPercentageBountyV1 = await ethers.getContractFactory('TieredPercentageBountyV1'); - const tieredPercentageBountyV1 = await TieredPercentageBountyV1.deploy(); - await tieredPercentageBountyV1.deployed(); - await optionalSleep(10000); - console.log(`TieredPercentageBountyV1 Deployed to ${tieredPercentageBountyV1.address}\n`); - console.log('Deploying TieredFixedBountyV1 implementation...'); const TieredFixedBountyV1 = await ethers.getContractFactory('TieredFixedBountyV1'); const tieredFixedBountyV1 = await TieredFixedBountyV1.deploy(); @@ -165,18 +151,6 @@ async function deployContracts() { await optionalSleep(10000); console.log(`AtomicBountyBeacon Deployed to ${atomicBountyBeacon.address}\n`); - console.log('Deploying OngoingBountyBeacon...'); - const ongoingBountyBeacon = await BountyBeacon.deploy(ongoingBountyV1.address); - await ongoingBountyBeacon.deployed(); - await optionalSleep(10000); - console.log(`OngoingBountyBeacon Deployed to ${ongoingBountyBeacon.address}\n`); - - console.log('Deploying TieredBountyBeacon...'); - const tieredBountyBeacon = await BountyBeacon.deploy(tieredPercentageBountyV1.address); - await tieredBountyBeacon.deployed(); - await optionalSleep(10000); - console.log(`TieredBountyBeacon Deployed to ${tieredBountyBeacon.address}\n`); - console.log('Deploying TieredFixedBountyBeacon...'); const tieredFixedBountyBeacon = await BountyBeacon.deploy(tieredFixedBountyV1.address); await tieredFixedBountyBeacon.deployed(); @@ -188,8 +162,6 @@ async function deployContracts() { const bountyFactory = await BountyFactory.deploy( openQProxy.address, atomicBountyBeacon.address, - ongoingBountyBeacon.address, - tieredBountyBeacon.address, tieredFixedBountyBeacon.address ); await bountyFactory.deployed(); @@ -202,13 +174,9 @@ async function deployContracts() { console.log('\nBOUNTY PROXY and IMPLEMENTATION ADDRESSES'); console.log(`AtomicBountyV1 (Implementation) deployed to ${atomicBountyV1.address}\n`); - console.log(`OngoingBountyV1 (Implementation) deployed to ${ongoingBountyV1.address}\n`); - console.log(`TieredPercentageBountyV1 (Implementation) deployed to ${tieredPercentageBountyV1.address}\n`); console.log(`TieredFixedBountyV1 (Implementation) deployed to ${tieredFixedBountyV1.address}\n`); console.log(`AtomicBountyBeacon deployed to ${atomicBountyBeacon.address}`); - console.log(`OngoingBountyBeacon deployed to ${ongoingBountyBeacon.address}`); - console.log(`TieredBountyBeacon deployed to ${tieredBountyBeacon.address}`); console.log(`TieredFixedBountyBeacon deployed to ${tieredFixedBountyBeacon.address}`); console.log(`BountyFactory deployed to: ${bountyFactory.address}`); @@ -256,8 +224,6 @@ DEPOSIT_MANAGER_PROXY_ADDRESS=${depositManagerProxy.address} DEPOSIT_MANAGER_IMPLEMENTATION_ADDRESS=${depositManager.address} OPENQ_BOUNTY_FACTORY_ADDRESS=${bountyFactory.address} ATOMIC_BOUNTY_BEACON_ADDRESS=${atomicBountyBeacon.address} -ONGOING_BOUNTY_BEACON_ADDRESS=${ongoingBountyBeacon.address} -TIERED_BOUNTY_BEACON_ADDRESS=${tieredBountyBeacon.address} TIERED_FIXED_BOUNTY_BEACON_ADDRESS=${tieredFixedBountyBeacon.address} OPENQ_TOKEN_WHITELIST_ADDRESS=${openQTokenWhitelist.address} OPENQ_DEPLOY_BLOCK_NUMBER=${deployBlockNumber}