@boostxyz/sdk 0.0.0-alpha.9 → 1.1.0-alpha.23

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 (254) hide show
  1. package/dist/Actions/Action.cjs +1 -1
  2. package/dist/Actions/Action.cjs.map +1 -1
  3. package/dist/Actions/Action.js +2 -2
  4. package/dist/Actions/ContractAction.d.ts +11 -11
  5. package/dist/Actions/ContractAction.d.ts.map +1 -1
  6. package/dist/Actions/ERC721MintAction.d.ts +14 -14
  7. package/dist/Actions/ERC721MintAction.d.ts.map +1 -1
  8. package/dist/Actions/EventAction.cjs +1 -1
  9. package/dist/Actions/EventAction.cjs.map +1 -1
  10. package/dist/Actions/EventAction.d.ts +174 -41
  11. package/dist/Actions/EventAction.d.ts.map +1 -1
  12. package/dist/Actions/EventAction.js +557 -129
  13. package/dist/Actions/EventAction.js.map +1 -1
  14. package/dist/AllowLists/AllowList.cjs +1 -1
  15. package/dist/AllowLists/AllowList.cjs.map +1 -1
  16. package/dist/AllowLists/AllowList.d.ts +6 -4
  17. package/dist/AllowLists/AllowList.d.ts.map +1 -1
  18. package/dist/AllowLists/AllowList.js +45 -23
  19. package/dist/AllowLists/AllowList.js.map +1 -1
  20. package/dist/AllowLists/OpenAllowList.d.ts +423 -0
  21. package/dist/AllowLists/OpenAllowList.d.ts.map +1 -0
  22. package/dist/AllowLists/SimpleAllowList.cjs +1 -1
  23. package/dist/AllowLists/SimpleAllowList.cjs.map +1 -1
  24. package/dist/AllowLists/SimpleAllowList.d.ts +92 -37
  25. package/dist/AllowLists/SimpleAllowList.d.ts.map +1 -1
  26. package/dist/AllowLists/SimpleAllowList.js +60 -75
  27. package/dist/AllowLists/SimpleAllowList.js.map +1 -1
  28. package/dist/AllowLists/SimpleDenyList.cjs +1 -1
  29. package/dist/AllowLists/SimpleDenyList.cjs.map +1 -1
  30. package/dist/AllowLists/SimpleDenyList.d.ts +203 -11
  31. package/dist/AllowLists/SimpleDenyList.d.ts.map +1 -1
  32. package/dist/AllowLists/SimpleDenyList.js +11 -112
  33. package/dist/AllowLists/SimpleDenyList.js.map +1 -1
  34. package/dist/Auth/PassthroughAuth.cjs +1 -1
  35. package/dist/Auth/PassthroughAuth.js +1 -1
  36. package/dist/Boost.cjs +1 -1
  37. package/dist/Boost.cjs.map +1 -1
  38. package/dist/Boost.d.ts +20 -21
  39. package/dist/Boost.d.ts.map +1 -1
  40. package/dist/Boost.js +43 -57
  41. package/dist/Boost.js.map +1 -1
  42. package/dist/BoostCore-Btl5BdAs.cjs +3 -0
  43. package/dist/BoostCore-Btl5BdAs.cjs.map +1 -0
  44. package/dist/BoostCore-CD56zbYX.js +2641 -0
  45. package/dist/BoostCore-CD56zbYX.js.map +1 -0
  46. package/dist/BoostCore.cjs +1 -2
  47. package/dist/BoostCore.cjs.map +1 -1
  48. package/dist/BoostCore.d.ts +749 -78
  49. package/dist/BoostCore.d.ts.map +1 -1
  50. package/dist/BoostCore.js +29 -1150
  51. package/dist/BoostCore.js.map +1 -1
  52. package/dist/BoostRegistry.cjs +1 -1
  53. package/dist/BoostRegistry.cjs.map +1 -1
  54. package/dist/BoostRegistry.d.ts +80 -25
  55. package/dist/BoostRegistry.d.ts.map +1 -1
  56. package/dist/BoostRegistry.js +164 -82
  57. package/dist/BoostRegistry.js.map +1 -1
  58. package/dist/Budgets/Budget.cjs +1 -1
  59. package/dist/Budgets/Budget.cjs.map +1 -1
  60. package/dist/Budgets/Budget.d.ts.map +1 -1
  61. package/dist/Budgets/Budget.js +2 -2
  62. package/dist/Budgets/Budget.js.map +1 -1
  63. package/dist/Budgets/ManagedBudget.cjs +1 -1
  64. package/dist/Budgets/ManagedBudget.cjs.map +1 -1
  65. package/dist/Budgets/ManagedBudget.d.ts +103 -221
  66. package/dist/Budgets/ManagedBudget.d.ts.map +1 -1
  67. package/dist/Budgets/ManagedBudget.js +81 -298
  68. package/dist/Budgets/ManagedBudget.js.map +1 -1
  69. package/dist/Budgets/VestingBudget.d.ts +223 -89
  70. package/dist/Budgets/VestingBudget.d.ts.map +1 -1
  71. package/dist/Deployable/Contract.cjs +1 -1
  72. package/dist/Deployable/Contract.cjs.map +1 -1
  73. package/dist/Deployable/Contract.d.ts +4 -5
  74. package/dist/Deployable/Contract.d.ts.map +1 -1
  75. package/dist/Deployable/Contract.js +5 -7
  76. package/dist/Deployable/Contract.js.map +1 -1
  77. package/dist/Deployable/Deployable.cjs.map +1 -1
  78. package/dist/Deployable/Deployable.d.ts +1 -1
  79. package/dist/Deployable/Deployable.d.ts.map +1 -1
  80. package/dist/Deployable/Deployable.js +3 -5
  81. package/dist/Deployable/Deployable.js.map +1 -1
  82. package/dist/Deployable/DeployableTarget.cjs +1 -1
  83. package/dist/Deployable/DeployableTarget.cjs.map +1 -1
  84. package/dist/Deployable/DeployableTarget.d.ts +13 -13
  85. package/dist/Deployable/DeployableTarget.d.ts.map +1 -1
  86. package/dist/Deployable/DeployableTarget.js +28 -25
  87. package/dist/Deployable/DeployableTarget.js.map +1 -1
  88. package/dist/Deployable/DeployableTargetWithRBAC.cjs +2 -0
  89. package/dist/Deployable/DeployableTargetWithRBAC.cjs.map +1 -0
  90. package/dist/Deployable/DeployableTargetWithRBAC.d.ts +248 -0
  91. package/dist/Deployable/DeployableTargetWithRBAC.d.ts.map +1 -0
  92. package/dist/Deployable/DeployableTargetWithRBAC.js +320 -0
  93. package/dist/Deployable/DeployableTargetWithRBAC.js.map +1 -0
  94. package/dist/Incentive-CcnOIc8L.cjs +2 -0
  95. package/dist/Incentive-CcnOIc8L.cjs.map +1 -0
  96. package/dist/Incentive-rM5nKznp.js +313 -0
  97. package/dist/Incentive-rM5nKznp.js.map +1 -0
  98. package/dist/Incentives/AllowListIncentive.cjs +1 -1
  99. package/dist/Incentives/AllowListIncentive.cjs.map +1 -1
  100. package/dist/Incentives/AllowListIncentive.d.ts +38 -16
  101. package/dist/Incentives/AllowListIncentive.d.ts.map +1 -1
  102. package/dist/Incentives/AllowListIncentive.js +43 -29
  103. package/dist/Incentives/AllowListIncentive.js.map +1 -1
  104. package/dist/Incentives/CGDAIncentive.cjs +1 -1
  105. package/dist/Incentives/CGDAIncentive.cjs.map +1 -1
  106. package/dist/Incentives/CGDAIncentive.d.ts +234 -21
  107. package/dist/Incentives/CGDAIncentive.d.ts.map +1 -1
  108. package/dist/Incentives/CGDAIncentive.js +46 -32
  109. package/dist/Incentives/CGDAIncentive.js.map +1 -1
  110. package/dist/Incentives/ERC1155Incentive.d.ts +224 -37
  111. package/dist/Incentives/ERC1155Incentive.d.ts.map +1 -1
  112. package/dist/Incentives/ERC20Incentive.cjs +1 -1
  113. package/dist/Incentives/ERC20Incentive.cjs.map +1 -1
  114. package/dist/Incentives/ERC20Incentive.d.ts +234 -30
  115. package/dist/Incentives/ERC20Incentive.d.ts.map +1 -1
  116. package/dist/Incentives/ERC20Incentive.js +62 -46
  117. package/dist/Incentives/ERC20Incentive.js.map +1 -1
  118. package/dist/{Budgets/SimpleBudget.d.ts → Incentives/ERC20VariableCriteriaIncentive.d.ts} +333 -438
  119. package/dist/Incentives/ERC20VariableCriteriaIncentive.d.ts.map +1 -0
  120. package/dist/Incentives/ERC20VariableIncentive.d.ts +231 -29
  121. package/dist/Incentives/ERC20VariableIncentive.d.ts.map +1 -1
  122. package/dist/Incentives/Incentive.cjs +1 -1
  123. package/dist/Incentives/Incentive.cjs.map +1 -1
  124. package/dist/Incentives/Incentive.d.ts +4 -4
  125. package/dist/Incentives/Incentive.d.ts.map +1 -1
  126. package/dist/Incentives/Incentive.js +16 -296
  127. package/dist/Incentives/Incentive.js.map +1 -1
  128. package/dist/Incentives/PointsIncentive.cjs +1 -1
  129. package/dist/Incentives/PointsIncentive.cjs.map +1 -1
  130. package/dist/Incentives/PointsIncentive.d.ts +40 -18
  131. package/dist/Incentives/PointsIncentive.d.ts.map +1 -1
  132. package/dist/Incentives/PointsIncentive.js +38 -24
  133. package/dist/Incentives/PointsIncentive.js.map +1 -1
  134. package/dist/SimpleDenyList-BDXpY74P.js +133 -0
  135. package/dist/SimpleDenyList-BDXpY74P.js.map +1 -0
  136. package/dist/SimpleDenyList-DNj5qDWM.cjs +2 -0
  137. package/dist/SimpleDenyList-DNj5qDWM.cjs.map +1 -0
  138. package/dist/Validators/SignerValidator.cjs +1 -1
  139. package/dist/Validators/SignerValidator.cjs.map +1 -1
  140. package/dist/Validators/SignerValidator.d.ts +16 -16
  141. package/dist/Validators/SignerValidator.d.ts.map +1 -1
  142. package/dist/Validators/SignerValidator.js +32 -28
  143. package/dist/Validators/SignerValidator.js.map +1 -1
  144. package/dist/Validators/Validator.cjs +1 -1
  145. package/dist/Validators/Validator.cjs.map +1 -1
  146. package/dist/Validators/Validator.d.ts +1 -1
  147. package/dist/Validators/Validator.js +2 -2
  148. package/dist/Validators/Validator.js.map +1 -1
  149. package/dist/claiming.cjs.map +1 -1
  150. package/dist/claiming.d.ts +1 -1
  151. package/dist/claiming.js.map +1 -1
  152. package/dist/componentInterfaces-BBCFkrZv.js +14 -0
  153. package/dist/componentInterfaces-BBCFkrZv.js.map +1 -0
  154. package/dist/componentInterfaces-DRI_dQ-P.cjs +2 -0
  155. package/dist/componentInterfaces-DRI_dQ-P.cjs.map +1 -0
  156. package/dist/deployments-DF_6-7hH.cjs +2 -0
  157. package/dist/deployments-DF_6-7hH.cjs.map +1 -0
  158. package/dist/deployments-fJsWblwS.js +56 -0
  159. package/dist/deployments-fJsWblwS.js.map +1 -0
  160. package/dist/deployments.json +58 -0
  161. package/dist/errors.cjs +1 -1
  162. package/dist/errors.cjs.map +1 -1
  163. package/dist/errors.d.ts +256 -20
  164. package/dist/errors.d.ts.map +1 -1
  165. package/dist/errors.js +183 -26
  166. package/dist/errors.js.map +1 -1
  167. package/dist/{generated-57_Kffpz.js → generated-CsNyWPKA.js} +3843 -2084
  168. package/dist/generated-CsNyWPKA.js.map +1 -0
  169. package/dist/generated-DHerxf1y.cjs +3 -0
  170. package/dist/generated-DHerxf1y.cjs.map +1 -0
  171. package/dist/index.cjs +1 -1
  172. package/dist/index.d.ts +5 -0
  173. package/dist/index.d.ts.map +1 -1
  174. package/dist/index.js +142 -108
  175. package/dist/index.js.map +1 -1
  176. package/dist/transfers.cjs.map +1 -1
  177. package/dist/transfers.d.ts +1 -1
  178. package/dist/transfers.js.map +1 -1
  179. package/dist/utils.cjs +1 -1
  180. package/dist/utils.cjs.map +1 -1
  181. package/dist/utils.d.ts +26 -12
  182. package/dist/utils.d.ts.map +1 -1
  183. package/dist/utils.js +38 -23
  184. package/dist/utils.js.map +1 -1
  185. package/package.json +20 -10
  186. package/src/Actions/Action.test.ts +14 -13
  187. package/src/Actions/ContractAction.test.ts +10 -10
  188. package/src/Actions/ContractAction.ts +11 -12
  189. package/src/Actions/ERC721MintAction.test.ts +6 -6
  190. package/src/Actions/ERC721MintAction.ts +14 -15
  191. package/src/Actions/EventAction.test.ts +735 -109
  192. package/src/Actions/EventAction.ts +527 -88
  193. package/src/AllowLists/AllowList.test.ts +7 -7
  194. package/src/AllowLists/AllowList.ts +5 -3
  195. package/src/AllowLists/OpenAllowList.test.ts +40 -0
  196. package/src/AllowLists/OpenAllowList.ts +45 -0
  197. package/src/AllowLists/SimpleAllowList.test.ts +4 -4
  198. package/src/AllowLists/SimpleAllowList.ts +40 -61
  199. package/src/AllowLists/SimpleDenyList.test.ts +4 -4
  200. package/src/AllowLists/SimpleDenyList.ts +41 -17
  201. package/src/Auth/PassthroughAuth.test.ts +1 -1
  202. package/src/Boost.ts +21 -24
  203. package/src/BoostCore.test.ts +361 -306
  204. package/src/BoostCore.ts +403 -220
  205. package/src/BoostRegistry.test.ts +53 -0
  206. package/src/BoostRegistry.ts +161 -40
  207. package/src/Budgets/Budget.test.ts +2 -2
  208. package/src/Budgets/Budget.ts +1 -2
  209. package/src/Budgets/ManagedBudget.test.ts +106 -19
  210. package/src/Budgets/ManagedBudget.ts +49 -321
  211. package/src/Budgets/VestingBudget.test.ts +7 -7
  212. package/src/Budgets/VestingBudget.ts +36 -106
  213. package/src/Deployable/Contract.ts +4 -5
  214. package/src/Deployable/Deployable.ts +1 -1
  215. package/src/Deployable/DeployableTarget.ts +30 -19
  216. package/src/Deployable/DeployableTargetWithRBAC.test.ts +103 -0
  217. package/src/Deployable/DeployableTargetWithRBAC.ts +447 -0
  218. package/src/Incentives/AllowListIncentive.test.ts +12 -12
  219. package/src/Incentives/AllowListIncentive.ts +30 -15
  220. package/src/Incentives/CGDAIncentive.test.ts +9 -6
  221. package/src/Incentives/CGDAIncentive.ts +39 -18
  222. package/src/Incentives/ERC1155Incentive.test.ts +3 -3
  223. package/src/Incentives/ERC1155Incentive.ts +30 -29
  224. package/src/Incentives/ERC20Incentive.test.ts +9 -6
  225. package/src/Incentives/ERC20Incentive.ts +54 -27
  226. package/src/Incentives/ERC20VariableCriteriaIncentive.test.ts +184 -0
  227. package/src/Incentives/ERC20VariableCriteriaIncentive.ts +325 -0
  228. package/src/Incentives/ERC20VariableIncentive.test.ts +8 -11
  229. package/src/Incentives/ERC20VariableIncentive.ts +50 -26
  230. package/src/Incentives/Incentive.test.ts +4 -1
  231. package/src/Incentives/Incentive.ts +7 -6
  232. package/src/Incentives/PointsIncentive.test.ts +24 -25
  233. package/src/Incentives/PointsIncentive.ts +32 -17
  234. package/src/Validators/SignerValidator.test.ts +6 -6
  235. package/src/Validators/SignerValidator.ts +20 -17
  236. package/src/Validators/Validator.test.ts +2 -2
  237. package/src/Validators/Validator.ts +1 -1
  238. package/src/claiming.ts +1 -1
  239. package/src/errors.ts +345 -21
  240. package/src/index.test.ts +118 -36
  241. package/src/index.ts +5 -0
  242. package/src/transfers.ts +1 -1
  243. package/src/utils.test.ts +2 -2
  244. package/src/utils.ts +61 -12
  245. package/dist/Budgets/SimpleBudget.d.ts.map +0 -1
  246. package/dist/componentInterfaces-CKCBwG16.cjs +0 -2
  247. package/dist/componentInterfaces-CKCBwG16.cjs.map +0 -1
  248. package/dist/componentInterfaces-DYkaxBda.js +0 -13
  249. package/dist/componentInterfaces-DYkaxBda.js.map +0 -1
  250. package/dist/generated-57_Kffpz.js.map +0 -1
  251. package/dist/generated-wKBNvm48.cjs +0 -3
  252. package/dist/generated-wKBNvm48.cjs.map +0 -1
  253. package/src/Budgets/SimpleBudget.test.ts +0 -152
  254. package/src/Budgets/SimpleBudget.ts +0 -564
