Skip to content

Dev#55

Merged
JaCoderX merged 4 commits into
mainfrom
dev
Feb 7, 2026
Merged

Dev#55
JaCoderX merged 4 commits into
mainfrom
dev

Conversation

@JaCoderX
Copy link
Copy Markdown
Member

@JaCoderX JaCoderX commented Feb 7, 2026

Summary by CodeRabbit

  • New Features

    • Broadcaster management now supports location-specific updates.
    • Contracts now accept plain ETH transfers instead of a dedicated deposit call.
  • Bug Fixes & Improvements

    • Removed overly specific error types to simplify failure responses.
    • Streamlined error reporting for protected-function checks and SDK error messages.
  • Version Updates

    • Bumped release to 1.0.0-alpha.4.

This commit refactors the function protection validation logic in the `EngineBlox` library by removing the `functionSignature` parameter from the `_validateContractFunctionProtection` function and its associated error. The changes streamline the validation process, ensuring that only the `functionSelector` is checked for protection status. Additionally, updates are made to the ABI files and TypeScript interfaces to reflect this simplification, enhancing code clarity and maintainability. These modifications align with ongoing efforts to optimize the contract's security mechanisms.
This commit updates the `updateBroadcasterRequest` and `executeBroadcasterUpdate` functions in the `SecureOwnable` contract to include a `location` parameter, allowing for more precise management of broadcaster addresses. The changes ensure that the broadcaster can be updated at a specific index in the authorized wallets set, improving flexibility and control over broadcaster assignments. Additionally, the corresponding interface and definitions have been updated to reflect this enhancement, aligning with ongoing efforts to optimize contract functionality and maintain robust security practices.
…files

This commit increments the version number to 1.0.0-alpha.4 in the `package.json`, `package-lock.json`, and SDK-related package files. The changes ensure consistency across the project and prepare for the next release cycle, aligning with ongoing version management efforts to maintain clarity and organization in the codebase.
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Feb 7, 2026

📝 Walkthrough

Walkthrough

Adds a uint256 location parameter to broadcaster update APIs across contracts and ABIs, removes several address-related errors and an Eth deposit event/function in AccountBlox, simplifies a protection error by dropping functionSignature, updates selectors/interfaces/SDK types, and bumps package versions to 1.0.0-alpha.4.

Changes

