Skip to content

Commit

Permalink
Merge pull request #58 from corpus-ventures/personalInviteFee
Browse files Browse the repository at this point in the history
make personalInvite fee independent
  • Loading branch information
Malteish authored Nov 23, 2022
2 parents 4fc22ea + c548cf9 commit bcc242a
Show file tree
Hide file tree
Showing 10 changed files with 126 additions and 97 deletions.
4 changes: 2 additions & 2 deletions contracts/ContinuousFundraising.sol
Original file line number Diff line number Diff line change
Expand Up @@ -141,12 +141,12 @@ contract ContinuousFundraising is
uint256 currencyAmount = (_amount * tokenPrice) /
(10 ** token.decimals());
uint256 fee;
if (token.feeSettings().investmentFeeDenominator() == 0) {
if (token.feeSettings().continuousFundraisungFeeDenominator() == 0) {
fee = 0;
} else {
fee =
currencyAmount /
token.feeSettings().investmentFeeDenominator();
token.feeSettings().continuousFundraisungFeeDenominator();
currency.safeTransferFrom(
_msgSender(),
token.feeSettings().feeCollector(),
Expand Down
85 changes: 45 additions & 40 deletions contracts/FeeSettings.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@ pragma solidity ^0.8.0;

import "@openzeppelin/contracts/access/Ownable.sol";

struct Change {
uint tokenFeeDenominator;
uint investmentFeeDenominator;
uint time;
struct Fees {
uint256 tokenFeeDenominator;
uint256 continuousFundraisungFeeDenominator;
uint256 personalInviteFeeDenominator;
uint256 time;
}

/*
Expand All @@ -16,70 +17,74 @@ contract FeeSettings is Ownable {
/// @notice Denominator to calculate fees paid Token.sol
uint256 public tokenFeeDenominator;
/// @notice Denominator to calculate fees paid in all investment contracts
uint256 public investmentFeeDenominator;
uint256 public continuousFundraisungFeeDenominator;
/// @notice Denominator to calculate fees paid in all investment contracts
uint256 public personalInviteFeeDenominator;
/// @notice address used to pay platform fees to.
address public feeCollector;

Change public change;
Fees public proposedFees;

event SetTokenFeeDenominator(uint256 value);
event SetInvestmentFeeDenominator(uint256 value);
event SetContinuousFundraisungFeeDenominator(uint256 value);
event SetPersonalInviteFeeDenominator(uint256 value);
event FeeCollectorChanged(address indexed newFeeCollector);
event ChangeProposed(Change proposal);
event ChangeProposed(Fees proposal);

constructor(
uint256 _tokenFeeDenominator,
uint256 _investmentFeeDenominator,
Fees memory _fees,
address _feeCollector
) {
require(
_tokenFeeDenominator >= 20 || _tokenFeeDenominator == 0,
"Fee must be below 5% or 0"
);
tokenFeeDenominator = _tokenFeeDenominator;
require(
_investmentFeeDenominator >= 20 || _investmentFeeDenominator == 0,
"Fee must be below 5% or 0"
);
investmentFeeDenominator = _investmentFeeDenominator;
checkFeeLimits(_fees);
tokenFeeDenominator = _fees.tokenFeeDenominator;
continuousFundraisungFeeDenominator = _fees.continuousFundraisungFeeDenominator;
personalInviteFeeDenominator = _fees.personalInviteFeeDenominator;
require(_feeCollector != address(0), "Fee collector cannot be 0x0");
feeCollector = _feeCollector;
}

function planFeeChange(Change memory _change) public onlyOwner {
require(
_change.tokenFeeDenominator >= 20 ||
_change.tokenFeeDenominator == 0,
"Fee must be below 5% or 0"
);
require(
_change.investmentFeeDenominator >= 20 ||
_change.investmentFeeDenominator == 0,
"Fee must be below 5% or 0"
);
function planFeeChange(Fees memory _fees) public onlyOwner {
checkFeeLimits(_fees);
require(
_change.time > block.timestamp + 12 weeks,
_fees.time > block.timestamp + 12 weeks,
"Fee change must be at least 12 weeks in the future"
); // can only be executed in 3 months
change = _change;
emit ChangeProposed(_change);
proposedFees = _fees;
emit ChangeProposed(_fees);
}

function executeFeeChange() public onlyOwner {
require(
block.timestamp >= change.time,
block.timestamp >= proposedFees.time,
"Fee change must be executed after the change time"
);
tokenFeeDenominator = change.tokenFeeDenominator;
investmentFeeDenominator = change.investmentFeeDenominator;
emit SetTokenFeeDenominator(change.tokenFeeDenominator);
emit SetInvestmentFeeDenominator(change.investmentFeeDenominator);
delete change;
tokenFeeDenominator = proposedFees.tokenFeeDenominator;
continuousFundraisungFeeDenominator = proposedFees.continuousFundraisungFeeDenominator;
personalInviteFeeDenominator = proposedFees.personalInviteFeeDenominator;
emit SetTokenFeeDenominator(proposedFees.tokenFeeDenominator);
emit SetContinuousFundraisungFeeDenominator(proposedFees.continuousFundraisungFeeDenominator);
emit SetPersonalInviteFeeDenominator(proposedFees.personalInviteFeeDenominator);
delete proposedFees;
}

function setFeeCollector(address _feeCollector) public onlyOwner {
require(_feeCollector != address(0), "Fee collector cannot be 0x0");
feeCollector = _feeCollector;
emit FeeCollectorChanged(_feeCollector);
}

function checkFeeLimits(Fees memory _fees) internal pure {
require(
_fees.tokenFeeDenominator >= 20 || _fees.tokenFeeDenominator == 0,
"Fee must be below 5% or 0"
);
require(
_fees.continuousFundraisungFeeDenominator >= 20 || _fees.continuousFundraisungFeeDenominator == 0,
"Fee must be below 5% or 0"
);
require(
_fees.personalInviteFeeDenominator >= 20 || _fees.personalInviteFeeDenominator == 0,
"Fee must be below 5% or 0"
);
}
}
4 changes: 2 additions & 2 deletions contracts/PersonalInvite.sol
Original file line number Diff line number Diff line change
Expand Up @@ -67,12 +67,12 @@ contract PersonalInvite {
(10 ** _token.decimals());

uint256 fee;
if (_token.feeSettings().investmentFeeDenominator() == 0) {
if (_token.feeSettings().personalInviteFeeDenominator() == 0) {
fee = 0;
} else {
fee =
currencyAmount /
_token.feeSettings().investmentFeeDenominator();
_token.feeSettings().personalInviteFeeDenominator();
_currency.safeTransferFrom(
_buyer,
_token.feeSettings().feeCollector(),
Expand Down
11 changes: 6 additions & 5 deletions test/ContinuousFundraising.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ contract ContinuousFundraisingTest is Test {

function setUp() public {
list = new AllowList();
feeSettings = new FeeSettings(100, 100, admin);
Fees memory fees = Fees(100,100,100,100);
feeSettings = new FeeSettings(fees, admin);

token = new Token(
trustedForwarder,
Expand Down Expand Up @@ -199,7 +200,7 @@ contract ContinuousFundraisingTest is Test {
// receiver should have the 990 FPT that were paid, minus the fee
uint currencyAmount = 990 * 10 ** _paymentTokenDecimals;
uint256 currencyFee = currencyAmount /
token.feeSettings().investmentFeeDenominator();
token.feeSettings().continuousFundraisungFeeDenominator();
assertTrue(
_paymentToken.balanceOf(receiver) ==
currencyAmount - currencyFee,
Expand Down Expand Up @@ -337,13 +338,13 @@ contract ContinuousFundraisingTest is Test {
paymentToken.balanceOf(receiver) ==
costInPaymentToken -
costInPaymentToken /
token.feeSettings().investmentFeeDenominator(),
token.feeSettings().continuousFundraisungFeeDenominator(),
"receiver has payment tokens"
);
assertTrue(
paymentToken.balanceOf(token.feeSettings().feeCollector()) ==
costInPaymentToken /
token.feeSettings().investmentFeeDenominator(),
token.feeSettings().continuousFundraisungFeeDenominator(),
"fee collector has collected fee in payment tokens"
);
assertTrue(
Expand Down Expand Up @@ -470,7 +471,7 @@ contract ContinuousFundraisingTest is Test {
token.feeSettings().tokenFeeDenominator();
uint256 paymentTokenFee = (costInPaymentTokenForMinAmount * 3) /
2 /
token.feeSettings().investmentFeeDenominator();
token.feeSettings().continuousFundraisungFeeDenominator();
assertTrue(
paymentToken.balanceOf(receiver) ==
(costInPaymentTokenForMinAmount * 3) / 2 - paymentTokenFee,
Expand Down
8 changes: 3 additions & 5 deletions test/ContinuousFundraisingERC2771.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -67,11 +67,9 @@ contract ContinuousFundraisingTest is Test {

function setUp() public {
list = new AllowList();
feeSettings = new FeeSettings(
tokenFeeDenominator,
paymentTokenFeeDenominator,
admin
);
Fees memory fees = Fees(tokenFeeDenominator,paymentTokenFeeDenominator,paymentTokenFeeDenominator,0);
feeSettings = new FeeSettings(fees, admin);

token = new Token(
trustedForwarder,
address(feeSettings),
Expand Down
62 changes: 39 additions & 23 deletions test/FeeSettings.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -37,26 +37,30 @@ contract FeeSettingsTest is Test {
) public {
vm.assume(!feeInValidRange(fee));
FeeSettings _feeSettings;
Fees memory fees = Fees(fee,100,100,0);
vm.expectRevert("Fee must be below 5% or 0");
_feeSettings = new FeeSettings(fee, 100, admin);
_feeSettings = new FeeSettings(fees, admin);
}

function testEnforceInvestmentFeeDenominatorRangeinConstructor(
uint8 fee
) public {
vm.assume(!feeInValidRange(fee));
FeeSettings _feeSettings;
Fees memory fees = Fees(fee,100,100,0);
vm.expectRevert("Fee must be below 5% or 0");
_feeSettings = new FeeSettings(100, fee, admin);
_feeSettings = new FeeSettings(fees, admin);
}

function testEnforceTokenFeeDenominatorRangeinFeeChanger(uint8 fee) public {
vm.assume(!feeInValidRange(fee));
FeeSettings _feeSettings = new FeeSettings(100, 100, admin);
Fees memory fees = Fees(100,100,100,0);
FeeSettings _feeSettings = new FeeSettings(fees, admin);

Change memory feeChange = Change({
Fees memory feeChange = Fees({
tokenFeeDenominator: fee,
investmentFeeDenominator: 100,
continuousFundraisungFeeDenominator: 100,
personalInviteFeeDenominator: 100,
time: block.timestamp + 7884001
});
vm.expectRevert("Fee must be below 5% or 0");
Expand All @@ -67,11 +71,13 @@ contract FeeSettingsTest is Test {
uint8 fee
) public {
vm.assume(!feeInValidRange(fee));
FeeSettings _feeSettings = new FeeSettings(100, 100, admin);
Fees memory fees = Fees(100,100,100,0);
FeeSettings _feeSettings = new FeeSettings(fees, admin);

Change memory feeChange = Change({
Fees memory feeChange = Fees({
tokenFeeDenominator: 100,
investmentFeeDenominator: fee,
continuousFundraisungFeeDenominator: fee,
personalInviteFeeDenominator: 100,
time: block.timestamp + 7884001
});
vm.expectRevert("Fee must be below 5% or 0");
Expand All @@ -80,12 +86,14 @@ contract FeeSettingsTest is Test {

function testEnforceFeeChangeDelay(uint delay) public {
vm.assume(delay <= 12 weeks);
Fees memory fees = Fees(50,50,50,0);
vm.prank(admin);
FeeSettings _feeSettings = new FeeSettings(50, 50, admin);
FeeSettings _feeSettings = new FeeSettings(fees, admin);

Change memory feeChange = Change({
Fees memory feeChange = Fees({
tokenFeeDenominator: 100,
investmentFeeDenominator: 100,
continuousFundraisungFeeDenominator: 100,
personalInviteFeeDenominator: 100,
time: block.timestamp + delay
});
vm.prank(admin);
Expand All @@ -104,12 +112,14 @@ contract FeeSettingsTest is Test {
vm.assume(delayAnnounced > 12 weeks && delayAnnounced < 1000000000000);
vm.assume(feeInValidRange(tokenFee));
vm.assume(feeInValidRange(investmentFee));
Fees memory fees = Fees(50,50,50,0);
vm.prank(admin);
FeeSettings _feeSettings = new FeeSettings(50, 50, admin);
FeeSettings _feeSettings = new FeeSettings(fees, admin);

Change memory feeChange = Change({
Fees memory feeChange = Fees({
tokenFeeDenominator: tokenFee,
investmentFeeDenominator: investmentFee,
continuousFundraisungFeeDenominator: investmentFee,
personalInviteFeeDenominator: 100,
time: block.timestamp + delayAnnounced
});
vm.prank(admin);
Expand All @@ -129,12 +139,14 @@ contract FeeSettingsTest is Test {
vm.assume(delayAnnounced > 12 weeks && delayAnnounced < 100000000000);
vm.assume(feeInValidRange(tokenFee));
vm.assume(feeInValidRange(investmentFee));
Fees memory fees = Fees(50,50,50,0);
vm.prank(admin);
FeeSettings _feeSettings = new FeeSettings(50, 50, admin);
FeeSettings _feeSettings = new FeeSettings(fees, admin);

Change memory feeChange = Change({
Fees memory feeChange = Fees({
tokenFeeDenominator: tokenFee,
investmentFeeDenominator: investmentFee,
continuousFundraisungFeeDenominator: investmentFee,
personalInviteFeeDenominator: 100,
time: block.timestamp + delayAnnounced
});
vm.prank(admin);
Expand All @@ -145,7 +157,7 @@ contract FeeSettingsTest is Test {
_feeSettings.executeFeeChange();

assertEq(_feeSettings.tokenFeeDenominator(), tokenFee);
assertEq(_feeSettings.investmentFeeDenominator(), investmentFee);
assertEq(_feeSettings.continuousFundraisungFeeDenominator(), investmentFee);
//assertEq(_feeSettings.change, 0);
}

Expand All @@ -156,14 +168,15 @@ contract FeeSettingsTest is Test {
vm.assume(feeInValidRange(tokenFee));
vm.assume(feeInValidRange(investmentFee));
FeeSettings _feeSettings;
_feeSettings = new FeeSettings(tokenFee, investmentFee, admin);
Fees memory fees = Fees(tokenFee,investmentFee,investmentFee,0);
_feeSettings = new FeeSettings(fees, admin);
assertEq(
_feeSettings.tokenFeeDenominator(),
tokenFee,
"Token fee mismatch"
);
assertEq(
_feeSettings.investmentFeeDenominator(),
_feeSettings.continuousFundraisungFeeDenominator(),
investmentFee,
"Investment fee mismatch"
);
Expand All @@ -172,13 +185,15 @@ contract FeeSettingsTest is Test {
function testFeeCollector0FailsInConstructor() public {
vm.expectRevert("Fee collector cannot be 0x0");
FeeSettings _feeSettings;
_feeSettings = new FeeSettings(100, 100, address(0));
Fees memory fees = Fees(100,100,100,0);
_feeSettings = new FeeSettings(fees, address(0));
}

function testFeeCollector0FailsInSetter() public {
FeeSettings _feeSettings;
Fees memory fees = Fees(100,100,100,0);
vm.prank(admin);
_feeSettings = new FeeSettings(100, 100, admin);
_feeSettings = new FeeSettings(fees, admin);
vm.expectRevert("Fee collector cannot be 0x0");
vm.prank(admin);
_feeSettings.setFeeCollector(address(0));
Expand All @@ -187,8 +202,9 @@ contract FeeSettingsTest is Test {
function testUpdateFeeCollector(address newCollector) public {
vm.assume(newCollector != address(0));
FeeSettings _feeSettings;
Fees memory fees = Fees(100,100,100,0);
vm.prank(admin);
_feeSettings = new FeeSettings(100, 100, admin);
_feeSettings = new FeeSettings(fees, admin);
vm.prank(admin);
_feeSettings.setFeeCollector(newCollector);
assertEq(_feeSettings.feeCollector(), newCollector);
Expand Down
Loading

0 comments on commit bcc242a

Please sign in to comment.