diff --git a/dao/src/bid_escrow/contract.rs b/dao/src/bid_escrow/contract.rs
index 6f323e97..969b8dd7 100644
--- a/dao/src/bid_escrow/contract.rs
+++ b/dao/src/bid_escrow/contract.rs
@@ -408,6 +408,14 @@ impl BidEscrowContract {
to self.access_control {
/// Changes the ownership of the contract. Transfers ownership to the `owner`.
/// Only the current owner is permitted to call this method.
+ /// [`Read more`](AccessControl::propose_new_owner())
+ pub fn propose_new_owner(&mut self, owner: Address);
+
+ /// Accepts the new owner proposition. This can be called only by the proposed owner.
+ /// [`Read more`](AccessControl::accept_new_owner())
+ pub fn accept_new_owner(&mut self);
+
+ /// Changes the ownership of the contract to the new address.
/// [`Read more`](AccessControl::change_ownership())
pub fn change_ownership(&mut self, owner: Address);
diff --git a/dao/src/core_contracts/dao_nft.rs b/dao/src/core_contracts/dao_nft.rs
index f40210db..1e07f4ac 100644
--- a/dao/src/core_contracts/dao_nft.rs
+++ b/dao/src/core_contracts/dao_nft.rs
@@ -35,6 +35,12 @@ impl DaoNft {
to self.access_control {
/// Changes the ownership of the contract. Transfers ownership to the `owner`.
/// Only the current owner is permitted to call this method.
+ /// [`Read more`](AccessControl::propose_new_owner())
+ pub fn propose_new_owner(&mut self, owner: Address);
+ /// Accepts the new owner proposition. This can be called only by the proposed owner.
+ /// [`Read more`](AccessControl::accept_new_owner())
+ pub fn accept_new_owner(&mut self);
+ /// Changes the ownership of the contract to the new address.
/// [`Read more`](AccessControl::change_ownership())
pub fn change_ownership(&mut self, owner: Address);
/// Adds a new address to the whitelist.
diff --git a/dao/src/core_contracts/kyc_ntf.rs b/dao/src/core_contracts/kyc_ntf.rs
index a5392dad..8dfbec4a 100644
--- a/dao/src/core_contracts/kyc_ntf.rs
+++ b/dao/src/core_contracts/kyc_ntf.rs
@@ -37,6 +37,15 @@ impl KycNftContract {
delegate! {
to self.token {
+ /// Changes the ownership of the contract. Transfers ownership to the `owner`.
+ /// Only the current owner is permitted to call this method.
+ /// [`Read more`](crate::modules::access_control::AccessControl::propose_new_owner())
+ pub fn propose_new_owner(&mut self, owner: Address);
+ /// Accepts the new owner proposition. This can be called only by the proposed owner.
+ /// [`Read more`](crate::modules::access_control::AccessControl::accept_new_owner())
+ pub fn accept_new_owner(&mut self);
+ /// Changes the ownership of the contract to the new address.
+ /// [`Read more`](AccessControl::change_ownership())
pub fn change_ownership(&mut self, owner: Address);
/// Adds a new address to the whitelist.
pub fn add_to_whitelist(&mut self, address: Address);
diff --git a/dao/src/core_contracts/reputation/token.rs b/dao/src/core_contracts/reputation/token.rs
index 4688bc50..7e538eaf 100644
--- a/dao/src/core_contracts/reputation/token.rs
+++ b/dao/src/core_contracts/reputation/token.rs
@@ -34,7 +34,13 @@ impl ReputationContract {
/// Changes ownership of the contract. Transfer the ownership to the `owner`. Only the current owner
/// is permitted to call this method.
///
- /// See [AccessControl](AccessControl::change_ownership())
+ /// See [AccessControl](AccessControl::propose_new_owner())
+ pub fn propose_new_owner(&mut self, owner: Address);
+ /// Accepts the new owner proposition. This can be called only by the proposed owner.
+ /// See [AccessControl](AccessControl::accept_new_owner())
+ pub fn accept_new_owner(&mut self);
+ /// Changes the ownership of the contract to the new address.
+ /// [`Read more`](AccessControl::change_ownership())
pub fn change_ownership(&mut self, owner: Address);
/// Adds a new address to the whitelist.
///
diff --git a/dao/src/core_contracts/va_nft.rs b/dao/src/core_contracts/va_nft.rs
index 93b79302..05545669 100644
--- a/dao/src/core_contracts/va_nft.rs
+++ b/dao/src/core_contracts/va_nft.rs
@@ -39,7 +39,13 @@ impl VaNftContract {
to self.token {
/// Changes the ownership of the contract. Transfers ownership to the `owner`.
/// Only the current owner is permitted to call this method.
- /// [`Read more`](crate::modules::access_control::AccessControl::change_ownership())
+ /// [`Read more`](crate::modules::access_control::AccessControl::propose_new_owner())
+ pub fn propose_new_owner(&mut self, owner: Address);
+ /// Accepts the new owner proposition. This can be called only by the proposed owner.
+ /// [`Read more`](crate::modules::access_control::AccessControl::accept_new_owner())
+ pub fn accept_new_owner(&mut self);
+ /// Changes the ownership of the contract to the new address.
+ /// [`Read more`](AccessControl::change_ownership())
pub fn change_ownership(&mut self, owner: Address);
/// Adds a new address to the whitelist.
/// [`Read more`](crate::modules::access_control::AccessControl::add_to_whitelist())
diff --git a/dao/src/core_contracts/variable_repository.rs b/dao/src/core_contracts/variable_repository.rs
index 972b6403..c8617498 100644
--- a/dao/src/core_contracts/variable_repository.rs
+++ b/dao/src/core_contracts/variable_repository.rs
@@ -61,6 +61,12 @@ impl VariableRepositoryContract {
pub fn get_owner(&self) -> Option
;
/// Changes the ownership of the contract. Transfers ownership to the `owner`.
/// Only the current owner is permitted to call this method.
+ /// [`Read more`](AccessControl::propose_new_owner())
+ pub fn propose_new_owner(&mut self, owner: Address);
+ /// Accepts the new owner proposition. This can be called only by the proposed owner.
+ /// [`Read more`](AccessControl::accept_new_owner())
+ pub fn accept_new_owner(&mut self);
+ /// Changes the ownership of the contract to the new address.
/// [`Read more`](AccessControl::change_ownership())
pub fn change_ownership(&mut self, owner: Address);
/// Adds a new address to the whitelist.
diff --git a/dao/src/modules/access_control.rs b/dao/src/modules/access_control.rs
index caf14266..2cd9d830 100644
--- a/dao/src/modules/access_control.rs
+++ b/dao/src/modules/access_control.rs
@@ -1,5 +1,6 @@
//! AccessControl module.
use crate::modules::{Owner, Whitelist};
+use odra::contract_env::caller;
use odra::types::Address;
/// A AccessControl module storage definition.
@@ -23,16 +24,37 @@ impl AccessControl {
self.whitelist.add_to_whitelist(address);
}
- /// Changes ownership of the contract. Transfer the ownership to the `owner`. Only the current owner
- /// is permited to call this method.
+ /// Proposes a change of ownership of the contract. Owner will be changed if accepted by propsed
+ /// new owner. Only the current owner is permited to call this method.
///
/// # Errors
/// Throws [`NotAnOwner`](crate::utils::Error::NotAnOwner) if caller
/// is not the current owner.
///
+ pub fn propose_new_owner(&mut self, owner: Address) {
+ self.owner.ensure_owner();
+ self.owner.propose_owner(owner);
+ }
+
+ /// Accepts the new owner proposition. This can be called only by the proposed owner.
+ ///
/// # Events
/// Emits [`OwnerChanged`](crate::modules::owner::events::OwnerChanged),
/// [`AddedToWhitelist`](crate::modules::whitelist::events::AddedToWhitelist) events.
+ pub fn accept_new_owner(&mut self) {
+ let caller = caller();
+ self.owner.accept_owner(caller);
+ self.whitelist.add_to_whitelist(caller);
+ }
+
+ /// Changes the ownership of the contract to the new address.
+ ///
+ /// # Events
+ /// Emits [`OwnerChanged`](crate::modules::owner::events::OwnerChanged) event.
+ ///
+ /// # Errors
+ /// Throws [`NotAnOwner`](crate::utils::Error::NotAnOwner) if caller
+ /// is not the current owner.
pub fn change_ownership(&mut self, owner: Address) {
self.owner.ensure_owner();
self.owner.change_ownership(owner);
diff --git a/dao/src/modules/owner.rs b/dao/src/modules/owner.rs
index 91047d95..d749e4a4 100644
--- a/dao/src/modules/owner.rs
+++ b/dao/src/modules/owner.rs
@@ -9,6 +9,7 @@ use odra::Variable;
#[odra::module]
pub struct Owner {
pub owner: Variable,
+ pub proposed_owner: Variable