Cohort / File(s) Summary
Broadcaster API & ABIs
abi/AccountBlox.abi.json, abi/RoleBlox.abi.json, abi/SecureBlox.abi.json, abi/SecureOwnable.abi.json, abi/SimpleRWA20.abi.json, abi/SimpleVault.abi.json, sdk/typescript/abi/*
Added uint256 location parameter to updateBroadcasterRequest and executeBroadcasterUpdate signatures; removed InvalidAddress/NotNewAddress errors where present.
Core Contracts - SecureOwnable & Definitions
contracts/core/security/SecureOwnable.sol, contracts/core/security/interface/ISecureOwnable.sol, contracts/core/security/lib/definitions/SecureOwnableDefinitions.sol
Updated public/external function signatures to include location; updated selector constants and function schema entries to match new signatures; request encoding now includes location and computes broadcaster per-location.
Engine / Validation Changes
contracts/core/lib/EngineBlox.sol, contracts/utils/SharedValidation.sol, abi/EngineBlox.abi.json, sdk/typescript/abi/EngineBlox.abi.json, sdk/typescript/utils/contract-errors.ts
Removed functionSignature string from ContractFunctionMustBeProtected error and from internal validation callsites; updated SDK error signature mapping and user message; validation now uses only functionSelector.
AccountBlox: ETH receive behavior
contracts/examples/templates/AccountBlox.sol, abi/AccountBlox.abi.json, sdk/typescript/abi/AccountBlox.abi.json
Removed named deposit() payable function and EthReceived event; added Solidity receive() external payable to accept plain ETH transfers.
SDK / Types / Interfaces
sdk/typescript/contracts/SecureOwnable.tsx, sdk/typescript/interfaces/core.security.index.tsx, sdk/typescript/types/core.security.index.tsx, sdk/typescript/utils/interface-ids.tsx, sdk/typescript/utils/contract-errors.ts
Updated TypeScript contract method and interface signatures to accept location: bigint; updated interface ID computation and error mappings to reflect changed function signatures and error params.
Tests & Sanity Scripts
test/foundry/.../*.t.sol, test/foundry/CommonBase.sol, test/foundry/unit/SecureOwnable.t.sol, scripts/sanity/.../*.cjs, scripts/sanity-sdk/.../*.ts, scripts/sanity/guard-controller/guard-controller-tests.cjs
Updated call sites to pass a location argument (often 0/0n), adjusted revert expectations for simplified error payloads, replaced deposit() invocation tests with plain ETH transfers, and added/reworked SecureOwnable tests for location-based revoke semantics.
SDK Packaging & Versioning
package.json, package/package.json, sdk/typescript/package.json
Bumped versions from 1.0.0-alpha.31.0.0-alpha.4; updated publish/sync script tags and peer dependency ranges.
Misc - Test Constants & Selectors
test/foundry/CommonBase.sol, contracts/core/security/lib/definitions/SecureOwnableDefinitions.sol, sdk/typescript/types/core.security.index.tsx
Updated UPDATE_BROADCASTER_* selector constants and any computed selector strings to reflect (address,uint256) signatures.

Sequence Diagram(s)

(Skipped — changes are API/signature and selector updates without a new multi-component sequential flow that benefits from a diagram.)

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • Dev #42 — Related change to ContractFunctionMustBeProtected validation and selector/protection logic.
  • Foundry Fuzz Testing Framework + Tests #36 — Touches UPDATE_BROADCASTER_SELECTOR constant and foundry test fixtures for broadcaster selector changes.
  • Dev #30 — Overlaps SecureOwnable broadcaster API changes and related contract logic.

Poem

🐰 A hop to code, a twitch of my nose,
Location added where the broadcaster goes,
Old errors tucked away, deposit turns to receive,
Selectors updated — new calls to weave,
Alpha.4 hops forth, with tests all aglow. 🥕

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 inconclusive)
Check name Status Explanation Resolution
Title check ❓ Inconclusive The title 'Dev' is vague and generic, providing no meaningful information about the substantial changes made across ABI files, contract implementations, and SDK code. Replace with a descriptive title that summarizes the main change, such as 'Add location parameter to broadcaster update functions' or 'Refactor broadcaster location management and remove deprecated deposit function'.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch dev

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (4)
scripts/sanity/guard-controller/guard-controller-tests.cjs (1)

21-21: ⚠️ Potential issue | 🟡 Minor

Stale step description: still says "Deposit native tokens."

Line 21 still reads ' 3. Deposit native tokens from owner wallet to contract', which doesn't reflect the "direct transfer" wording used everywhere else in this PR. Consider updating for consistency.

Suggested fix
-        console.log('   3. Deposit native tokens from owner wallet to contract');
+        console.log('   3. Transfer native tokens directly to contract via receive()');
abi/SecureBlox.abi.json (1)

290-307: ⚠️ Potential issue | 🔴 Critical

Location parameter update is consistent, but error removal is incomplete across ABI files.

All 12 ABI files with executeBroadcasterUpdate and updateBroadcasterRequest functions have been updated with the location parameter. However, InvalidAddress error definitions remain in 3 files (SimpleVault.abi.json, SimpleRWA20.abi.json, and EngineBlox.abi.json) while they were removed in others (SecureBlox, RoleBlox, SecureOwnable, AccountBlox). Complete the error removal in SimpleVault and SimpleRWA20 to maintain consistency across the codebase.

scripts/sanity-sdk/secure-ownable/meta-tx-execution-tests.ts (1)

95-102: ⚠️ Potential issue | 🟡 Minor

findUnusedWallet may return a wallet assigned to another role (owner, recovery).

The method only excludes the current broadcaster address, but the returned wallet could collide with owner or recovery, which might cause the broadcaster update to be rejected on-chain if the contract validates against existing role holders. Consider excluding all role addresses.

🛡️ Suggested fix
-  private findUnusedWallet(excludeAddress: Address): Address {
+  private findUnusedWallet(excludeAddress: Address): Address {
+    const excludeSet = new Set([
+      excludeAddress.toLowerCase(),
+      this.roles.broadcaster.toLowerCase(),
+      ...(this.roles.owner ? [this.roles.owner.toLowerCase()] : []),
+      ...(this.roles.recovery ? [this.roles.recovery.toLowerCase()] : []),
+    ]);
     for (const wallet of Object.values(this.wallets)) {
-      if (wallet.address.toLowerCase() !== excludeAddress.toLowerCase()) {
+      if (!excludeSet.has(wallet.address.toLowerCase())) {
         return wallet.address;
       }
     }
     throw new Error('No unused wallet found');
   }
contracts/core/security/SecureOwnable.sol (1)

365-396: ⚠️ Potential issue | 🟡 Minor

_updateBroadcaster: Case 1 silently no-ops when revoking at an empty slot.

When newBroadcaster == address(0) and oldBroadcaster == address(0) (no wallet at location), the function returns without reverting or logging. The transaction will be marked COMPLETED even though nothing changed. Consider whether this silent no-op is intentional or whether it should revert to signal the owner that the revocation target was already empty.

Proposed fix (if a revert is preferred)
         // Case 1: Revoke existing broadcaster at location
         if (newBroadcaster == address(0)) {
             if (oldBroadcaster != address(0)) {
                 _revokeWallet(EngineBlox.BROADCASTER_ROLE, oldBroadcaster);
                 _logComponentEvent(abi.encode(oldBroadcaster, address(0)));
+            } else {
+                revert SharedValidation.ResourceNotFound(EngineBlox.BROADCASTER_ROLE);
             }
             return;
         }
🤖 Fix all issues with AI agents
In `@contracts/examples/templates/AccountBlox.sol`:
- Around line 57-63: The receive() handler currently accepts ETH
silently—declare a receive event (e.g., event ReceivedETH(address indexed from,
uint256 amount);) and emit it inside the receive() function (emit
ReceivedETH(msg.sender, msg.value);) so every plain ETH transfer to the contract
is recorded for auditability; add the event near other contract events and
update the receive() body to emit it while keeping the function payable and
without external calls.

In `@test/foundry/unit/SecureOwnable.t.sol`:
- Around line 234-260: Add fuzz and invariant coverage for the new
location-based revoke path: create a fuzz test (e.g.,
testFuzz_UpdateBroadcasterRequest_RevokeAtLocation(uint256 location)) that seeds
broadcaster list to at least two entries, clamps/location via bound(location, 0,
broadcasters.length-1), submits a revoke-at-location request with address(0) and
advances/approves, then assert post-conditions (length decreased by one,
remaining elements equal to expected removal-at-index behavior, no duplicates,
and owner protection prevents removing last broadcaster). Also add an invariant
harness (e.g., invariant_BroadcasterListSafety) that runs across fuzzed
sequences asserting broadcasters.length >= 1, broadcasters.length <=
MAX_BROADCASTERS if applicable, no duplicate addresses, and that total
broadcaster identities are conserved except when valid revokes occur; reference
the functions secureBlox.updateBroadcasterRequest,
secureBlox.updateBroadcasterDelayedApproval, secureBlox.getBroadcasters and the
existing test_UpdateBroadcasterRequest_RevokeAtLocation_ZeroAddress for
placement and semantics.
🧹 Nitpick comments (7)
scripts/sanity/guard-controller/guard-controller-tests.cjs (1)

952-952: Consider extracting the hardcoded gas limit.

The gas: 100000 magic number could be a named constant (e.g., RECEIVE_GAS_LIMIT) for clarity and easy adjustment if receive() logic changes later.

package.json (1)

3-3: Version bump to alpha.4 is consistent across all references.

The version field and all three script tags (release:sync-versions:tag:alpha, publish:contracts, publish:sdk) consistently reference alpha.4.

One consideration: using alpha.4 as an npm dist-tag (via --tag alpha.4) means each alpha release creates a separate dist-tag. Consumers installing via npm install <pkg>@alpha won't get this version — they'd need @alpha.4 explicitly. If you intend for an alpha dist-tag to always point to the latest alpha, consider also publishing with --tag alpha or adding a follow-up npm dist-tag add <pkg>@1.0.0-alpha.4 alpha step.

Also applies to: 34-34, 40-41

test/foundry/fuzz/SecureOwnableFuzz.t.sol (1)

49-66: Consider fuzzing the location parameter as well.

The location parameter is hardcoded to 0. Since this is a new parameter, fuzzing it alongside newBroadcaster would improve coverage of input validation and edge cases for the location value.

♻️ Suggested change
-    function testFuzz_BroadcasterUpdate(address newBroadcaster) public {
+    function testFuzz_BroadcasterUpdate(address newBroadcaster, uint256 location) public {
         vm.assume(newBroadcaster != address(0));
         vm.assume(newBroadcaster != broadcaster);
         vm.assume(newBroadcaster != owner);
         vm.assume(newBroadcaster != recovery);
 
         vm.prank(owner);
-        EngineBlox.TxRecord memory requestTx = secureBlox.updateBroadcasterRequest(newBroadcaster, 0);
+        EngineBlox.TxRecord memory requestTx = secureBlox.updateBroadcasterRequest(newBroadcaster, location);

As per coding guidelines, "Write fuzz tests for input validation and edge cases".

test/foundry/security/AccessControl.t.sol (1)

76-78: Call site correctly updated; consider specifying the expected revert selector.

The vm.expectRevert() on Line 76 doesn't specify an error selector, unlike other tests in this file (e.g., Lines 21, 37, 83) which use abi.encodeWithSelector(...). This makes the test less precise — it will pass on any revert rather than confirming the specific access control error.

sdk/typescript/utils/interface-ids.tsx (1)

33-102: Consider adding a test that cross-validates these computed interface IDs against the Solidity-computed values.

A mismatch between the TypeScript-computed IDs and Solidity's type(IInterface).interfaceId would silently break supportsInterface checks at runtime. The comment on lines 26-28 already notes this risk. A dedicated integration test that asserts equality between the two would catch drift early.

scripts/sanity/secure-ownable/broadcaster-update-tests.cjs (1)

477-494: findUnusedWalletForBroadcaster doesn't check against the owner or recovery addresses.

The function finds a wallet different from the current broadcaster but doesn't exclude addresses currently assigned to the owner or recovery roles. If wallet1 happens to be the owner, this could assign the same address to both broadcaster and owner roles, potentially causing test failures or unexpected behavior.

This is likely fine for a controlled sanity test environment where role assignments are known, but worth noting.

contracts/core/security/SecureOwnable.sol (1)

159-163: NatSpec accurately documents zero-address revocation, but consider documenting the no-op edge case.

The @param docs mention "zero address to revoke at location", but don't mention what happens if the location is empty. A brief note like "revocation of an empty slot is a no-op" would improve clarity for integrators.

Comment on lines 57 to +63
/**
* @dev Explicit deposit function for ETH deposits
* @notice Users must call this function to deposit ETH to the contract
* @notice Direct ETH transfers to the contract will revert (no receive() function)
* @dev Accepts plain ETH transfers (no calldata).
* @notice General-use wallet: ETH can be sent naturally; balance is credited.
* @custom:security No external calls—reentrancy-safe; outgoing ETH only via GuardController execution.
*/
event EthReceived(address indexed from, uint256 amount);

