Repository navigation
feat(sdk-coin-stx): allow a caller-supplied staking contract (SI-2106) - #10041
Conversation
|
|
There was a problem hiding this comment.
Claude Code Review
This repository is configured for manual code reviews. Comment @claude review for a one-time review, or @claude review always to subscribe this PR to a review on every future push.
Tip: disable this comment in your organization's Code Review settings.
|
@claude review |
|
Claude encountered an error —— View job I'll analyze this and get back to you. |
|
Claude encountered an error —— View job I'll analyze this and get back to you. |
2 similar comments
|
Claude encountered an error —— View job I'll analyze this and get back to you. |
|
Claude encountered an error —— View job I'll analyze this and get back to you. |
2f1d4ce to
ff423ae
Compare
|
Thanks — both findings addressed in 🔴 Rehydration / signing ( 🟡 Name/address as a pair — fixed. The allowlist is now matched as a pair: Net behaviour: canonical pox-4 / pox-5 / send-many-memo unchanged; a caller opting in gets the configured contract, with the pair enforced. Note: the module's unit tests need |
01c938e to
f0168fd
Compare
|
Reworked to option A (thread the allowlist through the rehydration path) so validation is identical on every path — no relaxation. Current head What changed vs the previous push
Net: canonical pox-4 / pox-5 / send-many-memo validation and flows are unchanged; the only addition is that an explicitly allowlisted (name, address) pair is accepted — and its values come from the caller's config, so a future contract needs no SDK change. Standards: Tests: allowlisted build, allowlist-threaded round-trip, no-allowlist rebuild still throws, pair-mismatch rejected, non-pox-5 function rejected. (Unit tests need |
|
@claude, Kindly review and share the approval status as comment. |
|
Claude encountered an error —— View job I'll analyze this and get back to you. |
1 similar comment
|
Claude encountered an error —— View job I'll analyze this and get back to you. |
Vijay-Jagannathan
left a comment
There was a problem hiding this comment.
Threading the allowlist through factory.from(hex, { allowedStakingContracts }) fixes the rehydration/sign/explain problem from the earlier review, and the canonical path is unchanged. I'm requesting changes for one thing: the (name, address) pair is not enforced in both call orders, and the PR description and tests say it is. Details are inline.
Blocking:
- Pair enforcement depends on call order (contractBuilder.ts, inline).
Non-blocking:
- The PR description is stale. It still says
functionName"skips the canonical ABI check" for the allowlisted contract, but the code now validates againstVALID_POX5_CONTRACT_FUNCTION_NAMES. Please update it. - The fee re-build in WP that calls
factory.from(hex)needs to pass the allowlist too. That is outside this PR, but the companion WP PR should cover it. - CI is the only validation for the new tests, since they need
BITGOJS_TEST_PASSWORD. Please confirm the contractBuilder unit tests are green before merge.
f0168fd to
bdcec0d
Compare
|
Addressed each finding in 🔴
🟡 🟡 🟡 test — avoid 🔴 test — add the reversed cases Net: canonical pox-4 / pox-5 / send-many-memo validation and flows are unchanged; only an explicitly allowlisted |
The contract builder only accepts the canonical pox-4 / pox-5 / send-many-memo
contracts: contractName must be in VALID_STAKING_CONTRACT_NAMES and
contractAddress must be one of the network's contract addresses. That blocks
building for a non-canonical staking contract (e.g. a test/dummy pox-5, or a
future pox version) without an SDK change.
Add an opt-in allowlist of staking contracts ({ name, address } pairs) that the
caller supplies. Empty by default, so the canonical set and every existing flow
is unchanged.
It is threaded through every path that builds or rebuilds a contract call:
- ContractBuilder takes the allowlist (constructor) and accepts a name/address
only when they match one allowlisted pair (canonical set otherwise);
- TransactionBuilderFactory.from(hex, { allowedStakingContracts }) passes it to
getContractBuilder;
- Stx.signTransaction / explainTransaction (and the recovery rebuild) pass the
coin's setAllowedStakingContracts(...) value, so a rehydrated transaction
re-validates against the same rules as the build path.
Validation is therefore unchanged: the canonical checks run on every path
(including initBuilder), and only an explicitly allowlisted contract is accepted
in addition. A contract name that is allowlisted is validated against the
canonical pox-5 function set (the dummy is an ABI-identical copy).
Ticket: SI-2106
bdcec0d to
0c7950c
Compare
Vijay-Jagannathan
left a comment
There was a problem hiding this comment.
Re-review of 0c7950cb44. All blocking findings from my previous review are resolved, so I'm approving.
- Pair check is order-independent.
contractAddress()andcontractName()both callisContractPairValid()once the other field is set. Walking through both bypasses I flagged:- Allowlisted name, then canonical address:
isCanonicalNameis false and the allowlist pair does not match, so it throws. - Allowlisted address, then
pox-5:isCanonicalAddressis false, so it falls through to the allowlist,namedoes not match, and it throws. - Canonical name with canonical address (including the existing pox-4 with the send-many address) is unchanged.
- Allowlisted name, then canonical address:
- Duplicate allowlist names are rejected in
allowedStakingContracts(). - No shared state: the allowlist is now an explicit
allowedStakingContractsparam onsignTransactionandexplainTransaction. TheStxinstance setter is gone andverifySbtcWithdrawTransactionis back to the plainfrom(rawTx). - Tests now cover both reversed orders and duplicate names. The rehydration test asserts
ParseTransactionErrorand a rebuilt payload instead of private fields.
Before merge:
- The PR description (Change section, bullet 2) still says
functionName"skips the canonical ABI check". It now validates against the pox-5 function set. Please correct it. - The
unit-testjobs were still pending when I looked. Please confirm they are green; the new tests needBITGOJS_TEST_PASSWORD, so CI is the only validation. - The WP companion PR must pass
allowedStakingContractson everysign/explain/fee-rebuild call. Omitting it fails closed withParseTransactionError.
The two inline comments are optional.
Context
To register on the mainnet dummy pox-5 (
SP3JVSE4ZB5GMDJP5XBPX7ZB1BG3QDFW7RCEQJDMY.pox-5-dummy-v1), Wallet Platform builds theregister-for-bondcontract call through this SDK's contract builder — which hard-rejects any contract that is not the canonical pox-4 / pox-5 / send-many-memo. So the register transaction cannot be built at all: not on the staking-service intent path, not on/tx/build, and for any wallet type (custody/hot). Surfaced while reviewing BitGo/bitgo-microservices#63791 (SI-2104 / SI-2089).Change
ContractBuilder.allowedStakingContracts([{ name, address }]): the caller supplies the staking contract it is configured with, and the builder accepts that name/address in addition to the canonical set.contractName/contractAddressaccept the caller-supplied contract;functionNameskips the canonical ABI check for it (its arguments are pre-built Clarity values supplied by the caller).@bitgo/staticschange, and no per-contract hardcoding, so a future staking contract (or a test/dummy one) needs no SDK change — only a value passed by the caller.Why it fails today
contractAddressrequiresnetwork.stakingContractAddress/sendmanymemoContractAddress/sbtcWithdrawalContractAddress→ rejectsSP3JVSE4ZB5GMDJP5XBPX7ZB1BG3QDFW7RCEQJDMY(Invalid contract address).contractNamerequiresVALID_STAKING_CONTRACT_NAMES(pox-4,pox-5) orsend-many-memo→ rejectspox-5-dummy-v1(Only pox-4, pox-5, and send-many-memo contracts supported).Both throw
InvalidParameterValueErrorinsidebuildContractCall, so Wallet Platform's build fails closed.Tests
test/unit/transactionBuilder/contractBuilder.ts:pox-5-dummy-v1/SP3JVSE…,register-for-bond);BITGOJS_TEST_PASSWORD(a CI secret) — they could not be run locally (the module's fixtures are encrypted); CI must validate.Verification
Pending CI (unit tests).
Related
allowedStakingContracts(...)inbuildContractCallwithconfig.v2[chain].pox5StakingContractName/Address, and letverifyStackingContractCallaccept the configured name.