Skip to content

Commit

Permalink
add happy day testcase for bundle staking (#418)
Browse files Browse the repository at this point in the history
  • Loading branch information
doerfli committed Jul 3, 2024
1 parent 0687846 commit bab6a62
Show file tree
Hide file tree
Showing 7 changed files with 116 additions and 12 deletions.
1 change: 1 addition & 0 deletions contracts/instance/module/IComponents.sol
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ interface IComponents {

struct ComponentInfo {
string name; // component name (needs to be unique per instance)
// TODO: why here **AND** in ProductInfo/PoolInfo?
NftId productNftId;
IERC20Metadata token;
TokenHandler tokenHandler;
Expand Down
3 changes: 3 additions & 0 deletions contracts/pool/BasicPoolAuthorization.sol
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ contract BasicPoolAuthorization
_authorize(functions, BasicPool.setMaxCapitalAmount.selector, "setMaxCapitalAmount");
_authorize(functions, BasicPool.setBundleOwnerRole.selector, "setBundleOwnerRole");
_authorize(functions, BasicPool.setFees.selector, "setFees");
_authorize(functions, BasicPool.stake.selector, "stake");
_authorize(functions, BasicPool.unstake.selector, "unstake");
_authorize(functions, BasicPool.extend.selector, "extend");

_authorize(functions, IInstanceLinkedComponent.withdrawFees.selector, "withdrawFees");

Expand Down
6 changes: 3 additions & 3 deletions contracts/pool/BundleService.sol
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ contract BundleService is
)
external
virtual
restricted()
// TODO: restricted() (once #462 is done)
{
IBundle.BundleInfo memory bundleInfo = instance.getInstanceReader().getBundleInfo(bundleNftId);
StateId bundleState = instance.getInstanceReader().getMetadata(bundleNftId.toKey32(BUNDLE())).state;
Expand All @@ -265,7 +265,7 @@ contract BundleService is
)
external
virtual
restricted()
// TODO: restricted() (once #462 is done)
{
InstanceStore instanceStore = instance.getInstanceStore();
(
Expand All @@ -291,7 +291,7 @@ contract BundleService is
function extend(NftId bundleNftId, Seconds lifetimeExtension)
external
virtual
restricted
// TODO: restricted() (once #462 is done)
returns (Timestamp extendedExpiredAt)
{
(NftId poolNftId,, IInstance instance) = _getAndVerifyActiveComponent(POOL());
Expand Down
8 changes: 4 additions & 4 deletions contracts/pool/PoolService.sol
Original file line number Diff line number Diff line change
Expand Up @@ -186,8 +186,8 @@ contract PoolService is
view
returns (Fee memory stakingFee)
{
NftId productNftId = instanceReader.getPoolInfo(poolNftId).productNftId;
return instanceReader.getPoolInfo(productNftId).stakingFee;
NftId productNftId = instanceReader.getComponentInfo(poolNftId).productNftId;
return instanceReader.getProductInfo(productNftId).stakingFee;
}

function closeBundle(NftId bundleNftId)
Expand All @@ -210,7 +210,7 @@ contract PoolService is
function stake(NftId bundleNftId, Amount amount)
external
virtual
restricted()
// TODO: restricted() (once #462 is done)
returns(Amount netAmount)
{
(NftId poolNftId,, IInstance instance) = _getAndVerifyActiveComponent(POOL());
Expand Down Expand Up @@ -259,7 +259,7 @@ contract PoolService is
function unstake(NftId bundleNftId, Amount amount)
external
virtual
restricted()
// TODO: restricted() (once #462 is done)
returns(Amount netAmount)
{
(NftId poolNftId,, IInstance instance) = _getAndVerifyActiveComponent(POOL());
Expand Down
89 changes: 89 additions & 0 deletions test/TestBundle.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.20;

import {console} from "../lib/forge-std/src/Test.sol";

import {Amount, AmountLib} from "../contracts/type/Amount.sol";
import {BasicPoolAuthorization} from "../contracts/pool/BasicPoolAuthorization.sol";
import {Fee, FeeLib} from "../contracts/type/Fee.sol";
import {IBundle} from "../contracts/instance/module/IBundle.sol";
import {IComponents} from "../contracts/instance/module/IComponents.sol";
import {IKeyValueStore} from "../contracts/shared/IKeyValueStore.sol";
import {ILifecycle} from "../contracts/shared/ILifecycle.sol";
import {Key32} from "../contracts/type/Key32.sol";
import {NftId, NftIdLib} from "../contracts/type/NftId.sol";
import {ObjectType, BUNDLE} from "../contracts/type/ObjectType.sol";
import {Pool} from "../contracts/pool/Pool.sol";
import {IPoolService} from "../contracts/pool/IPoolService.sol";
import {POOL_OWNER_ROLE, PUBLIC_ROLE} from "../contracts/type/RoleId.sol";
import {Seconds, SecondsLib} from "../contracts/type/Seconds.sol";
import {SimplePool} from "./mock/SimplePool.sol";
import {StateId, ACTIVE, PAUSED, CLOSED} from "../contracts/type/StateId.sol";
import {TimestampLib} from "../contracts/type/Timestamp.sol";
import {GifTest} from "./base/GifTest.sol";
import {UFixedLib} from "../contracts/type/UFixed.sol";

contract TestBundle is GifTest {


/// @dev test staking of an existing bundle
function test_Bundle_stakeBundle() public {
// GIVEN
initialStakingFee = FeeLib.percentageFee(4);
_prepareProduct(false);

IComponents.ComponentInfo memory poolComponentInfo = instanceReader.getComponentInfo(poolNftId);

vm.startPrank(investor);
token.approve(address(pool.getTokenHandler()), 2000);

Seconds lifetime = SecondsLib.toSeconds(604800);
bundleNftId = pool.createBundle(
FeeLib.zero(),
1000,
lifetime,
""
);
vm.stopPrank();

assertTrue(!bundleNftId.eqz(), "bundle nft id is zero");

assertEq(token.balanceOf(poolComponentInfo.wallet), 1000, "pool wallet token balance not 1000");
uint256 investorBalanceBefore = token.balanceOf(investor);

assertEq(instanceReader.getBalanceAmount(poolNftId).toInt(), 1000, "pool balance not 1000");
assertEq(instanceReader.getFeeAmount(poolNftId).toInt(), 40, "pool fees not 40");

assertEq(instanceReader.getBalanceAmount(bundleNftId).toInt(), 960, "bundle balance not 960");
assertEq(instanceReader.getFeeAmount(bundleNftId).toInt(), 0, "bundle fees 0");

uint256 stakeAmount = 1000;
Amount stakeAmt = AmountLib.toAmount(stakeAmount);
Amount stakeNetAmt = AmountLib.toAmount(960);
vm.startPrank(investor);

// THEN - expect log event
vm.expectEmit();
emit IPoolService.LogPoolServiceBundleStaked(instanceNftId, poolNftId, bundleNftId, stakeAmt, stakeNetAmt);

// WHEN - pool is staked with another 1000 tokens
pool.stake(bundleNftId, stakeAmt);

// THEN - assert all counters are updated
assertEq(token.balanceOf(poolComponentInfo.wallet), 2000, "pool wallet token balance not 2000");
assertEq(token.balanceOf(investor), investorBalanceBefore - stakeAmount, "investor token balance not 0");

assertEq(instanceReader.getBalanceAmount(poolNftId).toInt(), 2000, "pool balance not 2000");
assertEq(instanceReader.getFeeAmount(poolNftId).toInt(), 80, "pool fees not 80");

assertEq(instanceReader.getBalanceAmount(bundleNftId).toInt(), 1920, "bundle balance not 1920");
assertEq(instanceReader.getFeeAmount(bundleNftId).toInt(), 0, "bundle fees 0");
}

function _fundInvestor(uint256 amount) internal {
vm.startPrank(registryOwner);
token.transfer(investor, amount);
vm.stopPrank();
}

}
12 changes: 11 additions & 1 deletion test/base/GifTest.sol
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
// GIF_MANAGER_ROLE,
// GIF_ADMIN_ROLE,
// ADMIN_ROLE,
PUBLIC_ROLE,
PRODUCT_OWNER_ROLE,
ORACLE_OWNER_ROLE,
POOL_OWNER_ROLE,
Expand Down Expand Up @@ -171,12 +172,14 @@ contract GifTest is GifDeployer {

uint8 initialProductFeePercentage = 2;
uint8 initialPoolFeePercentage = 3;
uint8 initialStakingFeePercentage = 0;
uint8 initialBundleFeePercentage = 4;
uint8 initialDistributionFeePercentage = 20;
uint8 initialMinDistributionOwnerFeePercentage = 2;

Fee public initialProductFee = FeeLib.percentageFee(initialProductFeePercentage);
Fee public initialPoolFee = FeeLib.percentageFee(initialPoolFeePercentage);
Fee public initialStakingFee = FeeLib.percentageFee(initialStakingFeePercentage);
Fee public initialBundleFee = FeeLib.percentageFee(initialBundleFeePercentage);
Fee public initialDistributionFee = FeeLib.percentageFee(initialDistributionFeePercentage);
Fee public initialMinDistributionOwnerFee = FeeLib.percentageFee(initialMinDistributionOwnerFeePercentage);
Expand Down Expand Up @@ -460,7 +463,14 @@ contract GifTest is GifDeployer {
initialDistributionFee,
initialMinDistributionOwnerFee);
vm.stopPrank();


vm.startPrank(poolOwner);
pool.setFees(
initialPoolFee,
initialStakingFee,
FeeLib.zero());
vm.stopPrank();

// solhint-disable
console.log("product nft id", productNftId.toInt());
console.log("product component at", address(product));
Expand Down
9 changes: 5 additions & 4 deletions test/component/distribution/Referral.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -126,8 +126,8 @@ contract ReferralTest is ReferralTestBase {
assertTrue(instanceReader.getPolicyState(policyNftId) == ACTIVE(), "policy state not ACTIVE");

uint256 netPremium = 100;
uint256 expectedPremium = netPremium + 14; // 100 (net premium) + 14 (distribution fee 3 + 11 distributor commission)
assertEq(token.balanceOf(address(customer)), initialCustomerBalance - expectedPremium, "customer balance not 886");
uint256 expectedPremium = netPremium + 17; // 100 (net premium) + 14 (distribution fee 3 + pool fee 3 + 11 distributor commission)
assertEq(token.balanceOf(address(customer)), initialCustomerBalance - expectedPremium, "customer balance not 883");

{
IPolicy.PolicyInfo memory policyInfo = instanceReader.getPolicyInfo(policyNftId);
Expand All @@ -146,8 +146,9 @@ contract ReferralTest is ReferralTestBase {
assertEq(instanceReader.getFeeAmount(distributorNftId).toInt(), 3, "sumCommisions not 3");

// check pool financials and balance
assertEq(instanceReader.getBalanceAmount(poolNftId).toInt(), initialPoolBalance + netPremium, "unexpected pool balance (1)");
assertEq(token.balanceOf(pool.getWallet()), initialPoolBalance + netPremium, "unexpected pool balance (2)");
uint256 expectedPoolFee = 3;
assertEq(instanceReader.getBalanceAmount(poolNftId).toInt(), initialPoolBalance + netPremium + expectedPoolFee, "unexpected pool balance (1)");
assertEq(token.balanceOf(pool.getWallet()), initialPoolBalance + netPremium + expectedPoolFee, "unexpected pool balance (2)");

assertEq(instanceBundleSet.activePolicies(bundleNftId), 1, "expected one active policy");
assertTrue(instanceBundleSet.getActivePolicy(bundleNftId, 0).eq(policyNftId), "active policy nft id in bundle manager not equal to policy nft id");
Expand Down

0 comments on commit bab6a62

Please sign in to comment.