@boostxyz/sdk 0.0.0-alpha.2 → 0.0.0-alpha.21

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.
Files changed (271) hide show
  1. package/dist/Actions/Action.cjs +2 -1
  2. package/dist/Actions/Action.cjs.map +1 -0
  3. package/dist/Actions/Action.d.ts +1 -1
  4. package/dist/Actions/Action.d.ts.map +1 -1
  5. package/dist/Actions/Action.js +14 -12
  6. package/dist/Actions/Action.js.map +1 -0
  7. package/dist/Actions/ContractAction.d.ts +57 -14
  8. package/dist/Actions/ContractAction.d.ts.map +1 -1
  9. package/dist/Actions/ERC721MintAction.d.ts +50 -23
  10. package/dist/Actions/ERC721MintAction.d.ts.map +1 -1
  11. package/dist/Actions/EventAction.cjs +2 -1
  12. package/dist/Actions/EventAction.cjs.map +1 -0
  13. package/dist/Actions/EventAction.d.ts +405 -36
  14. package/dist/Actions/EventAction.d.ts.map +1 -1
  15. package/dist/Actions/EventAction.js +15 -209
  16. package/dist/Actions/EventAction.js.map +1 -0
  17. package/dist/AllowLists/AllowList.cjs +2 -1
  18. package/dist/AllowLists/AllowList.cjs.map +1 -0
  19. package/dist/AllowLists/AllowList.d.ts +6 -5
  20. package/dist/AllowLists/AllowList.d.ts.map +1 -1
  21. package/dist/AllowLists/AllowList.js +46 -22
  22. package/dist/AllowLists/AllowList.js.map +1 -0
  23. package/dist/AllowLists/OpenAllowList.d.ts +423 -0
  24. package/dist/AllowLists/OpenAllowList.d.ts.map +1 -0
  25. package/dist/AllowLists/SimpleAllowList.cjs +2 -1
  26. package/dist/AllowLists/SimpleAllowList.cjs.map +1 -0
  27. package/dist/AllowLists/SimpleAllowList.d.ts +124 -40
  28. package/dist/AllowLists/SimpleAllowList.d.ts.map +1 -1
  29. package/dist/AllowLists/SimpleAllowList.js +76 -76
  30. package/dist/AllowLists/SimpleAllowList.js.map +1 -0
  31. package/dist/AllowLists/SimpleDenyList.cjs +2 -1
  32. package/dist/AllowLists/SimpleDenyList.cjs.map +1 -0
  33. package/dist/AllowLists/SimpleDenyList.d.ts +234 -13
  34. package/dist/AllowLists/SimpleDenyList.d.ts.map +1 -1
  35. package/dist/AllowLists/SimpleDenyList.js +12 -200
  36. package/dist/AllowLists/SimpleDenyList.js.map +1 -0
  37. package/dist/Auth/Auth.cjs +1 -0
  38. package/dist/Auth/Auth.cjs.map +1 -0
  39. package/dist/Auth/Auth.js +1 -0
  40. package/dist/Auth/Auth.js.map +1 -0
  41. package/dist/Auth/PassthroughAuth.cjs +2 -1
  42. package/dist/Auth/PassthroughAuth.cjs.map +1 -0
  43. package/dist/Auth/PassthroughAuth.js +5 -4
  44. package/dist/Auth/PassthroughAuth.js.map +1 -0
  45. package/dist/Boost.cjs +2 -1
  46. package/dist/Boost.cjs.map +1 -0
  47. package/dist/Boost.d.ts +105 -14
  48. package/dist/Boost.d.ts.map +1 -1
  49. package/dist/Boost.js +138 -5
  50. package/dist/Boost.js.map +1 -0
  51. package/dist/BoostCore-DolmDuXW.cjs +3 -0
  52. package/dist/BoostCore-DolmDuXW.cjs.map +1 -0
  53. package/dist/BoostCore-Z97KVu4V.js +1448 -0
  54. package/dist/BoostCore-Z97KVu4V.js.map +1 -0
  55. package/dist/BoostCore.cjs +2 -2
  56. package/dist/BoostCore.cjs.map +1 -0
  57. package/dist/BoostCore.d.ts +788 -79
  58. package/dist/BoostCore.d.ts.map +1 -1
  59. package/dist/BoostCore.js +30 -1103
  60. package/dist/BoostCore.js.map +1 -0
  61. package/dist/BoostRegistry.cjs +2 -1
  62. package/dist/BoostRegistry.cjs.map +1 -0
  63. package/dist/BoostRegistry.d.ts +95 -26
  64. package/dist/BoostRegistry.d.ts.map +1 -1
  65. package/dist/BoostRegistry.js +183 -89
  66. package/dist/BoostRegistry.js.map +1 -0
  67. package/dist/Budgets/Budget.cjs +2 -1
  68. package/dist/Budgets/Budget.cjs.map +1 -0
  69. package/dist/Budgets/Budget.d.ts +1 -1
  70. package/dist/Budgets/Budget.d.ts.map +1 -1
  71. package/dist/Budgets/Budget.js +15 -13
  72. package/dist/Budgets/Budget.js.map +1 -0
  73. package/dist/Budgets/ManagedBudget.cjs +2 -1
  74. package/dist/Budgets/ManagedBudget.cjs.map +1 -0
  75. package/dist/Budgets/ManagedBudget.d.ts +112 -192
  76. package/dist/Budgets/ManagedBudget.d.ts.map +1 -1
  77. package/dist/Budgets/ManagedBudget.js +91 -291
  78. package/dist/Budgets/ManagedBudget.js.map +1 -0
  79. package/dist/Budgets/VestingBudget.d.ts +277 -91
  80. package/dist/Budgets/VestingBudget.d.ts.map +1 -1
  81. package/dist/Deployable/Contract.cjs +2 -1
  82. package/dist/Deployable/Contract.cjs.map +1 -0
  83. package/dist/Deployable/Contract.d.ts +4 -5
  84. package/dist/Deployable/Contract.d.ts.map +1 -1
  85. package/dist/Deployable/Contract.js +7 -8
  86. package/dist/Deployable/Contract.js.map +1 -0
  87. package/dist/Deployable/Deployable.cjs +1 -0
  88. package/dist/Deployable/Deployable.cjs.map +1 -0
  89. package/dist/Deployable/Deployable.d.ts +9 -3
  90. package/dist/Deployable/Deployable.d.ts.map +1 -1
  91. package/dist/Deployable/Deployable.js +10 -5
  92. package/dist/Deployable/Deployable.js.map +1 -0
  93. package/dist/Deployable/DeployableTarget.cjs +2 -1
  94. package/dist/Deployable/DeployableTarget.cjs.map +1 -0
  95. package/dist/Deployable/DeployableTarget.d.ts +16 -15
  96. package/dist/Deployable/DeployableTarget.d.ts.map +1 -1
  97. package/dist/Deployable/DeployableTarget.js +49 -42
  98. package/dist/Deployable/DeployableTarget.js.map +1 -0
  99. package/dist/Deployable/DeployableTargetWithRBAC.cjs +2 -0
  100. package/dist/Deployable/DeployableTargetWithRBAC.cjs.map +1 -0
  101. package/dist/Deployable/DeployableTargetWithRBAC.d.ts +179 -0
  102. package/dist/Deployable/DeployableTargetWithRBAC.d.ts.map +1 -0
  103. package/dist/Deployable/DeployableTargetWithRBAC.js +222 -0
  104. package/dist/Deployable/DeployableTargetWithRBAC.js.map +1 -0
  105. package/dist/EventAction-CBKzuNoN.cjs +2 -0
  106. package/dist/EventAction-CBKzuNoN.cjs.map +1 -0
  107. package/dist/EventAction-DWuuc_Qy.js +1528 -0
  108. package/dist/EventAction-DWuuc_Qy.js.map +1 -0
  109. package/dist/Incentive-BxzEtN26.js +298 -0
  110. package/dist/Incentive-BxzEtN26.js.map +1 -0
  111. package/dist/Incentive-CrF3-ayL.cjs +2 -0
  112. package/dist/Incentive-CrF3-ayL.cjs.map +1 -0
  113. package/dist/Incentives/AllowListIncentive.cjs +2 -1
  114. package/dist/Incentives/AllowListIncentive.cjs.map +1 -0
  115. package/dist/Incentives/AllowListIncentive.d.ts +65 -21
  116. package/dist/Incentives/AllowListIncentive.d.ts.map +1 -1
  117. package/dist/Incentives/AllowListIncentive.js +52 -36
  118. package/dist/Incentives/AllowListIncentive.js.map +1 -0
  119. package/dist/Incentives/CGDAIncentive.cjs +2 -1
  120. package/dist/Incentives/CGDAIncentive.cjs.map +1 -0
  121. package/dist/Incentives/CGDAIncentive.d.ts +315 -26
  122. package/dist/Incentives/CGDAIncentive.d.ts.map +1 -1
  123. package/dist/Incentives/CGDAIncentive.js +64 -39
  124. package/dist/Incentives/CGDAIncentive.js.map +1 -0
  125. package/dist/Incentives/ERC1155Incentive.d.ts +291 -43
  126. package/dist/Incentives/ERC1155Incentive.d.ts.map +1 -1
  127. package/dist/Incentives/ERC20Incentive.cjs +2 -1
  128. package/dist/Incentives/ERC20Incentive.cjs.map +1 -0
  129. package/dist/Incentives/ERC20Incentive.d.ts +270 -33
  130. package/dist/Incentives/ERC20Incentive.d.ts.map +1 -1
  131. package/dist/Incentives/ERC20Incentive.js +69 -46
  132. package/dist/Incentives/ERC20Incentive.js.map +1 -0
  133. package/dist/{Budgets/SimpleBudget.d.ts → Incentives/ERC20VariableCriteriaIncentive.d.ts} +338 -421
  134. package/dist/Incentives/ERC20VariableCriteriaIncentive.d.ts.map +1 -0
  135. package/dist/Incentives/ERC20VariableIncentive.d.ts +262 -32
  136. package/dist/Incentives/ERC20VariableIncentive.d.ts.map +1 -1
  137. package/dist/Incentives/Incentive.cjs +2 -1
  138. package/dist/Incentives/Incentive.cjs.map +1 -0
  139. package/dist/Incentives/Incentive.d.ts +5 -8
  140. package/dist/Incentives/Incentive.d.ts.map +1 -1
  141. package/dist/Incentives/Incentive.js +17 -278
  142. package/dist/Incentives/Incentive.js.map +1 -0
  143. package/dist/Incentives/PointsIncentive.cjs +2 -1
  144. package/dist/Incentives/PointsIncentive.cjs.map +1 -0
  145. package/dist/Incentives/PointsIncentive.d.ts +81 -23
  146. package/dist/Incentives/PointsIncentive.d.ts.map +1 -1
  147. package/dist/Incentives/PointsIncentive.js +57 -36
  148. package/dist/Incentives/PointsIncentive.js.map +1 -0
  149. package/dist/SimpleDenyList-BUR17Tt1.cjs +2 -0
  150. package/dist/SimpleDenyList-BUR17Tt1.cjs.map +1 -0
  151. package/dist/SimpleDenyList-CGaWjuld.js +132 -0
  152. package/dist/SimpleDenyList-CGaWjuld.js.map +1 -0
  153. package/dist/Validators/SignerValidator.cjs +2 -1
  154. package/dist/Validators/SignerValidator.cjs.map +1 -0
  155. package/dist/Validators/SignerValidator.d.ts +310 -17
  156. package/dist/Validators/SignerValidator.d.ts.map +1 -1
  157. package/dist/Validators/SignerValidator.js +165 -36
  158. package/dist/Validators/SignerValidator.js.map +1 -0
  159. package/dist/Validators/Validator.cjs +2 -1
  160. package/dist/Validators/Validator.cjs.map +1 -0
  161. package/dist/Validators/Validator.d.ts +2 -2
  162. package/dist/Validators/Validator.d.ts.map +1 -1
  163. package/dist/Validators/Validator.js +10 -8
  164. package/dist/Validators/Validator.js.map +1 -0
  165. package/dist/claiming.cjs +2 -0
  166. package/dist/claiming.cjs.map +1 -0
  167. package/dist/claiming.d.ts +43 -0
  168. package/dist/claiming.d.ts.map +1 -0
  169. package/dist/claiming.js +17 -0
  170. package/dist/claiming.js.map +1 -0
  171. package/dist/componentInterfaces-BBCFkrZv.js +14 -0
  172. package/dist/componentInterfaces-BBCFkrZv.js.map +1 -0
  173. package/dist/componentInterfaces-DRI_dQ-P.cjs +2 -0
  174. package/dist/componentInterfaces-DRI_dQ-P.cjs.map +1 -0
  175. package/dist/deployments-DVXioW2i.cjs +2 -0
  176. package/dist/deployments-DVXioW2i.cjs.map +1 -0
  177. package/dist/deployments-oykLv3_Z.js +43 -0
  178. package/dist/deployments-oykLv3_Z.js.map +1 -0
  179. package/dist/deployments.json +44 -0
  180. package/dist/errors.cjs +2 -1
  181. package/dist/errors.cjs.map +1 -0
  182. package/dist/errors.d.ts +421 -1
  183. package/dist/errors.d.ts.map +1 -1
  184. package/dist/errors.js +297 -39
  185. package/dist/errors.js.map +1 -0
  186. package/dist/{generated-x_abr3Yv.js → generated-CKt2yCQd.js} +3143 -3002
  187. package/dist/generated-CKt2yCQd.js.map +1 -0
  188. package/dist/generated-CyTNlOwM.cjs +3 -0
  189. package/dist/generated-CyTNlOwM.cjs.map +1 -0
  190. package/dist/index.cjs +2 -1
  191. package/dist/index.cjs.map +1 -0
  192. package/dist/index.d.ts +10 -9
  193. package/dist/index.d.ts.map +1 -1
  194. package/dist/index.js +144 -1353
  195. package/dist/index.js.map +1 -0
  196. package/dist/transfers.cjs +2 -0
  197. package/dist/transfers.cjs.map +1 -0
  198. package/dist/transfers.d.ts +198 -0
  199. package/dist/transfers.d.ts.map +1 -0
  200. package/dist/transfers.js +84 -0
  201. package/dist/transfers.js.map +1 -0
  202. package/dist/utils.cjs +2 -1
  203. package/dist/utils.cjs.map +1 -0
  204. package/dist/utils.d.ts +26 -1350
  205. package/dist/utils.d.ts.map +1 -1
  206. package/dist/utils.js +38 -636
  207. package/dist/utils.js.map +1 -0
  208. package/package.json +37 -11
  209. package/src/Actions/Action.test.ts +79 -0
  210. package/src/Actions/Action.ts +61 -0
  211. package/src/Actions/ContractAction.test.ts +197 -0
  212. package/src/Actions/ContractAction.ts +300 -0
  213. package/src/Actions/ERC721MintAction.test.ts +112 -0
  214. package/src/Actions/ERC721MintAction.ts +291 -0
  215. package/src/Actions/EventAction.test.ts +787 -0
  216. package/src/Actions/EventAction.ts +1218 -0
  217. package/src/AllowLists/AllowList.test.ts +64 -0
  218. package/src/AllowLists/AllowList.ts +62 -0
  219. package/src/AllowLists/OpenAllowList.test.ts +40 -0
  220. package/src/AllowLists/OpenAllowList.ts +45 -0
  221. package/src/AllowLists/SimpleAllowList.test.ts +52 -0
  222. package/src/AllowLists/SimpleAllowList.ts +262 -0
  223. package/src/AllowLists/SimpleDenyList.test.ts +52 -0
  224. package/src/AllowLists/SimpleDenyList.ts +250 -0
  225. package/src/Auth/Auth.ts +11 -0
  226. package/src/Auth/PassthroughAuth.test.ts +12 -0
  227. package/src/Auth/PassthroughAuth.ts +80 -0
  228. package/src/Boost.ts +287 -0
  229. package/src/BoostCore.test.ts +894 -0
  230. package/src/BoostCore.ts +1438 -0
  231. package/src/BoostRegistry.test.ts +53 -0
  232. package/src/BoostRegistry.ts +588 -0
  233. package/src/Budgets/Budget.test.ts +27 -0
  234. package/src/Budgets/Budget.ts +60 -0
  235. package/src/Budgets/ManagedBudget.test.ts +217 -0
  236. package/src/Budgets/ManagedBudget.ts +534 -0
  237. package/src/Budgets/VestingBudget.test.ts +123 -0
  238. package/src/Budgets/VestingBudget.ts +530 -0
  239. package/src/Deployable/Contract.ts +228 -0
  240. package/src/Deployable/Deployable.ts +250 -0
  241. package/src/Deployable/DeployableTarget.ts +234 -0
  242. package/src/Deployable/DeployableTargetWithRBAC.ts +323 -0
  243. package/src/Incentives/AllowListIncentive.test.ts +143 -0
  244. package/src/Incentives/AllowListIncentive.ts +336 -0
  245. package/src/Incentives/CGDAIncentive.test.ts +135 -0
  246. package/src/Incentives/CGDAIncentive.ts +476 -0
  247. package/src/Incentives/ERC1155Incentive.test.ts +87 -0
  248. package/src/Incentives/ERC1155Incentive.ts +465 -0
  249. package/src/Incentives/ERC20Incentive.test.ts +133 -0
  250. package/src/Incentives/ERC20Incentive.ts +490 -0
  251. package/src/Incentives/ERC20VariableCriteriaIncentive.test.ts +184 -0
  252. package/src/Incentives/ERC20VariableCriteriaIncentive.ts +309 -0
  253. package/src/Incentives/ERC20VariableIncentive.test.ts +139 -0
  254. package/src/Incentives/ERC20VariableIncentive.ts +428 -0
  255. package/src/Incentives/Incentive.test.ts +95 -0
  256. package/src/Incentives/Incentive.ts +86 -0
  257. package/src/Incentives/PointsIncentive.test.ts +138 -0
  258. package/src/Incentives/PointsIncentive.ts +367 -0
  259. package/src/Validators/SignerValidator.test.ts +159 -0
  260. package/src/Validators/SignerValidator.ts +683 -0
  261. package/src/Validators/Validator.test.ts +21 -0
  262. package/src/Validators/Validator.ts +55 -0
  263. package/src/claiming.ts +56 -0
  264. package/src/errors.ts +866 -0
  265. package/src/index.test.ts +122 -0
  266. package/src/index.ts +58 -0
  267. package/src/transfers.ts +284 -0
  268. package/src/utils.test.ts +44 -0
  269. package/src/utils.ts +247 -0
  270. package/dist/Budgets/SimpleBudget.d.ts.map +0 -1
  271. package/dist/generated-BaaleHW-.cjs +0 -2