function deposit() external payable {
emit EthReceived(msg.sender, msg.value);
// ETH is automatically added to contract balance
}

receive() external payable {}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

cat -n contracts/examples/templates/AccountBlox.sol

Repository: PracticalParticle/Bloxchain-Protocol

Length of output: 3656


🏁 Script executed:

rg -n --type=sol "contract\s+AccountBlox\b" contracts/examples/templates/AccountBlox.sol -A 5

Repository: PracticalParticle/Bloxchain-Protocol

Length of output: 107


🏁 Script executed:

rg -n --type=sol "ReentrancyGuard|receive\(\)|fallback\(\)|event.*Eth" contracts/examples/templates/AccountBlox.sol

Repository: PracticalParticle/Bloxchain-Protocol

Length of output: 107


🏁 Script executed:

rg -n "ReentrancyGuard" contracts/core/execution/GuardController.sol contracts/core/access/RuntimeRBAC.sol contracts/core/security/SecureOwnable.sol contracts/core/base/BaseStateMachine.sol

Repository: PracticalParticle/Bloxchain-Protocol

Length of output: 785


🏁 Script executed:

rg -n "event.*Received|event.*Eth" contracts/examples/templates/AccountBlox.sol contracts/core/execution/GuardController.sol contracts/core/access/RuntimeRBAC.sol contracts/core/security/SecureOwnable.sol

