Transact from sub to eth - #1145
Conversation
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## bridge-next-gen #1145 +/- ##
==================================================
Coverage ? 79.72%
==================================================
Files ? 14
Lines ? 429
Branches ? 76
==================================================
Hits ? 342
Misses ? 71
Partials ? 16
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. |
alistair-singh
left a comment
There was a problem hiding this comment.
Looks good! Just one comment tests.
| /// @notice Use when you _really_ really _really_ don't trust the called | ||
| /// contract. This prevents the called contract from causing reversion of | ||
| /// the caller in as many ways as we can. |
There was a problem hiding this comment.
We should understand how using zexcessivelySafeCall` can still fail? And potentially have tests for at least one case to make sure we don't poisen pill the inbound queue.
There was a problem hiding this comment.
Yeah, an unsafe call could be dangerous so we need to be very careful here. Except that I would also like to introduce white-list access control, something like the SafeCallFilter but on Ethereum side.
There was a problem hiding this comment.
My thoughts about this:
-
I think
excessivelySafeCall(used by Nomad) is too complicated for our needs. When issuing a call, we are only interested in whether the call succeeded or not. Thereturndatawe can ignore. For this reason, I prefer that we use this safe call solution: https://github.com/ethereum-optimism/optimism/blob/b36eb5515cc2a34a15383b2eee488dbac83d6caf/packages/contracts-bedrock/src/libraries/SafeCall.sol#L12 -
I am optimistic we've accounted for all the ways a contract call can be unsafe. This includes guards against re-entrancy (nonce check), gas limits, and returnbomb attacks. Therefore I don't see a reason to include a safe call filter. If we think a call can still be unsafe, we need to understand why. For now I would just remove the safe call filter.
There was a problem hiding this comment.
@yrong How does SafeCallFilter work? Will we have to restrict allowing transact to only explicitly specified contracts and/or functions? This won't work - we 100% need permissionless support for anyone to integrate transacting with any contract and any function without permission.
And yeah agree with @vgeddes on just ignoring all returndata
There was a problem hiding this comment.
How does SafeCallFilter work? Will we have to restrict allowing transact to only explicitly specified contracts and/or functions?
It's not by us or requires governance from the relaychain, but instead from the Parachain sovereign through xcm(i.e. require another call added in our system pallet), they can increase the whitelist step by step entirely under their control.
In this way, we can release the transact support without introducing potential risk.
There was a problem hiding this comment.
Allow arbitray transact without any black(white)-list 606e867
|
|
||
| ## Explanation | ||
|
|
||
| We use penpal for the integration, basically it works as follows: |
There was a problem hiding this comment.
Fee flow:
- User represents a user who kicks off an extrinsic on the parachain.
- Parachain represents the source parachain, its sovereign or its agent depending on context.
| Sequence | Where | Who | What |
|---|---|---|---|
| 1 | Parachain | User | pays(DOT, Native) to node to execute custom extrinsic; pays (DOT) to Treasury for delivery as part of custom extrinsic. |
| 2 | Bridge Hub | Parachain | pays(DOT) to Treasury Account for delivery(local fee), pays(DOT) to Parachain sovereign for delivery(remote fee), essentially a refund. Remote fee converted to ETH here. |
| 3 | Gateway | Relayer | pays(ETH) to validate and execute message. |
| 4 | Gateway | Parachain Agent | pays(ETH) to relayer for delivery(reward+refund) and execution. |
Does this balance? No, Parachain agent pays for delivery and execution on the Ethereum side. User only pays for calling the extrinsic and delivery on the source Parachain. Because the custom extrinsic essentially allows the user to impersonate the parachain on ethereum side it becomes the Parachains job to charge appropriately for both delivery and execution. This doesn't mean there is something wrong with the implementation, just that this needs to be communication to creator of the custom extrinsic.
There was a problem hiding this comment.
For step 1 user pays(DOT) to Treasury for both the delivery cost on BH and execution cost on Ethereum.
For step 2 the sovereign of Penpal only pays(DOT) for the delivery(local fee) portion, there is no refund in this case.
Co-authored-by: Clara van Staden <claravanstaden64@gmail.com>
1113521 to
b89cc6c
Compare
| if (!success) { | ||
| revert AgentTransactCallFailed(); | ||
| } | ||
| emit TransactExecuted(params.agentID, params.target, params.payload); |
There was a problem hiding this comment.
params.payload could be very large, cheaper to hash it when emitting event
| emit TransactExecuted(params.agentID, params.target, params.payload); | |
| emit TransactExecuted(params.agentID, params.target, keccak256(params.payload)); |
| /// @dev Payload of the call | ||
| bytes payload; | ||
| /// @dev Max gas cost of the call | ||
| uint64 dynamicGas; |
There was a problem hiding this comment.
The message packet already has a maxDispatchGas, which is the upper limit a transact can consume. So I am not sure what role this dynamicGas plays.
The gas estimator on BridgeHub should add a buffer to maxDispatchGas to cover the cost of dispatching via the agent.
There was a problem hiding this comment.
Yes, it's the same thing. Just rename it for less confusion.
27c14e9
| // Emitted when funds are withdrawn from an agent | ||
| event AgentFundsWithdrawn(bytes32 indexed agentID, address indexed recipient, uint256 amount); | ||
|
|
||
| event TransactExecuted(bytes32 indexed agentID, address indexed target, bytes payload); |
There was a problem hiding this comment.
| event TransactExecuted(bytes32 indexed agentID, address indexed target, bytes payload); | |
| event Transacted(bytes32 indexed agentID, address indexed target, bytes32 payloadHash); |
| /// @param _calldata The data to send to the remote contract | ||
| /// @return success and returndata, as `.call()`. Returndata is capped to | ||
| /// `_maxCopy` bytes. | ||
| function excessivelySafeCall(address _target, uint256 _gas, uint256 _value, uint16 _maxCopy, bytes memory _calldata) |
There was a problem hiding this comment.
We're no longer using this, can we remove it?
3dcd8ed to
fe513c7
Compare
|
Obsolete |
Resolves: SNO-586,SNO-866,SNO-696
Requires: Snowfork/polkadot-sdk#116