Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
30 changes: 29 additions & 1 deletion contracts/agent-vault/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,20 @@ pub struct TaskDoneEvent {
pub refund: i128,
}

#[contractevent]
pub struct AddAssetEvent {
#[topic]
pub asset: Address,
pub admin: Address,
}

#[contractevent]
pub struct RemoveAssetEvent {
#[topic]
pub asset: Address,
pub admin: Address,
}

#[contracterror]
#[derive(Clone, Copy, PartialEq, Eq)]
pub enum VaultError {
Expand Down Expand Up @@ -270,6 +284,13 @@ impl AgentVault {
Self::extend_persistent_ttl(&env, &asset_key);

log!(&env, "Asset added to whitelist: {}", asset);

AddAssetEvent {
asset: asset.clone(),
admin: admin.clone(),
}
.publish(&env);

Ok(())
}

Expand All @@ -288,9 +309,16 @@ impl AgentVault {
let asset_key = DataKey::AssetSupported(asset.clone());
if env.storage().persistent().has(&asset_key) {
env.storage().persistent().remove(&asset_key);

log!(&env, "Asset removed from whitelist: {}", asset);

RemoveAssetEvent {
asset: asset.clone(),
admin: admin.clone(),
}
.publish(&env);
}

log!(&env, "Asset removed from whitelist: {}", asset);
Ok(())
}

Expand Down
80 changes: 77 additions & 3 deletions contracts/agent-vault/src/tests.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::{AgentVault, AgentVaultClient, DataKey, VaultError};
use soroban_sdk::testutils::{Address as _, Ledger as _};
use soroban_sdk::{token, Address, Env};
use crate::{AddAssetEvent, AgentVault, AgentVaultClient, DataKey, RemoveAssetEvent, VaultError};
use soroban_sdk::testutils::{Address as _, Events as _, Ledger as _};
use soroban_sdk::{token, vec, Address, Env, Event as _};

struct TestEnv {
env: Env,
Expand Down Expand Up @@ -1242,3 +1242,77 @@ fn test_get_user_tasks_separate_users() {
assert_eq!(t.client.get_user_tasks(&user2).len(), 0);
assert_eq!(t.client.get_user_tasks(&user1).len(), 1);
}

// Asset whitelist events (#37)

#[test]
fn test_add_asset_emits_event() {
let t = setup_test();
t.client.init(&t.admin, &t.usdc_sac);

let asset = Address::generate(&t.env);
t.client.add_asset(&t.admin, &asset);

// The only event so far should be the AddAssetEvent for this asset/admin.
let expected = AddAssetEvent {
asset: asset.clone(),
admin: t.admin.clone(),
};
assert_eq!(
t.env.events().all(),
vec![
&t.env,
(
t.contract_id.clone(),
expected.topics(&t.env),
expected.data(&t.env),
),
],
);

assert!(t.client.is_supported_asset(&asset));
}

#[test]
fn test_remove_asset_emits_event() {
let t = setup_test();
t.client.init(&t.admin, &t.usdc_sac);

let asset = Address::generate(&t.env);
t.client.add_asset(&t.admin, &asset);

// `env.events().all()` reflects the most recent invocation, so calling
// remove_asset last leaves exactly its RemoveAssetEvent in the buffer.
t.client.remove_asset(&t.admin, &asset);

let expected = RemoveAssetEvent {
asset: asset.clone(),
admin: t.admin.clone(),
};
assert_eq!(
t.env.events().all(),
vec![
&t.env,
(
t.contract_id.clone(),
expected.topics(&t.env),
expected.data(&t.env),
),
],
);

assert!(!t.client.is_supported_asset(&asset));
}

#[test]
fn test_remove_nonexistent_asset_emits_no_event() {
let t = setup_test();
t.client.init(&t.admin, &t.usdc_sac);

let asset = Address::generate(&t.env);

// Asset was never whitelisted: remove is a no-op and must not emit an event.
t.client.remove_asset(&t.admin, &asset);

assert!(t.env.events().all().events().is_empty());
}