Skip to content

Commit

Permalink
proxy deployer test & updates
Browse files Browse the repository at this point in the history
  • Loading branch information
psorinionut committed Nov 13, 2023
1 parent 5967c88 commit 0a9e5ea
Show file tree
Hide file tree
Showing 7 changed files with 238 additions and 11 deletions.
5 changes: 5 additions & 0 deletions contracts/adder/src/adder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@ pub trait Adder {
self.sum().set(initial_value);
}

#[endpoint]
fn upgrade(&self, new_value: BigUint) {
self.sum().set(new_value);
}

/// Add desired amount to the storage variable.
#[payable("*")]
#[endpoint]
Expand Down
5 changes: 3 additions & 2 deletions contracts/adder/wasm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
////////////////////////////////////////////////////

// Init: 1
// Endpoints: 2
// Endpoints: 3
// Async Callback (empty): 1
// Total number of exported functions: 4
// Total number of exported functions: 5

#![no_std]

Expand All @@ -23,6 +23,7 @@ multiversx_sc_wasm_adapter::endpoints! {
(
init => init
getSum => sum
upgrade => upgrade
add => add
)
}
Expand Down
3 changes: 3 additions & 0 deletions contracts/proxy-deployer/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,6 @@ features = ["esdt-token-payment-legacy-decode"]

[dev-dependencies.multiversx-sc-scenario]
version = "=0.43.4"

[dev-dependencies.adder]
path = "../adder"
20 changes: 14 additions & 6 deletions contracts/proxy-deployer/src/contract_interactions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ use crate::config;