Repository: PracticalParticle/Bloxchain-Protocol

Length of output: 62


🏁 Script executed:

grep -n "nonReentrant" contracts/core/execution/GuardController.sol contracts/core/access/RuntimeRBAC.sol contracts/core/security/SecureOwnable.sol

Repository: PracticalParticle/Bloxchain-Protocol

Length of output: 62


🏁 Script executed:

grep -n "class\|contract" contracts/core/execution/GuardController.sol | head -5
grep -n "class\|contract" contracts/core/access/RuntimeRBAC.sol | head -5
grep -n "class\|contract" contracts/core/security/SecureOwnable.sol | head -5

Repository: PracticalParticle/Bloxchain-Protocol

Length of output: 1201


🏁 Script executed:

grep -n "extends\|is\|BaseStateMachine" contracts/core/execution/GuardController.sol | head -2
grep -n "extends\|is\|BaseStateMachine" contracts/core/access/RuntimeRBAC.sol | head -2
grep -n "extends\|is\|BaseStateMachine" contracts/core/security/SecureOwnable.sol | head -2

Repository: PracticalParticle/Bloxchain-Protocol

Length of output: 454


🏁 Script executed:

head -50 contracts/core/execution/GuardController.sol | tail -20
head -50 contracts/core/access/RuntimeRBAC.sol | tail -20
head -50 contracts/core/security/SecureOwnable.sol | tail -20

