diff --git a/.changeset/chilly-buses-itch.md b/.changeset/chilly-buses-itch.md new file mode 100644 index 000000000..a5c5bfadb --- /dev/null +++ b/.changeset/chilly-buses-itch.md @@ -0,0 +1,5 @@ +--- +"@boostxyz/sdk": patch +--- + +allow 4-byte function selectors in incentive criteria diff --git a/packages/sdk/src/Incentives/ERC20PeggedVariableCriteriaIncentive.ts b/packages/sdk/src/Incentives/ERC20PeggedVariableCriteriaIncentive.ts index 907a0680e..3ca154cce 100644 --- a/packages/sdk/src/Incentives/ERC20PeggedVariableCriteriaIncentive.ts +++ b/packages/sdk/src/Incentives/ERC20PeggedVariableCriteriaIncentive.ts @@ -29,6 +29,7 @@ import { decodeAbiParameters, decodeFunctionData, encodeAbiParameters, + pad, parseEther, parseEventLogs, zeroAddress, @@ -844,7 +845,7 @@ export function prepareERC20PeggedVariableCriteriaIncentivePayload({ maxReward, criteria: { criteriaType: criteria.criteriaType, - signature: criteria.signature, + signature: pad(criteria.signature), fieldIndex: criteria.fieldIndex, targetContract: criteria.targetContract, }, diff --git a/packages/sdk/src/Incentives/ERC20PeggedVariableCriteriaIncentiveV2.test.ts b/packages/sdk/src/Incentives/ERC20PeggedVariableCriteriaIncentiveV2.test.ts index c53938e13..b087e4b87 100644 --- a/packages/sdk/src/Incentives/ERC20PeggedVariableCriteriaIncentiveV2.test.ts +++ b/packages/sdk/src/Incentives/ERC20PeggedVariableCriteriaIncentiveV2.test.ts @@ -358,4 +358,34 @@ describe("ERC20PeggedVariableCriteriaIncentive", () => { expect(balanceAfterClaim - balanceBeforeClaim).toBe(signedAmount); }) + + test("should deploy with a 4-byte function selector", async () => { + const fourByteSignature = "0xa9059cbb" as Hex; // transfer(address,uint256) + + const incentiveWithFourByteSelector = fixtures.core.ERC20PeggedVariableCriteriaIncentiveV2({ + asset: budgets.erc20.assertValidAddress(), + peg: zeroAddress, + limit: 1000000n, + reward: 1000000n, + maxReward: 1000000n, + criteria: { + criteriaType: SignatureType.FUNC, + signature: fourByteSignature, + fieldIndex: 1, + targetContract: budgets.erc20.assertValidAddress(), + valueType: ValueType.WAD, + }, + }); + + const newBoost = await freshBoost(fixtures, { + budget: budgets.budget, + incentives: [incentiveWithFourByteSelector], + }); + const incentive = newBoost.incentives[0] as ERC20PeggedVariableCriteriaIncentiveV2; + const deployedCriteria = await incentive.getIncentiveCriteria(); + + expect(isAddress(newBoost.incentives[0]!.assertValidAddress())).toBe(true); + expect(deployedCriteria.signature.length).toBe(66); + expect(deployedCriteria.signature.endsWith(fourByteSignature.slice(2))).toBe(true); + }); }); diff --git a/packages/sdk/src/Incentives/ERC20PeggedVariableCriteriaIncentiveV2.ts b/packages/sdk/src/Incentives/ERC20PeggedVariableCriteriaIncentiveV2.ts index b1da45041..cfac316c7 100644 --- a/packages/sdk/src/Incentives/ERC20PeggedVariableCriteriaIncentiveV2.ts +++ b/packages/sdk/src/Incentives/ERC20PeggedVariableCriteriaIncentiveV2.ts @@ -29,6 +29,7 @@ import { decodeAbiParameters, decodeFunctionData, encodeAbiParameters, + pad, parseEther, parseEventLogs, zeroAddress, @@ -923,7 +924,7 @@ export function prepareERC20PeggedVariableCriteriaIncentiveV2Payload({ maxReward, criteria: { criteriaType: criteria.criteriaType, - signature: criteria.signature, + signature: pad(criteria.signature), fieldIndex: criteria.fieldIndex, targetContract: criteria.targetContract, valueType: criteria.valueType, diff --git a/packages/sdk/src/Incentives/ERC20VariableCriteriaIncentive.ts b/packages/sdk/src/Incentives/ERC20VariableCriteriaIncentive.ts index 2306d12b7..788c125a3 100644 --- a/packages/sdk/src/Incentives/ERC20VariableCriteriaIncentive.ts +++ b/packages/sdk/src/Incentives/ERC20VariableCriteriaIncentive.ts @@ -13,6 +13,7 @@ import { decodeAbiParameters, decodeFunctionData, encodeAbiParameters, + pad, parseEther, parseEventLogs, zeroAddress, @@ -429,7 +430,7 @@ export function prepareERC20VariableCriteriaIncentivePayload({ maxReward: maxReward, criteria: { criteriaType: criteria.criteriaType, - signature: criteria.signature, + signature: pad(criteria.signature), fieldIndex: criteria.fieldIndex, targetContract: criteria.targetContract, }, diff --git a/packages/sdk/src/Incentives/ERC20VariableCriteriaIncentiveV2.test.ts b/packages/sdk/src/Incentives/ERC20VariableCriteriaIncentiveV2.test.ts index c45074861..652faecb7 100644 --- a/packages/sdk/src/Incentives/ERC20VariableCriteriaIncentiveV2.test.ts +++ b/packages/sdk/src/Incentives/ERC20VariableCriteriaIncentiveV2.test.ts @@ -272,4 +272,32 @@ describe("ERC20VariableCriteriaIncentiveV2", () => { true, ); }); + + test("should deploy with a 4-byte function selector", async () => { + const fourByteSignature = "0xa9059cbb" as Hex; // transfer(address,uint256) + + const incentiveWithFourByteSelector = fixtures.core.ERC20VariableCriteriaIncentiveV2({ + asset: budgets.erc20.assertValidAddress(), + limit: 1000000n, + reward: 1000000n, + criteria: { + criteriaType: SignatureType.FUNC, + signature: fourByteSignature, + fieldIndex: 1, + targetContract: budgets.erc20.assertValidAddress(), + valueType: ValueType.WAD, + }, + }); + + const newBoost = await freshBoost(fixtures, { + budget: budgets.budget, + incentives: [incentiveWithFourByteSelector], + }); + const incentive = newBoost.incentives[0] as ERC20VariableCriteriaIncentiveV2; + const deployedCriteria = await incentive.getIncentiveCriteria(); + + expect(isAddress(newBoost.incentives[0]!.assertValidAddress())).toBe(true); + expect(deployedCriteria.signature.length).toBe(66); + expect(deployedCriteria.signature.endsWith(fourByteSignature.slice(2))).toBe(true); + }); }); diff --git a/packages/sdk/src/Incentives/ERC20VariableCriteriaIncentiveV2.ts b/packages/sdk/src/Incentives/ERC20VariableCriteriaIncentiveV2.ts index a09622875..cb518ecd0 100644 --- a/packages/sdk/src/Incentives/ERC20VariableCriteriaIncentiveV2.ts +++ b/packages/sdk/src/Incentives/ERC20VariableCriteriaIncentiveV2.ts @@ -14,6 +14,7 @@ import { decodeAbiParameters, decodeFunctionData, encodeAbiParameters, + pad, parseEther, parseEventLogs, zeroAddress, @@ -501,7 +502,7 @@ export function prepareERC20VariableCriteriaIncentiveV2Payload({ maxReward: maxReward, criteria: { criteriaType: criteria.criteriaType, - signature: criteria.signature, + signature: pad(criteria.signature), fieldIndex: criteria.fieldIndex, targetContract: criteria.targetContract, valueType: criteria.valueType,