Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Start Time for Permissions #668

Merged
merged 31 commits into from
Jan 21, 2025
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
9de20c1
feat: add optional start time for permissions
joemonem Nov 20, 2024
c839fd6
test: start time for permission
joemonem Nov 20, 2024
7e2b54f
chore: version bump
joemonem Nov 21, 2024
65e1555
chore: changelog entry
joemonem Nov 21, 2024
6a3b79e
test: turn back env time for last check to pass in test_permission_st…
joemonem Nov 21, 2024
11bf4a5
test: marketplace integration test quick adjustments
joemonem Nov 21, 2024
9a951f7
merge with development
joemonem Nov 21, 2024
fdf4adf
ref: remove all permissions during migration to avoid breaking state
joemonem Nov 25, 2024
66eb8f7
fix: clear all permissions instead of permissioned actions during mig…
joemonem Nov 27, 2024
d63e724
fix: fmt
joemonem Nov 27, 2024
07d2d11
Merge branch 'development' into permission-start-time
crnbarr93 Nov 28, 2024
c5337eb
fix: invalid permissioning reference
crnbarr93 Nov 28, 2024
0a4bf80
Merge branch 'development' into permission-start-time
joemonem Dec 11, 2024
c2fd453
chore: merge fix
joemonem Dec 11, 2024
0995795
Merge branch 'main' into permission-start-time
joemonem Dec 11, 2024
719cc79
chore: merge fix
joemonem Dec 11, 2024
3edcc6e
feat: detect and remove old version of local permission during migration
joemonem Dec 13, 2024
233a694
test: migration for permissions
joemonem Dec 13, 2024
d269eae
merge with main
joemonem Dec 19, 2024
a5f3784
test: refactor start_time to use rstest
joemonem Jan 8, 2025
34642f3
fix: add start and expiration time validation
joemonem Jan 8, 2025
1148f9d
ref: update outdated permissions during migration, check for expired …
joemonem Jan 8, 2025
d15b2fc
merge with main
joemonem Jan 8, 2025
da79280
ref: go through all permissions during migration
joemonem Jan 9, 2025
6549e6d
fix: look for whitelisted and blacklisted instead of whitelist and bl…
joemonem Jan 10, 2025
16893d3
Merge branch 'main' into permission-start-time
joemonem Jan 10, 2025
d424888
test: replace integration tests for migration into unit tests
joemonem Jan 15, 2025
42febe4
chore: clippy and fmt fix
joemonem Jan 15, 2025
96d9bb0
test: rstets for validate_times in permissioning
joemonem Jan 15, 2025
bd27400
ref: remove unused fixtures
crnbarr93 Jan 16, 2025
29d55d0
merge with main
joemonem Jan 20, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- ADODB now supports pre-release tagging [(#560)](https://github.com/andromedaprotocol/andromeda-core/pull/560)
- Validator Staking: Updated according to audit [(#565)](https://github.com/andromedaprotocol/andromeda-core/pull/565)
- Conditional Splitter: Change lock_time's type from MillisecondsDuration to Expiry [(#567)](https://github.com/andromedaprotocol/andromeda-core/pull/567)
- Permissions now have an optional start time [(#668)](https://github.com/andromedaprotocol/andromeda-core/pull/668)

### Fixed

Expand Down
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion contracts/data-storage/andromeda-boolean/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ pub fn instantiate(
None => info.sender,
Some(owner) => Addr::unchecked(owner),
},
Permission::Local(LocalPermission::Whitelisted(None)),
Permission::Local(LocalPermission::whitelisted(None, None)),
)?;
}

Expand Down
4 changes: 2 additions & 2 deletions contracts/fungible-tokens/andromeda-cw20/src/testing/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ fn test_transfer() {
]);

// Blacklist the sender who otherwise would have been able to call the function successfully
let permission = Permission::Local(LocalPermission::blacklisted(None));
let permission = Permission::Local(LocalPermission::blacklisted(None, None));
let actors = vec![AndrAddr::from_string("sender")];
let action = "Transfer";
let ctx = ExecuteContext::new(deps.as_mut(), mock_info("owner", &[]), mock_env());
Expand All @@ -125,7 +125,7 @@ fn test_transfer() {
assert_eq!(err, ContractError::Unauthorized {});

// Now whitelist the sender, that should allow him to call the function successfully
let permission = Permission::Local(LocalPermission::whitelisted(None));
let permission = Permission::Local(LocalPermission::whitelisted(None, None));
let actors = vec![AndrAddr::from_string("sender")];
let action = "Transfer";
let ctx = ExecuteContext::new(deps.as_mut(), mock_info("owner", &[]), mock_env());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ pub fn instantiate(
deps.storage,
SEND_CW20_ACTION,
addr,
Permission::Local(LocalPermission::whitelisted(None)),
Permission::Local(LocalPermission::whitelisted(None, None)),
)?;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ fn init(deps: DepsMut, info: MessageInfo) {
owner: None,
actor_permission: Some(ActorPermission {
actors: vec![AndrAddr::from_string("actor")],
permission: LocalPermission::whitelisted(None),
permission: LocalPermission::whitelisted(None, None),
}),
},
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,7 @@ fn execute_start_auction(
deps.storage,
auction_id.to_string(),
whitelisted_address,
Permission::Local(LocalPermission::Whitelisted(None)),
Permission::Local(LocalPermission::whitelisted(None, None)),
)?;
}
};
Expand Down Expand Up @@ -427,7 +427,7 @@ fn execute_update_auction(
deps.storage,
token_auction_state.auction_id.to_string(),
whitelisted_address,
Permission::Local(LocalPermission::Whitelisted(None)),
Permission::Local(LocalPermission::whitelisted(None, None)),
)?;
}
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ pub fn instantiate(
deps.storage,
SEND_CW20_ACTION,
addr,
Permission::Local(LocalPermission::Whitelisted(None)),
Permission::Local(LocalPermission::whitelisted(None, None)),
)?;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ fn test_instantiate_with_multiple_authorized_cw20_addresses() {
ADOContract::get_permission(deps.as_ref().storage, SEND_CW20_ACTION, raw_addr).unwrap();
assert_eq!(
permission,
Some(Permission::Local(LocalPermission::Whitelisted(None)))
Some(Permission::Local(LocalPermission::whitelisted(None, None)))
);
}

Expand Down Expand Up @@ -1024,7 +1024,7 @@ fn test_execute_authorize_cw20_contract() {
.unwrap();
assert_eq!(
permission,
Some(Permission::Local(LocalPermission::Whitelisted(None)))
Some(Permission::Local(LocalPermission::whitelisted(None, None)))
);

// Test successful authorization with expiration
Expand All @@ -1042,7 +1042,7 @@ fn test_execute_authorize_cw20_contract() {
vec![
attr("action", "authorize_contract"),
attr("address", "cw20_contract_with_expiry"),
attr("permission", format!("whitelisted:{}", expiration)),
attr("permission", format!("whitelisted until:{}", expiration)),
]
);

Expand All @@ -1055,9 +1055,10 @@ fn test_execute_authorize_cw20_contract() {
.unwrap();
assert_eq!(
permission,
Some(Permission::Local(LocalPermission::Whitelisted(Some(
expiration
))))
Some(Permission::Local(LocalPermission::whitelisted(
None,
Some(expiration),
)))
);
}

Expand All @@ -1081,7 +1082,7 @@ fn test_execute_deauthorize_cw20_contract() {
.unwrap();
assert_eq!(
permission,
Some(Permission::Local(LocalPermission::Whitelisted(None)))
Some(Permission::Local(LocalPermission::whitelisted(None, None)))
);

// Now deauthorize the CW20 contract
Expand Down Expand Up @@ -1181,7 +1182,7 @@ fn test_authorize_token_contract() {
vec![
attr("action", "authorize_contract"),
attr("address", "nft_contract"),
attr("permission", format!("whitelisted:{}", expiration)),
attr("permission", format!("whitelisted until:{}", expiration)),
]
);

Expand Down
2 changes: 1 addition & 1 deletion contracts/os/andromeda-ibc-registry/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ pub fn instantiate(
deps.storage,
STORE_DENOM_INFO,
service_address.clone(),
Permission::Local(LocalPermission::Whitelisted(None)),
Permission::Local(LocalPermission::whitelisted(None, None)),
)?;

Ok(resp.add_attribute("service_address", service_address))
Expand Down
2 changes: 1 addition & 1 deletion packages/std/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "andromeda-std"
version = "1.3.4"
version = "1.4.0"
edition = "2021"
rust-version = "1.75.0"
description = "The standard library for creating an Andromeda Digital Object"
Expand Down
117 changes: 82 additions & 35 deletions packages/std/src/ado_base/permissioning.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,44 +49,73 @@ pub struct PermissionedActionsResponse {
/// Expiration defaults to `Never` if not provided
#[cw_serde]
pub enum LocalPermission {
Blacklisted(Option<Expiry>),
Blacklisted {
start: Option<Expiry>,
expiration: Option<Expiry>,
},
Limited {
start: Option<Expiry>,
expiration: Option<Expiry>,
uses: u32,
},
Whitelisted(Option<Expiry>),
Whitelisted {
start: Option<Expiry>,
expiration: Option<Expiry>,
},
}

impl std::default::Default for LocalPermission {
fn default() -> Self {
Self::Whitelisted(None)
Self::Whitelisted {
start: None,
expiration: None,
}
}
}

impl LocalPermission {
pub fn blacklisted(expiration: Option<Expiry>) -> Self {
Self::Blacklisted(expiration)
pub fn blacklisted(start: Option<Expiry>, expiration: Option<Expiry>) -> Self {
Self::Blacklisted { start, expiration }
}

pub fn whitelisted(expiration: Option<Expiry>) -> Self {
Self::Whitelisted(expiration)
pub fn whitelisted(start: Option<Expiry>, expiration: Option<Expiry>) -> Self {
Self::Whitelisted { start, expiration }
}

pub fn limited(expiration: Option<Expiry>, uses: u32) -> Self {
Self::Limited { expiration, uses }
pub fn limited(start: Option<Expiry>, expiration: Option<Expiry>, uses: u32) -> Self {
Self::Limited {
start,
expiration,
uses,
}
}

pub fn is_permissioned(&self, env: &Env, strict: bool) -> bool {
match self {
Self::Blacklisted(expiration) => {
Self::Blacklisted { start, expiration } => {
// If start time hasn't started yet, then it should return true
if let Some(start) = start {
if !start.get_time(&env.block).is_expired(&env.block) {
return true;
}
}
if let Some(expiration) = expiration {
if expiration.get_time(&env.block).is_expired(&env.block) {
return !strict;
}
}
false
}
Self::Limited { expiration, uses } => {
Self::Limited {
start,
expiration,
uses,
} => {
if let Some(start) = start {
if !start.get_time(&env.block).is_expired(&env.block) {
return true;
}
}
if let Some(expiration) = expiration {
if expiration.get_time(&env.block).is_expired(&env.block) {
return !strict;
Expand All @@ -97,7 +126,12 @@ impl LocalPermission {
}
true
}
Self::Whitelisted(expiration) => {
Self::Whitelisted { start, expiration } => {
if let Some(start) = start {
if !start.get_time(&env.block).is_expired(&env.block) {
return !strict;
}
}
if let Some(expiration) = expiration {
if expiration.get_time(&env.block).is_expired(&env.block) {
return !strict;
Expand All @@ -110,18 +144,30 @@ impl LocalPermission {

pub fn get_expiration(&self, env: Env) -> MillisecondsExpiration {
match self {
Self::Blacklisted(expiration) => {
Self::Blacklisted { expiration, .. } => {
expiration.clone().unwrap_or_default().get_time(&env.block)
}
Self::Limited { expiration, .. } => {
expiration.clone().unwrap_or_default().get_time(&env.block)
}
Self::Whitelisted(expiration) => {
Self::Whitelisted { expiration, .. } => {
expiration.clone().unwrap_or_default().get_time(&env.block)
}
}
}

pub fn get_start_time(&self, env: Env) -> MillisecondsExpiration {
match self {
Self::Blacklisted { start, .. } => {
start.clone().unwrap_or_default().get_time(&env.block)
}
Self::Limited { start, .. } => start.clone().unwrap_or_default().get_time(&env.block),
Self::Whitelisted { start, .. } => {
start.clone().unwrap_or_default().get_time(&env.block)
}
}
}

pub fn consume_use(&mut self) -> Result<(), ContractError> {
if let Self::Limited { uses, .. } = self {
*uses = uses.saturating_sub(1);
Expand All @@ -134,27 +180,28 @@ impl LocalPermission {
impl fmt::Display for LocalPermission {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let self_as_string = match self {
Self::Blacklisted(expiration) => {
if let Some(expiration) = expiration {
format!("blacklisted:{expiration}")
} else {
"blacklisted".to_string()
}
}
Self::Limited { expiration, uses } => {
if let Some(expiration) = expiration {
format!("limited:{expiration}:{uses}")
} else {
format!("limited:{uses}")
}
}
Self::Whitelisted(expiration) => {
if let Some(expiration) = expiration {
format!("whitelisted:{expiration}")
} else {
"whitelisted".to_string()
}
}
Self::Blacklisted { start, expiration } => match (start, expiration) {
(Some(s), Some(e)) => format!("blacklisted starting from:{s} until:{e}"),
(Some(s), None) => format!("blacklisted starting from:{s}"),
(None, Some(e)) => format!("blacklisted until:{e}"),
(None, None) => "blacklisted".to_string(),
},
Self::Limited {
start,
expiration,
uses,
} => match (start, expiration) {
(Some(s), Some(e)) => format!("limited starting from:{s} until:{e} uses:{uses}"),
(Some(s), None) => format!("limited starting from:{s} uses:{uses}"),
(None, Some(e)) => format!("limited until:{e} uses:{uses}"),
(None, None) => format!("limited uses:{uses}"),
},
Self::Whitelisted { start, expiration } => match (start, expiration) {
(Some(s), Some(e)) => format!("whitelisted starting from:{s} until:{e}"),
(Some(s), None) => format!("whitelisted starting from:{s}"),
(None, Some(e)) => format!("whitelisted until:{e}"),
(None, None) => "whitelisted".to_string(),
},
};
write!(f, "{self_as_string}")
}
Expand Down
Loading