@@ -0,0 +1,184 @@
1
+ import { Mock } from 'node:test';
2
+ import { selectors as eventSelectors } from '@boostxyz/signatures/events';
3
+ import { selectors as funcSelectors } from '@boostxyz/signatures/functions';
4
+ import type { MockERC20 } from '@boostxyz/test/MockERC20';
5
+ import type { MockERC721 } from '@boostxyz/test/MockERC721';
6
+ import { accounts } from '@boostxyz/test/accounts';
7
+ import {
8
+ type BudgetFixtures,
9
+ type Fixtures,
10
+ defaultOptions,
11
+ deployFixtures,
12
+ freshBoost,
13
+ fundBudget,
14
+ fundErc20,
15
+ fundErc721,
16
+ } from '@boostxyz/test/helpers';
17
+ import { loadFixture } from '@nomicfoundation/hardhat-network-helpers';
18
+ import { type Hex, isAddress, parseEther } from 'viem';
19
+ import { beforeAll, beforeEach, describe, expect, test } from 'vitest';
20
+ import { SignatureType } from '../Actions/EventAction';
21
+ import type { Boost } from '../Boost';
22
+ import type {
23
+ ERC20VariableCriteriaIncentive,
24
+ ERC20VariableCriteriaIncentivePayload,
25
+ IncentiveCriteria,
26
+ } from './ERC20VariableCriteriaIncentive';
27
+
28
+ /**
29
+ * A basic ERC721 mint scalar criteria for testing
30
+ *
31
+ * @param {MockERC721} erc721 - The ERC721 contract
32
+ * @returns {IncentiveCriteria} - Returns a basic incentive criteria
33
+ */
34
+ export function basicErc721TransferScalarCriteria(
35
+ erc721: MockERC721,
36
+ ): IncentiveCriteria {
37
+ return {
38
+ criteriaType: SignatureType.FUNC,
39
+ signature: funcSelectors['transferFrom(address,address,uint256)'] as Hex, // Function selector for mint
40
+ fieldIndex: 2, // Field where the scalar value resides
41
+ targetContract: erc721.assertValidAddress(),
42
+ };
43
+ }
44
+
45
+ /**
46
+ * A basic ERC721 mint scalar criteria for testing
47
+ *
48
+ * @param {MockERC721} erc721 - The ERC721 contract
49
+ * @returns {IncentiveCriteria} - Returns a basic incentive criteria
50
+ */
51
+ export function basicErc721MintScalarCriteria(
52
+ erc721: MockERC721,
53
+ ): IncentiveCriteria {
54
+ return {
55
+ criteriaType: SignatureType.EVENT,
56
+ signature: eventSelectors[
57
+ 'Transfer(address indexed,address indexed,uint256 indexed)'
58
+ ] as Hex, // Function selector for mint
59
+ fieldIndex: 2, // Field where the scalar value resides
60
+ targetContract: erc721.assertValidAddress(),
61
+ };
62
+ }
63
+
64
+ /**
65
+ * A basic ERC721 mint scalar payload for testing
66
+ *
67
+ * @param {MockERC721} erc721 - The ERC721 contract
68
+ * @returns {ERC20VariableCriteriaIncentivePayload} - Returns a full variable criteria incentive payload
69
+ */
70
+ export function basicErc721TransferScalarPayload(
71
+ erc721: MockERC721,
72
+ ): ERC20VariableCriteriaIncentivePayload {
73
+ return {
74
+ asset: erc721.assertValidAddress(),
75
+ reward: 1n,
76
+ limit: 1n,
77
+ criteria: basicErc721TransferScalarCriteria(erc721),
78
+ };
79
+ }
80
+
81
+ let fixtures: Fixtures,
82
+ erc20: MockERC20,
83
+ erc721: MockERC721,
84
+ erc20Incentive: ERC20VariableCriteriaIncentive,
85
+ budgets: BudgetFixtures,
86
+ boost: Boost;
87
+
88
+ describe('ERC20VariableCriteriaIncentive', () => {
89
+ beforeAll(async () => {
90
+ fixtures = await loadFixture(deployFixtures(defaultOptions));
91
+ });
92
+
93
+ beforeEach(async () => {
94
+ budgets = await loadFixture(fundBudget(defaultOptions, fixtures));
95
+ erc20 = await loadFixture(fundErc20(defaultOptions));
96
+ erc721 = await loadFixture(fundErc721(defaultOptions));
97
+ erc20Incentive = fixtures.core.ERC20VariableCriteriaIncentive({
98
+ asset: budgets.erc20.assertValidAddress(),
99
+ reward: 1n,
100
+ limit: 1n,
101
+ criteria: basicErc721TransferScalarCriteria(erc721),
102
+ });
103
+
104
+ boost = await freshBoost(fixtures, {
105
+ budget: budgets.budget,
106
+ incentives: [erc20Incentive],
107
+ });
108
+ expect(isAddress(boost.incentives[0]!.assertValidAddress())).toBe(true);
109
+ });
110
+
111
+ describe('getIncentiveCriteria', () => {
112
+ test('should fetch incentive criteria successfully', async () => {
113
+ const incentive = boost.incentives[0] as ERC20VariableCriteriaIncentive;
114
+ const criteria = await incentive.getIncentiveCriteria();
115
+ expect(criteria).toMatchObject({
116
+ criteriaType: SignatureType.FUNC,
117
+ signature: expect.any(String),
118
+ fieldIndex: expect.any(Number),
119
+ targetContract: expect.any(String),
120
+ });
121
+ });
122
+ });
123
+
124
+ describe('getIncentiveScalar', () => {
125
+ test('should return a valid scalar for function-based criteria', async () => {
126
+ const recipient = accounts[1].account;
127
+
128
+ const { hash } = await erc721.transferFromRaw(
129
+ accounts[0].account,
130
+ recipient,
131
+ 1n,
132
+ );
133
+ const scalar = await erc20Incentive.getIncentiveScalar({ hash });
134
+
135
+ expect(scalar).toBe(1n);
136
+ });
137
+
138
+ test('should return a valid scalar for event-based criteria', async () => {
139
+ erc20Incentive = fixtures.core.ERC20VariableCriteriaIncentive({
140
+ asset: budgets.erc20.assertValidAddress(),
141
+ reward: 1n,
142
+ limit: 1n,
143
+ criteria: basicErc721MintScalarCriteria(erc721),
144
+ });
145
+
146
+ boost = await freshBoost(fixtures, {
147
+ budget: budgets.budget,
148
+ incentives: [erc20Incentive],
149
+ });
150
+ const recipient = accounts[1].account;
151
+ const { hash } = await erc721.transferFromRaw(
152
+ accounts[0].account,
153
+ recipient,
154
+ 1n,
155
+ );
156
+ const scalar = await erc20Incentive.getIncentiveScalar({ hash });
157
+
158
+ expect(scalar).toBe(1n);
159
+ });
160
+
161
+ test('should throw NoMatchingLogsError for event criteria with no matching logs', async () => {
162
+ const recipient = accounts[1].account;
163
+
164
+ const { hash } = await erc20.mintRaw(recipient, parseEther('100'));
165
+
166
+ try {
167
+ await erc20Incentive.getIncentiveScalar({ hash });
168
+ } catch (e) {
169
+ expect((e as Error).name).toBe('DecodedArgsError');
170
+ }
171
+ });
172
+
173
+ test('should throw DecodedArgsError for invalid function-based data', async () => {
174
+ const recipient = accounts[1].account;
175
+ const { hash } = await erc20.mintRaw(recipient, parseEther('100'));
176
+
177
+ try {
178
+ await erc20Incentive.getIncentiveScalar({ hash });
179
+ } catch (e) {
180
+ expect((e as Error).name).toBe('DecodedArgsError');
181
+ }
182
+ });
183
+ });
184
+ });
@@ -0,0 +1,325 @@
1
+ import {
2
+ erc20VariableCriteriaIncentiveAbi,
3
+ readErc20VariableCriteriaIncentiveGetIncentiveCriteria,
4
+ } from '@boostxyz/evm';
5
+ import { bytecode } from '@boostxyz/evm/artifacts/contracts/incentives/ERC20VariableCriteriaIncentive.sol/ERC20VariableCriteriaIncentive.json';
6
+ import events from '@boostxyz/signatures/events';
7
+ import functions from '@boostxyz/signatures/functions';
8
+ import { getTransaction, getTransactionReceipt } from '@wagmi/core';
9
+ import {
10
+ type AbiEvent,
11
+ type AbiFunction,
12
+ type Address,
13
+ type Hex,
14
+ type Log,
15
+ decodeFunctionData,
16
+ encodeAbiParameters,
17
+ parseEventLogs,
18
+ } from 'viem';
19
+ import { ERC20VariableCriteriaIncentive as ERC20VariableCriteriaIncentiveBases } from '../../dist/deployments.json';
20
+ import { SignatureType } from '../Actions/EventAction';
21
+ import type {
22
+ DeployableOptions,
23
+ GenericDeployableParams,
24
+ } from '../Deployable/Deployable';
25
+ import { DeployableTarget } from '../Deployable/DeployableTarget';
26
+ import {
27
+ DecodedArgsError,
28
+ FieldActionValidationError,
29
+ IncentiveCriteriaNotFoundError,
30
+ InvalidCriteriaTypeError,
31
+ NoMatchingLogsError,
32
+ } from '../errors';
33
+ import type { ReadParams } from '../utils';
34
+ import { ERC20VariableIncentive } from './ERC20VariableIncentive';
35
+
36
+ export interface ERC20VariableCriteriaIncentivePayload {
37
+ /**
38
+ * The address of the incentivized asset.
39
+ *
40
+ * @type {Address}
41
+ */
42
+ asset: Address;
43
+ /**
44
+ * The amount of the asset to distribute as reward.
45
+ *
46
+ * @type {bigint}
47
+ */
48
+ reward: bigint;
49
+ /**
50
+ * The total spending limit of the asset that will be distributed.
51
+ *
52
+ * @type {bigint}
53
+ */
54
+ limit: bigint;
55
+ /**
56
+ * The criteria for the incentive that determines how the reward is distributed.
57
+ *
58
+ * @type {IncentiveCriteria}
59
+ */
60
+ criteria: IncentiveCriteria;
61
+ }
62
+
63
+ export interface IncentiveCriteria {
64
+ /**
65
+ * The type of criteria used, either function signature or event signature.
66
+ *
67
+ * @type {SignatureType}
68
+ */
69
+ criteriaType: SignatureType;
70
+ /**
71
+ * The function or event signature used for criteria matching.
72
+ *
73
+ * @type {Hex}
74
+ */
75
+ signature: Hex;
76
+ /**
77
+ * The index of the field from where the scalar value is extracted.
78
+ *
79
+ * @type {number}
80
+ */
81
+ fieldIndex: number;
82
+ /**
83
+ * The address of the contract where the event/function is called/emitted.
84
+ *
85
+ * @type {Address}
86
+ */
87
+ targetContract: Address;
88
+ }
89
+
90
+ export interface ReadIncentiveCriteriaParams
91
+ extends ReadParams<
92
+ typeof erc20VariableCriteriaIncentiveAbi,
93
+ 'getIncentiveCriteria'
94
+ > {}
95
+
96
+ export interface GetIncentiveScalarParams {
97
+ hash: Hex;
98
+ }
99
+
100
+ /**
101
+ * Extended ERC20 Variable Criteria Incentive class that fetches incentive criteria and scalar
102
+ */
103
+ export class ERC20VariableCriteriaIncentive extends DeployableTarget<
104
+ ERC20VariableCriteriaIncentivePayload,
105
+ typeof erc20VariableCriteriaIncentiveAbi
106
+ > {
107
+ public override readonly abi = erc20VariableCriteriaIncentiveAbi;
108
+ /**
109
+ * @inheritdoc
110
+ *
111
+ * @public
112
+ * @static
113
+ * @type {Record<number, Address>}
114
+ */
115
+ public static override bases: Record<number, Address> = {
116
+ 31337: import.meta.env.VITE_ERC20_VARIABLE_CRITERIA_INCENTIVE_BASE,
117
+ ...(ERC20VariableCriteriaIncentiveBases as Record<number, Address>),
118
+ };
119
+
120
+ /**
121
+ *Functions from the ERC20VariableIncentive contract
122
+ */
123
+
124
+ /**
125
+ * Fetches the IncentiveCriteria struct from the contract
126
+ *
127
+ * @returns {Promise<IncentiveCriteria>} Incentive criteria structure
128
+ * @throws {IncentiveCriteriaNotFoundError}
129
+ */
130
+ public async getIncentiveCriteria(): Promise<IncentiveCriteria> {
131
+ try {
132
+ const criteria =
133
+ await readErc20VariableCriteriaIncentiveGetIncentiveCriteria(
134
+ this._config,
135
+ {
136
+ address: this.assertValidAddress(),
137
+ },
138
+ );
139
+
140
+ return criteria;
141
+ } catch (e) {
142
+ throw new IncentiveCriteriaNotFoundError(e as Error);
143
+ }
144
+ }
145
+
146
+ /**
147
+ * Fetches the incentive scalar from a transaction hash
148
+ *
149
+ * @param {GetIncentiveScalarParams} params
150
+ * @returns {Promise<bigint>}
151
+ * @throws {InvalidCriteriaTypeError | NoMatchingLogsError | DecodedArgsError}
152
+ */
153
+ public async getIncentiveScalar({
154
+ hash,
155
+ }: GetIncentiveScalarParams): Promise<bigint> {
156
+ const criteria = await this.getIncentiveCriteria();
157
+ const transaction = await getTransaction(this._config, {
158
+ hash,
159
+ });
160
+ if (criteria.criteriaType === SignatureType.EVENT) {
161
+ const transactionReceipt = await getTransactionReceipt(this._config, {
162
+ hash,
163
+ });
164
+
165
+ const logs = transactionReceipt.logs;
166
+
167
+ if (logs.length === 0) {
168
+ throw new NoMatchingLogsError(
169
+ `No logs found for event signature ${criteria.signature}`,
170
+ );
171
+ }
172
+
173
+ // Decode the event log
174
+ try {
175
+ // Decode function data
176
+ const eventAbi = (events.abi as Record<Hex, AbiEvent>)[
177
+ criteria.signature
178
+ ] as AbiEvent;
179
+ const decodedEvents = parseEventLogs({
180
+ abi: [eventAbi],
181
+ logs,
182
+ });
183
+ if (decodedEvents == undefined || decodedEvents.length === 0) {
184
+ throw new NoMatchingLogsError(
185
+ `No logs found for event signature ${criteria.signature}`,
186
+ );
187
+ }
188
+ const scalarValue = (decodedEvents[0]?.args as string[])[
189
+ criteria.fieldIndex
190
+ ];
191
+
192
+ if (scalarValue === undefined) {
193
+ throw new DecodedArgsError(
194
+ `Decoded argument at index ${criteria.fieldIndex} is undefined`,
195
+ );
196
+ }
197
+ return BigInt(scalarValue);
198
+ } catch (e) {
199
+ throw new DecodedArgsError(
200
+ `Failed to decode event log for signature ${criteria.signature}: ${(e as Error).message}`,
201
+ );
202
+ }
203
+ } else if (criteria.criteriaType === SignatureType.FUNC) {
204
+ // Fetch the transaction data
205
+ try {
206
+ // Decode function data
207
+ const func = (functions.abi as Record<Hex, AbiFunction>)[
208
+ criteria.signature
209
+ ] as AbiFunction;
210
+
211
+ const decodedFunction = decodeFunctionData({
212
+ abi: [func],
213
+ data: transaction.input,
214
+ });
215
+ const scalarValue = decodedFunction.args[criteria.fieldIndex] as string;
216
+ if (scalarValue === undefined || scalarValue === null) {
217
+ throw new DecodedArgsError(
218
+ `Decoded argument at index ${criteria.fieldIndex} is undefined`,
219
+ );
220
+ }
221
+ return BigInt(scalarValue);
222
+ } catch (e) {
223
+ throw new DecodedArgsError(
224
+ `Failed to decode function data for signature ${criteria.signature}: ${(e as Error).message}`,
225
+ );
226
+ }
227
+ } else {
228
+ throw new InvalidCriteriaTypeError(
229
+ `Invalid criteria type ${criteria.criteriaType}`,
230
+ );
231
+ }
232
+ }
233
+ /**
234
+ * @inheritdoc
235
+ *
236
+ * @public
237
+ * @param {?ERC20VariableCriteriaIncentivePayload} [_payload]
238
+ * @param {?DeployableOptions} [_options]
239
+ * @returns {GenericDeployableParams}
240
+ */
241
+ public override buildParameters(
242
+ _payload?: ERC20VariableCriteriaIncentivePayload,
243
+ _options?: DeployableOptions,
244
+ ): GenericDeployableParams {
245
+ const [payload, options] = this.validateDeploymentConfig(
246
+ _payload,
247
+ _options,
248
+ );
249
+ return {
250
+ abi: erc20VariableCriteriaIncentiveAbi,
251
+ bytecode: bytecode as Hex,
252
+ args: [prepareERC20VariableCriteriaIncentivePayload(payload)],
253
+ ...this.optionallyAttachAccount(options.account),
254
+ };
255
+ }
256
+
257
+ /**
258
+ * Builds the claim data for the ERC20VariableCriteriaIncentive.
259
+ *
260
+ * @public
261
+ * @param {bigint} rewardAmount
262
+ * @returns {Hex} Returns the encoded claim data
263
+ * @description This function returns the encoded claim data for the ERC20VariableCriteriaIncentive.
264
+ */
265
+ public buildClaimData(rewardAmount: bigint) {
266
+ return encodeAbiParameters(
267
+ [{ type: 'uint256', name: 'rewardAmount' }],
268
+ [rewardAmount],
269
+ );
270
+ }
271
+ }
272
+
273
+ /**
274
+ *
275
+ *
276
+ * @param {InitPayloadExtended} param0
277
+ * @param {Address} param0.asset - The address of the ERC20 asset to incentivize.
278
+ * @param {bigint} param0.reward - The reward amount to distribute per action.
279
+ * @param {bigint} param0.limit - The total limit of the asset distribution.
280
+ * @param {IncentiveCriteria} param0.criteria - The incentive criteria for reward distribution.
281
+ * @returns {Hex}
282
+ */
283
+ export function prepareERC20VariableCriteriaIncentivePayload({
284
+ asset,
285
+ reward,
286
+ limit,
287
+ criteria,
288
+ }: ERC20VariableCriteriaIncentivePayload) {
289
+ return encodeAbiParameters(
290
+ [
291
+ {
292
+ type: 'tuple',
293
+ name: 'initPayloadExtended',
294
+ components: [
295
+ { type: 'address', name: 'asset' },
296
+ { type: 'uint256', name: 'reward' },
297
+ { type: 'uint256', name: 'limit' },
298
+ {
299
+ type: 'tuple',
300
+ name: 'criteria',
301
+ components: [
302
+ { type: 'uint8', name: 'criteriaType' },
303
+ { type: 'bytes32', name: 'signature' },
304
+ { type: 'uint8', name: 'fieldIndex' },
305
+ { type: 'address', name: 'targetContract' },
306
+ ],
307
+ },
308
+ ],
309
+ },
310
+ ],
311
+ [
312
+ {
313
+ asset: asset,
314
+ reward: reward,
315
+ limit: limit,
316
+ criteria: {
317
+ criteriaType: criteria.criteriaType,
318
+ signature: criteria.signature,
319
+ fieldIndex: criteria.fieldIndex,
320
+ targetContract: criteria.targetContract,
321
+ },
322
+ },
323
+ ],
324
+ );
325
+ }
@@ -2,7 +2,7 @@ import { readMockErc20BalanceOf } from '@boostxyz/evm';
2
2
  import { loadFixture } from '@nomicfoundation/hardhat-network-helpers';
