releasePartial() sends the wrong on-chain key to the contract — a raw UUID instead of the numeric onChainId every other operation uses

Abierto
#300 5 comentarios 0 reacciones 0 asignados Ver en GitHub

Los mantenedores suelen responder en 1 día

@PINYOPATTANAWASANPORN ya está trabajando en esto.

Desde el 13/10/2026.

  • #484 de @PINYOPATTANAWASANPORN — abierto

Evaluación

Dificultad
2/5
Tiempo estimado
1-3 horas
Aptitud para principiantes
35/100
Tipo de issue
Error
Claridad
Bien especificado
Estado de actividad
Estancado
Stack tecnológico
typescript

Línea de trabajo

Start in src/escrow/escrow.service.ts and compare releasePartial() with release() and refund(), which all use this.onChainKeyFor(escrow). Read onChainKeyFor to see how onChainId becomes a bigint ('9100' -> 9100n). Then open escrow.service.spec.ts; the releasePartial block expects ['milestone-1', 'GRECIPIENT', 300_000_000n], while release/refund expect 9100n. Done means the invoke uses onChainKeyFor(escrow) and the spec assertions match. Linked PR #484 is already open.

Escrito por el modelo de indexación a partir del texto del issue.

Descripción

Every other Soroban call in EscrowService resolves the on-chain identifier through onChainKeyFor(escrow) (src/escrow/escrow.service.ts), which returns the numeric escrow.onChainId persisted at fund time (or a deterministic derived fallback): poolWithdraw, refund, and invokeRelease (backing both release() and splitRelease()) all use it.

releasePartial() alone does not do this:

const result = await this.invokeOnLockedEscrow(
  escrow,
  'releasePartial',
  () =>
    this.soroban.invoke(
      'release_partial',
      [
        escrow.milestoneId ?? escrow.bountyId ?? escrow.id,
        recipientAddress,
        this.toStroops(amount),
      ],
      this.contractOpts(escrow),
    ),
);

The first argument is escrow.milestoneId ?? escrow.bountyId ?? escrow.id — a raw UUID string, not the bigint numeric key the escrow was actually fund()-ed under. Since escrow::fund stores the on-chain record keyed by issue_id: u64 (see the SorobanClientService docstring), and every other release/refund path looks that same record up via the numeric onChainId, releasePartial is passing a completely different, non-numeric key. This isn't just an architecture gap (already covered by #160/#162, which flag that release_partial has no real contract counterpart at all) — it's a narrower, independently-fixable inconsistency: even once a real release_partial-equivalent entrypoint exists, this code would still be looking the escrow up under the wrong identifier compared to the fund/release/refund calls for the very same row.

The bug is baked into the test suite as expected behavior — escrow.service.spec.ts asserts soroban.invoke is called with ['milestone-1', 'GRECIPIENT', 300_000_000n] (the raw milestoneId string) even though the same fixture (lockedEscrow()) sets onChainId: '9100', which every other describe block (release, refund) correctly expects to see converted to 9100n.

Fix: change releasePartial's invoke call to use this.onChainKeyFor(escrow) like every sibling method, and update the test fixture/expectations to match.

Lenguaje dominante
TypeScript
Estrellas
2
Forks
90
Merge medio
31 min
PR fusionados (30 d)
20

Preparar el entorno

  • Incluye un Dockerfile o un archivo de Docker Compose
  • Sin plantilla de pull request
  • Sin guía de contribución

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Más de MergeFi/backend

Todos los issues de MergeFi/backend

Issues similares

Más issues de TypeScript

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.