Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

contracts: XCM support #121

Open
4 tasks
HCastano opened this issue Nov 1, 2021 · 9 comments
Open
4 tasks

contracts: XCM support #121

HCastano opened this issue Nov 1, 2021 · 9 comments
Assignees
Labels
D3-involved Can be fixed by an expert coder with good knowledge of the codebase. I5-enhancement An additional feature request. T6-XCM This PR/Issue is related to XCM.

Comments

@HCastano
Copy link
Contributor

HCastano commented Nov 1, 2021

The Vision

Contracts should be able to execute and send arbitrary XCM messages. This will allow contracts to participate in the wider ecosystem. A common use case would be to make use of assets on statemint.

The Plan

A while ago I created a chain extension to support executing, sending and receiving XCM messages from a contract: https://github.com/paritytech/pallet-contracts-xcm

This is a prototype but already outlines all the features we need:

  • Sending XCM programs
  • Executing XCM programs locally
  • Receiving replies
    • We opted for polling here instead of callbacks. So no ink_xcm_receive. This solves the weight problems around receiving replies.

It doesn't do this in a secure way, though. It is a prototype. For example, it doesn't charge storage deposits for the reply id and reply buffer.

It is a chain extension rather than a core API solely because of technical reasons: It depends on the XCM crates which are part of the polkadot repo. However, pallet-contracts is in the substrate repository on which polkadot depends. Therefore pallet-contracts can't depend on XCM as this would be a circle. As a workaround we placed the code into another repository. The only way to do that is a chain extension. The real implementation should be bundled with pallet-contracts once we have the monorepo. It still needs to be optional as some chains might decide not to implement it. Hence it might make sense to keep it a chain extension rather than a core API.

  • Port existing chain extensions to XCMv3
  • Move extension into the soon to be existent monorepo
  • Make it production ready (make it sound with regard to resource usage, add docs, add tests)
  • Update ink! support (ink! needs support for multiple chain extensions first)

Open Questions

If you want to help us out and contribute to this issue, in this section you can find open questions and tasks where we would appreciate any input.


Here you can find the board with specific sub-tasks to this milestone:
<Link to your project's view>

@bernardoaraujor
Copy link
Contributor

bernardoaraujor commented Nov 13, 2021

hi guys 👋

how will XCM over SCs work in terms of:

  • XCMP's asynchronicity - How can SC logic "await"?
  • XCMP irreversibility - How are cancelled SCs handled after assets have already been teleported away from the contract chain?

cc @KiChjang

@athei
Copy link
Member

athei commented Nov 13, 2021

We add a new host function that allows sending XCM functions to a MultiLocation. The contracts pallet decodes bytes and checks the XCM version and returns an error when the dest is not able to receive the used version. Apart from that we do not care at all about the contents of bytes.

ink_env::send_xcm(dest: MultiLocation, bytes: &[u8]) -> Result<(), ErrorCode>;

Whenever a contract is the target of an XCM message it gets called and the gas meter is set according to the BuyWeight instruction of the received XCM message. We add another exported function xcm_received that is called instead of call in this case. seal_input will return the XCM message and seal_caller the MultiLocation sender of the message.

XCMP's asynchronicity - How can SC logic "await"?

The send_xcm function will be fire and forget. If a reply is expected this needs to be modeled in terms of code in the xcm_received function. Specifying a callback at call side won't work because the XCM code is mostly opaque to pallet contracts for now.

I expect it to be done like this:

  • Send xcm message
  • Write to storage that there is a pending operation
  • End current contract call
  • XCM reply triggers send_xcm which finalizes the operation in storage

XCMP irreversibility - How are cancelled SCs handled after assets have already been teleported away from the contract chain?

We can buffer all XCM messages and only emit them at the end if the contract call did not revert.

@athei
Copy link
Member

athei commented Nov 16, 2021

Integrate XCM: Discussion 2021-11-16

Whiteboard Mess

ink_env::send_xcm(location: MultiLocation, bytes: &[u8])

Example Usage in ink!:

// Contract developer is responsible for ensuring this
assert!(self.env().transferred_value >= execution_to_buy);

// It's the responsibility of the contract developer to ensure that the right amount of Weight is paid for.
// We may also need to assume that the `MultiAsset` being sent is initially just the Native asset of the chain
let xcm_msg: XcmMessage = {,
    QueryId,
    WithdrawAsset(MultiAsset),
    
    BuyExecution(execution_to_buy),
    
    RefundSurplus()
};

