You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
initialize (src/lib.rs) requires both addresses to authorize but never requires them to be distinct:
pubfninitialize(env:Env,admin:Address,operator:Address) -> Result<(),SLAError>{
...admin.require_auth();
operator.require_auth();// two signatures required...
env.storage().instance().set(&ADMIN_KEY,&admin);
env.storage().instance().set(&OPERATOR_KEY,&operator);// ...but they may be the same address
...}
The two-party requirement is real (both must sign), yet the same address can fill both roles — one signature satisfies require_auth twice.
Consequences:
The separation-of-duties the design implies is optional at deployment: the role model (fix: cross_contract_safety hardcodes error symbol and drops context #28) exists so config/roles (admin) and calculations (operator) are distinct; initialize lets a single address hold both, and the runtime setters can recreate that state (companion issue), so the invariant is never established.
The two-party consent is illusory in the single-address case: require_auth() on the same address twice is one signature; a deployer reading the code as "two parties must agree" is misled.
No signal marks the merged deployment: get_full_audit_state returns admin == operator with no flag, so downstream tooling cannot distinguish "deliberate single-key deployment" from "misconfiguration".
Root cause
initialize was written to require auth from both arguments without considering that the arguments may be equal; no role-distinctness invariant was defined (the setters companion issue shows the same gap).
Why this is architecturally hard
Enforcing distinct roles at initialize is a behavior change for any existing deployment that merged them; the error choice (reuse InvalidInput vs. new variant) is an ABI decision (companion error-catalog issue).
The policy question — must admin and operator always differ? — affects set_operator/propose_operator (companion issue) and the renounce flow; the invariant should be defined once and enforced at every mutation point.
The two-party semantics (both must authorize) and the distinctness rule are separate contracts; the docs should state both, and tests should cover the single-address case.
Acceptance criteria
initialize with admin == operator is either rejected or explicitly documented as a supported mode.
The role-distinctness invariant is documented and enforced consistently across initialize and the role setters.
Tests cover the equal-address deployment case.
Out of scope
The role-setter equal-role gap (companion issue in batch 08) and the two-party initialize descriptor mislabel (companion issue in batch 03).
Getting started
just test
Good first files to read: apexchainx_calculator/src/lib.rs (initialize, require_admin, require_operator).
Problem
initialize(src/lib.rs) requires both addresses to authorize but never requires them to be distinct:The two-party requirement is real (both must sign), yet the same address can fill both roles — one signature satisfies
require_authtwice.Consequences:
initializelets a single address hold both, and the runtime setters can recreate that state (companion issue), so the invariant is never established.require_auth()on the same address twice is one signature; a deployer reading the code as "two parties must agree" is misled.get_full_audit_statereturns admin == operator with no flag, so downstream tooling cannot distinguish "deliberate single-key deployment" from "misconfiguration".Root cause
initializewas written to require auth from both arguments without considering that the arguments may be equal; no role-distinctness invariant was defined (the setters companion issue shows the same gap).Why this is architecturally hard
initializeis a behavior change for any existing deployment that merged them; the error choice (reuseInvalidInputvs. new variant) is an ABI decision (companion error-catalog issue).set_operator/propose_operator(companion issue) and the renounce flow; the invariant should be defined once and enforced at every mutation point.Acceptance criteria
initializewithadmin == operatoris either rejected or explicitly documented as a supported mode.initializeand the role setters.Out of scope
The role-setter equal-role gap (companion issue in batch 08) and the two-party
initializedescriptor mislabel (companion issue in batch 03).Getting started
just testGood first files to read:
apexchainx_calculator/src/lib.rs(initialize,require_admin,require_operator).