#[multiversx_sc::module]
pub trait ContractInteractionsModule: config::ConfigModule {
#[endpoint(deployContract)]
fn deploy_contract(
#[endpoint(contractDeploy)]
fn contract_deploy(
&self,
template_address_id: AddressId,
args: MultiValueEncoded<ManagedBuffer>,
Expand Down Expand Up @@ -39,15 +39,19 @@ pub trait ContractInteractionsModule: config::ConfigModule {
new_contract_address
}

#[endpoint(upgradeContract)]
fn upgrade_contract(
#[endpoint(contractUpgrade)]
fn contract_upgrade(
&self,
contract_address: ManagedAddress,
template_address_id: AddressId,
args: MultiValueEncoded<ManagedBuffer>,
) {
let caller = self.blockchain().get_caller();
require!(self.deployer_contract_addresses(&caller).contains(&contract_address), "Caller is not the deployer of the contract");
require!(
self.deployer_contract_addresses(&caller)
.contains(&contract_address),
"Caller is not the deployer of the contract"
);

let mut arguments = ManagedArgBuffer::new();
for arg in args {
Expand Down Expand Up @@ -78,7 +82,11 @@ pub trait ContractInteractionsModule: config::ConfigModule {
args: MultiValueEncoded<ManagedBuffer>,
) {
let caller = self.blockchain().get_caller();
require!(self.deployer_contract_addresses(&caller).contains(&contract_address), "Caller is not the deployer of the contract");
require!(
self.deployer_contract_addresses(&caller)
.contains(&contract_address),
"Caller is not the deployer of the contract"
);

let gas_left = self.blockchain().get_gas_left();
let mut contract_call = self
Expand Down
4 changes: 3 additions & 1 deletion contracts/proxy-deployer/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ pub mod config;
pub mod contract_interactions;

#[multiversx_sc::contract]
pub trait ProxyDeployer: contract_interactions::ContractInteractionsModule + config::ConfigModule {
pub trait ProxyDeployer:
contract_interactions::ContractInteractionsModule + config::ConfigModule
{
#[init]
fn init(&self) {}

Expand Down
208 changes: 208 additions & 0 deletions contracts/proxy-deployer/tests/proxy_deployer_blackbox_test.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,208 @@
use multiversx_sc::{
codec::top_encode_to_vec_u8_or_panic,
storage::mappers::SingleValue,
types::{Address, ManagedAddress, ManagedBuffer, MultiValueEncoded},
};
use multiversx_sc_scenario::{api::StaticApi, num_bigint::BigUint, scenario_model::*, *};

use adder::ProxyTrait as _;
use proxy_deployer::{
config::ProxyTrait as _, contract_interactions::ProxyTrait as _, ProxyTrait as _,
};

const PROXY_DEPLOYER_ADDRESS_EXPR: &str = "sc:proxy_deployer";
const TEMPLATE_CONTRACT_ADDRESS_EXPR: &str = "sc:template_contract";
const DEPLOYED_CONTRACT_ADDRESS_EXPR: &str = "sc:deployed_contract";
const OWNER_ADDRESS_EXPR: &str = "address:owner";

const PROXY_DEPLOYER_PATH_EXPR: &str = "file:output/proxy-deployer.wasm";
const DEPLOYED_CONTRACT_PATH_EXPR: &str = "file:~/contracts/adder/output/adder.wasm";

type ProxyDeployerContract = ContractInfo<proxy_deployer::Proxy<StaticApi>>;
type TemplateContract = ContractInfo<adder::Proxy<StaticApi>>;

fn world() -> ScenarioWorld {
let mut blockchain = ScenarioWorld::new();
blockchain.set_current_dir_from_workspace("contracts/proxy-deployer");

blockchain.register_contract(PROXY_DEPLOYER_PATH_EXPR, proxy_deployer::ContractBuilder);
blockchain.register_contract(DEPLOYED_CONTRACT_PATH_EXPR, adder::ContractBuilder);

blockchain
}

struct ProxyDeployerTestState {
world: ScenarioWorld,
proxy_deployer_contract: ProxyDeployerContract,
template_contract: TemplateContract,
template_contracts_ids: Vec<u64>,
deployed_contracts: Vec<Address>,
}

impl ProxyDeployerTestState {
fn new() -> Self {
let mut world = world();
world.start_trace().set_state_step(
SetStateStep::new().put_account(OWNER_ADDRESS_EXPR, Account::new().nonce(1)),
);
let proxy_deployer_contract = ProxyDeployerContract::new(PROXY_DEPLOYER_ADDRESS_EXPR);
let template_contract = TemplateContract::new(TEMPLATE_CONTRACT_ADDRESS_EXPR);

Self {
world,
proxy_deployer_contract,
template_contract,
template_contracts_ids: vec![],
deployed_contracts: vec![],
}
}

fn deploy_proxy_deployer_contract(&mut self) -> &mut Self {
let proxy_deployer_code = self.world.code_expression(PROXY_DEPLOYER_PATH_EXPR);
let template_contract_code = self.world.code_expression(DEPLOYED_CONTRACT_PATH_EXPR);

self.world
.set_state_step(SetStateStep::new().new_address(
OWNER_ADDRESS_EXPR,
1,
PROXY_DEPLOYER_ADDRESS_EXPR,
))
.sc_deploy(
ScDeployStep::new()
.from(OWNER_ADDRESS_EXPR)
.code(proxy_deployer_code)
.call(self.proxy_deployer_contract.init()),
)
.set_state_step(SetStateStep::new().new_address(
OWNER_ADDRESS_EXPR,
2,
TEMPLATE_CONTRACT_ADDRESS_EXPR,
))
.sc_deploy(
ScDeployStep::new()
.from(OWNER_ADDRESS_EXPR)
.code(template_contract_code)
.call(self.template_contract.init(BigUint::from(0u64))),
)
.sc_call_use_result(
ScCallStep::new().from(OWNER_ADDRESS_EXPR).call(
self.proxy_deployer_contract.add_contract_template(
ManagedAddress::from_address(&self.template_contract.to_address()),
),
),
|r: TypedResponse<u64>| {
self.template_contracts_ids.push(r.result.unwrap());
},
);

self
}

fn deploy_contract(
&mut self,
template_address_id: u64,
args: MultiValueEncoded<StaticApi, ManagedBuffer<StaticApi>>,
) -> &mut Self {
self.world
.set_state_step(SetStateStep::new().new_address(
PROXY_DEPLOYER_ADDRESS_EXPR,
0,
DEPLOYED_CONTRACT_ADDRESS_EXPR,
))
.sc_call_use_result(
ScCallStep::new()
.from(OWNER_ADDRESS_EXPR)
.to(PROXY_DEPLOYER_ADDRESS_EXPR)
.call(
self.proxy_deployer_contract
.contract_deploy(template_address_id, args),
),
|r: TypedResponse<ManagedAddress<StaticApi>>| {
self.deployed_contracts.push(r.result.unwrap().to_address());
},
);

self
}

fn upgrade_contract(
&mut self,
contract_address: &Address,
template_address_id: u64,
args: MultiValueEncoded<StaticApi, ManagedBuffer<StaticApi>>,
) -> &mut Self {
self.world.sc_call(
ScCallStep::new()
.from(OWNER_ADDRESS_EXPR)
.to(PROXY_DEPLOYER_ADDRESS_EXPR)
.call(self.proxy_deployer_contract.contract_upgrade(
ManagedAddress::from_address(contract_address),
template_address_id,
args,
)),
);

self
}

fn call_endpoint(
&mut self,
contract_address: &Address,
function_name: &str,
args: MultiValueEncoded<StaticApi, ManagedBuffer<StaticApi>>,
) -> &mut Self {
let function = ManagedBuffer::from(function_name);
self.world.sc_call(
ScCallStep::new()
.from(OWNER_ADDRESS_EXPR)
.to(PROXY_DEPLOYER_ADDRESS_EXPR)
.call(self.proxy_deployer_contract.call_contract_endpoint(
ManagedAddress::from_address(contract_address),
function,
args,
)),
);

self
}

fn check_contract_storage(&mut self, expected_value: u64) {
let mut deployed_contract = TemplateContract::new(DEPLOYED_CONTRACT_ADDRESS_EXPR);

self.world.sc_query(
ScQueryStep::new()
.call(deployed_contract.sum())
.expect_value(SingleValue::from(BigUint::from(expected_value))),
);
}
}

#[test]
fn proxy_deployer_blackbox_test() {
let mut state = ProxyDeployerTestState::new();
state.deploy_proxy_deployer_contract();

// Test contract deploy
let mut deploy_args = MultiValueEncoded::new();
deploy_args.push(ManagedBuffer::from(top_encode_to_vec_u8_or_panic(&1u64)));
state.deploy_contract(state.template_contracts_ids[0], deploy_args);
state.check_contract_storage(1u64);
let contract_address = state.deployed_contracts[0].to_owned();

// Test endpoint call
let mut call_args = MultiValueEncoded::new();
call_args.push(ManagedBuffer::from(top_encode_to_vec_u8_or_panic(&9u64)));
state.call_endpoint(&contract_address, "add", call_args);
state.check_contract_storage(10u64);

// Test contract upgrade
state.world.dump_state_step();
let mut upgrade_args = MultiValueEncoded::new();
upgrade_args.push(ManagedBuffer::from(top_encode_to_vec_u8_or_panic(&5u64)));
state.upgrade_contract(
&contract_address,
state.template_contracts_ids[0],
upgrade_args,
);
state.check_contract_storage(5u64);
}
4 changes: 2 additions & 2 deletions contracts/proxy-deployer/wasm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ multiversx_sc_wasm_adapter::endpoints! {
(
init => init
upgrade => upgrade
deployContract => deploy_contract
upgradeContract => upgrade_contract
contractDeploy => contract_deploy
contractUpgrade => contract_upgrade
callContractEndpoint => call_contract_endpoint
addContractTemplate => add_contract_template
removeContractTemplate => remove_contract_template
Expand Down

0 comments on commit 0a9e5ea

Please sign in to comment.