// TODO: XCM currently doesn't support a `SmartContract` `MultiLocation` destination, we'll need to add support for that
let location = MultiLocation();
ink_env::send_xcm(location, xcm_msg.encode()) -> Result<(), XcmSendError>;

enum XcmSendError {
    XcmVersionNotSupported,
    UnknownLocation,
}

pallet-contracts

seal_send_xcm(location: MultiLocation, msg: &[u8]) ➜ XcmSendError

  • Implement routing for MultiLocation to contracts.
  • BuyExecution has to be reflected to contracts.
    • It is subtracted from contract balance.
    • Contract developer must make sure transferred_value is sufficient, otherwise they sabotage their own contract.
  • XCM-Origin is set to contract account ➜ The contract pays for XCM.
  • Buffer XCM Message, send it only out if contract didn't revert.
  • Add an RPC call for dry-running an XCM Message.
    • This enables developers to get an estimate of how much value they should put into the BuyExecution(value, …) for the callback into their contract.

Note

Currently, pallet-contracts enforces the free balance of a contract's account to be larger than the existential deposit. This is so no dust related accidents can happen. With these changes we can no longer enforce this invariant because we can't control the contents of the XCM (it could send away its own balance). I suggest:

pallet-contracts makes sure that the initial deposit that is subtracted from the caller in order to pay for the contract data structure is at least the existential deposit. It cannot be moved away by XCM and it can only be removed when the contract terminates.

This makes sure that a contract's acount always exist on-chain and no dust related accidents can happen.

XCM Receive

extern "C" {
    /// Called by pallet_contracts when a xcm message is addressed
    /// to a contract.
    pub fn xcm_receive() {
        xcm_receive(seal_caller(), seal_input());
    }
}

// In `ink!`:
#[ink(xcm_receive)]
pub fn ink_xcm_receive(src: MultiLocation, msg: &[u8]) {
    // Handle stuff
    // Called by `xcm_receive`
}

Cross Chain Message Flow

Cross-chain-message-flow

Cross Chain Error Handling

Cross-Chain Messages

Two problems here:

  1. Our contract updates some of its state, and a call to a remote chain fails. There's no way for us to revert the state of our smart contract
  2. We make a cross chain call which updates the state of the target chain, afterwards we resume execution and our smart contract fails. There's no way to revert the changes on the remote chain

We figured that maybe if a receive failed we could emit an event to notify external actors. However, a problem arises when we think about who actually ends up paying for the event. We aren't able to allocate any weight in WithdrawAsset or BuyExecution since that weight could be spent before we are able to emit an event.

// Event emitted by `pallet-contracts`
struct XcmReceiveFailure {
    err: DispatchError,
    location: MultiLocation,
}

Doing it anyway

We figured that we should provide xcm_receive anyway, even without a foolproof solution to reversion and error reporting. Sending out an event on receive failure might also be too complicated.

We basically provide this as a "no guards included" bare functionality and monitor what people build with it. This will give us more insight in howto provide more safe abstractions.

@cmichi
Copy link

cmichi commented Apr 23, 2022

Persisting some of our discussions:

#[ink(xcm_receive, max_gas_consumed = 50_000)]
pub fn ink_xcm_receive(src: MultiLocation, msg: &[u8]) {
  if msg[0] == 1 {
    // expensive computation
  } else {
    // cheap computation
  }
}

The max_gas_consumed value is put into the metadata, so that the calling parachain has information about which value they should put for BuyExecution: it would be weight_limit: Some(max_gas_consumed).

Note: Gas is a synonym for Weight.

How a contract would be called:

XCM {
  BuyExecution(…),
  Transact(…),
}

Necessary follow-up issues:

  • Add a new RPC in pallet-contracts for dry_run_xcm_receive.
  • Add a sub-command for cargo-contract to execute dry_run_xcm_receive.

Test use-cases for our MVP:

  • Call Statemine, transer asset from one account to another, send reply to contract that this succeeded.
  • Call contract on another chain and send reply.

@cmichi
Copy link

cmichi commented Apr 25, 2022

Persisting this here: It's still unclear how the UI would display our MVP in a meaningful way.

@athei
Copy link
Member

athei commented Jun 28, 2022

We will do the MVP as a chain extension in a separate repository to get around the fact that we can't depend on polkadot from substrate. This will be useful for that: paritytech/substrate#11751

