Skip to content

feat: qubic solana smart contract (review only)#15

Open
jean-michelet wants to merge 29 commits into
qubic:mainfrom
avicenne-studio:feat/qubic-solana-smart-contract
Open

feat: qubic solana smart contract (review only)#15
jean-michelet wants to merge 29 commits into
qubic:mainfrom
avicenne-studio:feat/qubic-solana-smart-contract

Conversation

@jean-michelet

Copy link
Copy Markdown

No description provided.

SoufianeBenbah and others added 29 commits May 12, 2026 10:51
- Replace #pragma pack and C-style arrays with QPI Array<uint8, N>
- Replace char/string literals with ASCII codes
- Replace [i] indexing with .set(i) / .get(i)
- Change static const to static constexpr
- Mark order filled before transfers to prevent replay on partial failure
- Reorder transfers: recipient first, then relayer and fees
- QSBOrderMessage layout changes from 240 to 245 bytes (protocolName padded to 16)
- Contract verifier: PASSED
…o skip IPO on local testnet

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Uncomment TESTNET_PREFILL_QUS so all customSeeds get 10B QU at epoch start
- Add admin, oracle-1..6, pauser, relayer, user seeds to customSeeds
- Fix QSB INITIALIZE() admin to real key (SINUBYSBZ… from .temp/qubic-admin.json)
  instead of placeholder id(100,200,300,400)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…tnet

- Set TESTNET_EPOCH_DURATION to 1,000,000 ticks (~5.8 days at 500ms/tick)
  to avoid epoch transitions during QA sessions
- Set PAUSE_BEFORE_CLEAR_MEMORY=0 so epoch transitions auto-complete
  without requiring an interactive F10 keypress (incompatible with Docker)
- Remove ONLY_LOGGING=ON cmake flag from Dockerfile

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add jean wallet seed (BYUYXZ...) to customSeeds for testnet genesis funding
- Reduce TESTNET_EPOCH_DURATION from 1000000 to 10000 ticks

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
INITIALIZE hardcodes the real deployment admin key; the test suite's
ADMIN constant is different, so all admin-gated procedures silently
failed. Fix the constructor to transfer admin from the deployment key
to the test ADMIN immediately after INITIALIZE, using increaseEnergy
to ensure the deployment key has a spectrum entry first.

Also annotates CMakeLists.txt with why the alignment sanitizer must be
disabled for contract_qsb.cpp (struct totals not divisible by 4), and
adds a PrintStructSizes test to surface alignment regressions.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Pausers could previously unpause the bridge, allowing a compromised or
malicious pauser key to cancel a security pause. Unpause now checks
isAdmin instead of isAdminOrPauser, and logs QSBReasonNotAdmin on
rejection.

Tests: renamed TestUnpause to TestUnpause_ByAdmin; added
TestUnpause_FailsForPauser covering the revoked case.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Setting admin to zero re-enables the bootstrap path in isAdmin()
(isZero check returns true → everyone is admin). Guard against this by
rejecting NULL_ID with the new QSBReasonInvalidAdmin reason code.

TestTransferAdmin_ToNullId updated to assert failure and verify the
admin is unchanged.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
AddRole had two silent failure paths: when the oracle/pauser array is
full (for-loop exhausted without finding an inactive slot) and when
input.role is neither Oracle nor Pauser. Both now log with the
appropriate reason code and return instead of falling through silently.

OverrideLock used QSBReasonNonceUsed when no order matched the nonce,
which implies the nonce was already consumed by a completed fill.
Replaced with QSBReasonOrderNotFound so callers can distinguish the
two cases.

New reason codes: QSBReasonInvalidRole (22), QSBReasonOrderNotFound (23).

Tests added: TestAddRole_InvalidRole, TestAddRole_OracleFull,
TestAddRole_PauserFull, TestOverrideLock_OrderNotFound.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Reduce QSB_MAX_FILLED_ORDERS from 2048 to 256 (power-of-2 per QPI::Array
  constraint; 5x the ~50 max concurrent orders)
- Add filledOrdersPrev buffer: on ring wrap, copy filledOrders → filledOrdersPrev,
  zero filledOrders, then increment orderEra
- isOrderFilled checks both buffers, blocking replays across the era boundary
- Unlock now accepts orderEra == currentEra or currentEra - 1 (grace window for
  in-flight orders signed just before a wrap)
- Add makeOracleKey/createOrderSignature test helpers (real FourQ signatures)
- Add TestUnlock_PreviousEraAccepted, TestUnlock_TwoErasAgoRejected,
  TestUnlock_NoReplayAfterEraTransition
