Skip to content

Commit

Permalink
Merge pull request #203 from multiversx/phase-three
Browse files Browse the repository at this point in the history
Sovereign-Forge Phase Three
  • Loading branch information
andreiblt1304 authored Dec 10, 2024
2 parents ab26a6f + 7e7ac8f commit fa66115
Show file tree
Hide file tree
Showing 14 changed files with 380 additions and 19 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

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

19 changes: 16 additions & 3 deletions chain-factory/src/factory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,18 +89,31 @@ pub trait FactoryModule: only_admin::OnlyAdminModule {

#[only_admin]
#[endpoint(deployEsdtSafe)]
fn deploy_esdt_safe(&self, is_sovereign_chain: bool) -> ManagedAddress {
fn deploy_esdt_safe(
&self,
is_sovereign_chain: bool,
header_verifier_address: ManagedAddress,
) -> ManagedAddress {
let source_address = self.enshrine_esdt_safe_template().get();
let metadata = self.blockchain().get_code_metadata(&source_address);

self.tx()
let esdt_safe_address = self
.tx()
.typed(EsdtSafeProxy)
.init(is_sovereign_chain)
.gas(60_000_000)
.from_source(source_address)
.code_metadata(metadata)
.returns(ReturnsNewManagedAddress)
.sync_call()
.sync_call();

self.tx()
.to(header_verifier_address)
.typed(HeaderverifierProxy)
.set_esdt_safe_address(&esdt_safe_address)
.sync_call();

esdt_safe_address
}

#[only_admin]
Expand Down
3 changes: 3 additions & 0 deletions common/proxies/src/chain_factory_proxy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -156,14 +156,17 @@ where

pub fn deploy_esdt_safe<
Arg0: ProxyArg<bool>,
Arg1: ProxyArg<ManagedAddress<Env::Api>>,
>(
self,
is_sovereign_chain: Arg0,
header_verifier_address: Arg1,
) -> TxTypedCall<Env, From, To, NotPayable, Gas, ManagedAddress<Env::Api>> {
self.wrapped_tx
.payment(NotPayable)
.raw_call("deployEsdtSafe")
.argument(&is_sovereign_chain)
.argument(&header_verifier_address)
.original_result()
}

Expand Down
13 changes: 13 additions & 0 deletions common/proxies/src/sovereign_forge_proxy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,19 @@ where
.original_result()
}

pub fn deploy_phase_three<
Arg0: ProxyArg<bool>,
>(
self,
is_sovereign_chain: Arg0,
) -> TxTypedCall<Env, From, To, NotPayable, Gas, ()> {
self.wrapped_tx
.payment(NotPayable)
.raw_call("deployPhaseThree")
.argument(&is_sovereign_chain)
.original_result()
}

pub fn chain_factories<
Arg0: ProxyArg<u32>,
>(
Expand Down
3 changes: 3 additions & 0 deletions sovereign-forge/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ path = "../chain-config"
[dependencies.header-verifier]
path = "../header-verifier"

[dependencies.esdt-safe]
path = "../esdt-safe"

[dependencies.proxies]
path = "../common/proxies"

Expand Down
8 changes: 6 additions & 2 deletions sovereign-forge/src/common/sc_deploy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,15 @@ pub trait ScDeployModule: super::utils::UtilsModule + super::storage::StorageMod
}

#[inline]
fn deploy_esdt_safe(&self, is_sovereign_chain: bool) -> ManagedAddress {
fn deploy_esdt_safe(
&self,
is_sovereign_chain: bool,
header_verifier_address: &ManagedAddress,
) -> ManagedAddress {
self.tx()
.to(self.get_chain_factory_address())
.typed(ChainFactoryContractProxy)
.deploy_esdt_safe(is_sovereign_chain)
.deploy_esdt_safe(is_sovereign_chain, header_verifier_address)
.returns(ReturnsResult)
.sync_call()
}
Expand Down
17 changes: 17 additions & 0 deletions sovereign-forge/src/common/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,13 @@ pub enum ScArray {

#[multiversx_sc::module]
pub trait UtilsModule: super::storage::StorageModule {
fn require_phase_two_completed(&self, caller: &ManagedAddress) {
require!(
self.is_contract_deployed(caller, ScArray::HeaderVerifier),
"The Header-Verifier SC is not deployed, you skipped the second phase"
);
}

fn require_phase_1_completed(&self, caller: &ManagedAddress) {
require!(
!self.sovereigns_mapper(caller).is_empty(),
Expand All @@ -63,6 +70,16 @@ pub trait UtilsModule: super::storage::StorageModule {
.any(|sc| sc.id == sc_id)
}

fn get_contract_address(&self, caller: &ManagedAddress, sc_id: ScArray) -> ManagedAddress {
let chain_id = self.sovereigns_mapper(caller).get();

self.sovereign_deployed_contracts(&chain_id)
.iter()
.find(|sc| sc.id == sc_id)
.unwrap()
.address
}

fn generate_chain_id(&self) -> ManagedBuffer {
loop {
let new_chain_id = self.generated_random_4_char_string();
Expand Down
25 changes: 25 additions & 0 deletions sovereign-forge/src/phases.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,10 @@ pub trait PhasesModule:
let caller = blockchain_api.get_caller();

self.require_phase_1_completed(&caller);
require!(
!self.is_contract_deployed(&caller, ScArray::HeaderVerifier),
"The Header-Verifier contract is already deployed"
);

let header_verifier_address = self.deploy_header_verifier(bls_keys);

Expand All @@ -102,4 +106,25 @@ pub trait PhasesModule:
self.sovereign_deployed_contracts(&self.sovereigns_mapper(&caller).get())
.insert(header_verifier_contract_info);
}

#[endpoint(deployPhaseThree)]
fn deploy_phase_three(&self, is_sovereign_chain: bool) {
let caller = self.blockchain().get_caller();

self.require_phase_two_completed(&caller);
require!(
!self.is_contract_deployed(&caller, ScArray::ESDTSafe),
"The ESDT-Safe SC is already deployed"
);

let header_verifier_address = self.get_contract_address(&caller, ScArray::HeaderVerifier);

let esdt_safe_address = self.deploy_esdt_safe(is_sovereign_chain, &header_verifier_address);

let esdt_safe_contract_info =
ContractInfo::new(ScArray::ESDTSafe, esdt_safe_address.clone());

self.sovereign_deployed_contracts(&self.sovereigns_mapper(&caller).get())
.insert(esdt_safe_contract_info);
}
}
168 changes: 158 additions & 10 deletions sovereign-forge/tests/sovereign_forge_unit_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ use multiversx_sc_scenario::{
};
use proxies::{
chain_config_proxy::ChainConfigContractProxy, chain_factory_proxy::ChainFactoryContractProxy,
header_verifier_proxy::HeaderverifierProxy, sovereign_forge_proxy::SovereignForgeProxy,
esdt_safe_proxy::EsdtSafeProxy, header_verifier_proxy::HeaderverifierProxy,
sovereign_forge_proxy::SovereignForgeProxy,
};
use setup_phase::SetupPhaseModule;
use sovereign_forge::common::{
Expand All @@ -29,6 +30,9 @@ const HEADER_VERIFIER_ADDRESS: TestSCAddress = TestSCAddress::new("header-verifi
const HEADER_VERIFIER_CODE_PATH: MxscPath =
MxscPath::new("../header-verifier/output/header-verifier.mxsc.json");

const ESDT_SAFE_ADDRESS: TestSCAddress = TestSCAddress::new("esdt-safe");
const ESDT_SAFE_CODE_PATH: MxscPath = MxscPath::new("../esdt-safe/output/esdt-safe.mxsc.json");

const TOKEN_HANDLER_ADDRESS: TestSCAddress = TestSCAddress::new("token-handler");

const BALANCE: u128 = 100_000_000_000_000_000;
Expand All @@ -41,6 +45,7 @@ fn world() -> ScenarioWorld {
blockchain.register_contract(FACTORY_CODE_PATH, chain_factory::ContractBuilder);
blockchain.register_contract(CONFIG_CODE_PATH, chain_config::ContractBuilder);
blockchain.register_contract(HEADER_VERIFIER_CODE_PATH, header_verifier::ContractBuilder);
blockchain.register_contract(ESDT_SAFE_CODE_PATH, esdt_safe::ContractBuilder);

blockchain
}
Expand Down Expand Up @@ -70,7 +75,7 @@ impl SovereignForgeTestState {
FORGE_ADDRESS,
CONFIG_ADDRESS,
HEADER_VERIFIER_ADDRESS,
FACTORY_ADDRESS,
ESDT_SAFE_ADDRESS,
FACTORY_ADDRESS,
)
.code(FACTORY_CODE_PATH)
Expand Down Expand Up @@ -129,6 +134,21 @@ impl SovereignForgeTestState {
self
}

fn deploy_esdt_safe_template(&mut self) -> &mut Self {
let is_sovereign_chain = false;

self.world
.tx()
.from(OWNER_ADDRESS)
.typed(EsdtSafeProxy)
.init(is_sovereign_chain)
.code(ESDT_SAFE_CODE_PATH)
.new_address(ESDT_SAFE_ADDRESS)
.run();

self
}

fn register_token_handler(
&mut self,
shard_id: u32,
Expand Down Expand Up @@ -187,6 +207,16 @@ impl SovereignForgeTestState {
}
}

fn finish_setup(&mut self) {
self.register_chain_factory(1, FACTORY_ADDRESS, None);
self.register_chain_factory(2, FACTORY_ADDRESS, None);
self.register_chain_factory(3, FACTORY_ADDRESS, None);
self.register_token_handler(1, TOKEN_HANDLER_ADDRESS, None);
self.register_token_handler(2, TOKEN_HANDLER_ADDRESS, None);
self.register_token_handler(3, TOKEN_HANDLER_ADDRESS, None);
self.complete_setup_phase(None);
}

fn deploy_phase_one(
&mut self,
payment: &BigUint<StaticApi>,
Expand Down Expand Up @@ -237,14 +267,20 @@ impl SovereignForgeTestState {
}
}

fn finish_setup(&mut self) {
self.register_chain_factory(1, FACTORY_ADDRESS, None);
self.register_chain_factory(2, FACTORY_ADDRESS, None);
self.register_chain_factory(3, FACTORY_ADDRESS, None);
self.register_token_handler(1, TOKEN_HANDLER_ADDRESS, None);
self.register_token_handler(2, TOKEN_HANDLER_ADDRESS, None);
self.register_token_handler(3, TOKEN_HANDLER_ADDRESS, None);
self.complete_setup_phase(None);
fn deploy_phase_three(&mut self, is_sovereign_chain: bool, expect_error: Option<ExpectError>) {
let transaction = self
.world
.tx()
.from(OWNER_ADDRESS)
.to(FORGE_ADDRESS)
.typed(SovereignForgeProxy)
.deploy_phase_three(is_sovereign_chain);

if let Some(error) = expect_error {
transaction.returns(error).run();
} else {
transaction.run();
}
}
}

Expand Down Expand Up @@ -499,3 +535,115 @@ fn deploy_phase_two_header_already_deployed() {
&bls_keys,
);
}

#[test]
fn deploy_phase_three() {
let mut state = SovereignForgeTestState::new();
state.deploy_sovereign_forge();
state.deploy_chain_factory();
state.deploy_chain_config_template();
state.finish_setup();

let deploy_cost = BigUint::from(100_000u32);

state.deploy_phase_one(
&deploy_cost,
1,
2,
BigUint::from(2u32),
MultiValueEncoded::new(),
None,
);

state.deploy_header_verifier_template();
state.deploy_esdt_safe_template();

let mut bls_keys = MultiValueEncoded::new();
bls_keys.push(ManagedBuffer::from("bls1"));
bls_keys.push(ManagedBuffer::from("bls2"));

state.deploy_phase_two(None, &bls_keys);
state.deploy_phase_three(false, None);
}

#[test]
fn deploy_phase_three_without_phase_one() {
let mut state = SovereignForgeTestState::new();
state.deploy_sovereign_forge();
state.deploy_chain_factory();
state.deploy_chain_config_template();
state.finish_setup();

state.deploy_phase_three(
false,
Some(ExpectError(
4,
"The Header-Verifier SC is not deployed, you skipped the second phase",
)),
);
}

#[test]
fn deploy_phase_three_without_phase_two() {
let mut state = SovereignForgeTestState::new();
state.deploy_sovereign_forge();
state.deploy_chain_factory();
state.deploy_chain_config_template();
state.finish_setup();

let deploy_cost = BigUint::from(100_000u32);

state.deploy_phase_one(
&deploy_cost,
1,
2,
BigUint::from(2u32),
MultiValueEncoded::new(),
None,
);

state.deploy_header_verifier_template();
state.deploy_esdt_safe_template();

state.deploy_phase_three(
false,
Some(ExpectError(
4,
"The Header-Verifier SC is not deployed, you skipped the second phase",
)),
);
}

#[test]
fn deploy_phase_three_already_deployed() {
let mut state = SovereignForgeTestState::new();
state.deploy_sovereign_forge();
state.deploy_chain_factory();
state.deploy_chain_config_template();
state.finish_setup();

let deploy_cost = BigUint::from(100_000u32);

state.deploy_phase_one(
&deploy_cost,
1,
2,
BigUint::from(2u32),
MultiValueEncoded::new(),
None,
);

state.deploy_header_verifier_template();
state.deploy_esdt_safe_template();

let mut bls_keys = MultiValueEncoded::new();
bls_keys.push(ManagedBuffer::from("bls1"));
bls_keys.push(ManagedBuffer::from("bls2"));

state.deploy_phase_two(None, &bls_keys);
state.deploy_phase_three(false, None);
state.deploy_phase_three(
false,
Some(ExpectError(4, "The ESDT-Safe SC is already deployed")),
);
}
Loading

0 comments on commit fa66115

Please sign in to comment.