@bananapus/core-v6 0.0.32 → 0.0.34
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ADMINISTRATION.md +8 -7
- package/RISKS.md +38 -1
- package/package.json +2 -2
- package/references/entrypoints.md +1 -1
- package/script/Deploy.s.sol +2 -1
- package/src/JBERC20.sol +101 -30
- package/src/JBRulesets.sol +67 -94
- package/src/JBTerminalStore.sol +64 -23
- package/src/JBTokens.sol +1 -1
- package/src/abstract/JBPermissioned.sol +28 -0
- package/src/interfaces/IJBRulesetDataHook.sol +6 -1
- package/src/interfaces/IJBToken.sol +3 -3
- package/test/TestCashOutHooks.sol +12 -2
- package/test/TestDataHookFuzzing.sol +4 -4
- package/test/TestForwardedTokenConsumption.sol +7 -1
- package/test/TestJBERC20Inheritance.sol +3 -1
- package/test/TestTokenFlow.sol +2 -2
- package/test/audit/CashOutReenterPay.t.sol +5 -0
- package/test/audit/CodexHeldFeeRounding.t.sol +159 -0
- package/test/helpers/TestBaseWorkflow.sol +1 -1
- package/test/units/static/JBERC20/JBERC20Setup.sol +8 -3
- package/test/units/static/JBERC20/TestInitialize.sol +12 -13
- package/test/units/static/JBERC20/TestName.sol +1 -1
- package/test/units/static/JBERC20/TestNonces.sol +2 -1
- package/test/units/static/JBERC20/TestSymbol.sol +1 -1
- package/test/units/static/JBTerminalStore/TestPreviewCashOutFrom.sol +1 -1
- package/test/units/static/JBTerminalStore/TestRecordCashOutsFor.sol +4 -4
- package/test/units/static/JBTokens/JBTokensSetup.sol +5 -1
|
@@ -3,6 +3,8 @@ pragma solidity 0.8.28;
|
|
|
3
3
|
|
|
4
4
|
import {TestBaseWorkflow} from "./helpers/TestBaseWorkflow.sol";
|
|
5
5
|
import {JBERC20} from "../src/JBERC20.sol";
|
|
6
|
+
import {IJBPermissions} from "../src/interfaces/IJBPermissions.sol";
|
|
7
|
+
import {IJBProjects} from "../src/interfaces/IJBProjects.sol";
|
|
6
8
|
import {IJBRulesetApprovalHook} from "../src/interfaces/IJBRulesetApprovalHook.sol";
|
|
7
9
|
import {IJBToken} from "../src/interfaces/IJBToken.sol";
|
|
8
10
|
import {JBConstants} from "../src/libraries/JBConstants.sol";
|
|
@@ -15,7 +17,7 @@ import {JBTerminalConfig} from "../src/structs/JBTerminalConfig.sol";
|
|
|
15
17
|
|
|
16
18
|
import {ERC20Votes} from "../src/JBERC20.sol";
|
|
17
19
|
|
|
18
|
-
contract JBERC20Inheritance_Local is JBERC20, TestBaseWorkflow {
|
|
20
|
+
contract JBERC20Inheritance_Local is JBERC20(IJBPermissions(address(1)), IJBProjects(address(2))), TestBaseWorkflow {
|
|
19
21
|
/// This test is to verify that the inheritance order of JBERC20 is correct and that it calls the
|
|
20
22
|
/// `ERC20Votes._update()`
|
|
21
23
|
/// forge-config: default.allow_internal_expect_revert = true
|
package/test/TestTokenFlow.sol
CHANGED
|
@@ -99,8 +99,8 @@ contract TestTokenFlow_Local is TestBaseWorkflow {
|
|
|
99
99
|
});
|
|
100
100
|
} else {
|
|
101
101
|
// Create a new `IJBToken` and change it's owner to the `JBTokens` contract.
|
|
102
|
-
IJBToken _newToken = IJBToken(Clones.clone(address(new JBERC20())));
|
|
103
|
-
_newToken.initialize({name: "NewTestName", symbol: "NewTestSymbol",
|
|
102
|
+
IJBToken _newToken = IJBToken(Clones.clone(address(new JBERC20(jbPermissions(), jbProjects()))));
|
|
103
|
+
_newToken.initialize({name: "NewTestName", symbol: "NewTestSymbol", tokens: address(_tokens)});
|
|
104
104
|
|
|
105
105
|
// Mock the token can be added to the project.
|
|
106
106
|
vm.mockCall(
|
|
@@ -260,6 +260,7 @@ contract CashOutReenterPay is TestBaseWorkflow {
|
|
|
260
260
|
ruleset.cashOutTaxRate(), // Use the ruleset's 50% cash out tax rate.
|
|
261
261
|
cashOutCount, // Number of tokens being cashed out.
|
|
262
262
|
totalSupply, // Total supply for the bonding curve.
|
|
263
|
+
PAY_AMOUNT, // effectiveSurplusValue — full initial funding, no payouts yet.
|
|
263
264
|
specifications // Our malicious hook specification.
|
|
264
265
|
)
|
|
265
266
|
);
|
|
@@ -475,6 +476,9 @@ contract CashOutReenterPay is TestBaseWorkflow {
|
|
|
475
476
|
// Read the current total supply for the bonding curve calculation.
|
|
476
477
|
uint256 totalSupply = _tokens.totalSupplyOf(_projectId);
|
|
477
478
|
|
|
479
|
+
// Read the current surplus for the bonding curve.
|
|
480
|
+
uint256 surplus = jbTerminalStore().balanceOf(address(_terminal), _projectId, JBConstants.NATIVE_TOKEN);
|
|
481
|
+
|
|
478
482
|
// Mock the data hook to return no hook specifications (simple cashout).
|
|
479
483
|
vm.mockCall(
|
|
480
484
|
DATA_HOOK,
|
|
@@ -483,6 +487,7 @@ contract CashOutReenterPay is TestBaseWorkflow {
|
|
|
483
487
|
ruleset.cashOutTaxRate(), // Pass through the ruleset's tax rate.
|
|
484
488
|
cashOutCount, // Number of tokens being cashed out.
|
|
485
489
|
totalSupply, // Current total supply.
|
|
490
|
+
surplus, // effectiveSurplusValue — current terminal balance.
|
|
486
491
|
new JBCashOutHookSpecification[](0) // No hooks for this cashout.
|
|
487
492
|
)
|
|
488
493
|
);
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
pragma solidity ^0.8.6;
|
|
3
|
+
|
|
4
|
+
import {TestBaseWorkflow} from "../helpers/TestBaseWorkflow.sol";
|
|
5
|
+
import {IJBController} from "../../src/interfaces/IJBController.sol";
|
|
6
|
+
import {IJBMultiTerminal} from "../../src/interfaces/IJBMultiTerminal.sol";
|
|
7
|
+
import {IJBRulesetApprovalHook} from "../../src/interfaces/IJBRulesetApprovalHook.sol";
|
|
8
|
+
import {JBConstants} from "../../src/libraries/JBConstants.sol";
|
|
9
|
+
import {JBAccountingContext} from "../../src/structs/JBAccountingContext.sol";
|
|
10
|
+
import {JBCurrencyAmount} from "../../src/structs/JBCurrencyAmount.sol";
|
|
11
|
+
import {JBFundAccessLimitGroup} from "../../src/structs/JBFundAccessLimitGroup.sol";
|
|
12
|
+
import {JBRulesetConfig} from "../../src/structs/JBRulesetConfig.sol";
|
|
13
|
+
import {JBRulesetMetadata} from "../../src/structs/JBRulesetMetadata.sol";
|
|
14
|
+
import {JBSplitGroup} from "../../src/structs/JBSplitGroup.sol";
|
|
15
|
+
import {JBTerminalConfig} from "../../src/structs/JBTerminalConfig.sol";
|
|
16
|
+
|
|
17
|
+
contract CodexHeldFeeRoundingTest is TestBaseWorkflow {
|
|
18
|
+
IJBController private _controller;
|
|
19
|
+
IJBMultiTerminal private _terminal;
|
|
20
|
+
|
|
21
|
+
uint256 private _projectId;
|
|
22
|
+
address private _projectOwner;
|
|
23
|
+
address private _beneficiary;
|
|
24
|
+
|
|
25
|
+
function setUp() public override {
|
|
26
|
+
super.setUp();
|
|
27
|
+
|
|
28
|
+
_projectOwner = multisig();
|
|
29
|
+
_beneficiary = beneficiary();
|
|
30
|
+
_terminal = jbMultiTerminal();
|
|
31
|
+
_controller = jbController();
|
|
32
|
+
|
|
33
|
+
JBRulesetMetadata memory metadata = JBRulesetMetadata({
|
|
34
|
+
reservedPercent: 0,
|
|
35
|
+
cashOutTaxRate: 0,
|
|
36
|
+
baseCurrency: uint32(uint160(JBConstants.NATIVE_TOKEN)),
|
|
37
|
+
pausePay: false,
|
|
38
|
+
pauseCreditTransfers: false,
|
|
39
|
+
allowOwnerMinting: false,
|
|
40
|
+
allowSetCustomToken: false,
|
|
41
|
+
allowTerminalMigration: true,
|
|
42
|
+
allowSetTerminals: false,
|
|
43
|
+
ownerMustSendPayouts: false,
|
|
44
|
+
allowSetController: false,
|
|
45
|
+
allowAddAccountingContext: true,
|
|
46
|
+
allowAddPriceFeed: false,
|
|
47
|
+
holdFees: true,
|
|
48
|
+
useTotalSurplusForCashOuts: false,
|
|
49
|
+
useDataHookForPay: false,
|
|
50
|
+
useDataHookForCashOut: false,
|
|
51
|
+
dataHook: address(0),
|
|
52
|
+
metadata: 0
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
JBCurrencyAmount[] memory payoutLimits = new JBCurrencyAmount[](1);
|
|
56
|
+
payoutLimits[0] = JBCurrencyAmount({amount: 100, currency: uint32(uint160(JBConstants.NATIVE_TOKEN))});
|
|
57
|
+
|
|
58
|
+
JBCurrencyAmount[] memory surplusAllowances = new JBCurrencyAmount[](1);
|
|
59
|
+
surplusAllowances[0] = JBCurrencyAmount({amount: 0, currency: uint32(uint160(JBConstants.NATIVE_TOKEN))});
|
|
60
|
+
|
|
61
|
+
JBFundAccessLimitGroup[] memory fundAccessLimits = new JBFundAccessLimitGroup[](1);
|
|
62
|
+
fundAccessLimits[0] = JBFundAccessLimitGroup({
|
|
63
|
+
terminal: address(_terminal),
|
|
64
|
+
token: JBConstants.NATIVE_TOKEN,
|
|
65
|
+
payoutLimits: payoutLimits,
|
|
66
|
+
surplusAllowances: surplusAllowances
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
JBRulesetConfig[] memory rulesetConfigs = new JBRulesetConfig[](1);
|
|
70
|
+
rulesetConfigs[0] = JBRulesetConfig({
|
|
71
|
+
mustStartAtOrAfter: 0,
|
|
72
|
+
duration: 0,
|
|
73
|
+
weight: 0,
|
|
74
|
+
weightCutPercent: 0,
|
|
75
|
+
approvalHook: IJBRulesetApprovalHook(address(0)),
|
|
76
|
+
metadata: metadata,
|
|
77
|
+
splitGroups: new JBSplitGroup[](0),
|
|
78
|
+
fundAccessLimitGroups: fundAccessLimits
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
JBAccountingContext[] memory contexts = new JBAccountingContext[](1);
|
|
82
|
+
contexts[0] = JBAccountingContext({
|
|
83
|
+
token: JBConstants.NATIVE_TOKEN, decimals: 18, currency: uint32(uint160(JBConstants.NATIVE_TOKEN))
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
JBTerminalConfig[] memory terminalConfigs = new JBTerminalConfig[](1);
|
|
87
|
+
terminalConfigs[0] = JBTerminalConfig({terminal: _terminal, accountingContextsToAccept: contexts});
|
|
88
|
+
|
|
89
|
+
// Project 1 is the fee project.
|
|
90
|
+
_controller.launchProjectFor({
|
|
91
|
+
owner: _projectOwner,
|
|
92
|
+
projectUri: "fee-project",
|
|
93
|
+
rulesetConfigurations: rulesetConfigs,
|
|
94
|
+
terminalConfigurations: terminalConfigs,
|
|
95
|
+
memo: ""
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
_projectId = _controller.launchProjectFor({
|
|
99
|
+
owner: _projectOwner,
|
|
100
|
+
projectUri: "project",
|
|
101
|
+
rulesetConfigurations: rulesetConfigs,
|
|
102
|
+
terminalConfigurations: terminalConfigs,
|
|
103
|
+
memo: ""
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function test_partialHeldFeeRepaymentCanEraseRemainingFee() external {
|
|
108
|
+
// Seed the project with enough balance to send a payout that holds fees.
|
|
109
|
+
_terminal.pay{value: 100}({
|
|
110
|
+
projectId: _projectId,
|
|
111
|
+
amount: 100,
|
|
112
|
+
token: JBConstants.NATIVE_TOKEN,
|
|
113
|
+
beneficiary: _beneficiary,
|
|
114
|
+
minReturnedTokens: 0,
|
|
115
|
+
memo: "",
|
|
116
|
+
metadata: new bytes(0)
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
_terminal.sendPayoutsOf({
|
|
120
|
+
projectId: _projectId,
|
|
121
|
+
token: JBConstants.NATIVE_TOKEN,
|
|
122
|
+
amount: 40,
|
|
123
|
+
currency: uint32(uint160(JBConstants.NATIVE_TOKEN)),
|
|
124
|
+
minTokensPaidOut: 0
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
// 40 gross produces a 1 wei fee and 39 wei net payout.
|
|
128
|
+
assertEq(address(_projectOwner).balance, 39);
|
|
129
|
+
|
|
130
|
+
vm.prank(_projectOwner);
|
|
131
|
+
_terminal.addToBalanceOf{value: 1}({
|
|
132
|
+
projectId: _projectId,
|
|
133
|
+
token: JBConstants.NATIVE_TOKEN,
|
|
134
|
+
amount: 1,
|
|
135
|
+
shouldReturnHeldFees: true,
|
|
136
|
+
memo: "",
|
|
137
|
+
metadata: new bytes(0)
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
// After repaying only 1 wei of the 39 wei payout, the fee should still be owed in full.
|
|
141
|
+
uint256 feeProjectBalanceBefore = jbTerminalStore().balanceOf(address(_terminal), 1, JBConstants.NATIVE_TOKEN);
|
|
142
|
+
assertEq(feeProjectBalanceBefore, 0);
|
|
143
|
+
|
|
144
|
+
vm.warp(block.timestamp + 2_419_200);
|
|
145
|
+
_terminal.processHeldFeesOf(_projectId, JBConstants.NATIVE_TOKEN, 10);
|
|
146
|
+
|
|
147
|
+
uint256 feeProjectBalanceAfter = jbTerminalStore().balanceOf(address(_terminal), 1, JBConstants.NATIVE_TOKEN);
|
|
148
|
+
uint256 projectBalanceAfter =
|
|
149
|
+
jbTerminalStore().balanceOf(address(_terminal), _projectId, JBConstants.NATIVE_TOKEN);
|
|
150
|
+
|
|
151
|
+
// The fee project never receives the original 1 wei fee.
|
|
152
|
+
assertEq(feeProjectBalanceAfter, 0);
|
|
153
|
+
// The payer project only gets its explicit top-up recorded.
|
|
154
|
+
assertEq(projectBalanceAfter, 61);
|
|
155
|
+
// One wei remains stranded in the terminal: actual native balance exceeds tracked balances.
|
|
156
|
+
assertEq(address(_terminal).balance, 62);
|
|
157
|
+
assertEq(address(_terminal).balance - (feeProjectBalanceAfter + projectBalanceAfter), 1);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
@@ -293,7 +293,7 @@ contract TestBaseWorkflow is JBTest, DeployPermit2 {
|
|
|
293
293
|
_jbPermissions = new JBPermissions(_trustedForwarder);
|
|
294
294
|
_jbProjects = new JBProjects(_multisig, address(0), _trustedForwarder);
|
|
295
295
|
_jbDirectory = new JBDirectory(_jbPermissions, _jbProjects, _multisig);
|
|
296
|
-
_jbErc20 = new JBERC20();
|
|
296
|
+
_jbErc20 = new JBERC20(_jbPermissions, _jbProjects);
|
|
297
297
|
_jbTokens = new JBTokens(_jbDirectory, _jbErc20);
|
|
298
298
|
_jbRulesets = new JBRulesets(_jbDirectory);
|
|
299
299
|
_jbPrices = new JBPrices(_jbDirectory, _jbPermissions, _jbProjects, _multisig, _trustedForwarder);
|
|
@@ -3,6 +3,8 @@ pragma solidity 0.8.28;
|
|
|
3
3
|
|
|
4
4
|
import {Clones} from "@openzeppelin/contracts/proxy/Clones.sol";
|
|
5
5
|
import {JBERC20} from "../../../../src/JBERC20.sol";
|
|
6
|
+
import {IJBPermissions} from "../../../../src/interfaces/IJBPermissions.sol";
|
|
7
|
+
import {IJBProjects} from "../../../../src/interfaces/IJBProjects.sol";
|
|
6
8
|
import {IJBToken} from "../../../../src/interfaces/IJBToken.sol";
|
|
7
9
|
import {JBTest} from "../../../helpers/JBTest.sol";
|
|
8
10
|
|
|
@@ -11,7 +13,10 @@ Contract that deploys a target contract with other mock contracts to satisfy the
|
|
|
11
13
|
Tests relative to this contract will be dependent on mock calls/emits and stdStorage.
|
|
12
14
|
*/
|
|
13
15
|
contract JBERC20Setup is JBTest {
|
|
14
|
-
|
|
16
|
+
// Mocks
|
|
17
|
+
address _tokens = makeAddr("tokens");
|
|
18
|
+
IJBProjects _projects = IJBProjects(makeAddr("projects"));
|
|
19
|
+
IJBPermissions _permissions = IJBPermissions(makeAddr("permissions"));
|
|
15
20
|
|
|
16
21
|
// Implementation (constructor sets _name = "invalid", cannot be initialized)
|
|
17
22
|
IJBToken public _implementation;
|
|
@@ -20,8 +25,8 @@ contract JBERC20Setup is JBTest {
|
|
|
20
25
|
IJBToken public _erc20;
|
|
21
26
|
|
|
22
27
|
function erc20Setup() public virtual {
|
|
23
|
-
// Deploy the implementation
|
|
24
|
-
_implementation = new JBERC20();
|
|
28
|
+
// Deploy the implementation with immutable permissions and projects
|
|
29
|
+
_implementation = new JBERC20(_permissions, _projects);
|
|
25
30
|
|
|
26
31
|
// Clone it — clones start with empty storage, so initialize() works
|
|
27
32
|
_erc20 = IJBToken(Clones.clone(address(_implementation)));
|
|
@@ -4,7 +4,6 @@ pragma solidity 0.8.28;
|
|
|
4
4
|
import {IERC20Metadata} from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
|
|
5
5
|
import {JBERC20} from "../../../../src/JBERC20.sol";
|
|
6
6
|
import {JBERC20Setup} from "./JBERC20Setup.sol";
|
|
7
|
-
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
|
|
8
7
|
|
|
9
8
|
contract TestInitialize_Local is JBERC20Setup {
|
|
10
9
|
string _name = "Nana";
|
|
@@ -17,21 +16,21 @@ contract TestInitialize_Local is JBERC20Setup {
|
|
|
17
16
|
function test_ImplementationCannotBeInitialized() external {
|
|
18
17
|
// The implementation has _name = "invalid" set in constructor, so initialize() must revert.
|
|
19
18
|
vm.expectRevert(JBERC20.JBERC20_AlreadyInitialized.selector);
|
|
20
|
-
_implementation.initialize(_name, _symbol,
|
|
19
|
+
_implementation.initialize(_name, _symbol, _tokens);
|
|
21
20
|
}
|
|
22
21
|
|
|
23
22
|
function test_WhenANameIsAlreadySet() external {
|
|
24
23
|
// it will revert
|
|
25
24
|
|
|
26
|
-
_erc20.initialize(_name, _symbol,
|
|
25
|
+
_erc20.initialize(_name, _symbol, _tokens);
|
|
27
26
|
|
|
28
|
-
// ensure
|
|
29
|
-
address
|
|
30
|
-
assertEq(
|
|
27
|
+
// ensure TOKENS is set
|
|
28
|
+
address setTokens = address(JBERC20(address(_erc20)).TOKENS());
|
|
29
|
+
assertEq(setTokens, _tokens);
|
|
31
30
|
|
|
32
31
|
// will fail as internal name is no longer zero length
|
|
33
32
|
vm.expectRevert();
|
|
34
|
-
_erc20.initialize(_name, _symbol,
|
|
33
|
+
_erc20.initialize(_name, _symbol, _tokens);
|
|
35
34
|
}
|
|
36
35
|
|
|
37
36
|
function test_WhenName_EQNothing() external {
|
|
@@ -39,17 +38,17 @@ contract TestInitialize_Local is JBERC20Setup {
|
|
|
39
38
|
|
|
40
39
|
// will fail as internal name is no longer than zero length
|
|
41
40
|
vm.expectRevert();
|
|
42
|
-
_erc20.initialize("", _symbol,
|
|
41
|
+
_erc20.initialize("", _symbol, _tokens);
|
|
43
42
|
}
|
|
44
43
|
|
|
45
44
|
function test_WhenNameIsValidAndNotAlreadySet() external {
|
|
46
|
-
// it will set the name
|
|
45
|
+
// it will set the name, symbol, and store references
|
|
47
46
|
|
|
48
|
-
_erc20.initialize(_name, _symbol,
|
|
47
|
+
_erc20.initialize(_name, _symbol, _tokens);
|
|
49
48
|
|
|
50
|
-
// ensure
|
|
51
|
-
address
|
|
52
|
-
assertEq(
|
|
49
|
+
// ensure TOKENS is set
|
|
50
|
+
address setTokens = address(JBERC20(address(_erc20)).TOKENS());
|
|
51
|
+
assertEq(setTokens, _tokens);
|
|
53
52
|
|
|
54
53
|
// name is set
|
|
55
54
|
string memory _setName = IERC20Metadata(address(_erc20)).name();
|
|
@@ -15,7 +15,7 @@ contract TestName_Local is JBERC20Setup {
|
|
|
15
15
|
|
|
16
16
|
function test_WhenANameIsSet() external {
|
|
17
17
|
// it will return the name
|
|
18
|
-
_erc20.initialize("NANAPUS", "NANA",
|
|
18
|
+
_erc20.initialize("NANAPUS", "NANA", _tokens);
|
|
19
19
|
|
|
20
20
|
string memory _setName = _token.name();
|
|
21
21
|
assertEq(_setName, "NANAPUS");
|
|
@@ -6,6 +6,7 @@ import {JBERC20Setup} from "./JBERC20Setup.sol";
|
|
|
6
6
|
import {SigUtils} from "./SigUtils.sol";
|
|
7
7
|
|
|
8
8
|
contract TestNonces_Local is JBERC20Setup {
|
|
9
|
+
address _user = makeAddr("user");
|
|
9
10
|
IERC20Permit _token;
|
|
10
11
|
SigUtils sigUtils;
|
|
11
12
|
|
|
@@ -30,7 +31,7 @@ contract TestNonces_Local is JBERC20Setup {
|
|
|
30
31
|
function test_WhenAUserHasNotCalledPermit() external view {
|
|
31
32
|
// it will return zero
|
|
32
33
|
|
|
33
|
-
uint256 _nonce = _token.nonces(
|
|
34
|
+
uint256 _nonce = _token.nonces(_user);
|
|
34
35
|
|
|
35
36
|
assertEq(_nonce, 0);
|
|
36
37
|
}
|
|
@@ -16,7 +16,7 @@ contract TestSymbol_Local is JBERC20Setup {
|
|
|
16
16
|
function test_WhenASymbolIsSet() external {
|
|
17
17
|
// it will return a non-empty string
|
|
18
18
|
|
|
19
|
-
_erc20.initialize("NANAPUS", "NANA",
|
|
19
|
+
_erc20.initialize("NANAPUS", "NANA", _tokens);
|
|
20
20
|
|
|
21
21
|
string memory _setSymbol = _token.symbol();
|
|
22
22
|
assertEq(_setSymbol, "NANA");
|
|
@@ -453,7 +453,7 @@ contract TestPreviewCashOutFor_Local is JBTerminalStoreSetup {
|
|
|
453
453
|
mockExpect(
|
|
454
454
|
address(_dataHook),
|
|
455
455
|
abi.encodeCall(IJBRulesetDataHook.beforeCashOutRecordedWith, (_context)),
|
|
456
|
-
abi.encode(0, 10e18, _totalSupply, _spec)
|
|
456
|
+
abi.encode(0, 10e18, _totalSupply, 3e18, _spec)
|
|
457
457
|
);
|
|
458
458
|
|
|
459
459
|
(, uint256 reclaimAmount, uint256 cashOutTaxRate, JBCashOutHookSpecification[] memory hookSpecifications) = _store.previewCashOutFrom({
|
|
@@ -417,7 +417,7 @@ contract TestRecordCashOutsFor_Local is JBTerminalStoreSetup {
|
|
|
417
417
|
mockExpect(
|
|
418
418
|
address(_dataHook),
|
|
419
419
|
abi.encodeCall(IJBRulesetDataHook.beforeCashOutRecordedWith, (_context)),
|
|
420
|
-
abi.encode(0, 1e18, _totalSupply, _spec)
|
|
420
|
+
abi.encode(0, 1e18, _totalSupply, 3e18, _spec)
|
|
421
421
|
);
|
|
422
422
|
|
|
423
423
|
uint256 balanceBefore = _store.balanceOf(address(this), _projectId, _accountingContexts.token);
|
|
@@ -521,7 +521,7 @@ contract TestRecordCashOutsFor_Local is JBTerminalStoreSetup {
|
|
|
521
521
|
mockExpect(
|
|
522
522
|
address(_dataHook),
|
|
523
523
|
abi.encodeCall(IJBRulesetDataHook.beforeCashOutRecordedWith, (_context)),
|
|
524
|
-
abi.encode(0, 1e18, _totalSupply, _spec)
|
|
524
|
+
abi.encode(0, 1e18, _totalSupply, 3e18, _spec)
|
|
525
525
|
);
|
|
526
526
|
|
|
527
527
|
(, uint256 reclaimed,,) = _store.recordCashOutFor({
|
|
@@ -576,7 +576,7 @@ contract TestRecordCashOutsFor_Local is JBTerminalStoreSetup {
|
|
|
576
576
|
mockExpect(
|
|
577
577
|
address(_dataHook),
|
|
578
578
|
abi.encodeCall(IJBRulesetDataHook.beforeCashOutRecordedWith, (_context)),
|
|
579
|
-
abi.encode(0, 1e18, _totalSupply, _spec)
|
|
579
|
+
abi.encode(0, 1e18, _totalSupply, 3e18, _spec)
|
|
580
580
|
);
|
|
581
581
|
|
|
582
582
|
vm.expectRevert(abi.encodeWithSelector(JBTerminalStore.JBTerminalStore_NoopHookSpecHasAmount.selector, 1));
|
|
@@ -631,7 +631,7 @@ contract TestRecordCashOutsFor_Local is JBTerminalStoreSetup {
|
|
|
631
631
|
mockExpect(
|
|
632
632
|
address(_dataHook),
|
|
633
633
|
abi.encodeCall(IJBRulesetDataHook.beforeCashOutRecordedWith, (_context)),
|
|
634
|
-
abi.encode(0, 1e18, _totalSupply, _spec)
|
|
634
|
+
abi.encode(0, 1e18, _totalSupply, 3e18, _spec)
|
|
635
635
|
);
|
|
636
636
|
|
|
637
637
|
vm.expectRevert(abi.encodeWithSelector(JBTerminalStore.JBTerminalStore_NoopHookSpecHasAmount.selector, 1));
|
|
@@ -4,6 +4,8 @@ pragma solidity 0.8.28;
|
|
|
4
4
|
import {JBERC20} from "../../../../src/JBERC20.sol";
|
|
5
5
|
import {JBTokens} from "../../../../src/JBTokens.sol";
|
|
6
6
|
import {IJBDirectory} from "../../../../src/interfaces/IJBDirectory.sol";
|
|
7
|
+
import {IJBPermissions} from "../../../../src/interfaces/IJBPermissions.sol";
|
|
8
|
+
import {IJBProjects} from "../../../../src/interfaces/IJBProjects.sol";
|
|
7
9
|
import {IJBToken} from "../../../../src/interfaces/IJBToken.sol";
|
|
8
10
|
import {IJBTokens} from "../../../../src/interfaces/IJBTokens.sol";
|
|
9
11
|
import {JBTest} from "../../../helpers/JBTest.sol";
|
|
@@ -15,6 +17,8 @@ Tests relative to this contract will be dependent on mock calls/emits and stdSto
|
|
|
15
17
|
contract JBTokensSetup is JBTest {
|
|
16
18
|
// Mocks
|
|
17
19
|
IJBDirectory public directory = IJBDirectory(makeAddr("directory"));
|
|
20
|
+
IJBPermissions public permissions = IJBPermissions(makeAddr("permissions"));
|
|
21
|
+
IJBProjects public projects = IJBProjects(makeAddr("projects"));
|
|
18
22
|
IJBToken public jbToken;
|
|
19
23
|
|
|
20
24
|
// Target Contract
|
|
@@ -22,7 +26,7 @@ contract JBTokensSetup is JBTest {
|
|
|
22
26
|
|
|
23
27
|
function tokensSetup() public virtual {
|
|
24
28
|
// Instantiate the contract being tested
|
|
25
|
-
jbToken = new JBERC20();
|
|
29
|
+
jbToken = new JBERC20(permissions, projects);
|
|
26
30
|
_tokens = new JBTokens(directory, jbToken);
|
|
27
31
|
}
|
|
28
32
|
}
|