use core::fmt::Debug;
use soroban_sdk::{contractclient, Address, Env};
use crate as stellar_axelar_std;
use crate::events::Event;
use crate::interfaces::storage;
use crate::IntoEvent;
#[contractclient(name = "OwnableClient")]
pub trait OwnableInterface {
fn owner(env: &Env) -> Address;
fn transfer_ownership(env: &Env, new_owner: Address);
}
pub fn owner(env: &Env) -> Address {
storage::owner::interfaces_owner(env)
}
pub fn transfer_ownership<T: OwnableInterface>(env: &Env, new_owner: Address) {
let current_owner = T::owner(env);
current_owner.require_auth();
set_owner(env, &new_owner);
OwnershipTransferredEvent {
previous_owner: current_owner,
new_owner,
}
.emit(env);
}
pub fn set_owner(env: &Env, owner: &Address) {
storage::owner::set_interfaces_owner(env, owner);
}
#[derive(Clone, Debug, PartialEq, Eq, IntoEvent)]
pub struct OwnershipTransferredEvent {
pub previous_owner: Address,
pub new_owner: Address,
}
#[cfg(test)]
mod test {
use stellar_axelar_std::testutils::Address as _;
use stellar_axelar_std::{Address, Env};
use crate as stellar_axelar_std;
use crate::interfaces::testdata::Contract;
use crate::interfaces::{OwnableClient, OwnershipTransferredEvent};
use crate::{assert_auth, assert_auth_err, events};
fn prepare_client(env: &Env, owner: Option<Address>) -> OwnableClient<'_> {
let operator = Address::generate(env);
let contract_id = env.register(Contract, (owner, operator));
OwnableClient::new(env, &contract_id)
}
#[test]
fn owner_fails_if_owner_not_set() {
let env = Env::default();
let client = prepare_client(&env, None);
assert!(client.try_owner().is_err());
}
#[test]
fn owner_returns_correct_owner_when_set() {
let env = Env::default();
let owner = Address::generate(&env);
let client = prepare_client(&env, Some(owner.clone()));
assert_eq!(client.owner(), owner);
}
#[test]
fn transfer_ownership_fails_if_caller_is_not_owner() {
let env = Env::default();
let owner = Address::generate(&env);
let client = prepare_client(&env, Some(owner));
let new_owner = Address::generate(&env);
assert_auth_err!(new_owner, client.transfer_ownership(&new_owner));
}
#[test]
fn transfer_ownership_succeeds_if_caller_is_owner() {
let env = Env::default();
let owner = Address::generate(&env);
let client = prepare_client(&env, Some(owner.clone()));
assert_eq!(client.owner(), owner);
let new_owner = Address::generate(&env);
assert_auth!(owner, client.transfer_ownership(&new_owner));
goldie::assert!(events::fmt_last_emitted_event::<OwnershipTransferredEvent>(
&env
));
assert_eq!(client.owner(), new_owner);
}
}