- Update TestFilledOrders_RingBufferOverwritesOldEntries for double-buffer semantics

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The set_source_files_properties block was not reliable — the alignment
sanitizer fires in inline StackBuffer functions that may be linked from
another TU compiled without the flag. The real fix is USE_SANITIZER=OFF
at configure time.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Remove the clearLockedOrderEntry function which was defined but never
called. Replace its use in the new fillLockedOrderSlot test helper with
value-initialization (= {}). Also add build-test/ to .gitignore.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
GetLockedOrders and GetFilledOrders previously iterated the ring buffers
from index 0 forward (oldest-first). Switch to iterating backwards from
(nextOverwriteIdx - 1), so callers receive the most recently inserted
entries at offset 0. Both capacities are powers of 2, enabling cheap
wrap-around with bitwise AND.

Add TestGetLockedOrders_MostRecentFirst and TestGetFilledOrders_MostRecentFirst
to verify the ordering guarantee.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
GetLockedOrder searches by nonce, not by slot index. After the ring
buffer overwrites slot 0 with a new nonce, GetLockedOrder(0) should
return exists=false (nonce 0 is gone). Fix the test to assert this,
and also verify the new nonce is findable. Pre-existing failure unrelated
to the ordering change.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add QSB_OVERRIDE_LOCK_MAX_ATTEMPTS=3 and QSBReasonOverrideLimitReached.
Store overrideLockCount in LockedOrderEntry (byte +161, within existing
padding — struct stays 168 bytes). Block the 4th attempt and add tests
for counter increment and the blocked-after-max-attempts path.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…t test build

Add QSB_MAX_UNLOCK_SIGNATURES=8 so Unlock_input stays ≤1024 bytes
(was 6336 bytes with QSB_MAX_ORACLES=64). Update test helper to copy
up to the new capacity. Add Running Tests section to README_CLANG.md
with the clang-18/Ubuntu linker workaround.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…teProposalPayload

- Add QSB_MAX_PROPOSALS_PER_ADMIN=3: each admin is limited to 3 concurrent
  active proposals; returns QSBReasonTooManyProposals (33) on overflow.
- Add QSBReasonInvalidProposalType (34): Propose now rejects unknown proposal
  types instead of silently queuing them.
- Remove all unreachable guards from executeProposalPayload for AddAdmin,
  RemoveAdmin, SetAdminThreshold, and EditOracleThreshold — invariants are
  enforced at Propose time and cancelAllPendingProposals prevents races.
- Remove unused `newAdminCount` local variable from executeProposalPayload.
- Keep AddRole/RemoveRole execution-time checks (legitimately reachable via idempotency).
- 80/80 tests green.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…point per procedure

All procedure logic now lives in inline static tryXxx helpers that return
a typed result struct. The PUBLIC_PROCEDURE_WITH_LOCALS shell calls the
helper, maps outputs, builds the log message, and calls LOG_INFO once.

- Phase 1: removed dummy trailing params (i, j, same, entry) from all 12
  helpers; variables are now regular C++ locals inside each function
- Phase 2: added 7 result structs (LockResult, OverrideLockResult,
  UnlockResult, ProposeResult, ApproveProposalResult, CancelProposalResult,
  PauseResult)
- Phase 3+4: extracted tryLock, tryOverrideLock, tryUnlock, tryPropose,
  tryApproveProposal, tryCancelProposal, tryPause; procedure shells
  reduced to ~12-16 lines each
- Phase 5: extracted sweepExpiredProposals from END_EPOCH
- Removed trivial comments; kept non-obvious constraints and design notes
- 80/80 tests passing

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ures

New layout: constants/public-types → protected result structs → public
procedures/functions → protected helpers (low-level + try*) → epoch/init.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Removed comments that restate what identifiers/code already express
(struct-level labels, numbered I/O lists, REGISTER section labels,
function-level descriptions). Kept only non-obvious WHY comments:
QPI constraints, ring-buffer semantics, era grace window, refund
ordering, fill-before-transfer invariant, auto-approve design note,
test-key deployment warnings.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Previous session incorrectly set the constant to 4096 and introduced a
matching gTxRevenuePoints table for 4096 entries. This reverts both files
to the correct value (1024, matching main) and removes the dead 4096 table.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…nEpoch, test isolation

- INITIALIZE now sets real deployment keys (admin-1 and admin-2 from
  oracle/.temp/) instead of placeholder id(100,200,300,400) literals
- QSB constructionEpoch updated to 216 so INITIALIZE fires on a clean
  local testnet reset (epoch 216 = testnet starting epoch)
- contract_qsb.cpp constructor overrides admins back to stable test
  identities (ADMIN/ADMIN2) after calling INITIALIZE, so unit tests
  remain independent of the live deployment keys; removed two strict
  admin identity checks that depended on the old placeholder values

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants