Skip to content

Commit

Permalink
WIP: argo bridge
Browse files Browse the repository at this point in the history
  • Loading branch information
freakstatic committed May 28, 2024
1 parent 011d1a6 commit 37f3d91
Show file tree
Hide file tree
Showing 27 changed files with 1,368 additions and 7 deletions.
27 changes: 27 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

21 changes: 21 additions & 0 deletions bin/node/src/chain_spec/argo_bridge_config.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
use node_runtime::{argo_bridge::types::BridgeStatus, ArgoBridgeConfig};

pub fn production_config() -> ArgoBridgeConfig {
ArgoBridgeConfig {
status: BridgeStatus::Paused,
mint_allowance: 0,
bridging_fee: 0,
thawn_duration: 1,
..Default::default()
}
}

pub fn testing_config() -> ArgoBridgeConfig {
ArgoBridgeConfig {
status: BridgeStatus::Paused,
mint_allowance: 0,
bridging_fee: 0,
thawn_duration: 1,
..Default::default()
}
}
15 changes: 11 additions & 4 deletions bin/node/src/chain_spec/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
// Example: voting_period: 1 * DAY
#![allow(clippy::identity_op)]

pub mod argo_bridge_config;
pub mod content_config;
pub mod council_config;
pub mod forum_config;
Expand All @@ -30,10 +31,10 @@ pub use grandpa_primitives::AuthorityId as GrandpaId;

use node_runtime::{
constants::currency::{DOLLARS, MIN_NOMINATOR_BOND, MIN_VALIDATOR_BOND},
wasm_binary_unwrap, AuthorityDiscoveryConfig, BabeConfig, BalancesConfig, Block, ContentConfig,
ExistentialDeposit, GrandpaConfig, ImOnlineConfig, MaxNominations, ProjectTokenConfig,
SessionConfig, SessionKeys, StakerStatus, StakingConfig, StorageConfig, SystemConfig,
TransactionPaymentConfig, VestingConfig,
wasm_binary_unwrap, ArgoBridgeConfig, AuthorityDiscoveryConfig, BabeConfig, BalancesConfig,
Block, ContentConfig, ExistentialDeposit, GrandpaConfig, ImOnlineConfig, MaxNominations,
ProjectTokenConfig, SessionConfig, SessionKeys, StakerStatus, StakingConfig, StorageConfig,
SystemConfig, TransactionPaymentConfig, VestingConfig,
};
pub use pallet_im_online::sr25519::AuthorityId as ImOnlineId;
use sc_chain_spec::ChainSpecExtension;
Expand Down Expand Up @@ -183,6 +184,7 @@ pub fn testnet_genesis(
content_cfg: ContentConfig,
storage_cfg: StorageConfig,
project_token_cfg: ProjectTokenConfig,
argo_bridge_cfg: ArgoBridgeConfig,
) -> GenesisConfig {
// staking benchmakrs is not sensitive to actual value of min bonds so
// accounts are not funded with sufficient funds and fail with InsufficientBond err
Expand Down Expand Up @@ -335,6 +337,7 @@ pub fn testnet_genesis(
content: content_cfg,
storage: storage_cfg,
project_token: project_token_cfg,
argo_bridge: argo_bridge_cfg,
proposals_discussion: Default::default(),
members: Default::default(),
}
Expand All @@ -354,6 +357,7 @@ fn development_config_genesis() -> GenesisConfig {
content_config::testing_config(),
storage_config::testing_config(),
project_token_config::testing_config(),
argo_bridge_config::testing_config(),
)
}

Expand Down Expand Up @@ -387,6 +391,7 @@ fn local_testnet_genesis() -> GenesisConfig {
content_config::testing_config(),
storage_config::testing_config(),
project_token_config::testing_config(),
argo_bridge_config::testing_config(),
)
}

Expand Down Expand Up @@ -417,6 +422,7 @@ fn prod_test_config_genesis() -> GenesisConfig {
content_config::production_config(),
storage_config::production_config(),
project_token_config::production_config(),
argo_bridge_config::production_config(),
)
}

Expand Down Expand Up @@ -454,6 +460,7 @@ pub(crate) mod tests {
content_config::testing_config(),
storage_config::testing_config(),
project_token_config::testing_config(),
argo_bridge_config::testing_config(),
)
}

Expand Down
12 changes: 9 additions & 3 deletions bin/utils/chain-spec-builder/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@ use std::{
};

use joystream_node::chain_spec::{
self, content_config, initial_balances, joy_chain_spec_properties, project_token_config,
storage_config, AccountId, AuthorityDiscoveryId, BabeId, GrandpaId, ImOnlineId,
JOY_ADDRESS_PREFIX,
self, argo_bridge_config, content_config, initial_balances, joy_chain_spec_properties,
project_token_config, storage_config, AccountId, AuthorityDiscoveryId, BabeId, GrandpaId,
ImOnlineId, JOY_ADDRESS_PREFIX,
};

use sc_chain_spec::ChainType;
Expand Down Expand Up @@ -267,6 +267,11 @@ fn genesis_constructor(
_ => project_token_config::testing_config(),
};

let argo_bridge_cfg = match deployment {
ChainDeployment::mainnet => argo_bridge_config::production_config(),
_ => argo_bridge_config::testing_config(),
};

chain_spec::testnet_genesis(
fund_accounts,
authorities,
Expand All @@ -277,6 +282,7 @@ fn genesis_constructor(
content_cfg,
storage_cfg,
project_token_cfg,
argo_bridge_cfg,
)
}

Expand Down
56 changes: 56 additions & 0 deletions runtime-modules/argo-bridge/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
[package]
name = "pallet-argo-bridge"
version = '1.0.0'
authors = ['Joystream contributors']
edition = '2018'

[dependencies]
sp-io = { package = 'sp-io', default-features = false, git = 'https://github.com/joystream/substrate.git', rev = '1d0eefca86ef31b9e7727df01a6ed23ad65491e9'}
sp-std = { package = 'sp-std', default-features = false, git = 'https://github.com/joystream/substrate.git', rev = '1d0eefca86ef31b9e7727df01a6ed23ad65491e9'}
sp-runtime = { package = 'sp-runtime', default-features = false, git = 'https://github.com/joystream/substrate.git', rev = '1d0eefca86ef31b9e7727df01a6ed23ad65491e9'}
frame-support = { package = 'frame-support', default-features = false, git = 'https://github.com/joystream/substrate.git', rev = '1d0eefca86ef31b9e7727df01a6ed23ad65491e9'}
frame-system = { package = 'frame-system', default-features = false, git = 'https://github.com/joystream/substrate.git', rev = '1d0eefca86ef31b9e7727df01a6ed23ad65491e9'}
sp-arithmetic = { package = 'sp-arithmetic', default-features = false, git = 'https://github.com/joystream/substrate.git', rev = '1d0eefca86ef31b9e7727df01a6ed23ad65491e9'}
common = { package = 'pallet-common', default-features = false, path = '../common'}
storage = { package = 'pallet-storage', default-features = false, path = '../storage'}
balances = { package = 'pallet-balances', default-features = false, git = 'https://github.com/joystream/substrate.git', rev = '1d0eefca86ef31b9e7727df01a6ed23ad65491e9'}
membership = { package = 'pallet-membership', default-features = false, path = '../membership'}
codec = { package = 'parity-scale-codec', version = '3.1.2', default-features = false, features = ['derive'] }
serde = {version = '1.0.101', features = ['derive'], optional = true}
scale-info = { version = "2.1.1", default-features = false, features = ["derive"] }
sp-core = { package = 'sp-core', default-features = false, git = 'https://github.com/joystream/substrate.git', rev = '1d0eefca86ef31b9e7727df01a6ed23ad65491e9', optional = true }

# Benchmarking dependencies
frame-benchmarking = { package = 'frame-benchmarking', default-features = false, git = 'https://github.com/joystream/substrate.git', rev = '1d0eefca86ef31b9e7727df01a6ed23ad65491e9', optional = true}

[dev-dependencies]
sp-core = { package = 'sp-core', default-features = false, git = 'https://github.com/joystream/substrate.git', rev = '1d0eefca86ef31b9e7727df01a6ed23ad65491e9' }
randomness-collective-flip = { package = 'pallet-insecure-randomness-collective-flip', default-features = false, git = 'https://github.com/joystream/substrate.git', rev = '1d0eefca86ef31b9e7727df01a6ed23ad65491e9'}
staking-handler = { package = 'pallet-staking-handler', default-features = false, path = '../staking-handler'}
pallet-timestamp = { package = 'pallet-timestamp', default-features = false, git = 'https://github.com/joystream/substrate.git', rev = '1d0eefca86ef31b9e7727df01a6ed23ad65491e9'}
sp-storage = { package = 'sp-storage', default-features = false, git = 'https://github.com/joystream/substrate.git', rev = '1d0eefca86ef31b9e7727df01a6ed23ad65491e9'}

[features]
default = ['std', 'runtime-benchmarks']
runtime-benchmarks = [
"frame-benchmarking/runtime-benchmarks",
'sp-core',
"common/runtime-benchmarks",
]
std = [
'sp-std/std',
'sp-io/std',
'sp-runtime/std',
'frame-support/std',
'frame-system/std',
'sp-arithmetic/std',
'common/std',
'storage/std',
'balances/std',
'membership/std',
'codec/std',
'serde',
'scale-info/std',
'frame-benchmarking?/std',
]
try-runtime = ["frame-support/try-runtime"]
100 changes: 100 additions & 0 deletions runtime-modules/argo-bridge/src/benchmarking.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
#![cfg(feature = "runtime-benchmarks")]

use frame_support::{assert_err, assert_ok};

use super::*;
use crate::types::*;
use crate::Module as ArgoBridge;
use balances::Pallet as Balances;
use core::convert::TryFrom;
use frame_benchmarking::v1::{account, benchmarks};
use frame_system::Pallet as System;
use frame_system::{EventRecord, RawOrigin};
use sp_runtime::traits::One;
use sp_std::convert::TryInto;
use sp_std::vec;

use crate::{BridgeConstraints, BridgeStatus, RemoteAccount, RemoteTransfer};

const SEED: u32 = 0;

// We create this trait because we need to be compatible with the runtime
// in the mock for tests. In that case we need to be able to have `membership_id == account_id`
// We can't create an account from an `u32` or from a memberhsip_dd,
// so this trait allows us to get an account id from an u32, in the case of `64` which is what
// the mock use we get the parameter as a return.
// In the case of `AccountId32` we use the method provided by `frame_benchmarking` to get an
// AccountId.
pub trait CreateAccountId {
fn create_account_id(id: u32) -> Self;
}

impl CreateAccountId for u64 {
fn create_account_id(id: u32) -> Self {
id.into()
}
}

impl CreateAccountId for u32 {
fn create_account_id(id: u32) -> Self {
id.into()
}
}

impl CreateAccountId for sp_core::crypto::AccountId32 {
fn create_account_id(id: u32) -> Self {
account::<Self>("default", id, SEED)
}
}

fn assert_last_event<T: Config>(generic_event: <T as Config>::RuntimeEvent) {
let events = frame_system::Pallet::<T>::events();
let system_event: <T as frame_system::Config>::RuntimeEvent = generic_event.into();
assert!(
!events.is_empty(),
"If you are checking for last event there must be at least 1 event"
);
let EventRecord { event, .. } = &events[events.len() - 1];
assert_eq!(event, &system_event);
}

benchmarks! {
where_clause {
where
T: balances::Config,
T::AccountId: CreateAccountId
}

request_outbound_transfer{
let fee: BalanceOf<T> = 10u32.into();
let remote_chains = BoundedVec::try_from(vec![1u32]).unwrap();
let parameters = BridgeConstraints {
operator_account: Some(T::AccountId::create_account_id(1u32.into())),
pauser_accounts: Some(vec![T::AccountId::create_account_id(2u32.into())]),
bridging_fee: Some(fee),
thawn_duration: None::<T::BlockNumber>,
remote_chains: Some(remote_chains)
};
assert_ok!(ArgoBridge::<T>::update_bridge_constrains(
RawOrigin::Root.into(),
parameters
));

let dest_account = RemoteAccount {
account: [0; 32],
chain_id: 1,
};
let sender = T::AccountId::create_account_id(1u32.into());
let origin = RawOrigin::Signed(sender);
let transfer_id = ArgoBridge::<T>::next_transfer_id();
let amount = 100u32.into();
}: _(origin, dest_account, amount, fee)
verify {
let sender = T::AccountId::create_account_id(1u32.into());
assert_last_event::<T>(
RawEvent::OutboundTransferRequested(transfer_id, sender, dest_account, amount, fee).into());
}
}

#[cfg(test)]
mod tests {}
35 changes: 35 additions & 0 deletions runtime-modules/argo-bridge/src/errors.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
use crate::Module;
use frame_support::decl_error;
use sp_std::convert::TryInto;

decl_error! {
pub enum Error for Module<T: crate::Config> {

/// Bridge not on active state
BridgeNotActive,

/// Insufficient JOY Balance to cover the transaction costs
InsufficientJoyBalance,

/// The bridging_fee changed since the request transfer
FeeDifferentThanExpected,

/// Not enough mint allowance for transaction
InsufficienBridgMintAllowance,

/// Operator account required
NotOperatorAccount,

/// Pauser account required
NotPauserAccount,

/// Number of pauser accounts over the maximum allowed
InvalidNumberOfPauserAccounts,

/// Current block is lower than thawn_started_at + thawn_duration
ThawnNotFinished,

/// ChainId is not on the list of the supported chains
NotSupportedRemoteChainId
}
}
26 changes: 26 additions & 0 deletions runtime-modules/argo-bridge/src/events.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#![allow(clippy::unused_unit)]

use frame_support::decl_event;

use crate::{RemoteAccount, RemoteTransfer, TransferId};

use crate::types::*;

// Balance type alias
type BalanceOf<T> = <T as balances::Config>::Balance;

decl_event!(
pub enum Event<T>
where
AccountId = <T as frame_system::Config>::AccountId,
Balance = BalanceOf<T>,
BridgeConstraints = BridgeConstraintsOf<T>,
{
OutboundTransferRequested(TransferId, AccountId, RemoteAccount, Balance, Balance),
InboundTransferFinalized(RemoteTransfer, AccountId, Balance),
BridgePaused(AccountId),
BridgeThawnStarted(AccountId),
BridgeThawnFinished(),
BridgeConfigUpdated(BridgeConstraints),
}
);
Loading

0 comments on commit 37f3d91

Please sign in to comment.