@athei athei changed the title Minimal XCM Support for Contracts XCM Support for contracts Jul 28, 2022
@athei
Copy link
Member

athei commented Aug 18, 2022

Delayed to next month because it needs to be merged into polkadot and that takes more work than just an MVP: Docs, Tests, Review cycle.

@athei athei removed their assignment Mar 19, 2023
@ashutoshvarma
Copy link

@athei
Can you elaborate on why the callback design was discarded in favor of polling?
pallet-xcm's OnResponse already provides the dispatch callbacks for queries (notify).

@athei
Copy link
Member

athei commented Mar 20, 2023

Because it is unclear who pays for for the execution when there is no extrinsic attached to the execution. Even without the problem of fees we have the problem that the callback will be called from on_initialize which we want to avoid. Additionally it introduces difficult error states: What if the max_weight supplied to the call back is too low. You have no way of recovering. The contract state will be in limbo waiting for the the reply. Attaching this to an extrinsic will allow for re-try with higher weight.

It seems to me as a much simpler design.

@athei athei added Z4-involved and removed Z5-epic labels Mar 22, 2023
@athei athei changed the title XCM Support for contracts contracts: XCM support Apr 12, 2023
@athei athei transferred this issue from paritytech/substrate Aug 24, 2023
@the-right-joyce the-right-joyce added I5-enhancement An additional feature request. D3-involved Can be fixed by an expert coder with good knowledge of the codebase. and removed J0-enhancement labels Aug 25, 2023
@franciscoaguirre franciscoaguirre added the T6-XCM This PR/Issue is related to XCM. label Mar 25, 2024
serban300 pushed a commit to serban300/polkadot-sdk that referenced this issue Apr 8, 2024
* Add descriptions for folder structure + node

* Beef up descriptions of project components

* Fix list formatting

* Add note about nightly Rust

* Update README.md

Co-authored-by: Tomasz Drwięga <tomusdrw@users.noreply.github.com>

* Update README.md

Co-authored-by: Tomasz Drwięga <tomusdrw@users.noreply.github.com>

* Reword Tomek's currency-exchange suggestion

* Add link to Substrate's installation guide

Co-authored-by: Tomasz Drwięga <tomusdrw@users.noreply.github.com>
serban300 pushed a commit to serban300/polkadot-sdk that referenced this issue Apr 8, 2024
* Add descriptions for folder structure + node

* Beef up descriptions of project components

* Fix list formatting

* Add note about nightly Rust

* Update README.md

Co-authored-by: Tomasz Drwięga <tomusdrw@users.noreply.github.com>

* Update README.md

Co-authored-by: Tomasz Drwięga <tomusdrw@users.noreply.github.com>

* Reword Tomek's currency-exchange suggestion

* Add link to Substrate's installation guide

Co-authored-by: Tomasz Drwięga <tomusdrw@users.noreply.github.com>
serban300 pushed a commit to serban300/polkadot-sdk that referenced this issue Apr 9, 2024
* Add descriptions for folder structure + node

* Beef up descriptions of project components

* Fix list formatting

* Add note about nightly Rust

* Update README.md

Co-authored-by: Tomasz Drwięga <tomusdrw@users.noreply.github.com>

* Update README.md

Co-authored-by: Tomasz Drwięga <tomusdrw@users.noreply.github.com>

* Reword Tomek's currency-exchange suggestion

* Add link to Substrate's installation guide

Co-authored-by: Tomasz Drwięga <tomusdrw@users.noreply.github.com>
serban300 pushed a commit to serban300/polkadot-sdk that referenced this issue Apr 9, 2024
* Add descriptions for folder structure + node

* Beef up descriptions of project components

* Fix list formatting

* Add note about nightly Rust

* Update README.md

Co-authored-by: Tomasz Drwięga <tomusdrw@users.noreply.github.com>

* Update README.md

Co-authored-by: Tomasz Drwięga <tomusdrw@users.noreply.github.com>

* Reword Tomek's currency-exchange suggestion

* Add link to Substrate's installation guide

Co-authored-by: Tomasz Drwięga <tomusdrw@users.noreply.github.com>
serban300 pushed a commit to serban300/polkadot-sdk that referenced this issue Apr 9, 2024
* Add descriptions for folder structure + node

* Beef up descriptions of project components

* Fix list formatting

* Add note about nightly Rust

* Update README.md

