Skip to content

Restrict Asset Hub agent from executing contract calls in V2#1788

Merged
yrong merged 6 commits into
mainfrom
ron/restrict-agent-call-contract
Jun 25, 2026
Merged

Restrict Asset Hub agent from executing contract calls in V2#1788
yrong merged 6 commits into
mainfrom
ron/restrict-agent-call-contract

Conversation

@yrong

@yrong yrong commented May 12, 2026

Copy link
Copy Markdown
Contributor

No description provided.

@codecov

codecov Bot commented May 12, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 78.17%. Comparing base (d9107c5) to head (cce7ab8).
⚠️ Report is 22 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1788      +/-   ##
==========================================
+ Coverage   76.90%   78.17%   +1.26%     
==========================================
  Files          24       24              
  Lines         983      985       +2     
  Branches      186      187       +1     
==========================================
+ Hits          756      770      +14     
+ Misses        203      192      -11     
+ Partials       24       23       -1     
Flag Coverage Δ
solidity 78.17% <100.00%> (+1.26%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@yrong yrong marked this pull request as ready for review May 13, 2026 03:54
vm.expectEmit(true, false, false, true);
emit IGatewayV2.InboundMessageDispatched(1, topic, true, relayerRewardAddress);

address bridgeHubAgent = IGatewayV2(address(gateway)).agentOf(Constants.BRIDGE_HUB_AGENT_ID);

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.

Kind of a weird test to allow BH agent to make arbitrary contract calls, since this is privileged as well, right? Even if the BH agent doesn't hold funds.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Allowing BH is expected. Yes, it’s not privilege-based — it only disables the AH agent that holds the funds.

Comment thread contracts/src/Functions.sol Outdated

@claravanstaden claravanstaden left a comment

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.

I think this okay in principle. AH is the only agent that contains token transfer funds, right?

@claravanstaden

Copy link
Copy Markdown
Contributor

Added some more tests here: #1793

* Add tests for ensureNotAssetHubAgent

Strengthens coverage around the AssetHub-agent callContract block
introduced in #1788:

- positive: a v2_createAgent'd user agent can still callContract
- direct: ensureNotAssetHubAgent revert reason and allow/deny paths
  pinned via an exposed wrapper on MockGateway, including a fuzz
  invariant that only ASSET_HUB_AGENT_ID returns
  UnauthorizedPrivilegedAgent
- no-state-leak: AssetHub failure path emits no SaidHello, leaves
  agent balance and registration untouched
- dual-invariant: ASSET_HUB_AGENT_ID is rejected as a callContract
  origin AND still accepted as an unlockNativeToken recipient
- multi-command: a poisoned AssetHub-origin callContract bundled
  with a legit one fails every command; same payload from a user
  agent succeeds
- skipped: testAgentCallContractFailsForBridgeHub documents the
  latent AliasOrigin(Here) -> BRIDGE_HUB_AGENT_ID bypass that the
  current single-entry deny list does not cover

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Drop BridgeHub-block skip test

BridgeHub is intentionally non-privileged in the V2 deny list; only
ASSET_HUB_AGENT_ID is reserved. Remove the speculative
testAgentCallContractFailsForBridgeHub skip and clarify the existing
testEnsureNotAssetHubAgent_AllowsBridgeHub with a comment so future
readers know the allow is by design.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Drop ticket id from section comment

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Drop PR reference from section comment

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@claravanstaden claravanstaden requested a review from vgeddes June 3, 2026 11:06
@vgeddes

vgeddes commented Jun 5, 2026

Copy link
Copy Markdown
Collaborator

I'd like us to go a step further and remove support for CallContract entirely.

Comment thread contracts/src/interfaces/IGatewayBase.sol Outdated
Comment thread contracts/src/v2/Handlers.sol Outdated
function callContract(bytes32 origin, address executor, bytes calldata data) external {
CallContractParams memory params = abi.decode(data, (CallContractParams));
address agent = Functions.ensureAgent(origin);
address agent = Functions.ensureNotAssetHubAgent(origin);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I prefer this, its easier to audit.

Suggested change
address agent = Functions.ensureNotAssetHubAgent(origin);
if (agentID == Constants.ASSET_HUB_AGENT_ID) {
revert IGatewayBase.Unauthorized();
}
address agent = Functions.ensureAgent(origin);

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Per review feedback, inline the AssetHub deny check at the callContract
call site instead of the single-use ensureNotAssetHubAgent helper, and
revert with the existing Unauthorized error rather than a new
UnauthorizedPrivilegedAgent type. The V2 dispatcher swallows revert
reasons in a bare catch, so a distinct error gives no observable benefit.
@yrong yrong merged commit 99adc52 into main Jun 25, 2026
4 checks passed
@yrong yrong deleted the ron/restrict-agent-call-contract branch June 25, 2026 11:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants