Skip to content

Commit

Permalink
Merge pull request #82 from milkyway-labs/fabo/delay-ownership
Browse files Browse the repository at this point in the history
Fabo/delay ownership
  • Loading branch information
faboweb authored Dec 3, 2023
2 parents a17776b + e9cddc6 commit 2e0833f
Show file tree
Hide file tree
Showing 5 changed files with 34 additions and 6 deletions.
1 change: 1 addition & 0 deletions contracts/staking/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ pub fn instantiate(
total_fees: Uint128::zero(),
ibc_id_counter: 0,
rate: 1u128.into(),
owner_transfer_min_time: None,
};

STATE.save(deps.storage, &state)?;
Expand Down
5 changes: 4 additions & 1 deletion contracts/staking/src/error.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use cosmwasm_std::{StdError, Uint128};
use cosmwasm_std::{StdError, Timestamp, Uint128};
use cw_controllers::AdminError;
use cw_utils::PaymentError;
use milky_way::staking::BatchStatus;
Expand All @@ -21,6 +21,9 @@ pub enum ContractError {
#[error("No pending owner")]
NoPendingOwner {},

#[error("Ownership transfer not ready")]
OwnershipTransferNotReady { time_to_claim: Timestamp },

#[error("Payment error: {0}")]
Payment(#[from] PaymentError),

Expand Down
19 changes: 17 additions & 2 deletions contracts/staking/src/execute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -480,6 +480,7 @@ pub fn execute_remove_validator(
// Transfer ownership to another account; callable by the owner
// This will require the new owner to accept to take effect.
// No need to handle case of overwriting the pending owner
// Ownership can only be claimed after 7 days to mitigate fat finger errors
pub fn execute_transfer_ownership(
deps: DepsMut,
_env: Env,
Expand All @@ -488,8 +489,11 @@ pub fn execute_transfer_ownership(
) -> ContractResult<Response> {
ADMIN.assert_admin(deps.as_ref(), &info.sender)?;

let mut state = STATE.load(deps.storage)?;
let mut state: State = STATE.load(deps.storage)?;
state.pending_owner = Some(deps.api.addr_validate(&new_owner)?);
state.owner_transfer_min_time = Some(Timestamp::from_seconds(
_env.block.time.seconds() + 60 * 60 * 24 * 7,
)); // 7 days

STATE.save(deps.storage, &state)?;

Expand All @@ -509,6 +513,7 @@ pub fn execute_revoke_ownership_transfer(

let mut state = STATE.load(deps.storage)?;
state.pending_owner = None;
state.owner_transfer_min_time = None;

STATE.save(deps.storage, &state)?;

Expand All @@ -520,8 +525,18 @@ pub fn execute_accept_ownership(
_env: Env,
info: MessageInfo,
) -> ContractResult<Response> {
let mut state: State = STATE.load(deps.storage)?;
if state.owner_transfer_min_time.is_some()
&& state.owner_transfer_min_time.unwrap().seconds() > _env.block.time.seconds()
{
return Err(ContractError::OwnershipTransferNotReady {
time_to_claim: Timestamp::from_seconds(
state.owner_transfer_min_time.unwrap().seconds(),
),
});
}

let new_owner = {
let mut state = STATE.load(deps.storage)?;
match state.pending_owner {
Some(pending_owner) if pending_owner == info.sender => {
state.pending_owner = None;
Expand Down
1 change: 1 addition & 0 deletions contracts/staking/src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ pub struct State {
pub total_native_token: Uint128,
pub total_liquid_stake_token: Uint128,
pub pending_owner: Option<Addr>,
pub owner_transfer_min_time: Option<Timestamp>,
pub total_reward_amount: Uint128,
pub rate: Uint128,
pub total_fees: Uint128,
Expand Down
14 changes: 11 additions & 3 deletions contracts/staking/src/tests/ownership_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,15 +42,23 @@ mod ownership_tests {
new_owner: "new_owner".to_string(),
};

let res = execute(deps.as_mut(), mock_env(), info, msg);
let mut env = mock_env();

let res = execute(deps.as_mut(), env.clone(), info, msg);
assert!(res.is_ok());

let info = mock_info("new_owner", &coins(1000, "uosmo"));
let msg = ExecuteMsg::AcceptOwnership {};

let res2 = execute(deps.as_mut(), mock_env(), info, msg);
let res = execute(deps.as_mut(), env.clone(), info.clone(), msg.clone());
assert!(res.is_err()); // no time yet

let attrs = res2.unwrap().attributes;
env.block.time = mock_env().block.time.plus_seconds(60 * 60 * 24 * 7);

let res = execute(deps.as_mut(), env.clone(), info.clone(), msg.clone());
assert!(res.is_ok());

let attrs = res.unwrap().attributes;
assert_eq!(attrs[0].value, "accept_ownership");
assert_eq!(attrs[1].value, "new_owner");
}
Expand Down

0 comments on commit 2e0833f

Please sign in to comment.