use super::*;
use crate::trade_account_registry::{
TradeAccountRegistryConfigurables,
TradeAccountRegistryDeployConfig,
TradeAccountRegistryManager,
};
fn resume(fixture: &PropFixture) -> PropDeployConfig {
let mut config = PropDeployConfig::new(fixture.collateral_asset);
config.existing_registry = Some(ExistingRegistry {
registry_id: fixture.deployment.registry_id,
trade_account_oracle_id: ContractId::zeroed(),
trial_trade_account_oracle_id: ContractId::zeroed(),
});
config.max_offchain_age_seconds = Some(TEST_MAX_OFFCHAIN_AGE_SECONDS);
config
}
#[tokio::test]
async fn a_pinned_oracle_preserves_owner_cosigner_pool_and_funded_session() {
let fixture = PropFixture::new().await;
let original_session = fixture.session().await;
let oracle = &fixture.deployment.oracle;
oracle
.methods()
.set_cosigner(fixture.outsider.address())
.call()
.await
.unwrap();
oracle
.methods()
.transfer_ownership(Identity::Address(fixture.outsider.address()))
.call()
.await
.unwrap();
let mut config = resume(&fixture);
config.salt = Salt::new([0x5a; 32]);
config.existing_registry = None;
config.existing_pool = Some(fixture.deployment.pool_id);
config.existing_price_feed = Some(fixture.deployment.price_feed_id);
let wrong = PropDeployment::deploy(&fixture.deployer, &config)
.await
.unwrap();
assert_ne!(wrong.oracle_id, fixture.deployment.oracle_id);
let manager = TradeAccountRegistryManager::new(
fixture.deployer.clone(),
fixture.deployment.registry_id,
);
let wrong_wiring = manager
.live_prop_config(TradeAccountRegistryConfigurables::default())
.await
.unwrap()
.with_PROP_ACCOUNT_ORACLE_CONTRACT_ID(wrong.oracle_id)
.unwrap();
manager
.upgrade(
ContractId::zeroed(),
ContractId::zeroed(),
&TradeAccountRegistryDeployConfig {
registry_config: wrong_wiring,
..Default::default()
},
)
.await
.unwrap();
config = resume(&fixture);
config.salt = Salt::new([0x6b; 32]);
config.existing_oracle = Some(fixture.deployment.oracle_id);
let repaired = PropDeployment::deploy(&fixture.deployer, &config)
.await
.unwrap();
assert_eq!(repaired.oracle_id, fixture.deployment.oracle_id);
assert_eq!(repaired.pool_id, fixture.deployment.pool_id);
assert_eq!(repaired.price_feed_id, fixture.deployment.price_feed_id);
assert_eq!(
oracle
.methods()
.owner()
.simulate(Execution::state_read_only())
.await
.unwrap()
.value,
State::Initialized(Identity::Address(fixture.outsider.address()))
);
assert_eq!(
oracle
.methods()
.get_cosigner()
.simulate(Execution::state_read_only())
.await
.unwrap()
.value,
Some(fixture.outsider.address())
);
assert_eq!(
repaired
.registry
.methods()
.get_prop_oracle_id()
.simulate(Execution::state_read_only())
.await
.unwrap()
.value,
repaired.oracle_id
);
assert_eq!(fixture.session().await, original_session);
fixture.close_session().await;
let provider = fixture.deployer.try_provider().unwrap();
let before = provider.latest_block_height().await.unwrap();
config.existing_oracle = None;
let again = PropDeployment::deploy(&fixture.deployer, &config)
.await
.unwrap();
assert_eq!(again.oracle_id, repaired.oracle_id);
assert_eq!(provider.latest_block_height().await.unwrap(), before);
}
#[tokio::test]
async fn bad_oracle_bindings_fail_before_deployment_transactions() {
let fixture = PropFixture::new().await;
let provider = fixture.deployer.try_provider().unwrap();
let mut config = resume(&fixture);
config.salt = Salt::new([0x6c; 32]);
for oracle in [
ContractId::zeroed(),
ContractId::new([0xf1; 32]),
fixture.deployment.pool_id,
] {
config.existing_oracle = Some(oracle);
let before = provider.latest_block_height().await.unwrap();
assert!(
PropDeployment::deploy(&fixture.deployer, &config)
.await
.is_err()
);
assert_eq!(provider.latest_block_height().await.unwrap(), before);
}
config.existing_oracle = Some(fixture.deployment.oracle_id);
config.existing_pool = Some(ContractId::new([0xf2; 32]));
let before = provider.latest_block_height().await.unwrap();
let error = PropDeployment::deploy(&fixture.deployer, &config)
.await
.err()
.unwrap();
assert!(
error.to_string().contains("pool cannot be changed"),
"{error:#}"
);
assert_eq!(provider.latest_block_height().await.unwrap(), before);
let mut derived = PropDeployConfig::new(fixture.collateral_asset);
derived.existing_pool = config.existing_pool;
let error = PropDeployment::deploy(&fixture.deployer, &derived)
.await
.err()
.unwrap();
assert!(
error.to_string().contains("pool cannot be changed"),
"{error:#}"
);
assert_eq!(provider.latest_block_height().await.unwrap(), before);
config.existing_oracle = None;
config.existing_registry.as_mut().unwrap().registry_id = ContractId::new([0xf3; 32]);
assert!(
PropDeployment::deploy(&fixture.deployer, &config)
.await
.is_err()
);
assert_eq!(provider.latest_block_height().await.unwrap(), before);
}
#[tokio::test]
async fn pinned_oracle_resumes_after_create_or_proxy_initialization() {
let fixture = PropFixture::new().await;
for initialized_proxy in [false, true] {
let mut config = resume(&fixture);
config.salt = Salt::new([if initialized_proxy { 0x72 } else { 0x71 }; 32]);
config.existing_pool = Some(fixture.deployment.pool_id);
config.existing_price_feed = Some(fixture.deployment.price_feed_id);
config.cosigner = Some(fixture.outsider.address());
let bootstrap = upload_implementation(
&fixture.deployer,
PROP_ACCOUNT_ORACLE_BYTECODE,
PROP_ACCOUNT_ORACLE_STORAGE,
Configurables::default(),
&config,
)
.await
.unwrap();
let contract = regular_contract_with_implementation_storage(
PROP_ACCOUNT_ORACLE_PROXY_BYTECODE,
PROP_ACCOUNT_ORACLE_PROXY_STORAGE,
PROP_ACCOUNT_ORACLE_STORAGE,
config.salt,
)
.unwrap()
.with_configurables(
PropAccountOracleProxyContractConfigurables::default()
.with_INITIAL_OWNER(State::Initialized(Identity::Address(
fixture.deployer.address(),
)))
.unwrap()
.with_INITIAL_TARGET(bootstrap.into())
.unwrap(),
);
let (oracle_id, _) = deploy_regular(&fixture.deployer, contract).await.unwrap();
if initialized_proxy {
PropAccountOracleProxyContract::new(oracle_id, fixture.deployer.clone())
.methods()
.initialize_proxy()
.call()
.await
.unwrap();
}
config.existing_oracle = Some(oracle_id);
let deployed = PropDeployment::deploy(&fixture.deployer, &config)
.await
.unwrap();
assert_eq!(deployed.oracle_id, oracle_id);
assert_eq!(
deployed
.oracle
.methods()
.get_cosigner()
.simulate(Execution::state_read_only())
.await
.unwrap()
.value,
Some(fixture.outsider.address())
);
assert_eq!(
deployed
.oracle
.methods()
.get_prop_margin_pool()
.simulate(Execution::state_read_only())
.await
.unwrap()
.value,
Some(fixture.deployment.pool_id)
);
}
}