@@ -0,0 +1,894 @@
1
+ import { accounts } from '@boostxyz/test/accounts';
2
+ import {
3
+ type BudgetFixtures,
4
+ type Fixtures,
5
+ defaultOptions,
6
+ deployFixtures,
7
+ freshBoost,
8
+ fundBudget,
9
+ makeMockEventActionPayload,
10
+ } from '@boostxyz/test/helpers';
11
+ import { loadFixture } from '@nomicfoundation/hardhat-toolbox-viem/network-helpers';
12
+ import { pad, parseEther, zeroAddress } from 'viem';
13
+ import { beforeAll, beforeEach, describe, expect, test, vi } from 'vitest';
14
+ import { ContractAction } from './Actions/ContractAction';
15
+ import { BOOST_CORE_CLAIM_FEE } from './BoostCore';
16
+ import type { ERC20Incentive } from './Incentives/ERC20Incentive';
17
+ import { StrategyType } from './claiming';
18
+ import { BoostNotFoundError, IncentiveNotCloneableError } from './errors';
19
+ import { bytes4 } from './utils';
20
+
21
+ let fixtures: Fixtures, budgets: BudgetFixtures;
22
+
23
+ describe('BoostCore', () => {
24
+ beforeAll(async () => {
25
+ fixtures = await loadFixture(deployFixtures(defaultOptions));
26
+ });
27
+ beforeEach(async () => {
28
+ budgets = await loadFixture(fundBudget(defaultOptions, fixtures));
29
+ });
30
+
31
+ test('can get the total number of boosts', async () => {
32
+ const { core } = fixtures;
33
+
34
+ const { budget, erc20 } = budgets;
35
+ await core.createBoost({
36
+ protocolFee: 0n,
37
+ maxParticipants: 100n,
38
+ budget: budget,
39
+ action: core.EventAction(
40
+ makeMockEventActionPayload(
41
+ core.assertValidAddress(),
42
+ erc20.assertValidAddress(),
43
+ ),
44
+ ),
45
+ validator: core.SignerValidator({
46
+ signers: [defaultOptions.account.address],
47
+ validatorCaller: defaultOptions.account.address,
48
+ }),
49
+ allowList: core.SimpleAllowList({
50
+ owner: defaultOptions.account.address,
51
+ allowed: [defaultOptions.account.address],
52
+ }),
53
+ incentives: [
54
+ core.ERC20Incentive({
55
+ asset: erc20.assertValidAddress(),
56
+ reward: parseEther('1'),
57
+ limit: 100n,
58
+ strategy: StrategyType.POOL,
59
+ manager: budget.assertValidAddress(),
60
+ }),
61
+ ],
62
+ });
63
+ expect(await core.getBoostCount()).toBe(1n);
64
+ });
65
+
66
+ test('throws a typed error if no boost exists', async () => {
67
+ const { core } = fixtures;
68
+ try {
69
+ await core.getBoost(1000n)
70
+ } catch(e) {
71
+ expect(e instanceof BoostNotFoundError).toBe(true)
72
+ expect(e.id).toBe('1000')
73
+ }
74
+ })
75
+
76
+ test('can successfully create a boost using all base contract implementations', async () => {
77
+ const { core } = fixtures;
78
+ const { budget, erc20 } = budgets;
79
+ const boost = await core.createBoost({
80
+ protocolFee: 1n,
81
+ maxParticipants: 100n,
82
+ budget: budget,
83
+ action: core.EventAction(
84
+ makeMockEventActionPayload(
85
+ core.assertValidAddress(),
86
+ erc20.assertValidAddress(),
87
+ ),
88
+ ),
89
+ validator: core.SignerValidator({
90
+ signers: [defaultOptions.account.address],
91
+ validatorCaller: defaultOptions.account.address,
92
+ }),
93
+ allowList: core.SimpleAllowList({
94
+ owner: defaultOptions.account.address,
95
+ allowed: [defaultOptions.account.address],
96
+ }),
97
+ incentives: [
98
+ core.ERC20Incentive({
99
+ asset: erc20.assertValidAddress(),
100
+ reward: parseEther('1'),
101
+ limit: 100n,
102
+ strategy: StrategyType.POOL,
103
+ manager: budget.assertValidAddress(),
104
+ }),
105
+ ],
106
+ });
107
+ const onChainBoost = await core.readBoost(boost.id);
108
+
109
+ expect(boost.owner).toBe(onChainBoost.owner);
110
+ expect(boost.protocolFee).toBe(onChainBoost.protocolFee);
111
+ expect(boost.maxParticipants).toBe(onChainBoost.maxParticipants);
112
+
113
+ expect(boost.action.address).toBe(onChainBoost.action);
114
+ // just get some type safety here
115
+ if (boost.action instanceof ContractAction === false) return;
116
+ expect(await boost.action.chainId()).toBe(BigInt(31_337));
117
+ expect((await boost.action.target()).toLowerCase()).toBe(
118
+ core.assertValidAddress().toLowerCase(),
119
+ );
120
+ expect(await boost.action.selector()).toBe('0xdeadbeef');
121
+ expect(await boost.action.value()).toBe(0n);
122
+
123
+ expect(boost.validator.address?.toLowerCase()).toBe(
124
+ onChainBoost.validator.toLowerCase(),
125
+ );
126
+ expect(await boost.validator.signers(defaultOptions.account.address)).toBe(
127
+ true,
128
+ );
129
+
130
+ expect(boost.allowList.address?.toLowerCase()).toBe(
131
+ onChainBoost.allowList.toLowerCase(),
132
+ );
133
+ expect(
134
+ await boost.allowList.isAllowed(defaultOptions.account.address),
135
+ ).toBe(true);
136
+ expect(await boost.allowList.isAllowed(zeroAddress)).toBe(false);
137
+
138
+ expect(boost.budget.address?.toLowerCase()).toBe(
139
+ onChainBoost.budget.toLowerCase(),
140
+ );
141
+ expect(
142
+ await boost.budget.isAuthorized(defaultOptions.account.address),
143
+ ).toBe(true);
144
+
145
+ expect(boost.incentives.length).toBe(onChainBoost.incentives.length);
146
+ const incentive = boost.incentives.at(0) as ERC20Incentive;
147
+ expect(incentive.address?.toLowerCase()).toBe(
148
+ onChainBoost.incentives.at(0)?.toLowerCase(),
149
+ );
150
+ expect((await incentive.asset()).toLowerCase()).toBe(
151
+ erc20.address?.toLowerCase(),
152
+ );
153
+ expect(await incentive.currentReward()).toBe(parseEther('1'));
154
+ expect(await incentive.limit()).toBe(100n);
155
+ expect(await incentive.claims()).toBe(0n);
156
+ });
157
+
158
+ test('can read the raw on chain representation of a boost', async () => {
159
+ const { core } = fixtures;
160
+ const { budget, erc20 } = budgets;
161
+ const _boost = await core.createBoost({
162
+ protocolFee: 1n,
163
+ maxParticipants: 100n,
164
+ budget: budget,
165
+ action: core.EventAction(
166
+ makeMockEventActionPayload(
167
+ core.assertValidAddress(),
168
+ erc20.assertValidAddress(),
169
+ ),
170
+ ),
171
+ validator: core.SignerValidator({
172
+ signers: [defaultOptions.account.address],
173
+ validatorCaller: defaultOptions.account.address,
174
+ }),
175
+ allowList: core.SimpleAllowList({
176
+ owner: defaultOptions.account.address,
177
+ allowed: [defaultOptions.account.address],
178
+ }),
179
+ incentives: [
180
+ core.ERC20Incentive({
181
+ asset: erc20.assertValidAddress(),
182
+ reward: parseEther('1'),
183
+ limit: 100n,
184
+ strategy: StrategyType.POOL,
185
+ manager: budget.assertValidAddress(),
186
+ }),
187
+ ],
188
+ });
189
+ const boost = await core.readBoost(_boost.id);
190
+ expect(boost.protocolFee).toBe(1001n);
191
+ expect(boost.maxParticipants).toBe(100n);
192
+ expect(boost.budget).toBe(_boost.budget.assertValidAddress());
193
+ expect(boost.action).toBe(_boost.action.assertValidAddress());
194
+ expect(boost.validator).toBe(_boost.validator.assertValidAddress());
195
+ expect(boost.allowList).toBe(_boost.allowList.assertValidAddress());
196
+ expect(boost.incentives.at(0)).toBe(
197
+ _boost.incentives.at(0)?.assertValidAddress(),
198
+ );
199
+ });
200
+
201
+ test('can optionally supply a validator', async () => {
202
+ const { core } = fixtures;
203
+ const { budget, erc20 } = budgets;
204
+ const _boost = await core.createBoost({
205
+ protocolFee: 1n,
206
+ maxParticipants: 100n,
207
+ budget: budget,
208
+ action: core.EventAction(
209
+ makeMockEventActionPayload(
210
+ core.assertValidAddress(),
211
+ erc20.assertValidAddress(),
212
+ ),
213
+ ),
214
+ allowList: core.SimpleAllowList({
215
+ owner: defaultOptions.account.address,
216
+ allowed: [defaultOptions.account.address],
217
+ }),
218
+ incentives: [
219
+ core.ERC20Incentive({
220
+ asset: erc20.assertValidAddress(),
221
+ reward: parseEther('1'),
222
+ limit: 100n,
223
+ strategy: StrategyType.POOL,
224
+ manager: budget.assertValidAddress(),
225
+ }),
226
+ ],
227
+ });
228
+ const boost = await core.readBoost(_boost.id);
229
+ expect(boost.validator).toBe(_boost.validator.assertValidAddress());
230
+ });
231
+
232
+ test('can simulate a boost creation', async () => {
233
+ const { core } = fixtures;
234
+ const { budget, erc20 } = budgets;
235
+ const simulated = await core.simulateCreateBoost({
236
+ protocolFee: 1n,
237
+ maxParticipants: 100n,
238
+ budget: budget,
239
+ action: core.EventAction(
240
+ makeMockEventActionPayload(
241
+ core.assertValidAddress(),
242
+ erc20.assertValidAddress(),
243
+ ),
244
+ ),
245
+ allowList: core.SimpleAllowList({
246
+ owner: defaultOptions.account.address,
247
+ allowed: [defaultOptions.account.address],
248
+ }),
249
+ incentives: [
250
+ core.ERC20Incentive({
251
+ asset: erc20.assertValidAddress(),
252
+ reward: parseEther('1'),
253
+ limit: 100n,
254
+ strategy: StrategyType.POOL,
255
+ manager: budget.assertValidAddress(),
256
+ }),
257
+ ],
258
+ });
259
+ expect(simulated.request.__mode).toBe('prepared')
260
+ });
261
+
262
+ test('can reuse an existing action', async () => {
263
+ const { core } = fixtures;
264
+ const { budget, erc20 } = budgets;
265
+
266
+ // allocate more funds to the budget
267
+ await erc20.mint(defaultOptions.account.address, parseEther('110'));
268
+ await erc20.approve(budget.assertValidAddress(), parseEther('110'));
269
+ await budget.allocate({
270
+ amount: parseEther('110'),
271
+ asset: erc20.assertValidAddress(),
272
+ target: defaultOptions.account.address,
273
+ });
274
+
275
+ const _boost = await core.createBoost({
276
+ budget: budget,
277
+ action: core.EventAction(
278
+ makeMockEventActionPayload(
279
+ core.assertValidAddress(),
280
+ erc20.assertValidAddress(),
281
+ ),
282
+ ),
283
+ validator: core.SignerValidator({
284
+ signers: [defaultOptions.account.address],
285
+ validatorCaller: defaultOptions.account.address,
286
+ }),
287
+ allowList: core.SimpleAllowList({
288
+ owner: defaultOptions.account.address,
289
+ allowed: [defaultOptions.account.address],
290
+ }),
291
+ incentives: [
292
+ core.ERC20Incentive({
293
+ asset: erc20.assertValidAddress(),
294
+ reward: parseEther('1'),
295
+ limit: 100n,
296
+ strategy: StrategyType.POOL,
297
+ manager: budget.assertValidAddress(),
298
+ }),
299
+ ],
300
+ });
301
+ const boost = await core.createBoost({
302
+ budget: budget,
303
+ action: core.EventAction(_boost.action.assertValidAddress(), false),
304
+ validator: core.SignerValidator({
305
+ signers: [defaultOptions.account.address],
306
+ validatorCaller: defaultOptions.account.address,
307
+ }),
308
+ allowList: core.SimpleAllowList({
309
+ owner: defaultOptions.account.address,
310
+ allowed: [defaultOptions.account.address],
311
+ }),
312
+ incentives: [
313
+ core.ERC20Incentive({
314
+ asset: erc20.assertValidAddress(),
315
+ reward: parseEther('1'),
316
+ limit: 100n,
317
+ strategy: StrategyType.POOL,
318
+ manager: budget.assertValidAddress(),
319
+ }),
320
+ ],
321
+ });
322
+ const onChainBoost = await core.readBoost(boost.id);
323
+ expect(onChainBoost.action).toBe(_boost.action.assertValidAddress());
324
+ });
325
+
326
+ test('can reuse an existing validator', async () => {
327
+ const { core } = fixtures;
328
+ const { budget, erc20 } = budgets;
329
+
330
+ // allocate more erc20 funds to the budget from the owning accound
331
+ await erc20.mint(defaultOptions.account.address, parseEther('110'));
332
+ await erc20.approve(budget.assertValidAddress(), parseEther('110'));
333
+ await budget.allocate({
334
+ amount: parseEther('110'),
335
+ asset: erc20.assertValidAddress(),
336
+ target: defaultOptions.account.address,
337
+ });
338
+
339
+ const _boost = await core.createBoost({
340
+ budget: budget,
341
+ action: core.EventAction(
342
+ makeMockEventActionPayload(
343
+ core.assertValidAddress(),
344
+ erc20.assertValidAddress(),
345
+ ),
346
+ ),
347
+ validator: core.SignerValidator({
348
+ signers: [defaultOptions.account.address],
349
+ validatorCaller: defaultOptions.account.address,
350
+ }),
351
+ allowList: core.SimpleAllowList({
352
+ owner: defaultOptions.account.address,
353
+ allowed: [defaultOptions.account.address],
354
+ }),
355
+ incentives: [
356
+ core.ERC20Incentive({
357
+ asset: erc20.assertValidAddress(),
358
+ reward: parseEther('1'),
359
+ limit: 100n,
360
+ strategy: StrategyType.POOL,
361
+ manager: budget.assertValidAddress(),
362
+ }),
363
+ ],
364
+ });
365
+ const boost = await core.createBoost({
366
+ budget: budget,
367
+ action: core.EventAction(
368
+ makeMockEventActionPayload(
369
+ core.assertValidAddress(),
370
+ erc20.assertValidAddress(),
371
+ ),
372
+ ),
373
+ validator: core.SignerValidator(
374
+ _boost.validator.assertValidAddress(),
375
+ false,
376
+ ),
377
+ allowList: core.SimpleAllowList({
378
+ owner: defaultOptions.account.address,
379
+ allowed: [defaultOptions.account.address],
380
+ }),
381
+ incentives: [
382
+ core.ERC20Incentive({
383
+ asset: erc20.assertValidAddress(),
384
+ reward: parseEther('1'),
385
+ limit: 100n,
386
+ strategy: StrategyType.POOL,
387
+ manager: budget.assertValidAddress(),
388
+ }),
389
+ ],
390
+ });
391
+ const onChainBoost = await core.readBoost(boost.id);
392
+ expect(onChainBoost.validator).toBe(_boost.validator.assertValidAddress());
393
+ });
394
+
395
+ test('can reuse an existing allowlist', async () => {
396
+ const { core } = fixtures;
397
+ const { budget, erc20 } = budgets;
398
+
399
+ // allocate more erc20 funds to the budget from the owning accound
400
+ await erc20.mint(defaultOptions.account.address, parseEther('110'));
401
+ await erc20.approve(budget.assertValidAddress(), parseEther('110'));
402
+ await budget.allocate({
403
+ amount: parseEther('110'),
404
+ asset: erc20.assertValidAddress(),
405
+ target: defaultOptions.account.address,
406
+ });
407
+
408
+ const _boost = await core.createBoost({
409
+ budget: budget,
410
+ action: core.EventAction(
411
+ makeMockEventActionPayload(
412
+ core.assertValidAddress(),
413
+ erc20.assertValidAddress(),
414
+ ),
415
+ ),
416
+ validator: core.SignerValidator({
417
+ signers: [defaultOptions.account.address],
418
+ validatorCaller: defaultOptions.account.address,
419
+ }),
420
+ allowList: core.SimpleAllowList({
421
+ owner: defaultOptions.account.address,
422
+ allowed: [defaultOptions.account.address],
423
+ }),
424
+ incentives: [
425
+ core.ERC20Incentive({
426
+ asset: erc20.assertValidAddress(),
427
+ reward: parseEther('1'),
428
+ limit: 100n,
429
+ strategy: StrategyType.POOL,
430
+ manager: budget.assertValidAddress(),
431
+ }),
432
+ ],
433
+ });
434
+ const boost = await core.createBoost({
435
+ budget: budget,
436
+ action: core.EventAction(
437
+ makeMockEventActionPayload(
438
+ core.assertValidAddress(),
439
+ erc20.assertValidAddress(),
440
+ ),
441
+ ),
442
+ validator: core.SignerValidator({
443
+ signers: [defaultOptions.account.address],
444
+ validatorCaller: defaultOptions.account.address,
445
+ }),
446
+ allowList: core.SimpleAllowList(
447
+ _boost.allowList.assertValidAddress(),
448
+ false,
449
+ ),
450
+ incentives: [
451
+ core.ERC20Incentive({
452
+ asset: erc20.assertValidAddress(),
453
+ reward: parseEther('1'),
454
+ limit: 100n,
455
+ strategy: StrategyType.POOL,
456
+ manager: budget.assertValidAddress(),
457
+ }),
458
+ ],
459
+ });
460
+ const onChainBoost = await core.readBoost(boost.id);
461
+ expect(onChainBoost.allowList).toBe(_boost.allowList.assertValidAddress());
462
+ });
463
+
464
+ test('cannot reuse an existing incentive', async () => {
465
+ const { core } = fixtures;
466
+ const { budget, erc20 } = budgets;
467
+
468
+ // allocate more erc20 funds to the budget from the owning accound
469
+ await erc20.mint(defaultOptions.account.address, parseEther('110'));
470
+ await erc20.approve(budget.assertValidAddress(), parseEther('110'));
471
+ await budget.allocate({
472
+ amount: parseEther('110'),
473
+ asset: erc20.assertValidAddress(),
474
+ target: defaultOptions.account.address,
475
+ });
476
+
477
+ const incentive = core.ERC20Incentive({
478
+ asset: erc20.assertValidAddress(),
479
+ reward: parseEther('1'),
480
+ limit: 100n,
481
+ strategy: StrategyType.POOL,
482
+ manager: budget.assertValidAddress(),
483
+ });
484
+ const _boost = await core.createBoost({
485
+ budget: budget,
486
+ action: core.EventAction(
487
+ makeMockEventActionPayload(
488
+ core.assertValidAddress(),
489
+ erc20.assertValidAddress(),
490
+ ),
491
+ ),
492
+ validator: core.SignerValidator({
493
+ signers: [defaultOptions.account.address],
494
+ validatorCaller: defaultOptions.account.address,
495
+ }),
496
+ allowList: core.SimpleAllowList({
497
+ owner: defaultOptions.account.address,
498
+ allowed: [defaultOptions.account.address],
499
+ }),
500
+ incentives: [incentive],
501
+ });
502
+ try {
503
+ await core.createBoost({
504
+ budget: budget,
505
+ action: core.EventAction(
506
+ makeMockEventActionPayload(
507
+ core.assertValidAddress(),
508
+ erc20.assertValidAddress(),
509
+ ),
510
+ ),
511
+ validator: core.SignerValidator({
512
+ signers: [defaultOptions.account.address],
513
+ validatorCaller: defaultOptions.account.address,
514
+ }),
515
+ allowList: core.SimpleAllowList({
516
+ owner: defaultOptions.account.address,
517
+ allowed: [defaultOptions.account.address],
518
+ }),
519
+ incentives: [incentive],
520
+ });
521
+ } catch (e) {
522
+ expect(e).toBeInstanceOf(IncentiveNotCloneableError);
523
+ }
524
+ });
525
+
526
+ test('can offer multiple incentives', async () => {
527
+ const { registry, core } = fixtures;
528
+ const { budget, erc20, points, erc1155 } = budgets;
529
+ const allowList = await registry.initialize(
530
+ 'SharedAllowList',
531
+ core.SimpleAllowList({
532
+ owner: defaultOptions.account.address,
533
+ allowed: [defaultOptions.account.address],
534
+ }),
535
+ );
536
+
537
+ const erc20Incentive = core.ERC20Incentive({
538
+ asset: erc20.assertValidAddress(),
539
+ reward: 1n,
540
+ limit: 10n,
541
+ strategy: StrategyType.POOL,
542
+ manager: budget.assertValidAddress(),
543
+ });
544
+ // const erc1155Incentive = core.ERC1155Incentive({
545
+ // asset: erc1155.assertValidAddress(),
546
+ // strategy: ERC1155StrategyType.POOL,
547
+ // limit: 1n,
548
+ // tokenId: 1n,
549
+ // extraData: '0x',
550
+ // });
551
+ const cgdaIncentive = core.CGDAIncentive({
552
+ asset: erc20.assertValidAddress(),
553
+ initialReward: 1n,
554
+ totalBudget: 10n,
555
+ rewardBoost: 1n,
556
+ rewardDecay: 1n,
557
+ manager: budget.assertValidAddress(),
558
+ });
559
+ const allowListIncentive = core.AllowListIncentive({
560
+ allowList: allowList.assertValidAddress(),
561
+ limit: 5n,
562
+ });
563
+ const pointsIncentive = core.PointsIncentive({
564
+ venue: points.assertValidAddress(),
565
+ selector: bytes4('issue(address,uint256)'),
566
+ reward: 1n,
567
+ limit: 10n,
568
+ });
569
+
570
+ await core.createBoost({
571
+ protocolFee: 1n,
572
+ maxParticipants: 100n,
573
+ budget: budget,
574
+ action: core.EventAction(
575
+ makeMockEventActionPayload(
576
+ core.assertValidAddress(),
577
+ erc20.assertValidAddress(),
578
+ ),
579
+ ),
580
+ validator: core.SignerValidator({
581
+ signers: [defaultOptions.account.address],
582
+ validatorCaller: defaultOptions.account.address,
583
+ }),
584
+ allowList: core.SimpleAllowList(allowList.assertValidAddress()),
585
+ incentives: [
586
+ // erc1155Incentive,
587
+ erc20Incentive,
588
+ cgdaIncentive,
589
+ allowListIncentive,
590
+ pointsIncentive,
591
+ ],
592
+ });
593
+ expect(await erc20Incentive.reward()).toEqual(1n);
594
+ expect(await erc20Incentive.limit()).toEqual(10n);
595
+ expect((await cgdaIncentive.asset()).toLowerCase()).toEqual(
596
+ erc20.address?.toLowerCase(),
597
+ );
598
+ expect(await cgdaIncentive.currentReward()).toEqual(1n);
599
+ expect(
600
+ await (await allowListIncentive.allowList()).isAllowed(
601
+ defaultOptions.account.address,
602
+ ),
603
+ ).toEqual(true);
604
+ expect(await pointsIncentive.reward()).toEqual(1n);
605
+ expect(await pointsIncentive.currentReward()).toEqual(1n);
606
+ expect(await pointsIncentive.limit()).toEqual(10n);
607
+ });
608
+
609
+ test('can get the protocol fee', async () => {
610
+ const { core } = fixtures;
611
+
612
+ expect(await core.protocolFee()).toBe(1000n);
613
+ });
614
+
615
+ test('can get the protocol fee receiver', async () => {
616
+ const { core } = fixtures;
617
+
618
+ expect(await core.protocolFeeReceiver()).toBe(
619
+ defaultOptions.account.address,
620
+ );
621
+ });
622
+
623
+ test('can set the protocol fee receiver', async () => {
624
+ const { core } = fixtures;
625
+
626
+ await core.setProcolFeeReceiver(zeroAddress);
627
+
628
+ expect(await core.protocolFeeReceiver()).toBe(zeroAddress);
629
+ });
630
+
631
+ test('binds all actions, budgets, allowlists, incentives, and validators to reuse core options and account', () => {
632
+ const { core } = fixtures;
633
+
634
+ // const contractAction = core.ContractAction(zeroAddress);
635
+ // expect(contractAction._config).toEqual(defaultOptions.config);
636
+ // expect(contractAction._account).toEqual(defaultOptions.account);
637
+
638
+ // const erc721MintAction = core.ERC721MintAction(zeroAddress);
639
+ // expect(erc721MintAction._config).toEqual(defaultOptions.config);
640
+ // expect(erc721MintAction._account).toEqual(defaultOptions.account);
641
+
642
+ const eventAction = core.EventAction(zeroAddress);
643
+ expect(eventAction._config).toEqual(defaultOptions.config);
644
+ expect(eventAction._account).toEqual(defaultOptions.account);
645
+
646
+ const allowList = core.SimpleAllowList(zeroAddress);
647
+ expect(allowList._config).toEqual(defaultOptions.config);
648
+ expect(allowList._account).toEqual(defaultOptions.account);
649
+
650
+ const denyList = core.SimpleDenyList(zeroAddress);
651
+ expect(denyList._config).toEqual(defaultOptions.config);
652
+ expect(denyList._account).toEqual(defaultOptions.account);
653
+
654
+ const managedBudget = core.ManagedBudget(zeroAddress);
655
+ expect(managedBudget._config).toEqual(defaultOptions.config);
656
+ expect(managedBudget._account).toEqual(defaultOptions.account);
657
+
658
+ // const simpleBudget = core.SimpleBudget(zeroAddress);
659
+ // expect(simpleBudget._config).toEqual(defaultOptions.config);
660
+ // expect(simpleBudget._account).toEqual(defaultOptions.account);
661
+
662
+ // const vestingBudget = core.VestingBudget(zeroAddress);
663
+ // expect(vestingBudget._config).toEqual(defaultOptions.config);
664
+ // expect(vestingBudget._account).toEqual(defaultOptions.account);
665
+
666
+ const allowListIncentive = core.AllowListIncentive({
667
+ allowList: zeroAddress,
668
+ limit: 0n,
669
+ });
670
+ expect(allowListIncentive._config).toEqual(defaultOptions.config);
671
+ expect(allowListIncentive._account).toEqual(defaultOptions.account);
672
+
673
+ const cgdaIncentive = core.CGDAIncentive({
674
+ asset: zeroAddress,
675
+ initialReward: 0n,
676
+ rewardDecay: 0n,
677
+ rewardBoost: 0n,
678
+ totalBudget: 0n,
679
+ manager: zeroAddress,
680
+ });
681
+ expect(cgdaIncentive._config).toEqual(defaultOptions.config);
682
+ expect(cgdaIncentive._account).toEqual(defaultOptions.account);
683
+
684
+ const erc20Incentive = core.ERC20Incentive({
685
+ asset: zeroAddress,
686
+ strategy: 0,
687
+ reward: 0n,
688
+ limit: 0n,
689
+ });
690
+ expect(erc20Incentive._config).toEqual(defaultOptions.config);
691
+ expect(erc20Incentive._account).toEqual(defaultOptions.account);
692
+
693
+ const erc20VariableIncentive = core.ERC20VariableIncentive({
694
+ asset: zeroAddress,
695
+ reward: 0n,
696
+ limit: 0n,
697
+ });
698
+ expect(erc20VariableIncentive._config).toEqual(defaultOptions.config);
699
+ expect(erc20VariableIncentive._account).toEqual(defaultOptions.account);
700
+
701
+ // const erc1155Incentive = core.ERC1155Incentive({
702
+ // asset: zeroAddress,
703
+ // strategy: 0,
704
+ // tokenId: 1n,
705
+ // limit: 0n,
706
+ // extraData: '0x',
707
+ // });
708
+ // expect(erc1155Incentive._config).toEqual(defaultOptions.config);
709
+ // expect(erc1155Incentive._account).toEqual(defaultOptions.account);
710
+
711
+ const pointsIncentive = core.PointsIncentive({
712
+ venue: zeroAddress,
713
+ selector: '0x',
714
+ reward: 0n,
715
+ limit: 0n,
716
+ });
717
+ expect(pointsIncentive._config).toEqual(defaultOptions.config);
718
+ expect(pointsIncentive._account).toEqual(defaultOptions.account);
719
+
720
+ const signerValidator = core.SignerValidator(zeroAddress);
721
+ expect(signerValidator._config).toEqual(defaultOptions.config);
722
+ expect(signerValidator._account).toEqual(defaultOptions.account);
723
+ });
724
+
725
+ test('can subscribe to contract events', async () => {
726
+ const subscription = vi.fn();
727
+
728
+ const { core } = fixtures;
729
+ core.subscribe(subscription, { pollingInterval: 100 });
730
+ const { budget, erc20 } = budgets;
731
+ await core.createBoost({
732
+ protocolFee: 1n,
733
+ maxParticipants: 100n,
734
+ budget: budget,
735
+ action: core.EventAction(
736
+ makeMockEventActionPayload(
737
+ core.assertValidAddress(),
738
+ erc20.assertValidAddress(),
739
+ ),
740
+ ),
741
+ validator: core.SignerValidator({
742
+ signers: [defaultOptions.account.address],
743
+ validatorCaller: defaultOptions.account.address,
744
+ }),
745
+ allowList: core.SimpleAllowList({
746
+ owner: defaultOptions.account.address,
747
+ allowed: [defaultOptions.account.address],
748
+ }),
749
+ incentives: [
750
+ core.ERC20Incentive({
751
+ asset: erc20.assertValidAddress(),
752
+ reward: parseEther('1'),
753
+ limit: 100n,
754
+ strategy: StrategyType.POOL,
755
+ manager: budget.assertValidAddress(),
756
+ }),
757
+ ],
758
+ });
759
+
760
+ await new Promise((resolve) => {
761
+ setTimeout(resolve, 500);
762
+ });
763
+
764
+ expect(subscription).toHaveBeenCalledTimes(1);
765
+ });
766
+
767
+ test('can set a passthrough auth scheme', async () => {
768
+ const { core } = fixtures;
769
+
770
+ const auth = core.PassthroughAuth();
771
+ await auth.deploy();
772
+ await core.setCreateBoostAuth(auth);
773
+ expect((await core.createBoostAuth()).toLowerCase()).toBe(
774
+ auth.assertValidAddress(),
775
+ );
776
+ expect(await core.isAuthorized(zeroAddress)).toBe(true);
777
+ });
778
+
779
+ test('uses the provided validator when one is specified', async () => {
780
+ const { core } = fixtures;
781
+ const { budget, erc20 } = budgets;
782
+ const customValidator = core.SignerValidator({
783
+ signers: [budget.assertValidAddress()],
784
+ validatorCaller: core.assertValidAddress(),
785
+ });
786
+ const boost = await core.createBoost({
787
+ maxParticipants: 100n,
788
+ budget: budget,
789
+ action: core.EventAction(
790
+ makeMockEventActionPayload(
791
+ core.assertValidAddress(),
792
+ erc20.assertValidAddress(),
793
+ ),
794
+ ),
795
+ validator: customValidator,
796
+ allowList: core.SimpleAllowList({
797
+ owner: defaultOptions.account.address,
798
+ allowed: [defaultOptions.account.address],
799
+ }),
800
+ incentives: [
801
+ core.ERC20Incentive({
802
+ asset: erc20.assertValidAddress(),
803
+ reward: parseEther('1'),
804
+ limit: 100n,
805
+ strategy: StrategyType.POOL,
806
+ manager: budget.assertValidAddress(),
807
+ }),
808
+ ],
809
+ });
810
+
811
+ expect(boost.validator).toBe(customValidator);
812
+ const signers = await boost.validator.signers(budget.assertValidAddress());
813
+ expect(signers).toBe(true);
814
+ });
815
+
816
+ test('creates a boost with a default validator when none is provided', async () => {
817
+ const { core } = fixtures;
818
+ const { budget, erc20 } = budgets;
819
+ const boost = await core.createBoost({
820
+ maxParticipants: 100n,
821
+ budget: budget,
822
+ action: core.EventAction(
823
+ makeMockEventActionPayload(
824
+ core.assertValidAddress(),
825
+ erc20.assertValidAddress(),
826
+ ),
827
+ ),
828
+ allowList: core.OpenAllowList(),
829
+ incentives: [
830
+ core.ERC20Incentive({
831
+ asset: erc20.assertValidAddress(),
832
+ reward: parseEther('1'),
833
+ limit: 100n,
834
+ strategy: StrategyType.POOL,
835
+ manager: budget.assertValidAddress(),
836
+ }),
837
+ ],
838
+ });
839
+
840
+ const validator = boost.validator;
841
+
842
+ // expect boostCore to be a validatorCaller
843
+ expect(validator.payload?.validatorCaller).toBe(core.assertValidAddress());
844
+
845
+ // expect current account to be a signer
846
+ const signer = await validator.signers(defaultOptions.account.address);
847
+ expect(signer).toBeDefined();
848
+ expect(signer).toBe(true);
849
+ });
850
+
851
+ test('can retrieve the BoostClaimed event from a transaction hash', async () => {
852
+ // biome-ignore lint/style/noNonNullAssertion: we know this is defined
853
+ const referrer = accounts.at(1)!.account!,
854
+ // biome-ignore lint/style/noNonNullAssertion: we know this is defined
855
+ trustedSigner = accounts.at(0)!;
856
+ const erc20Incentive = fixtures.core.ERC20Incentive({
857
+ asset: budgets.erc20.assertValidAddress(),
858
+ strategy: StrategyType.POOL,
859
+ reward: 1n,
860
+ limit: 1n,
861
+ manager: budgets.budget.assertValidAddress(),
862
+ });
863
+ const boost = await freshBoost(fixtures, {
864
+ budget: budgets.budget,
865
+ incentives: [erc20Incentive],
866
+ });
867
+
868
+ const claimant = trustedSigner.account;
869
+ const incentiveData = pad('0xdef456232173821931823712381232131391321934');
870
+ const incentiveQuantity = 1;
871
+ const claimDataPayload = await boost.validator.encodeClaimData({
872
+ signer: trustedSigner,
873
+ incentiveData,
874
+ chainId: defaultOptions.config.chains[0].id,
875
+ incentiveQuantity,
876
+ claimant,
877
+ boostId: boost.id,
878
+ });
879
+
880
+ const { hash } = await fixtures.core.claimIncentiveRaw(
881
+ boost.id,
882
+ 0n,
883
+ referrer,
884
+ claimDataPayload,
885
+ { value: BOOST_CORE_CLAIM_FEE },
886
+ );
887
+
888
+ const claimInfo = await fixtures.core.getClaimFromTransaction({ hash });
889
+ expect(claimInfo).toBeDefined();
890
+ expect(claimInfo?.claimant).toBe(claimant);
891
+ expect(typeof claimInfo?.boostId).toBe('bigint');
892
+ expect(claimInfo?.referrer).toBe(referrer);
893
+ });
894
+ });