3
3
  import { encodeAbiParameters, isAddress, parseEther, zeroAddress } from 'viem';
4
4
  import { beforeAll, beforeEach, describe, expect, test } from 'vitest';
5
- import { accounts } from '../../test/accounts';
5
+ import { accounts } from '@boostxyz/test/accounts';
6
6
  import {
7
7
  type BudgetFixtures,
8
8
  type Fixtures,
@@ -10,7 +10,7 @@ import {
10
10
  deployFixtures,
11
11
  freshBoost,
12
12
  fundBudget,
13
- } from '../../test/helpers';
13
+ } from '@boostxyz/test/helpers';
14
14
  import { ERC20VariableIncentive } from './ERC20VariableIncentive';
15
15
 
16
16
  const BOOST_CORE_CLAIM_FEE = parseEther('0.000075');
@@ -19,7 +19,7 @@ let fixtures: Fixtures, budgets: BudgetFixtures;
19
19
 
20
20
  describe('ERC20VariableIncentive', () => {
21
21
  beforeAll(async () => {
22
- fixtures = await loadFixture(deployFixtures);
22
+ fixtures = await loadFixture(deployFixtures(defaultOptions));
23
23
  });
24
24
 
25
25
  beforeEach(async () => {
@@ -31,6 +31,7 @@ describe('ERC20VariableIncentive', () => {
31
31
  asset: zeroAddress,
32
32
  reward: 1n,
33
33
  limit: 1n,
34
+ manager: zeroAddress,
34
35
  });
35
36
  await action.deploy();
36
37
  expect(isAddress(action.assertValidAddress())).toBe(true);
@@ -47,6 +48,7 @@ describe('ERC20VariableIncentive', () => {
47
48
  asset: budgets.erc20.assertValidAddress(),
48
49
  reward: 1n,
49
50
  limit: 1n,
51
+ manager: zeroAddress,
50
52
  },
51
53
  );
52
54
  const boost = await freshBoost(fixtures, {
@@ -58,10 +60,7 @@ describe('ERC20VariableIncentive', () => {
58
60
  const incentiveQuantity = 1;
59
61
  const claimDataPayload = await boost.validator.encodeClaimData({
60
62
  signer: trustedSigner,
61
- incentiveData: encodeAbiParameters(
62
- [{ name: '', type: 'uint256' }],
63
- [parseEther('1')],
64
- ),
63
+ incentiveData: erc20VariableIncentive.buildClaimData(parseEther('1')),
65
64
  chainId: defaultOptions.config.chains[0].id,
66
65
  incentiveQuantity,
67
66
  claimant,
@@ -93,6 +92,7 @@ describe('ERC20VariableIncentive', () => {
93
92
  asset: budgets.erc20.assertValidAddress(),
94
93
  reward: 1n,
95
94
  limit: 1n,
95
+ manager: zeroAddress,
96
96
  },
97
97
  );
98
98
  const boost = await freshBoost(fixtures, {
@@ -104,10 +104,7 @@ describe('ERC20VariableIncentive', () => {
104
104
  const incentiveQuantity = 1;
105
105
  const claimDataPayload = await boost.validator.encodeClaimData({
106
106
  signer: trustedSigner,
107
- incentiveData: encodeAbiParameters(
108
- [{ name: '', type: 'uint256' }],
109
- [parseEther('1')],
110
- ),
107
+ incentiveData: erc20VariableIncentive.buildClaimData(parseEther('1')),
111
108
  chainId: defaultOptions.config.chains[0].id,
112
109
  incentiveQuantity,
113
110
  claimant,