Repository: PracticalParticle/Bloxchain-Protocol

Length of output: 2679


🏁 Script executed:

grep -n "nonReentrant\|function.*execute" contracts/core/execution/GuardController.sol | head -20

Repository: PracticalParticle/Bloxchain-Protocol

Length of output: 719


🏁 Script executed:

grep -n "function execute" contracts/core/base/BaseStateMachine.sol -A 3

Repository: PracticalParticle/Bloxchain-Protocol

Length of output: 62


🏁 Script executed:

grep -n "function executeWithTimeLock\|nonReentrant" contracts/core/execution/GuardController.sol -A 2

Repository: PracticalParticle/Bloxchain-Protocol

Length of output: 172


🏁 Script executed:

grep -n "function.*payable\|receive\|fallback" contracts/core/base/BaseStateMachine.sol

Repository: PracticalParticle/Bloxchain-Protocol

Length of output: 62


🏁 Script executed:

grep -n "nonReentrant" contracts/core/execution/GuardController.sol

Repository: PracticalParticle/Bloxchain-Protocol

Length of output: 62


🏁 Script executed:

grep -rn "nonReentrant" contracts/core/ --include="*.sol"

Repository: PracticalParticle/Bloxchain-Protocol

Length of output: 439


🏁 Script executed:

grep -n "@notice\|function " contracts/core/base/BaseStateMachine.sol | grep -A1 "nonReentrant\|execute"

