Skip to content

[Bug]: InviteSDK blocks late inviter attachment supported by InvitesV2 #55

Description

@L03TJ3

Summary

@goodsdks/invite-sdk@1.0.1 prevents a user who first registered a personal invite code without an inviter from later attaching an inviter. InvitesV2 and GoodWallet support this one-time transition. Align InviteSDK prechecks with the contract, then release a corrected version for SDK-only consumers such as GoodWidget.

Scope

  • Repo: GoodDollar/GoodSDKs
  • Package: @goodsdks/invite-sdk
  • Main file: packages/invite-sdk/src/sdks/viem-invite-sdk.tsInviteSDK.join
  • Reference contract: use gooddollar skills to look up the invite contract
  • Tests: InviteSDK join/precheck tests

Current Problems

  • InviteSDK.join rejects any non-zero codeToUser(myCode), including when that code belongs to the connected caller.
  • It also rejects any caller with joinedAt > 0.
  • InvitesV2 permits this valid sequence once: join(myCode, zeroHash), then join(myCode, inviterCode) while invitedBy is zero and the bounty is unpaid.
  • GoodWallet relies on that behavior by reusing the caller's existing personal code when an inviter code is supplied later.

Required Changes

  • Permit myCode when codeToUser(myCode) is the connected caller; continue rejecting codes owned by another address.
  • Replace the blanket joinedAt > 0 rejection with the InvitesV2 rule: allow one deferred inviter attachment only when the caller has no invitedBy, has not received their bounty, and supplies a valid non-zero inviter code.
  • Continue rejecting a second join after an inviter is attached, after bounty payment, self-invites, inactive campaigns, and codes owned by another account.
  • Release a new InviteSDK version and document this corrected join behavior.

Implementation Notes

  • Mirror InvitesV2.join exactly: the existing caller-owned code is valid, and invitedBy == address(0) is the relevant deferred-assignment condition—not joinedAt == 0.
  • Resolve the supplied inviter code before allowing the deferred path, so an unknown code remains rejected before transaction submission.
  • Preserve typed, actionable errors for invalid inviter, self-invite, already-attached inviter, bounty-paid user, inactive contract, and conflicting code owner.

Acceptance Criteria

  • A user can register with join(myCode, zeroHash) and later successfully call join(myCode, inviterCode).
  • The later call uses the same caller-owned myCode and reaches SDK simulation/submission.
  • A user cannot change or add another inviter once invitedBy is non-zero.
  • A code owned by another address, an unknown inviter code, self-invitation, inactive campaign, and a bounty-paid user remain rejected with typed errors.
  • Existing initial join and collection behavior remains unchanged.

Testing / Verification

  • Add an SDK test for initial self-registration followed by deferred inviter attachment.
  • Add negative SDK tests for a second inviter attachment, a conflicting code owner, unknown inviter code, self-invite, and bounty-paid caller.
  • Run the InviteSDK test suite and build.
  • Verify a GoodWidget consumer can use the released SDK version without direct InvitesV2 writes.

Evidence

  • InvitesV2 explicitly permits the deferred assignment in contracts/invite/InvitesV2.sol:122-157 and tests it in test/invite/InvitesV2.test.ts:244-250.
  • GoodWallet keeps invite-code entry available until invitedBy is set and reuses the existing personal code.
  • InviteSDK 1.0.1 currently rejects both caller-owned existing codes and callers with joinedAt > 0 before simulation.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

Status
QA-Needed

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions