Skip to content
Merged
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
166 changes: 154 additions & 12 deletions soroban-sdk/src/_migrating/v25_contracttrait.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,40 +48,93 @@
//! ## Example: Defining and Implementing a Trait
//!
//! ```
//! use soroban_sdk::{contract, contractimpl, contracttrait, Env};
//! use soroban_sdk::{contract, contractimpl, contracttrait, Address, Env};
//!
//! // Define a trait with default implementations
//! // A regular trait for admin access control - not exported as contract functions
//! pub trait RequireAuthForPause {
//! fn require_auth_for_pause(env: &Env);
//! }
//!
//! // Define a contracttrait with default implementations that require RequireAuthForPause
//! #[contracttrait]
//! pub trait Pausable {
//! pub trait Pausable: RequireAuthForPause {
//! fn is_paused(env: &Env) -> bool {
//! env.storage().instance().has(&"paused")
//! }
//!
//! fn pause(env: &Env) {
//! Self::require_auth_for_pause(env);
//! env.storage().instance().set(&"paused", &true);
//! }
Comment thread
leighmcculloch marked this conversation as resolved.
//!
//! fn unpause(env: &Env) {
//! Self::require_auth_for_pause(env);
//! env.storage().instance().remove(&"paused");
//! }
//! }
//!
//! #[contract]
//! pub struct MyContract;
//!
//! impl RequireAuthForPause for MyContract {
//! fn require_auth_for_pause(env: &Env) {
//! let admin: Address = env.storage().instance().get(&"admin").unwrap();
Comment thread
leighmcculloch marked this conversation as resolved.
//! admin.require_auth();
//! }
//! }
//!
//! // Implement the trait - default functions are automatically exported
//! #[contractimpl(contracttrait)]
//! impl Pausable for MyContract {}
//!
//! #[contractimpl]
//! impl MyContract {
//! pub fn __constructor(env: &Env, admin: Address) {
//! env.storage().instance().set(&"admin", &admin);
//! }
//!
//! pub fn do_something(env: &Env) {
//! if Self::is_paused(env) {
//! panic!("contract is paused");
//! }
//! // ... rest of the function
//! }
//! }
//!
//! #[test]
//! fn test() {
//! # }
//! # #[cfg(feature = "testutils")]
//! # fn main() {
//! use soroban_sdk::{testutils::{Address as _, MockAuth, MockAuthInvoke}, IntoVal};
//! let env = Env::default();
//! let admin = Address::generate(&env);
//! let contract_id = env.register(MyContract, (&admin,));
//! let client = PausableClient::new(&env, &contract_id);
//!
//! assert!(!client.is_paused());
//! client.mock_auths(&[MockAuth {
//! address: &admin,
//! invoke: &MockAuthInvoke {
//! contract: &contract_id,
//! fn_name: "pause",
//! args: ().into_val(&env),
//! sub_invokes: &[],
//! },
//! }]).pause();
//! assert!(client.is_paused());
//! client.mock_auths(&[MockAuth {
//! address: &admin,
//! invoke: &MockAuthInvoke {
//! contract: &contract_id,
//! fn_name: "unpause",
//! args: ().into_val(&env),
//! sub_invokes: &[],
//! },
//! }]).unpause();
//! assert!(!client.is_paused());
//! }
//! # #[cfg(not(feature = "testutils"))]
//! # fn main() { }
//! ```
//!
Expand All @@ -90,27 +143,41 @@
//! Contracts can override specific functions while keeping the defaults for others:
//!
//! ```
//! use soroban_sdk::{contract, contractimpl, contracttrait, Env};
//! use soroban_sdk::{contract, contractimpl, contracttrait, Address, Env};
//!
//! // A regular trait for admin access control - not exported as contract functions
//! pub trait RequireAuthForPause {
//! fn require_auth_for_pause(env: &Env);
//! }
//!
//! // Define a trait with default implementations
//! // Define a contracttrait with default implementations that require RequireAuthForPause
//! #[contracttrait]
//! pub trait Pausable {
//! pub trait Pausable: RequireAuthForPause {
//! fn is_paused(env: &Env) -> bool {
//! env.storage().instance().has(&"paused")
//! }
//!
//! fn pause(env: &Env) {
//! Self::require_auth_for_pause(env);
//! env.storage().instance().set(&"paused", &true);
//! }
Comment thread
leighmcculloch marked this conversation as resolved.
//!
//! fn unpause(env: &Env) {
//! Self::require_auth_for_pause(env);
//! env.storage().instance().remove(&"paused");
//! }
//! }
//!
//! #[contract]
//! pub struct MyContract;
//!
//! impl RequireAuthForPause for MyContract {
//! fn require_auth_for_pause(env: &Env) {
//! let admin: Address = env.storage().instance().get(&"admin").unwrap();
Comment thread
leighmcculloch marked this conversation as resolved.
//! admin.require_auth();
//! }
//! }
//!
//! // Implement the trait - override default implementations as needed
//! #[contractimpl(contracttrait)]
//! impl Pausable for MyContract {
Expand All @@ -123,13 +190,52 @@
//!
//! #[contractimpl]
//! impl MyContract {
//! pub fn __constructor(env: &Env, admin: Address) {
//! env.storage().instance().set(&"admin", &admin);
//! }
//!
//! pub fn do_something(env: &Env) {
//! if Self::is_paused(env) {
//! panic!("contract is paused");
//! }
//! // ... rest of the function
//! }
//! }
//!
//! #[test]
//! fn test() {
//! # }
//! # #[cfg(feature = "testutils")]
//! # fn main() {
//! use soroban_sdk::{testutils::{Address as _, MockAuth, MockAuthInvoke}, IntoVal};
//! let env = Env::default();
//! let admin = Address::generate(&env);
//! let contract_id = env.register(MyContract, (&admin,));
//! let client = PausableClient::new(&env, &contract_id);
//!
//! assert!(!client.is_paused());
//! client.mock_auths(&[MockAuth {
//! address: &admin,
//! invoke: &MockAuthInvoke {
//! contract: &contract_id,
//! fn_name: "pause",
//! args: ().into_val(&env),
//! sub_invokes: &[],
//! },
//! }]).pause();
//! assert!(client.is_paused());
//! client.mock_auths(&[MockAuth {
//! address: &admin,
//! invoke: &MockAuthInvoke {
//! contract: &contract_id,
//! fn_name: "unpause",
//! args: ().into_val(&env),
//! sub_invokes: &[],
//! },
//! }]).unpause();
//! assert!(!client.is_paused());
//! }
//! # #[cfg(not(feature = "testutils"))]
//! # fn main() { }
//! ```
//!
Expand All @@ -138,33 +244,51 @@
//! The generated `{TraitName}Client` can be used to call any contract that implements the trait:
//!
//! ```
//! use soroban_sdk::{contract, contractimpl, contracttrait, Env};
//! use soroban_sdk::{contract, contractimpl, contracttrait, Address, Env};
//!
//! // A regular trait for admin access control - not exported as contract functions
//! pub trait RequireAuthForPause {
//! fn require_auth_for_pause(env: &Env);
//! }
//!
//! // Define a trait with default implementations
//! // Define a contracttrait with default implementations that require RequireAuthForPause
//! #[contracttrait]
//! pub trait Pausable {
//! pub trait Pausable: RequireAuthForPause {
//! fn is_paused(env: &Env) -> bool {
//! env.storage().instance().has(&"paused")
//! }
//!
//! fn pause(env: &Env) {
//! Self::require_auth_for_pause(env);
//! env.storage().instance().set(&"paused", &true);
//! }
Comment thread
leighmcculloch marked this conversation as resolved.
//!
//! fn unpause(env: &Env) {
//! Self::require_auth_for_pause(env);
//! env.storage().instance().remove(&"paused");
//! }
//! }
//!
//! #[contract]
//! pub struct MyContract;
//!
//! impl RequireAuthForPause for MyContract {
//! fn require_auth_for_pause(env: &Env) {
//! let admin: Address = env.storage().instance().get(&"admin").unwrap();
Comment thread
leighmcculloch marked this conversation as resolved.
//! admin.require_auth();
//! }
//! }
//!
//! // Implement the trait - default functions are automatically exported
//! #[contractimpl(contracttrait)]
//! impl Pausable for MyContract {}
//!
//! #[contractimpl]
//! impl MyContract {
//! pub fn __constructor(env: &Env, admin: Address) {
//! env.storage().instance().set(&"admin", &admin);
//! }
//!
//! pub fn do_something(env: &Env) {
//! if Self::is_paused(env) {
//! panic!("contract is paused");
Expand All @@ -178,14 +302,32 @@
//! # }
//! # #[cfg(feature = "testutils")]
//! # fn main() {
//! use soroban_sdk::{testutils::{Address as _, MockAuth, MockAuthInvoke}, IntoVal};
//! let env = Env::default();
//! let contract_id = env.register(MyContract, ());
//! let admin = Address::generate(&env);
//! let contract_id = env.register(MyContract, (&admin,));
//! let client = PausableClient::new(&env, &contract_id);
//!
//! assert!(!client.is_paused());
//! client.pause();
//! client.mock_auths(&[MockAuth {
//! address: &admin,
//! invoke: &MockAuthInvoke {
//! contract: &contract_id,
//! fn_name: "pause",
//! args: ().into_val(&env),
//! sub_invokes: &[],
//! },
//! }]).pause();
//! assert!(client.is_paused());
//! client.unpause();
//! client.mock_auths(&[MockAuth {
//! address: &admin,
//! invoke: &MockAuthInvoke {
//! contract: &contract_id,
//! fn_name: "unpause",
//! args: ().into_val(&env),
//! sub_invokes: &[],
//! },
//! }]).unpause();
//! assert!(!client.is_paused());
//! }
//! # #[cfg(not(feature = "testutils"))]
Expand Down
Loading