Skip to content

Commit

Permalink
refactor: owner matches staking
Browse files Browse the repository at this point in the history
  • Loading branch information
gluax committed May 26, 2024
1 parent 9020d2a commit b628680
Show file tree
Hide file tree
Showing 24 changed files with 390 additions and 348 deletions.
86 changes: 0 additions & 86 deletions contract/src/config.rs

This file was deleted.

110 changes: 0 additions & 110 deletions contract/src/config_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,113 +16,3 @@ fn proper_initialization() {
let res = test_helpers::instantiate_staking_contract(deps.as_mut(), creator).unwrap();
assert_eq!(0, res.messages.len());
}

#[test]
fn two_step_transfer_ownership() {
let mut deps = mock_dependencies();

let creator = mock_info("creator", &coins(1000, "token"));
let _res = test_helpers::instantiate_staking_contract(deps.as_mut(), creator).unwrap();

let owner_addr = test_helpers::get_owner(deps.as_mut());
assert_eq!(owner_addr, "owner");

let pending_owner = test_helpers::get_pending_owner(deps.as_mut());
assert_eq!(pending_owner, None);

// new-owner accepts ownership before owner calls transfer_ownership
let new_owner = mock_info("new-owner", &coins(2, "token"));
let res = test_helpers::accept_ownership(deps.as_mut(), new_owner.clone());
assert!(res.is_err_and(|x| x == ContractError::NoPendingOwnerFound),);

// non-owner initiates transfering ownership
let non_owner = mock_info("non-owner", &coins(2, "token"));
let res = test_helpers::transfer_ownership(deps.as_mut(), non_owner.clone(), "new-owner".to_string());
assert!(res.is_err_and(|x| x == ContractError::NotOwner));

// owner initiates transfering ownership
let owner = mock_info("owner", &coins(2, "token"));
let res = test_helpers::transfer_ownership(deps.as_mut(), owner, "new-owner".to_string());
assert!(res.is_ok());

let owner_addr = test_helpers::get_owner(deps.as_mut());
assert_eq!(owner_addr, "owner");

let pending_owner = test_helpers::get_pending_owner(deps.as_mut());
assert_eq!(pending_owner, Some(Addr::unchecked("new-owner")));

// non-owner accepts ownership
let res = test_helpers::accept_ownership(deps.as_mut(), non_owner);
assert!(res.is_err_and(|x| x == ContractError::NotPendingOwner));

// new owner accepts ownership
let res = test_helpers::accept_ownership(deps.as_mut(), new_owner);
assert!(res.is_ok());

let owner = test_helpers::get_owner(deps.as_mut());
assert_eq!(owner, Addr::unchecked("new-owner"));

let pending_owner = test_helpers::get_pending_owner(deps.as_mut());
assert_eq!(pending_owner, None);
}

#[test]
pub fn allowlist_works() {
let mut deps = mock_dependencies();

let creator = mock_info("creator", &coins(2, "token"));
let _res = test_helpers::instantiate_staking_contract(deps.as_mut(), creator).unwrap();

// update the config with allowlist enabled
let owner = mock_info("owner", &coins(0, "token"));
let new_config = StakingConfig {
minimum_stake_to_register: 100,
minimum_stake_for_committee_eligibility: 200,
allowlist_enabled: true,
};
let res = test_helpers::set_staking_config(deps.as_mut(), owner.clone(), new_config);
assert!(res.is_ok());

// alice tries to register a data request executor, but she's not on the allowlist
let mut alice = TestExecutor::new("alice", Some(100));
let res = test_helpers::reg_and_stake(deps.as_mut(), alice.info(), &alice, None);
assert!(res.is_err_and(|x| x == ContractError::NotOnAllowlist));

// add alice to the allowlist
let res = test_helpers::add_to_allowlist(deps.as_mut(), owner.clone(), alice.pub_key());
assert!(res.is_ok());

// now alice can register a data request executor
let res = test_helpers::reg_and_stake(deps.as_mut(), alice.info(), &alice, None);
assert!(res.is_ok());

// alice unstakes, withdraws, then unregisters herself
alice.set_amount(0);
let _res = test_helpers::unstake(deps.as_mut(), alice.info(), &alice, 100).unwrap();
let _res = test_helpers::withdraw(deps.as_mut(), alice.info(), &alice, 100).unwrap();
let res = test_helpers::unregister(deps.as_mut(), alice.info(), &alice);
assert!(res.is_ok());

// remove alice from the allowlist
let res = test_helpers::remove_from_allowlist(deps.as_mut(), owner.clone(), alice.pub_key());
assert!(res.is_ok());

// now alice can't register a data request executor
alice.set_amount(2);
let res = test_helpers::reg_and_stake(deps.as_mut(), alice.info(), &alice, None);
assert!(res.is_err_and(|x| x == ContractError::NotOnAllowlist));

// update the config to disable the allowlist
let new_config = StakingConfig {
minimum_stake_to_register: 100,
minimum_stake_for_committee_eligibility: 200,
allowlist_enabled: false,
};
let res = test_helpers::set_staking_config(deps.as_mut(), owner, new_config);
assert!(res.is_ok());

// now alice can register a data request executor
alice.set_amount(100);
let res = test_helpers::reg_and_stake(deps.as_mut(), alice.info(), &alice, None);
assert!(res.is_ok());
}
1 change: 0 additions & 1 deletion contract/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
pub mod config;
pub mod consts;
pub mod contract;
mod crypto;
Expand Down
34 changes: 0 additions & 34 deletions contract/src/msgs/owner/execute.rs

