sprtd
August 23, 2024, 2:28am
1
I am proposing the addition of an extra step to further secure the ownership transfer process such that in the event the first owner mistakenly transfers ownership to a malicious actor, ownership is not at risk even when such a bad actor immediately calls accept_ownership
. The final transfer of ownership should be majorly determined by the first owner who must call an approve_ownership_transfer
function to securely authorize the ownership transfer to the intended entity.
Details here:
opened 11:05AM - 29 Jul 24 UTC
**🧐 Motivation**
The current two-step ownership transfer approach does not co… mpletely solve the issues surrounding secure transfer of ownership given that the new owner first has to simply call `accept_ownership` to finalize the transfer.
**📝 Details**
There is need to add an extra step to further secure the ownership transfer process such that in the event the first owner mistakenly transfers ownership to a malicious actor, ownership is not at risk even when such a bad actor immediately calls `accept_ownership`. The final transfer of ownership should be majorly determined by the first owner who must call an `approve_ownership_transfer` function to securely authorize the ownership transfer to the intended entity.
I'm proposing a three-step process:
- [x] 1. Transfer Ownership: `transfer_ownership` initiates the three-step ownership transfer process by setting the pending owner.
```rs
/// Starts the three-step ownership transfer process by setting the pending owner.
/// Can only be called by the intended first owner.
fn transfer_ownership(
ref self: ComponentState<TContractState>, new_owner: ContractAddress
) {
self.assert_only_owner();
self._propose_owner(new_owner);
}
```
- [x] 2. Accept Ownership: this is 2nd step which involves the ownership acceptance by the pending owner. to prevent name collision with the current `accept_ownership` of the 2-step approach, we may change the name as consensus can be reached by the community on this.
```rs
/// this is 2nd step which involves the ownership acceptance by the pending owner.
/// Can only be called by the intended pending owner.
fn consent_to_ownership(ref self: ComponentState<TContractState>) {
let caller = get_caller_address();
let pending_owner = self.Ownable_pending_owner.read();
assert(caller == pending_owner, Errors::NOT_PENDING_OWNER);
self._consent_to_ownership();
}
```
- [x] 3. ApproveOwnershipTransfer: `approve_ownership_transfer` finishes the ownership transfer process and this can only be called by the first owner to validate the transfer
```rs
/// completes the three-step ownership transfer process by authorizing the ownership transfer to the intended pending owner.
/// Can only be called by the first owner.
fn approve_ownership_transfer(
ref self: ComponentState<TContractState>, new_owner: ContractAddress
) {
self.assert_only_owner();
// assert that the pending owner has consented
assert(self._is_pending_ownership_consented(new_owner) == true, Errors::NOT_CONSENTED);
self._approve_ownership_transfer();
}
```