Co-authored-by: Tomasz Drwięga <tomusdrw@users.noreply.github.com>

* Update README.md

Co-authored-by: Tomasz Drwięga <tomusdrw@users.noreply.github.com>

* Reword Tomek's currency-exchange suggestion

* Add link to Substrate's installation guide

Co-authored-by: Tomasz Drwięga <tomusdrw@users.noreply.github.com>
serban300 pushed a commit to serban300/polkadot-sdk that referenced this issue Apr 9, 2024
* Add descriptions for folder structure + node

* Beef up descriptions of project components

* Fix list formatting

* Add note about nightly Rust

* Update README.md

Co-authored-by: Tomasz Drwięga <tomusdrw@users.noreply.github.com>

* Update README.md

Co-authored-by: Tomasz Drwięga <tomusdrw@users.noreply.github.com>

* Reword Tomek's currency-exchange suggestion

* Add link to Substrate's installation guide

Co-authored-by: Tomasz Drwięga <tomusdrw@users.noreply.github.com>
serban300 pushed a commit to serban300/polkadot-sdk that referenced this issue Apr 9, 2024
* Add descriptions for folder structure + node

* Beef up descriptions of project components

* Fix list formatting

* Add note about nightly Rust

* Update README.md

Co-authored-by: Tomasz Drwięga <tomusdrw@users.noreply.github.com>

* Update README.md

Co-authored-by: Tomasz Drwięga <tomusdrw@users.noreply.github.com>

* Reword Tomek's currency-exchange suggestion

* Add link to Substrate's installation guide

Co-authored-by: Tomasz Drwięga <tomusdrw@users.noreply.github.com>
serban300 pushed a commit to serban300/polkadot-sdk that referenced this issue Apr 9, 2024
* Add descriptions for folder structure + node

* Beef up descriptions of project components

* Fix list formatting

* Add note about nightly Rust

* Update README.md

Co-authored-by: Tomasz Drwięga <tomusdrw@users.noreply.github.com>

* Update README.md

Co-authored-by: Tomasz Drwięga <tomusdrw@users.noreply.github.com>

* Reword Tomek's currency-exchange suggestion

* Add link to Substrate's installation guide

Co-authored-by: Tomasz Drwięga <tomusdrw@users.noreply.github.com>
serban300 pushed a commit to serban300/polkadot-sdk that referenced this issue Apr 10, 2024
* Add descriptions for folder structure + node

* Beef up descriptions of project components

* Fix list formatting

* Add note about nightly Rust

* Update README.md

Co-authored-by: Tomasz Drwięga <tomusdrw@users.noreply.github.com>

* Update README.md

Co-authored-by: Tomasz Drwięga <tomusdrw@users.noreply.github.com>

* Reword Tomek's currency-exchange suggestion

* Add link to Substrate's installation guide

Co-authored-by: Tomasz Drwięga <tomusdrw@users.noreply.github.com>
serban300 pushed a commit to serban300/polkadot-sdk that referenced this issue Apr 10, 2024
* Add descriptions for folder structure + node

* Beef up descriptions of project components

* Fix list formatting

* Add note about nightly Rust

* Update README.md

Co-authored-by: Tomasz Drwięga <tomusdrw@users.noreply.github.com>

* Update README.md

Co-authored-by: Tomasz Drwięga <tomusdrw@users.noreply.github.com>

* Reword Tomek's currency-exchange suggestion

* Add link to Substrate's installation guide

Co-authored-by: Tomasz Drwięga <tomusdrw@users.noreply.github.com>
jonathanudd pushed a commit to jonathanudd/polkadot-sdk that referenced this issue Apr 10, 2024
* Add descriptions for folder structure + node

* Beef up descriptions of project components

* Fix list formatting

* Add note about nightly Rust

* Update README.md

Co-authored-by: Tomasz Drwięga <tomusdrw@users.noreply.github.com>

* Update README.md

Co-authored-by: Tomasz Drwięga <tomusdrw@users.noreply.github.com>

* Reword Tomek's currency-exchange suggestion

* Add link to Substrate's installation guide

Co-authored-by: Tomasz Drwięga <tomusdrw@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
D3-involved Can be fixed by an expert coder with good knowledge of the codebase. I5-enhancement An additional feature request. T6-XCM This PR/Issue is related to XCM.
Projects
Status: Backlog
Status: Code in review 🧐
Development

No branches or pull requests

8 participants