This file was deleted.

31 changes: 31 additions & 0 deletions contract/src/msgs/owner/execute/accept_ownership.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
use super::*;
use crate::contract::CONTRACT_VERSION;

#[cw_serde]
pub struct Execute;

impl Execute {
/// Accept transfer contract ownership (previously triggered by owner)
pub fn execute(self, deps: DepsMut, _env: Env, info: MessageInfo) -> Result<Response, ContractError> {
let pending_owner = PENDING_OWNER.load(deps.storage)?;
if pending_owner.is_none() {
return Err(ContractError::NoPendingOwnerFound);
}
if pending_owner.is_some_and(|owner| owner != info.sender) {
return Err(ContractError::NotPendingOwner);
}
OWNER.save(deps.storage, &info.sender)?;
PENDING_OWNER.save(deps.storage, &None)?;

Ok(Response::new()
.add_attribute("action", "accept-ownership")
.add_events([Event::new("seda-accept-ownership")
.add_attributes([("version", CONTRACT_VERSION), ("new_owner", info.sender.as_ref())])]))
}
}

impl From<Execute> for crate::msgs::ExecuteMsg {
fn from(value: Execute) -> Self {
super::ExecuteMsg::AcceptOwnership(value).into()
}
}
35 changes: 35 additions & 0 deletions contract/src/msgs/owner/execute/add_to_allowlist.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
use super::*;
use crate::contract::CONTRACT_VERSION;

#[cw_serde]
pub struct Execute {
/// The public key of the person.
pub(in crate::msgs::owner) public_key: PublicKey,
}

impl Execute {
/// Add a `Secp256k1PublicKey` to the allow list
pub fn execute(self, deps: DepsMut, info: MessageInfo) -> Result<Response, ContractError> {
// require the sender to be the OWNER
let owner = OWNER.load(deps.storage)?;
if info.sender != owner {
return Err(ContractError::NotOwner);
}

// add the address to the allowlist
ALLOWLIST.save(deps.storage, &self.public_key, &true)?;

Ok(Response::new().add_attribute("action", "add-to-allowlist").add_event(
Event::new("add-to-allowlist").add_attributes([
("version", CONTRACT_VERSION.to_string()),
("pub_key", hex::encode(self.public_key)),
]),
))
}
}

impl From<Execute> for crate::msgs::ExecuteMsg {
fn from(value: Execute) -> Self {
super::ExecuteMsg::AddToAllowlist(value).into()
}
}
32 changes: 32 additions & 0 deletions contract/src/msgs/owner/execute/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
use cosmwasm_std::Event;
use state::{ALLOWLIST, OWNER, PENDING_OWNER};

use super::*;
use crate::{error::ContractError, types::PublicKey};

pub(in crate::msgs::owner) mod accept_ownership;
pub(in crate::msgs::owner) mod add_to_allowlist;
pub(in crate::msgs::owner) mod remove_from_allowlist;
pub(in crate::msgs::owner) mod transfer_ownership;

#[cw_serde]
#[serde(untagged)]
pub enum ExecuteMsg {
TransferOwnership(transfer_ownership::Execute),
AcceptOwnership(accept_ownership::Execute),
/// Add a user to the allowlist.
AddToAllowlist(add_to_allowlist::Execute),
/// Remove a user from the allowlist.
RemoveFromAllowlist(remove_from_allowlist::Execute),
}

impl ExecuteMsg {
pub fn execute(self, deps: DepsMut, env: Env, info: MessageInfo) -> Result<Response, ContractError> {
match self {
ExecuteMsg::TransferOwnership(msg) => msg.execute(deps, env, info),
ExecuteMsg::AcceptOwnership(msg) => msg.execute(deps, env, info),
ExecuteMsg::AddToAllowlist(msg) => msg.execute(deps, info),
ExecuteMsg::RemoveFromAllowlist(msg) => msg.execute(deps, info),
}
}
}
35 changes: 35 additions & 0 deletions contract/src/msgs/owner/execute/remove_from_allowlist.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
use super::*;
use crate::contract::CONTRACT_VERSION;

#[cw_serde]
pub struct Execute {
/// The public key of the person.
pub(in crate::msgs::owner) public_key: PublicKey,
}

impl Execute {
/// Remove a `Secp256k1PublicKey` to the allow list
pub fn execute(self, deps: DepsMut, info: MessageInfo) -> Result<Response, ContractError> {
// require the sender to be the OWNER
let owner = OWNER.load(deps.storage)?;
if info.sender != owner {
return Err(ContractError::NotOwner);
}

// remove the address from the allowlist
ALLOWLIST.remove(deps.storage, &self.public_key);

Ok(Response::new()
.add_attribute("action", "remove-from-allowlist")
.add_event(Event::new("remove-from-allowlist").add_attributes([
("version", CONTRACT_VERSION.to_string()),
("pub_key", hex::encode(self.public_key)),
])))
}
}

impl From<Execute> for crate::msgs::ExecuteMsg {
fn from(value: Execute) -> Self {
super::ExecuteMsg::RemoveFromAllowlist(value).into()
}
}
Loading

0 comments on commit b628680

Please sign in to comment.