Giter VIP home page Giter VIP logo

axelar-cgp-substrate's Introduction

axelar-cgp-substrate

FILL UP!

axelar-cgp-substrate's People

Contributors

mikiquantum avatar nunoalexandre avatar

Stargazers

 avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

axelar-cgp-substrate's Issues

Implement XCM logic in Axelar execute pallet

Implementation of XCM on the Axelar Bridge Pallet

Context

In the PoC the axelar execution happens in the same chain as the destination call. Of course, this was only intended to show case the end to end flow with the integration with the axelar blockchain and the external relayers.
The more interesting approach is that a common good parachain (BridgeHub) has this pallet deployed in its runtime the core purpose is to store approved calls & forward them to the correspondent parachain for execution.

Axelar Pallet Changes

Parachain Global Identification - Chain Id

Every Batch is indexed by the destination ChainId, this value is a uint256 and unique to the axelar network. Ideally the ChainId is a composite UUID in the form of a String, that can describe chain types and other internal identifiers. But for now, we would need a map of Axelar ChainIds to Polkadot Parachain ids. This is important to be able to build the XCM Multilocation (universal format of identifying parachains/accounts/etc) when interacting with XCM. It seems that the most lightweight solution is to have a built in storage mapping in the Axelar Pallet that maintains the ParachainId associated to the AxelarChainId.

#[pallet::storage]
#[pallet::getter(fn chain_id_mapping)]
pub(super) type ChainIdMapping<T: Config> = StorageMap<
    _,
    Blake2_128Concat,
    // AxelarChainId
    u128,
    // Parachain Id
    u32,
    ValueQuery,
>;

This is a bit unfortunate since there has to be an admin function that has to maintain this mapping. I hope we can avoid this.
Lets ask Axelar how hard would it be to encode in the ChainId a composite identifier without collisions

Storage of authorized parachains

To avoid spamming, the execute function will check if the destination chainID is a well known parachain authorized in the BridgeHub, otherwise it should reject the execute call.

Admin function to add/remove authorized parachains

We should give each parachain the power to add or remove themselves through their own governance mechanisms from the bridge forwarding logic. We suggest to create a custom EnsureParachainOrigin:


#[pallet::storage]
#[pallet::getter(fn authorized_parachain)]
pub(super) type AutorizedParachain<T: Config> = StorageMap<
    _,
    Blake2_128Concat,
    // Parachain Id
    ParaId,
    // Empty
    (),
    ValueQuery,
>;

fn set_auth_para(origin, call_id: CallId) {
  // Only callable by sovereign para_id
  let who = EnsureParachainOrigin(origin)?;

  ParaCallId<T>::set(who.id, ());
  Self::deposit_event(Event::ParaIdAuthorized{who.id})
  
}

Incoming - Forward execution Origin header & XCM instructions

When a call has been approved by the Axelar validator network, then the next step is to forward the call to the correspondent parachain. The initial approach is to prepend proper identification to the XCM Sender so the receiving parachain can perform any authorization needed before executing the final encoded call.
Here is a rough schema of how the call can be formed:

let call = payload;

let msg = vec![
  // Provides the receiving chain with info
  // that this is coming over a bridge
  UniversalOrigin(
     GlobalConsensus(ETHEREUM)
  ),
  // Provides the address of the called contract.
  // I.e. this will be the "msg.sender" from the Ethereum side
  DescendOrigin(
     Junctions::X1(AccountKey20 {network: Some(ETHEREUM), key: sender})
  ),
  WithdrawAsset(fee_asset.clone().into()),
	BuyExecution(asset, &dest, dest_weight),
  RefundSurplus,
  // This will be the call that parachains provide to further process messages
  // from the Ethereum side comming from axelar.
  //
  // The `origin_kind` should also be "set-able" by the receiving chain.
  // The `require_weight_at_most` should also be "set-able" by the receiving chain.
  // The `call` can NOT have a sensible generic param set in the gateway.
  Transact { origin_kind, require_weight_at_most, call: DoubleEncoded<()>::from(call)}
];

// Use the associated type to forward the message. Usually, this would be done using `trait SendXcm`
T::Sender::deliver(msg).map_err(|e| Error::<T>::SendXcm{error: e})

A few pieces are worth making emphasis about:
UniversalOrigin - This is a newly introduced instruction in XCMv3 that allows an xcm origin in the context of the execution to change to an allowed alias for the next instructions to be executed. This way we can identify and propagate the ultimate origin outside of the polkadot system. Works in combination with Junction::GlobalConsensus(NetworkId) where NetworkId, can be a well known network like kusama, bitcoin, or ethereum or an arbitrary one identified with their genesis block hash.
DescendOrigin - Ensures that the origin dapp is captured and propagated along so further authentorization logic can be executed in the destination chain & pallet.

Transact call

The payload should have all the information needed to be executed in the target chain and formatted accordingly. The Axelar pallet should not need to "understand" its contents.

Outgoing - XCM Sender Identification

The Axelar gateway pallet has an extrinsic called CallContract that initiates the Axelar message validation and consensus. This extrinsic should only be callable from a parachain through XCM; the BridgeHub should only take care of forwarding calls not initiating them since it should not have any business logic role in the underlaying content of a remote call.
To achieve this a custom origin trait that identifies the "sender" as a Multilocation is needed: Parachain(5000) || (Parachain(5000), AccountId(x)) || ... In addition to having an EnsureParachainOrigin authorizing the call.

#[pallet::weight(<T as pallet::Config>::WeightInfo::call_contract())]
pub fn call_contract(
    origin: OriginFor<T>,
    destination_chain: String,
    destination_contract_address: String,
    payload: Vec<u8>,
) -> DispatchResult {
    // Only a parachain can call this function
    let para_id = EnsureParachainOnly()?;

    Self::deposit_event(Event::ContractCall {
        // Potentially concatenate here the BridgeHub ChainId in a format like `bridgehub_id/source_para_id`
        sender: para_id.0.to_string(),
        destination_chain,
        destination_contract_address,
        payload_hash: H256::from_slice(keccak_256(&payload).as_slice()),
        payload,
    });

    Ok(())
}

Integration e2e xcm test - mocking axelar network interactions

A comprehensive integration test that verifies the XCM requirements above described is required to ensure that the assumptions are working as expected. Using xcm-emulator.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.