@boostxyz/sdk 1.1.0-alpha.23 → 2.0.0-alpha.25
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/dist/Actions/Action.cjs +1 -1
- package/dist/Actions/Action.js +7 -7
- package/dist/Actions/EventAction.cjs +1 -1
- package/dist/Actions/EventAction.cjs.map +1 -1
- package/dist/Actions/EventAction.d.ts +32 -5
- package/dist/Actions/EventAction.d.ts.map +1 -1
- package/dist/Actions/EventAction.js +164 -137
- package/dist/Actions/EventAction.js.map +1 -1
- package/dist/AllowLists/AllowList.cjs +1 -1
- package/dist/AllowLists/AllowList.js +10 -10
- package/dist/AllowLists/SimpleAllowList.cjs +1 -1
- package/dist/AllowLists/SimpleAllowList.js +10 -10
- package/dist/AllowLists/SimpleDenyList.cjs +1 -1
- package/dist/AllowLists/SimpleDenyList.js +3 -3
- package/dist/Auth/PassthroughAuth.cjs +1 -1
- package/dist/Auth/PassthroughAuth.js +1 -1
- package/dist/BoostCore.cjs +2 -1
- package/dist/BoostCore.cjs.map +1 -1
- package/dist/BoostCore.d.ts +564 -1
- package/dist/BoostCore.d.ts.map +1 -1
- package/dist/BoostCore.js +1322 -29
- package/dist/BoostCore.js.map +1 -1
- package/dist/BoostRegistry.cjs +1 -1
- package/dist/BoostRegistry.js +27 -27
- package/dist/Budgets/Budget.cjs +1 -1
- package/dist/Budgets/Budget.js +2 -2
- package/dist/Budgets/ManagedBudget.cjs +1 -1
- package/dist/Budgets/ManagedBudget.js +23 -23
- package/dist/Deployable/DeployableTarget.cjs +1 -1
- package/dist/Deployable/DeployableTarget.js +1 -1
- package/dist/Deployable/DeployableTargetWithRBAC.cjs +1 -1
- package/dist/Deployable/DeployableTargetWithRBAC.js +23 -23
- package/dist/Incentives/AllowListIncentive.cjs +1 -1
- package/dist/Incentives/AllowListIncentive.js +8 -8
- package/dist/Incentives/CGDAIncentive.cjs +1 -1
- package/dist/Incentives/CGDAIncentive.js +12 -12
- package/dist/Incentives/ERC20Incentive.cjs +1 -1
- package/dist/Incentives/ERC20Incentive.js +16 -16
- package/dist/Incentives/ERC20VariableCriteriaIncentive.cjs +2 -0
- package/dist/Incentives/ERC20VariableCriteriaIncentive.cjs.map +1 -0
- package/dist/Incentives/ERC20VariableCriteriaIncentive.d.ts +42 -15
- package/dist/Incentives/ERC20VariableCriteriaIncentive.d.ts.map +1 -1
- package/dist/Incentives/ERC20VariableCriteriaIncentive.js +188 -0
- package/dist/Incentives/ERC20VariableCriteriaIncentive.js.map +1 -0
- package/dist/Incentives/ERC20VariableIncentive.cjs +2 -0
- package/dist/Incentives/ERC20VariableIncentive.cjs.map +1 -0
- package/dist/Incentives/ERC20VariableIncentive.d.ts +7 -5
- package/dist/Incentives/ERC20VariableIncentive.d.ts.map +1 -1
- package/dist/{Incentive-rM5nKznp.js → Incentives/ERC20VariableIncentive.js} +42 -67
- package/dist/Incentives/ERC20VariableIncentive.js.map +1 -0
- package/dist/Incentives/Incentive.cjs +1 -1
- package/dist/Incentives/Incentive.cjs.map +1 -1
- package/dist/Incentives/Incentive.d.ts +552 -3
- package/dist/Incentives/Incentive.d.ts.map +1 -1
- package/dist/Incentives/Incentive.js +40 -16
- package/dist/Incentives/Incentive.js.map +1 -1
- package/dist/Incentives/PointsIncentive.cjs +1 -1
- package/dist/Incentives/PointsIncentive.js +8 -8
- package/dist/{SimpleDenyList-DNj5qDWM.cjs → SimpleDenyList-BdlpZdDz.cjs} +2 -2
- package/dist/{SimpleDenyList-DNj5qDWM.cjs.map → SimpleDenyList-BdlpZdDz.cjs.map} +1 -1
- package/dist/{SimpleDenyList-BDXpY74P.js → SimpleDenyList-D0cyVUVv.js} +16 -16
- package/dist/{SimpleDenyList-BDXpY74P.js.map → SimpleDenyList-D0cyVUVv.js.map} +1 -1
- package/dist/Validators/LimitedSignerValidator.cjs +2 -0
- package/dist/Validators/LimitedSignerValidator.cjs.map +1 -0
- package/dist/Validators/LimitedSignerValidator.d.ts +806 -0
- package/dist/Validators/LimitedSignerValidator.d.ts.map +1 -0
- package/dist/Validators/LimitedSignerValidator.js +299 -0
- package/dist/Validators/LimitedSignerValidator.js.map +1 -0
- package/dist/Validators/SignerValidator.cjs +1 -1
- package/dist/Validators/SignerValidator.cjs.map +1 -1
- package/dist/Validators/SignerValidator.d.ts +2 -2
- package/dist/Validators/SignerValidator.js +5 -5
- package/dist/Validators/SignerValidator.js.map +1 -1
- package/dist/Validators/Validator.cjs +1 -1
- package/dist/Validators/Validator.cjs.map +1 -1
- package/dist/Validators/Validator.d.ts +22 -2
- package/dist/Validators/Validator.d.ts.map +1 -1
- package/dist/Validators/Validator.js +26 -17
- package/dist/Validators/Validator.js.map +1 -1
- package/dist/{componentInterfaces-BBCFkrZv.js → componentInterfaces-bIVo8eyA.js} +9 -9
- package/dist/componentInterfaces-bIVo8eyA.js.map +1 -0
- package/dist/{deployments-fJsWblwS.js → deployments-Ccx1MtoK.js} +5 -5
- package/dist/deployments-Ccx1MtoK.js.map +1 -0
- package/dist/{generated-CsNyWPKA.js → generated-BAKNSOjJ.js} +661 -381
- package/dist/generated-BAKNSOjJ.js.map +1 -0
- package/dist/generated-Cqn4wS01.cjs +3 -0
- package/dist/generated-Cqn4wS01.cjs.map +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +145 -132
- package/dist/index.js.map +1 -1
- package/dist/utils.cjs +1 -1
- package/dist/utils.cjs.map +1 -1
- package/dist/utils.d.ts +10 -0
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +27 -26
- package/dist/utils.js.map +1 -1
- package/package.json +21 -5
- package/src/Actions/EventAction.test.ts +381 -122
- package/src/Actions/EventAction.ts +85 -23
- package/src/BoostCore.test.ts +3 -3
- package/src/BoostCore.ts +51 -5
- package/src/Incentives/AllowListIncentive.test.ts +19 -21
- package/src/Incentives/CGDAIncentive.test.ts +20 -22
- package/src/Incentives/ERC1155Incentive.test.ts +14 -15
- package/src/Incentives/ERC20Incentive.test.ts +17 -19
- package/src/Incentives/ERC20VariableCriteriaIncentive.test.ts +62 -10
- package/src/Incentives/ERC20VariableCriteriaIncentive.ts +79 -37
- package/src/Incentives/ERC20VariableIncentive.test.ts +16 -18
- package/src/Incentives/ERC20VariableIncentive.ts +16 -8
- package/src/Incentives/Incentive.ts +4 -1
- package/src/Incentives/PointsIncentive.test.ts +3 -5
- package/src/Validators/LimitedSignerValidator.test.ts +223 -0
- package/src/Validators/LimitedSignerValidator.ts +707 -0
- package/src/Validators/SignerValidator.test.ts +21 -22
- package/src/Validators/SignerValidator.ts +2 -2
- package/src/Validators/Validator.test.ts +7 -1
- package/src/Validators/Validator.ts +30 -3
- package/src/index.test.ts +2 -0
- package/src/index.ts +1 -0
- package/src/utils.ts +11 -0
- package/dist/BoostCore-Btl5BdAs.cjs +0 -3
- package/dist/BoostCore-Btl5BdAs.cjs.map +0 -1
- package/dist/BoostCore-CD56zbYX.js +0 -2641
- package/dist/BoostCore-CD56zbYX.js.map +0 -1
- package/dist/Incentive-CcnOIc8L.cjs +0 -2
- package/dist/Incentive-CcnOIc8L.cjs.map +0 -1
- package/dist/Incentive-rM5nKznp.js.map +0 -1
- package/dist/componentInterfaces-BBCFkrZv.js.map +0 -1
- package/dist/deployments-fJsWblwS.js.map +0 -1
- package/dist/generated-CsNyWPKA.js.map +0 -1
- package/dist/generated-DHerxf1y.cjs +0 -3
- package/dist/generated-DHerxf1y.cjs.map +0 -1
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { readMockErc20BalanceOf } from
|
|
2
|
-
import { loadFixture } from
|
|
3
|
-
import { isAddress, pad, parseEther, zeroAddress } from
|
|
4
|
-
import { beforeAll, beforeEach, describe, expect, test } from
|
|
5
|
-
import { accounts } from
|
|
1
|
+
import { readMockErc20BalanceOf } from "@boostxyz/evm";
|
|
2
|
+
import { loadFixture } from "@nomicfoundation/hardhat-network-helpers";
|
|
3
|
+
import { isAddress, pad, parseEther, zeroAddress } from "viem";
|
|
4
|
+
import { beforeAll, beforeEach, describe, expect, test } from "vitest";
|
|
5
|
+
import { accounts } from "@boostxyz/test/accounts";
|
|
6
6
|
import {
|
|
7
7
|
type BudgetFixtures,
|
|
8
8
|
type Fixtures,
|
|
@@ -10,14 +10,14 @@ import {
|
|
|
10
10
|
deployFixtures,
|
|
11
11
|
freshBoost,
|
|
12
12
|
fundBudget,
|
|
13
|
-
} from
|
|
14
|
-
import { BOOST_CORE_CLAIM_FEE } from
|
|
15
|
-
import { StrategyType } from
|
|
16
|
-
import { ERC20Incentive } from
|
|
13
|
+
} from "@boostxyz/test/helpers";
|
|
14
|
+
import { BOOST_CORE_CLAIM_FEE } from "../BoostCore";
|
|
15
|
+
import { StrategyType } from "../claiming";
|
|
16
|
+
import { ERC20Incentive } from "./ERC20Incentive";
|
|
17
17
|
|
|
18
18
|
let fixtures: Fixtures, budgets: BudgetFixtures;
|
|
19
19
|
|
|
20
|
-
describe(
|
|
20
|
+
describe("ERC20Incentive", () => {
|
|
21
21
|
beforeAll(async () => {
|
|
22
22
|
fixtures = await loadFixture(deployFixtures(defaultOptions));
|
|
23
23
|
});
|
|
@@ -26,7 +26,7 @@ describe('ERC20Incentive', () => {
|
|
|
26
26
|
budgets = await loadFixture(fundBudget(defaultOptions, fixtures));
|
|
27
27
|
});
|
|
28
28
|
|
|
29
|
-
test(
|
|
29
|
+
test("can successfully be deployed", async () => {
|
|
30
30
|
const action = new ERC20Incentive(defaultOptions, {
|
|
31
31
|
asset: zeroAddress,
|
|
32
32
|
strategy: StrategyType.POOL,
|
|
@@ -38,7 +38,7 @@ describe('ERC20Incentive', () => {
|
|
|
38
38
|
expect(isAddress(action.assertValidAddress())).toBe(true);
|
|
39
39
|
});
|
|
40
40
|
|
|
41
|
-
test(
|
|
41
|
+
test("can claim", async () => {
|
|
42
42
|
// biome-ignore lint/style/noNonNullAssertion: we know this is defined
|
|
43
43
|
const referrer = accounts.at(1)!.account!,
|
|
44
44
|
// biome-ignore lint/style/noNonNullAssertion: we know this is defined
|
|
@@ -57,12 +57,11 @@ describe('ERC20Incentive', () => {
|
|
|
57
57
|
|
|
58
58
|
const claimant = trustedSigner.account;
|
|
59
59
|
const incentiveData = erc20Incentive.buildClaimData();
|
|
60
|
-
const incentiveQuantity = 1;
|
|
61
60
|
const claimDataPayload = await boost.validator.encodeClaimData({
|
|
62
61
|
signer: trustedSigner,
|
|
63
62
|
incentiveData,
|
|
64
63
|
chainId: defaultOptions.config.chains[0].id,
|
|
65
|
-
incentiveQuantity,
|
|
64
|
+
incentiveQuantity: boost.incentives.length,
|
|
66
65
|
claimant,
|
|
67
66
|
boostId: boost.id,
|
|
68
67
|
});
|
|
@@ -82,7 +81,7 @@ describe('ERC20Incentive', () => {
|
|
|
82
81
|
).toBe(1n);
|
|
83
82
|
});
|
|
84
83
|
|
|
85
|
-
test(
|
|
84
|
+
test("cannot claim twice", async () => {
|
|
86
85
|
// biome-ignore lint/style/noNonNullAssertion: we know this is defined
|
|
87
86
|
const referrer = accounts.at(1)!.account!;
|
|
88
87
|
// biome-ignore lint/style/noNonNullAssertion: we know this is defined
|
|
@@ -100,13 +99,12 @@ describe('ERC20Incentive', () => {
|
|
|
100
99
|
});
|
|
101
100
|
|
|
102
101
|
const claimant = trustedSigner.account;
|
|
103
|
-
const incentiveData = pad(
|
|
104
|
-
const incentiveQuantity = 1;
|
|
102
|
+
const incentiveData = pad("0xdef456232173821931823712381232131391321934");
|
|
105
103
|
const claimDataPayload = await boost.validator.encodeClaimData({
|
|
106
104
|
signer: trustedSigner,
|
|
107
105
|
incentiveData,
|
|
108
106
|
chainId: defaultOptions.config.chains[0].id,
|
|
109
|
-
incentiveQuantity,
|
|
107
|
+
incentiveQuantity: boost.incentives.length,
|
|
110
108
|
claimant,
|
|
111
109
|
boostId: boost.id,
|
|
112
110
|
});
|
|
@@ -124,7 +122,7 @@ describe('ERC20Incentive', () => {
|
|
|
124
122
|
0n,
|
|
125
123
|
referrer,
|
|
126
124
|
claimDataPayload,
|
|
127
|
-
{ value: parseEther(
|
|
125
|
+
{ value: parseEther("0.000075") },
|
|
128
126
|
);
|
|
129
127
|
} catch (e) {
|
|
130
128
|
expect(e).toBeInstanceOf(Error);
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { Mock } from 'node:test';
|
|
2
1
|
import { selectors as eventSelectors } from '@boostxyz/signatures/events';
|
|
3
2
|
import { selectors as funcSelectors } from '@boostxyz/signatures/functions';
|
|
4
3
|
import type { MockERC20 } from '@boostxyz/test/MockERC20';
|
|
@@ -15,15 +14,17 @@ import {
|
|
|
15
14
|
fundErc721,
|
|
16
15
|
} from '@boostxyz/test/helpers';
|
|
17
16
|
import { loadFixture } from '@nomicfoundation/hardhat-network-helpers';
|
|
18
|
-
import { type Hex, isAddress, parseEther } from 'viem';
|
|
17
|
+
import { type Hex, isAddress, parseEther, zeroAddress, zeroHash } from 'viem';
|
|
19
18
|
import { beforeAll, beforeEach, describe, expect, test } from 'vitest';
|
|
20
19
|
import { SignatureType } from '../Actions/EventAction';
|
|
21
20
|
import type { Boost } from '../Boost';
|
|
22
|
-
import
|
|
23
|
-
ERC20VariableCriteriaIncentive,
|
|
24
|
-
ERC20VariableCriteriaIncentivePayload,
|
|
25
|
-
IncentiveCriteria,
|
|
21
|
+
import {
|
|
22
|
+
type ERC20VariableCriteriaIncentive,
|
|
23
|
+
type ERC20VariableCriteriaIncentivePayload,
|
|
24
|
+
type IncentiveCriteria,
|
|
25
|
+
gasRebateIncentiveCriteria,
|
|
26
26
|
} from './ERC20VariableCriteriaIncentive';
|
|
27
|
+
import { allKnownSignatures } from '@boostxyz/test/allKnownSignatures';
|
|
27
28
|
|
|
28
29
|
/**
|
|
29
30
|
* A basic ERC721 mint scalar criteria for testing
|
|
@@ -130,7 +131,11 @@ describe('ERC20VariableCriteriaIncentive', () => {
|
|
|
130
131
|
recipient,
|
|
131
132
|
1n,
|
|
132
133
|
);
|
|
133
|
-
const scalar = await erc20Incentive.getIncentiveScalar({
|
|
134
|
+
const scalar = await erc20Incentive.getIncentiveScalar({
|
|
135
|
+
hash,
|
|
136
|
+
chainId: 31337,
|
|
137
|
+
knownSignatures: allKnownSignatures
|
|
138
|
+
});
|
|
134
139
|
|
|
135
140
|
expect(scalar).toBe(1n);
|
|
136
141
|
});
|
|
@@ -153,18 +158,61 @@ describe('ERC20VariableCriteriaIncentive', () => {
|
|
|
153
158
|
recipient,
|
|
154
159
|
1n,
|
|
155
160
|
);
|
|
156
|
-
const scalar = await erc20Incentive.getIncentiveScalar({
|
|
161
|
+
const scalar = await erc20Incentive.getIncentiveScalar({
|
|
162
|
+
hash,
|
|
163
|
+
chainId: 31337,
|
|
164
|
+
knownSignatures: allKnownSignatures
|
|
165
|
+
});
|
|
157
166
|
|
|
158
167
|
expect(scalar).toBe(1n);
|
|
159
168
|
});
|
|
160
169
|
|
|
170
|
+
test('gasRebateIncentiveCriteria generates correct incentive criteria', async () => {
|
|
171
|
+
// Ensure that the gasRebateIncentiveCriteria returns the correct structure
|
|
172
|
+
const gasRebateCriteria = gasRebateIncentiveCriteria();
|
|
173
|
+
|
|
174
|
+
erc20Incentive = fixtures.core.ERC20VariableCriteriaIncentive({
|
|
175
|
+
asset: budgets.erc20.assertValidAddress(),
|
|
176
|
+
reward: 1n,
|
|
177
|
+
limit: 1n,
|
|
178
|
+
criteria: gasRebateCriteria,
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
// Validate the returned structure against the expected criteria values
|
|
184
|
+
expect(gasRebateCriteria).toEqual({
|
|
185
|
+
criteriaType: SignatureType.EVENT,
|
|
186
|
+
signature: zeroHash,
|
|
187
|
+
fieldIndex: 255,
|
|
188
|
+
targetContract: zeroAddress,
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
boost = await freshBoost(fixtures, {
|
|
192
|
+
budget: budgets.budget,
|
|
193
|
+
incentives: [erc20Incentive],
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
// Validate that the deployed incentive has the correct criteria set up
|
|
197
|
+
const deployedIncentive = await boost.incentives[0] as ERC20VariableCriteriaIncentive;
|
|
198
|
+
const deployedCriteria = await deployedIncentive.getIncentiveCriteria();
|
|
199
|
+
expect(deployedCriteria.criteriaType).toBe(SignatureType.EVENT);
|
|
200
|
+
expect(deployedCriteria.signature).toBe(zeroHash);
|
|
201
|
+
expect(deployedCriteria.fieldIndex).toBe(255);
|
|
202
|
+
expect(deployedCriteria.targetContract).toBe(zeroAddress);
|
|
203
|
+
});
|
|
204
|
+
|
|
161
205
|
test('should throw NoMatchingLogsError for event criteria with no matching logs', async () => {
|
|
162
206
|
const recipient = accounts[1].account;
|
|
163
207
|
|
|
164
208
|
const { hash } = await erc20.mintRaw(recipient, parseEther('100'));
|
|
165
209
|
|
|
166
210
|
try {
|
|
167
|
-
await erc20Incentive.getIncentiveScalar({
|
|
211
|
+
await erc20Incentive.getIncentiveScalar({
|
|
212
|
+
hash,
|
|
213
|
+
chainId: 31337,
|
|
214
|
+
knownSignatures: allKnownSignatures
|
|
215
|
+
});
|
|
168
216
|
} catch (e) {
|
|
169
217
|
expect((e as Error).name).toBe('DecodedArgsError');
|
|
170
218
|
}
|
|
@@ -175,7 +223,11 @@ describe('ERC20VariableCriteriaIncentive', () => {
|
|
|
175
223
|
const { hash } = await erc20.mintRaw(recipient, parseEther('100'));
|
|
176
224
|
|
|
177
225
|
try {
|
|
178
|
-
await erc20Incentive.getIncentiveScalar({
|
|
226
|
+
await erc20Incentive.getIncentiveScalar({
|
|
227
|
+
hash,
|
|
228
|
+
chainId: 31337,
|
|
229
|
+
knownSignatures: allKnownSignatures
|
|
230
|
+
});
|
|
179
231
|
} catch (e) {
|
|
180
232
|
expect((e as Error).name).toBe('DecodedArgsError');
|
|
181
233
|
}
|
|
@@ -3,18 +3,17 @@ import {
|
|
|
3
3
|
readErc20VariableCriteriaIncentiveGetIncentiveCriteria,
|
|
4
4
|
} from '@boostxyz/evm';
|
|
5
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
6
|
import { getTransaction, getTransactionReceipt } from '@wagmi/core';
|
|
9
7
|
import {
|
|
10
8
|
type AbiEvent,
|
|
11
9
|
type AbiFunction,
|
|
12
10
|
type Address,
|
|
13
11
|
type Hex,
|
|
14
|
-
type Log,
|
|
15
12
|
decodeFunctionData,
|
|
16
13
|
encodeAbiParameters,
|
|
17
14
|
parseEventLogs,
|
|
15
|
+
zeroAddress,
|
|
16
|
+
zeroHash,
|
|
18
17
|
} from 'viem';
|
|
19
18
|
import { ERC20VariableCriteriaIncentive as ERC20VariableCriteriaIncentiveBases } from '../../dist/deployments.json';
|
|
20
19
|
import { SignatureType } from '../Actions/EventAction';
|
|
@@ -22,17 +21,17 @@ import type {
|
|
|
22
21
|
DeployableOptions,
|
|
23
22
|
GenericDeployableParams,
|
|
24
23
|
} from '../Deployable/Deployable';
|
|
25
|
-
import { DeployableTarget } from '../Deployable/DeployableTarget';
|
|
26
24
|
import {
|
|
27
25
|
DecodedArgsError,
|
|
28
|
-
FieldActionValidationError,
|
|
29
26
|
IncentiveCriteriaNotFoundError,
|
|
30
27
|
InvalidCriteriaTypeError,
|
|
31
28
|
NoMatchingLogsError,
|
|
32
29
|
} from '../errors';
|
|
33
|
-
import type
|
|
30
|
+
import { CheatCodes, type ReadParams } from '../utils';
|
|
34
31
|
import { ERC20VariableIncentive } from './ERC20VariableIncentive';
|
|
35
32
|
|
|
33
|
+
export { erc20VariableCriteriaIncentiveAbi };
|
|
34
|
+
|
|
36
35
|
export interface ERC20VariableCriteriaIncentivePayload {
|
|
37
36
|
/**
|
|
38
37
|
* The address of the incentivized asset.
|
|
@@ -94,16 +93,24 @@ export interface ReadIncentiveCriteriaParams
|
|
|
94
93
|
> {}
|
|
95
94
|
|
|
96
95
|
export interface GetIncentiveScalarParams {
|
|
96
|
+
chainId: number;
|
|
97
97
|
hash: Hex;
|
|
98
|
+
knownSignatures: Record<Hex, AbiFunction | AbiEvent>;
|
|
98
99
|
}
|
|
99
100
|
|
|
100
101
|
/**
|
|
101
102
|
* Extended ERC20 Variable Criteria Incentive class that fetches incentive criteria and scalar
|
|
103
|
+
*
|
|
104
|
+
* @export
|
|
105
|
+
* @class ERC20VariableCriteriaIncentive
|
|
106
|
+
* @typedef {ERC20VariableCriteriaIncentive}
|
|
107
|
+
* @extends {ERC20VariableIncentive<ERC20VariableCriteriaIncentivePayload, typeof erc20VariableCriteriaIncentiveAbi>}
|
|
102
108
|
*/
|
|
103
|
-
export class ERC20VariableCriteriaIncentive extends
|
|
109
|
+
export class ERC20VariableCriteriaIncentive extends ERC20VariableIncentive<
|
|
104
110
|
ERC20VariableCriteriaIncentivePayload,
|
|
105
111
|
typeof erc20VariableCriteriaIncentiveAbi
|
|
106
112
|
> {
|
|
113
|
+
//@ts-expect-error instantiated correctly
|
|
107
114
|
public override readonly abi = erc20VariableCriteriaIncentiveAbi;
|
|
108
115
|
/**
|
|
109
116
|
* @inheritdoc
|
|
@@ -124,15 +131,22 @@ export class ERC20VariableCriteriaIncentive extends DeployableTarget<
|
|
|
124
131
|
/**
|
|
125
132
|
* Fetches the IncentiveCriteria struct from the contract
|
|
126
133
|
*
|
|
134
|
+
* @param {?ReadParams} [params]
|
|
127
135
|
* @returns {Promise<IncentiveCriteria>} Incentive criteria structure
|
|
128
136
|
* @throws {IncentiveCriteriaNotFoundError}
|
|
129
137
|
*/
|
|
130
|
-
public async getIncentiveCriteria(
|
|
138
|
+
public async getIncentiveCriteria(
|
|
139
|
+
params?: ReadParams<
|
|
140
|
+
typeof erc20VariableCriteriaIncentiveAbi,
|
|
141
|
+
'getIncentiveCriteria'
|
|
142
|
+
>,
|
|
143
|
+
): Promise<IncentiveCriteria> {
|
|
131
144
|
try {
|
|
132
145
|
const criteria =
|
|
133
146
|
await readErc20VariableCriteriaIncentiveGetIncentiveCriteria(
|
|
134
147
|
this._config,
|
|
135
148
|
{
|
|
149
|
+
...params,
|
|
136
150
|
address: this.assertValidAddress(),
|
|
137
151
|
},
|
|
138
152
|
);
|
|
@@ -147,21 +161,30 @@ export class ERC20VariableCriteriaIncentive extends DeployableTarget<
|
|
|
147
161
|
* Fetches the incentive scalar from a transaction hash
|
|
148
162
|
*
|
|
149
163
|
* @param {GetIncentiveScalarParams} params
|
|
164
|
+
* @param {?ReadParams} [params]
|
|
150
165
|
* @returns {Promise<bigint>}
|
|
151
166
|
* @throws {InvalidCriteriaTypeError | NoMatchingLogsError | DecodedArgsError}
|
|
152
167
|
*/
|
|
153
|
-
public async getIncentiveScalar(
|
|
154
|
-
hash,
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
168
|
+
public async getIncentiveScalar(
|
|
169
|
+
{ chainId, hash, knownSignatures }: GetIncentiveScalarParams,
|
|
170
|
+
params?: ReadParams<
|
|
171
|
+
typeof erc20VariableCriteriaIncentiveAbi,
|
|
172
|
+
'getIncentiveCriteria'
|
|
173
|
+
>,
|
|
174
|
+
): Promise<bigint> {
|
|
175
|
+
const criteria = await this.getIncentiveCriteria(params);
|
|
160
176
|
if (criteria.criteriaType === SignatureType.EVENT) {
|
|
161
177
|
const transactionReceipt = await getTransactionReceipt(this._config, {
|
|
178
|
+
chainId,
|
|
162
179
|
hash,
|
|
163
180
|
});
|
|
164
|
-
|
|
181
|
+
if (criteria.fieldIndex === CheatCodes.GAS_REBATE_INCENTIVE) {
|
|
182
|
+
const totalCost =
|
|
183
|
+
transactionReceipt.gasUsed * transactionReceipt.effectiveGasPrice + // Normal gas cost
|
|
184
|
+
(transactionReceipt.blobGasUsed ?? 0n) *
|
|
185
|
+
(transactionReceipt.blobGasPrice ?? 0n); // Blob gas cost - account for potential undefined values
|
|
186
|
+
return totalCost;
|
|
187
|
+
}
|
|
165
188
|
const logs = transactionReceipt.logs;
|
|
166
189
|
|
|
167
190
|
if (logs.length === 0) {
|
|
@@ -173,9 +196,7 @@ export class ERC20VariableCriteriaIncentive extends DeployableTarget<
|
|
|
173
196
|
// Decode the event log
|
|
174
197
|
try {
|
|
175
198
|
// Decode function data
|
|
176
|
-
const eventAbi =
|
|
177
|
-
criteria.signature
|
|
178
|
-
] as AbiEvent;
|
|
199
|
+
const eventAbi = knownSignatures[criteria.signature] as AbiEvent;
|
|
179
200
|
const decodedEvents = parseEventLogs({
|
|
180
201
|
abi: [eventAbi],
|
|
181
202
|
logs,
|
|
@@ -202,12 +223,13 @@ export class ERC20VariableCriteriaIncentive extends DeployableTarget<
|
|
|
202
223
|
}
|
|
203
224
|
} else if (criteria.criteriaType === SignatureType.FUNC) {
|
|
204
225
|
// Fetch the transaction data
|
|
226
|
+
const transaction = await getTransaction(this._config, {
|
|
227
|
+
chainId,
|
|
228
|
+
hash,
|
|
229
|
+
});
|
|
205
230
|
try {
|
|
206
231
|
// Decode function data
|
|
207
|
-
const func =
|
|
208
|
-
criteria.signature
|
|
209
|
-
] as AbiFunction;
|
|
210
|
-
|
|
232
|
+
const func = knownSignatures[criteria.signature] as AbiFunction;
|
|
211
233
|
const decodedFunction = decodeFunctionData({
|
|
212
234
|
abi: [func],
|
|
213
235
|
data: transaction.input,
|
|
@@ -230,6 +252,7 @@ export class ERC20VariableCriteriaIncentive extends DeployableTarget<
|
|
|
230
252
|
);
|
|
231
253
|
}
|
|
232
254
|
}
|
|
255
|
+
|
|
233
256
|
/**
|
|
234
257
|
* @inheritdoc
|
|
235
258
|
*
|
|
@@ -253,21 +276,40 @@ export class ERC20VariableCriteriaIncentive extends DeployableTarget<
|
|
|
253
276
|
...this.optionallyAttachAccount(options.account),
|
|
254
277
|
};
|
|
255
278
|
}
|
|
279
|
+
}
|
|
256
280
|
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
281
|
+
/**
|
|
282
|
+
* Creates an IncentiveCriteria object representing a gas rebate incentive.
|
|
283
|
+
* This object defines a variable incentive criteria where the criteria will be the gas spent.
|
|
284
|
+
*
|
|
285
|
+
* The criteria uses a signatureType of EVENT, with a special `fieldIndex` of 255 (using CheatCodes enum), which indicates
|
|
286
|
+
* that the entire gas cost of the transaction will be used as the scalar value. If you don't want to
|
|
287
|
+
* rebate the entire gas cost, you can use a reward value on the incentive..
|
|
288
|
+
*
|
|
289
|
+
* - `criteriaType`: EVENT, indicating it's based on event logs.
|
|
290
|
+
* - `signature`: A zeroed signature (0x0000...0000), matching any event.
|
|
291
|
+
* - `fieldIndex`: 255, indicating the use of transaction gas cost using CheatCodes enum.
|
|
292
|
+
* - `targetContract`: A zeroed address (0x0000...0000), applicable to any contract.
|
|
293
|
+
*
|
|
294
|
+
* @returns {IncentiveCriteria} Returns an IncentiveCriteria object for a gas rebate.
|
|
295
|
+
*
|
|
296
|
+
* @example
|
|
297
|
+
* const incentive = gasRebateIncentiveCriteria();
|
|
298
|
+
* const actionPayload = {
|
|
299
|
+
* criteria: incentive,
|
|
300
|
+
* asset: "0xAssetAddress",
|
|
301
|
+
* reward: 0, // Set to zero to rebate the entire gas cost
|
|
302
|
+
* limit: BigInt(1000) // This is the total spend limit for the incentive
|
|
303
|
+
* };
|
|
304
|
+
* deployIncentive(actionPayload);
|
|
305
|
+
*/
|
|
306
|
+
export function gasRebateIncentiveCriteria(): IncentiveCriteria {
|
|
307
|
+
return {
|
|
308
|
+
criteriaType: SignatureType.EVENT,
|
|
309
|
+
signature: zeroHash,
|
|
310
|
+
fieldIndex: CheatCodes.GAS_REBATE_INCENTIVE,
|
|
311
|
+
targetContract: zeroAddress,
|
|
312
|
+
};
|
|
271
313
|
}
|
|
272
314
|
|
|
273
315
|
/**
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { readMockErc20BalanceOf } from
|
|
2
|
-
import { loadFixture } from
|
|
3
|
-
import { encodeAbiParameters, isAddress, parseEther, zeroAddress } from
|
|
4
|
-
import { beforeAll, beforeEach, describe, expect, test } from
|
|
5
|
-
import { accounts } from
|
|
1
|
+
import { readMockErc20BalanceOf } from "@boostxyz/evm";
|
|
2
|
+
import { loadFixture } from "@nomicfoundation/hardhat-network-helpers";
|
|
3
|
+
import { encodeAbiParameters, isAddress, parseEther, zeroAddress } from "viem";
|
|
4
|
+
import { beforeAll, beforeEach, describe, expect, test } from "vitest";
|
|
5
|
+
import { accounts } from "@boostxyz/test/accounts";
|
|
6
6
|
import {
|
|
7
7
|
type BudgetFixtures,
|
|
8
8
|
type Fixtures,
|
|
@@ -10,14 +10,14 @@ import {
|
|
|
10
10
|
deployFixtures,
|
|
11
11
|
freshBoost,
|
|
12
12
|
fundBudget,
|
|
13
|
-
} from
|
|
14
|
-
import { ERC20VariableIncentive } from
|
|
13
|
+
} from "@boostxyz/test/helpers";
|
|
14
|
+
import { ERC20VariableIncentive } from "./ERC20VariableIncentive";
|
|
15
15
|
|
|
16
|
-
const BOOST_CORE_CLAIM_FEE = parseEther(
|
|
16
|
+
const BOOST_CORE_CLAIM_FEE = parseEther("0.000075");
|
|
17
17
|
|
|
18
18
|
let fixtures: Fixtures, budgets: BudgetFixtures;
|
|
19
19
|
|
|
20
|
-
describe(
|
|
20
|
+
describe("ERC20VariableIncentive", () => {
|
|
21
21
|
beforeAll(async () => {
|
|
22
22
|
fixtures = await loadFixture(deployFixtures(defaultOptions));
|
|
23
23
|
});
|
|
@@ -26,7 +26,7 @@ describe('ERC20VariableIncentive', () => {
|
|
|
26
26
|
budgets = await loadFixture(fundBudget(defaultOptions, fixtures));
|
|
27
27
|
});
|
|
28
28
|
|
|
29
|
-
test(
|
|
29
|
+
test("can successfully be deployed", async () => {
|
|
30
30
|
const action = new ERC20VariableIncentive(defaultOptions, {
|
|
31
31
|
asset: zeroAddress,
|
|
32
32
|
reward: 1n,
|
|
@@ -37,7 +37,7 @@ describe('ERC20VariableIncentive', () => {
|
|
|
37
37
|
expect(isAddress(action.assertValidAddress())).toBe(true);
|
|
38
38
|
});
|
|
39
39
|
|
|
40
|
-
test(
|
|
40
|
+
test("can claim", async () => {
|
|
41
41
|
// biome-ignore lint/style/noNonNullAssertion: we know this is defined
|
|
42
42
|
const referrer = accounts.at(1)!.account!,
|
|
43
43
|
// biome-ignore lint/style/noNonNullAssertion: we know this is defined
|
|
@@ -57,12 +57,11 @@ describe('ERC20VariableIncentive', () => {
|
|
|
57
57
|
});
|
|
58
58
|
|
|
59
59
|
const claimant = trustedSigner.account;
|
|
60
|
-
const incentiveQuantity = 1;
|
|
61
60
|
const claimDataPayload = await boost.validator.encodeClaimData({
|
|
62
61
|
signer: trustedSigner,
|
|
63
|
-
incentiveData: erc20VariableIncentive.buildClaimData(parseEther(
|
|
62
|
+
incentiveData: erc20VariableIncentive.buildClaimData(parseEther("1")),
|
|
64
63
|
chainId: defaultOptions.config.chains[0].id,
|
|
65
|
-
incentiveQuantity,
|
|
64
|
+
incentiveQuantity: boost.incentives.length,
|
|
66
65
|
claimant,
|
|
67
66
|
boostId: boost.id,
|
|
68
67
|
});
|
|
@@ -81,7 +80,7 @@ describe('ERC20VariableIncentive', () => {
|
|
|
81
80
|
).toBe(1n);
|
|
82
81
|
});
|
|
83
82
|
|
|
84
|
-
test(
|
|
83
|
+
test("cannot claim twice", async () => {
|
|
85
84
|
// biome-ignore lint/style/noNonNullAssertion: we know this is defined
|
|
86
85
|
const referrer = accounts.at(1)!.account!;
|
|
87
86
|
// biome-ignore lint/style/noNonNullAssertion: we know this is defined
|
|
@@ -101,12 +100,11 @@ describe('ERC20VariableIncentive', () => {
|
|
|
101
100
|
});
|
|
102
101
|
|
|
103
102
|
const claimant = trustedSigner.account;
|
|
104
|
-
const incentiveQuantity = 1;
|
|
105
103
|
const claimDataPayload = await boost.validator.encodeClaimData({
|
|
106
104
|
signer: trustedSigner,
|
|
107
|
-
incentiveData: erc20VariableIncentive.buildClaimData(parseEther(
|
|
105
|
+
incentiveData: erc20VariableIncentive.buildClaimData(parseEther("1")),
|
|
108
106
|
chainId: defaultOptions.config.chains[0].id,
|
|
109
|
-
incentiveQuantity,
|
|
107
|
+
incentiveQuantity: boost.incentives.length,
|
|
110
108
|
claimant,
|
|
111
109
|
boostId: boost.id,
|
|
112
110
|
});
|
|
@@ -16,6 +16,7 @@ import {
|
|
|
16
16
|
} from '@boostxyz/evm';
|
|
17
17
|
import { bytecode } from '@boostxyz/evm/artifacts/contracts/incentives/ERC20VariableIncentive.sol/ERC20VariableIncentive.json';
|
|
18
18
|
import {
|
|
19
|
+
type Abi,
|
|
19
20
|
type Address,
|
|
20
21
|
type ContractEventName,
|
|
21
22
|
type Hex,
|
|
@@ -86,17 +87,20 @@ export type ERC20VariableIncentiveLog<
|
|
|
86
87
|
> = GenericLog<typeof erc20VariableIncentiveAbi, event>;
|
|
87
88
|
|
|
88
89
|
/**
|
|
89
|
-
*
|
|
90
|
+
* A modified ERC20 incentive implementation that allows claiming of variable token amounts with a spending limit
|
|
90
91
|
*
|
|
91
92
|
* @export
|
|
92
93
|
* @class ERC20VariableIncentive
|
|
93
94
|
* @typedef {ERC20VariableIncentive}
|
|
94
|
-
* @
|
|
95
|
+
* @template [Payload=ERC20VariableIncentivePayload | undefined]
|
|
96
|
+
* @template {Abi} [ABI=typeof erc20VariableIncentiveAbi]
|
|
97
|
+
* @extends {DeployableTarget<ERC20VariableIncentivePayload, ABI>}
|
|
95
98
|
*/
|
|
96
|
-
export class ERC20VariableIncentive
|
|
97
|
-
ERC20VariableIncentivePayload,
|
|
98
|
-
typeof erc20VariableIncentiveAbi
|
|
99
|
-
> {
|
|
99
|
+
export class ERC20VariableIncentive<
|
|
100
|
+
Payload = ERC20VariableIncentivePayload | undefined,
|
|
101
|
+
ABI extends Abi = typeof erc20VariableIncentiveAbi,
|
|
102
|
+
> extends DeployableTarget<Payload, ABI> {
|
|
103
|
+
//@ts-expect-error it is instantiated correctly
|
|
100
104
|
public override readonly abi = erc20VariableIncentiveAbi;
|
|
101
105
|
/**
|
|
102
106
|
* @inheritdoc
|
|
@@ -403,7 +407,7 @@ export class ERC20VariableIncentive extends DeployableTarget<
|
|
|
403
407
|
* @returns {GenericDeployableParams}
|
|
404
408
|
*/
|
|
405
409
|
public override buildParameters(
|
|
406
|
-
_payload?:
|
|
410
|
+
_payload?: Payload,
|
|
407
411
|
_options?: DeployableOptions,
|
|
408
412
|
): GenericDeployableParams {
|
|
409
413
|
const [payload, options] = this.validateDeploymentConfig(
|
|
@@ -413,7 +417,11 @@ export class ERC20VariableIncentive extends DeployableTarget<
|
|
|
413
417
|
return {
|
|
414
418
|
abi: erc20VariableIncentiveAbi,
|
|
415
419
|
bytecode: bytecode as Hex,
|
|
416
|
-
args: [
|
|
420
|
+
args: [
|
|
421
|
+
prepareERC20VariableIncentivePayload(
|
|
422
|
+
payload as ERC20VariableIncentivePayload,
|
|
423
|
+
),
|
|
424
|
+
],
|
|
417
425
|
...this.optionallyAttachAccount(options.account),
|
|
418
426
|
};
|
|
419
427
|
}
|
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
ACGDAIncentive,
|
|
5
5
|
AERC20Incentive,
|
|
6
6
|
AERC20VariableIncentive,
|
|
7
|
+
// AERC20VariableCriteriaIncentive
|
|
7
8
|
APointsIncentive,
|
|
8
9
|
} from '@boostxyz/evm/deploys/componentInterfaces.json';
|
|
9
10
|
import { readContract } from '@wagmi/core';
|
|
@@ -13,7 +14,7 @@ import { InvalidComponentInterfaceError } from '../errors';
|
|
|
13
14
|
import { AllowListIncentive } from './AllowListIncentive';
|
|
14
15
|
import { CGDAIncentive } from './CGDAIncentive';
|
|
15
16
|
import { ERC20Incentive } from './ERC20Incentive';
|
|
16
|
-
import
|
|
17
|
+
import { ERC20VariableCriteriaIncentive } from './ERC20VariableCriteriaIncentive';
|
|
17
18
|
import { ERC20VariableIncentive } from './ERC20VariableIncentive';
|
|
18
19
|
// import { ERC1155Incentive } from './ERC1155Incentive';
|
|
19
20
|
import { PointsIncentive } from './PointsIncentive';
|
|
@@ -25,6 +26,7 @@ export {
|
|
|
25
26
|
ERC20Incentive,
|
|
26
27
|
PointsIncentive,
|
|
27
28
|
ERC20VariableIncentive,
|
|
29
|
+
ERC20VariableCriteriaIncentive,
|
|
28
30
|
};
|
|
29
31
|
|
|
30
32
|
/**
|
|
@@ -54,6 +56,7 @@ export const IncentiveByComponentInterface = {
|
|
|
54
56
|
// [AERC1155Incentive as Hex]: ERC1155Incentive,
|
|
55
57
|
[ACGDAIncentive as Hex]: CGDAIncentive,
|
|
56
58
|
[AERC20VariableIncentive as Hex]: ERC20VariableIncentive,
|
|
59
|
+
// [AERC20VariableCriteriaIncentive as Hex]: ERC20VariableCriteriaIncentive
|
|
57
60
|
};
|
|
58
61
|
|
|
59
62
|
/**
|
|
@@ -53,12 +53,11 @@ describe("PointsIncentive", () => {
|
|
|
53
53
|
|
|
54
54
|
const claimant = trustedSigner.account;
|
|
55
55
|
const incentiveData = pad("0xdef456232173821931823712381232131391321934");
|
|
56
|
-
const incentiveQuantity = 1;
|
|
57
56
|
const claimDataPayload = await boost.validator.encodeClaimData({
|
|
58
57
|
signer: trustedSigner,
|
|
59
58
|
incentiveData,
|
|
60
59
|
chainId: defaultOptions.config.chains[0].id,
|
|
61
|
-
incentiveQuantity,
|
|
60
|
+
incentiveQuantity: boost.incentives.length,
|
|
62
61
|
claimant,
|
|
63
62
|
boostId: boost.id,
|
|
64
63
|
});
|
|
@@ -72,7 +71,7 @@ describe("PointsIncentive", () => {
|
|
|
72
71
|
boost.id,
|
|
73
72
|
0n,
|
|
74
73
|
referrer,
|
|
75
|
-
claimDataPayload
|
|
74
|
+
claimDataPayload,
|
|
76
75
|
);
|
|
77
76
|
expect(
|
|
78
77
|
await readPointsBalanceOf(defaultOptions.config, {
|
|
@@ -101,12 +100,11 @@ describe("PointsIncentive", () => {
|
|
|
101
100
|
|
|
102
101
|
const claimant = trustedSigner.account;
|
|
103
102
|
const incentiveData = pad("0xdef456232173821931823712381232131391321934");
|
|
104
|
-
const incentiveQuantity = 1;
|
|
105
103
|
const claimDataPayload = await boost.validator.encodeClaimData({
|
|
106
104
|
signer: trustedSigner,
|
|
107
105
|
incentiveData,
|
|
108
106
|
chainId: defaultOptions.config.chains[0].id,
|
|
109
|
-
incentiveQuantity,
|
|
107
|
+
incentiveQuantity: boost.incentives.length,
|
|
110
108
|
claimant,
|
|
111
109
|
boostId: boost.id,
|
|
112
110
|
});
|