create-kozalak-l1 0.1.0
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/README.md +87 -0
- package/dist/deploy.js +63 -0
- package/dist/forge.js +27 -0
- package/dist/index.js +176 -0
- package/dist/prompts.js +23 -0
- package/dist/scaffold.js +33 -0
- package/dist/templates.js +108 -0
- package/package.json +29 -0
- package/templates/erc20-gas/.env.example +19 -0
- package/templates/erc20-gas/.gitmodules +6 -0
- package/templates/erc20-gas/README.md +48 -0
- package/templates/erc20-gas/foundry.toml +35 -0
- package/templates/erc20-gas/gitignore +5 -0
- package/templates/erc20-gas/remappings.txt +2 -0
- package/templates/erc20-gas/script/DeployERC20Gas.s.sol +131 -0
- package/templates/erc20-gas/src/KozaGasToken.sol +105 -0
- package/templates/erc20-gas/test/DeployERC20Gas.t.sol +60 -0
- package/templates/erc20-gas/test/ERC20Gas.invariants.t.sol +144 -0
- package/templates/erc20-gas/test/ERC20Gas.t.sol +354 -0
- package/templates/erc721-collection/.env.example +37 -0
- package/templates/erc721-collection/.gitmodules +6 -0
- package/templates/erc721-collection/README.md +48 -0
- package/templates/erc721-collection/foundry.toml +35 -0
- package/templates/erc721-collection/gitignore +5 -0
- package/templates/erc721-collection/remappings.txt +2 -0
- package/templates/erc721-collection/script/DeployERC721Collection.s.sol +151 -0
- package/templates/erc721-collection/src/KozaCollection.sol +281 -0
- package/templates/erc721-collection/test/DeployERC721Collection.t.sol +76 -0
- package/templates/erc721-collection/test/ERC721Collection.invariants.t.sol +175 -0
- package/templates/erc721-collection/test/ERC721Collection.t.sol +501 -0
- package/templates/ictt-bridge/.env.example +19 -0
- package/templates/ictt-bridge/.gitmodules +9 -0
- package/templates/ictt-bridge/README.md +49 -0
- package/templates/ictt-bridge/foundry.toml +41 -0
- package/templates/ictt-bridge/gitignore +5 -0
- package/templates/ictt-bridge/remappings.txt +8 -0
- package/templates/ictt-bridge/script/DeployTokenHome.s.sol +139 -0
- package/templates/ictt-bridge/src/KozaTokenHome.sol +57 -0
- package/templates/ictt-bridge/src/KozaTokenRemote.sol +65 -0
- package/templates/ictt-bridge/test/ICTTBridge.t.sol +157 -0
- package/templates/soulbound-credential/.env.example +19 -0
- package/templates/soulbound-credential/.gitmodules +6 -0
- package/templates/soulbound-credential/README.md +48 -0
- package/templates/soulbound-credential/foundry.toml +35 -0
- package/templates/soulbound-credential/gitignore +5 -0
- package/templates/soulbound-credential/remappings.txt +2 -0
- package/templates/soulbound-credential/script/DeployCredential.s.sol +126 -0
- package/templates/soulbound-credential/src/KozaCredential.sol +201 -0
- package/templates/soulbound-credential/test/DeployCredential.t.sol +46 -0
- package/templates/soulbound-credential/test/Soulbound.invariants.t.sol +133 -0
- package/templates/soulbound-credential/test/Soulbound.t.sol +319 -0
- package/templates/treasury-multisig/.env.example +19 -0
- package/templates/treasury-multisig/.gitmodules +6 -0
- package/templates/treasury-multisig/README.md +48 -0
- package/templates/treasury-multisig/foundry.toml +35 -0
- package/templates/treasury-multisig/gitignore +5 -0
- package/templates/treasury-multisig/remappings.txt +2 -0
- package/templates/treasury-multisig/script/DeployTreasury.s.sol +128 -0
- package/templates/treasury-multisig/src/KozaTreasury.sol +55 -0
- package/templates/treasury-multisig/test/DeployTreasury.t.sol +50 -0
- package/templates/treasury-multisig/test/Treasury.t.sol +154 -0
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
pragma solidity 0.8.34;
|
|
3
|
+
|
|
4
|
+
import {Test} from "forge-std/Test.sol";
|
|
5
|
+
import {DeployTreasury} from "../script/DeployTreasury.s.sol";
|
|
6
|
+
import {KozaTreasury} from "../src/KozaTreasury.sol";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @title DeployTreasuryTest
|
|
10
|
+
* @notice Smoke tests for the Treasury deploy script. Calls `deploy(...)` directly;
|
|
11
|
+
* env-driven `run()` exercised on Fuji integration.
|
|
12
|
+
*/
|
|
13
|
+
contract DeployTreasuryTest is Test {
|
|
14
|
+
function test_Deploy_SetsDelayAndRoles() public {
|
|
15
|
+
DeployTreasury deployer = new DeployTreasury();
|
|
16
|
+
address broadcaster = makeAddr("broadcaster");
|
|
17
|
+
address admin = makeAddr("admin");
|
|
18
|
+
|
|
19
|
+
address[] memory proposers = new address[](1);
|
|
20
|
+
proposers[0] = makeAddr("proposer");
|
|
21
|
+
address[] memory executors = new address[](1);
|
|
22
|
+
executors[0] = makeAddr("executor");
|
|
23
|
+
|
|
24
|
+
(KozaTreasury treasury, address returnedDeployer) =
|
|
25
|
+
deployer.deploy(48 hours, proposers, executors, admin, broadcaster);
|
|
26
|
+
|
|
27
|
+
assertEq(treasury.getMinDelay(), 48 hours);
|
|
28
|
+
assertTrue(treasury.hasRole(treasury.PROPOSER_ROLE(), proposers[0]));
|
|
29
|
+
assertTrue(treasury.hasRole(treasury.CANCELLER_ROLE(), proposers[0]));
|
|
30
|
+
assertTrue(treasury.hasRole(treasury.EXECUTOR_ROLE(), executors[0]));
|
|
31
|
+
assertTrue(treasury.hasRole(treasury.DEFAULT_ADMIN_ROLE(), admin));
|
|
32
|
+
assertEq(returnedDeployer, broadcaster);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function test_Deploy_OpenExecutor() public {
|
|
36
|
+
DeployTreasury deployer = new DeployTreasury();
|
|
37
|
+
address broadcaster = makeAddr("broadcaster");
|
|
38
|
+
|
|
39
|
+
address[] memory proposers = new address[](1);
|
|
40
|
+
proposers[0] = makeAddr("proposer");
|
|
41
|
+
address[] memory executors = new address[](1);
|
|
42
|
+
executors[0] = address(0); // açık execute
|
|
43
|
+
|
|
44
|
+
(KozaTreasury treasury,) = deployer.deploy(1 days, proposers, executors, broadcaster, broadcaster);
|
|
45
|
+
|
|
46
|
+
// address(0) executor → herkes EXECUTOR_ROLE'a sahip sayılır (onlyRoleOrOpenRole)
|
|
47
|
+
assertTrue(treasury.hasRole(treasury.EXECUTOR_ROLE(), address(0)));
|
|
48
|
+
assertEq(treasury.getMinDelay(), 1 days);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
pragma solidity 0.8.34;
|
|
3
|
+
|
|
4
|
+
import {Test} from "forge-std/Test.sol";
|
|
5
|
+
import {KozaTreasury} from "../src/KozaTreasury.sol";
|
|
6
|
+
import {TimelockController} from "@openzeppelin/contracts/governance/TimelockController.sol";
|
|
7
|
+
import {IAccessControl} from "@openzeppelin/contracts/access/IAccessControl.sol";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* @title TreasuryTest
|
|
11
|
+
* @notice Smoke tests for KozaTreasury (Phase 1, Template 5) — TimelockController wrapper.
|
|
12
|
+
* @dev Wrapper olduğu için TimelockController'ın iç mantığını yeniden test etmiyoruz;
|
|
13
|
+
* sadece constructor forwarding'in doğru rolleri/delay'i kurduğunu ve uçtan uca bir
|
|
14
|
+
* schedule→bekle→execute akışının çalıştığını doğruluyoruz (audited library trust).
|
|
15
|
+
*/
|
|
16
|
+
contract TreasuryTest is Test {
|
|
17
|
+
KozaTreasury internal treasury;
|
|
18
|
+
|
|
19
|
+
address internal admin;
|
|
20
|
+
address internal proposer;
|
|
21
|
+
address internal executor;
|
|
22
|
+
address internal alice;
|
|
23
|
+
address payable internal recipient;
|
|
24
|
+
|
|
25
|
+
uint256 internal constant MIN_DELAY = 2 days;
|
|
26
|
+
|
|
27
|
+
bytes32 internal PROPOSER_ROLE;
|
|
28
|
+
bytes32 internal EXECUTOR_ROLE;
|
|
29
|
+
bytes32 internal CANCELLER_ROLE;
|
|
30
|
+
|
|
31
|
+
function setUp() public {
|
|
32
|
+
admin = makeAddr("admin");
|
|
33
|
+
proposer = makeAddr("proposer");
|
|
34
|
+
executor = makeAddr("executor");
|
|
35
|
+
alice = makeAddr("alice");
|
|
36
|
+
recipient = payable(makeAddr("recipient"));
|
|
37
|
+
|
|
38
|
+
address[] memory proposers = new address[](1);
|
|
39
|
+
proposers[0] = proposer;
|
|
40
|
+
address[] memory executors = new address[](1);
|
|
41
|
+
executors[0] = executor;
|
|
42
|
+
|
|
43
|
+
treasury = new KozaTreasury(MIN_DELAY, proposers, executors, admin);
|
|
44
|
+
|
|
45
|
+
PROPOSER_ROLE = treasury.PROPOSER_ROLE();
|
|
46
|
+
EXECUTOR_ROLE = treasury.EXECUTOR_ROLE();
|
|
47
|
+
CANCELLER_ROLE = treasury.CANCELLER_ROLE();
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/*//////////////////////////////////////////////////////////////
|
|
51
|
+
CONSTRUCTOR
|
|
52
|
+
//////////////////////////////////////////////////////////////*/
|
|
53
|
+
|
|
54
|
+
function test_Constructor_SetsRolesAndDelay() public view {
|
|
55
|
+
assertEq(treasury.getMinDelay(), MIN_DELAY);
|
|
56
|
+
assertTrue(treasury.hasRole(PROPOSER_ROLE, proposer));
|
|
57
|
+
assertTrue(treasury.hasRole(CANCELLER_ROLE, proposer));
|
|
58
|
+
assertTrue(treasury.hasRole(EXECUTOR_ROLE, executor));
|
|
59
|
+
assertTrue(treasury.hasRole(treasury.DEFAULT_ADMIN_ROLE(), admin));
|
|
60
|
+
assertFalse(treasury.hasRole(PROPOSER_ROLE, alice));
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function test_Constructor_AcceptsNativeFunds() public {
|
|
64
|
+
vm.deal(address(this), 5 ether);
|
|
65
|
+
(bool ok,) = address(treasury).call{value: 1 ether}("");
|
|
66
|
+
assertTrue(ok);
|
|
67
|
+
assertEq(address(treasury).balance, 1 ether);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/*//////////////////////////////////////////////////////////////
|
|
71
|
+
SCHEDULE → EXECUTE
|
|
72
|
+
//////////////////////////////////////////////////////////////*/
|
|
73
|
+
|
|
74
|
+
function test_ScheduleThenExecute_ReleasesFundsAfterDelay() public {
|
|
75
|
+
vm.deal(address(treasury), 10 ether);
|
|
76
|
+
|
|
77
|
+
bytes memory data = "";
|
|
78
|
+
bytes32 predecessor = bytes32(0);
|
|
79
|
+
bytes32 salt = bytes32(uint256(1));
|
|
80
|
+
|
|
81
|
+
vm.prank(proposer);
|
|
82
|
+
treasury.schedule(recipient, 3 ether, data, predecessor, salt, MIN_DELAY);
|
|
83
|
+
|
|
84
|
+
// delay dolmadan execute → revert
|
|
85
|
+
vm.expectRevert();
|
|
86
|
+
vm.prank(executor);
|
|
87
|
+
treasury.execute(recipient, 3 ether, data, predecessor, salt);
|
|
88
|
+
|
|
89
|
+
// delay sonrası execute → fonlar serbest
|
|
90
|
+
vm.warp(block.timestamp + MIN_DELAY);
|
|
91
|
+
vm.prank(executor);
|
|
92
|
+
treasury.execute(recipient, 3 ether, data, predecessor, salt);
|
|
93
|
+
|
|
94
|
+
assertEq(recipient.balance, 3 ether);
|
|
95
|
+
assertEq(address(treasury).balance, 7 ether);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function test_RevertWhen_ScheduleNotProposer() public {
|
|
99
|
+
vm.expectRevert(
|
|
100
|
+
abi.encodeWithSelector(IAccessControl.AccessControlUnauthorizedAccount.selector, alice, PROPOSER_ROLE)
|
|
101
|
+
);
|
|
102
|
+
vm.prank(alice);
|
|
103
|
+
treasury.schedule(recipient, 1 ether, "", bytes32(0), bytes32(0), MIN_DELAY);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function test_RevertWhen_ExecuteNotExecutor() public {
|
|
107
|
+
vm.deal(address(treasury), 1 ether);
|
|
108
|
+
vm.prank(proposer);
|
|
109
|
+
treasury.schedule(recipient, 1 ether, "", bytes32(0), bytes32(0), MIN_DELAY);
|
|
110
|
+
vm.warp(block.timestamp + MIN_DELAY);
|
|
111
|
+
|
|
112
|
+
vm.expectRevert(
|
|
113
|
+
abi.encodeWithSelector(IAccessControl.AccessControlUnauthorizedAccount.selector, alice, EXECUTOR_ROLE)
|
|
114
|
+
);
|
|
115
|
+
vm.prank(alice);
|
|
116
|
+
treasury.execute(recipient, 1 ether, "", bytes32(0), bytes32(0));
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function test_RevertWhen_ScheduleDelayBelowMinimum() public {
|
|
120
|
+
vm.expectRevert();
|
|
121
|
+
vm.prank(proposer);
|
|
122
|
+
treasury.schedule(recipient, 1 ether, "", bytes32(0), bytes32(0), MIN_DELAY - 1);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/*//////////////////////////////////////////////////////////////
|
|
126
|
+
CANCEL
|
|
127
|
+
//////////////////////////////////////////////////////////////*/
|
|
128
|
+
|
|
129
|
+
function test_Cancel_ByCanceller() public {
|
|
130
|
+
bytes32 salt = bytes32(uint256(7));
|
|
131
|
+
vm.prank(proposer);
|
|
132
|
+
treasury.schedule(recipient, 1 ether, "", bytes32(0), salt, MIN_DELAY);
|
|
133
|
+
|
|
134
|
+
bytes32 id = treasury.hashOperation(recipient, 1 ether, "", bytes32(0), salt);
|
|
135
|
+
assertTrue(treasury.isOperationPending(id));
|
|
136
|
+
|
|
137
|
+
vm.prank(proposer); // proposer also holds CANCELLER_ROLE
|
|
138
|
+
treasury.cancel(id);
|
|
139
|
+
assertFalse(treasury.isOperation(id));
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function test_RevertWhen_CancelNotCanceller() public {
|
|
143
|
+
bytes32 salt = bytes32(uint256(9));
|
|
144
|
+
vm.prank(proposer);
|
|
145
|
+
treasury.schedule(recipient, 1 ether, "", bytes32(0), salt, MIN_DELAY);
|
|
146
|
+
bytes32 id = treasury.hashOperation(recipient, 1 ether, "", bytes32(0), salt);
|
|
147
|
+
|
|
148
|
+
vm.expectRevert(
|
|
149
|
+
abi.encodeWithSelector(IAccessControl.AccessControlUnauthorizedAccount.selector, alice, CANCELLER_ROLE)
|
|
150
|
+
);
|
|
151
|
+
vm.prank(alice);
|
|
152
|
+
treasury.cancel(id);
|
|
153
|
+
}
|
|
154
|
+
}
|