Repository: PracticalParticle/Bloxchain-Protocol

Length of output: 325


🏁 Script executed:

sed -n '116,140p' contracts/core/execution/GuardController.sol

Repository: PracticalParticle/Bloxchain-Protocol

Length of output: 853


Emit an event for ETH receipt to maintain auditability.

The receive() function accepts ETH silently without emitting an event. Add an event emission for audit trail purposes, as per the coding guideline: "Emit events for critical state changes."

Note: The function is not protected by nonReentrant because it performs no external calls. The comment in the function documentation correctly notes reentrancy-safety is achieved through the constraint that outgoing ETH flows only via GuardController execution (which is protected by nonReentrant on internal functions).

Proposed change for the receive handler
+    event EthReceived(address indexed from, uint256 amount);
+
     /**
      * `@dev` Accepts plain ETH transfers (no calldata).
      * `@notice` General-use wallet: ETH can be sent naturally; balance is credited.
      * `@custom`:security No external calls—reentrancy-safe; outgoing ETH only via GuardController execution.
      */
     receive() external payable {
+        emit EthReceived(msg.sender, msg.value);
     }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
/**
* @dev Explicit deposit function for ETH deposits
* @notice Users must call this function to deposit ETH to the contract
* @notice Direct ETH transfers to the contract will revert (no receive() function)
* @dev Accepts plain ETH transfers (no calldata).
* @notice General-use wallet: ETH can be sent naturally; balance is credited.
* @custom:security No external calls—reentrancy-safe; outgoing ETH only via GuardController execution.
*/
event EthReceived(address indexed from, uint256 amount);
function deposit() external payable {
emit EthReceived(msg.sender, msg.value);
// ETH is automatically added to contract balance
}
receive() external payable {}
event EthReceived(address indexed from, uint256 amount);
/**
* `@dev` Accepts plain ETH transfers (no calldata).
* `@notice` General-use wallet: ETH can be sent naturally; balance is credited.
* `@custom`:security No external calls—reentrancy-safe; outgoing ETH only via GuardController execution.
*/
receive() external payable {
emit EthReceived(msg.sender, msg.value);
}
🤖 Prompt for AI Agents
In `@contracts/examples/templates/AccountBlox.sol` around lines 57 - 63, The
receive() handler currently accepts ETH silently—declare a receive event (e.g.,
event ReceivedETH(address indexed from, uint256 amount);) and emit it inside the
receive() function (emit ReceivedETH(msg.sender, msg.value);) so every plain ETH
transfer to the contract is recorded for auditability; add the event near other
contract events and update the receive() body to emit it while keeping the
function payable and without external calls.

Comment thread test/foundry/unit/SecureOwnable.t.sol
…reOwnable

This commit introduces a fuzz test for the `updateBroadcasterRequest` function, specifically targeting the revoke-at-location path. It ensures that the broadcaster list behaves correctly when revoking entries, including checks for length, index shifting, and duplicate prevention. Additionally, an invariant test is added to verify the safety of the broadcaster list, confirming that it maintains the required constraints on length and uniqueness. These enhancements improve the robustness of the test suite and align with ongoing efforts to ensure comprehensive coverage of broadcaster management functionalities.
@JaCoderX JaCoderX merged commit 9a47783 into main Feb 7, 2026
2 checks passed
@JaCoderX JaCoderX deleted the dev branch February 7, 2026 14:20
This was referenced Feb 14, 2026
Merged
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.

1 participant