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

Update the examples for protocol 22 support. #330

Merged
merged 5 commits into from
Dec 6, 2024
Merged
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
874 changes: 458 additions & 416 deletions account/Cargo.lock

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions account/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ crate-type = ["cdylib"]
doctest = false

[dependencies]
soroban-sdk = { version = "21.7.4" }
soroban-sdk = { version = "22.0.0" }

[dev-dependencies]
soroban-sdk = { version = "21.7.4", features = ["testutils"] }
soroban-sdk = { version = "22.0.0", features = ["testutils"] }
ed25519-dalek = { version = "1.0.1" }
rand = { version = "0.7.3" }

Expand Down
28 changes: 19 additions & 9 deletions account/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,15 +38,16 @@ pub enum AccError {
NegativeAmount = 2,
BadSignatureOrder = 3,
UnknownSigner = 4,
InvalidContext = 5,
}

const TRANSFER_FN: Symbol = symbol_short!("transfer");
const APPROVE_FN: Symbol = symbol_short!("approve");
const BURN_FN: Symbol = symbol_short!("burn");

#[contractimpl]
impl AccountContract {
// Initialize the contract with a list of ed25519 public key ('signers').
pub fn init(env: Env, signers: Vec<BytesN<32>>) {
pub fn __constructor(env: Env, signers: Vec<BytesN<32>>) {
// In reality this would need some additional validation on signers
// (deduplication etc.).
for signer in signers.iter() {
Expand All @@ -58,6 +59,9 @@ impl AccountContract {
}

// Adds a limit on any token transfers that aren't signed by every signer.
// For the sake of simplicity of the example the limit is only applied on
// a per-authorization basis; the 'real' limits should likely be time-based
// instead.
pub fn add_limit(env: Env, token: Address, limit: i128) {
// The current contract address is the account contract address and has
// the same semantics for `require_auth` call as any other account
Expand Down Expand Up @@ -175,22 +179,28 @@ fn verify_authorization_policy(
all_signed: bool,
spend_left_per_token: &mut Map<Address, i128>,
) -> Result<(), AccError> {
// There are no limitations when every signers signs the transaction.
if all_signed {
return Ok(());
}
let contract_context = match context {
Context::Contract(c) => {
// Allow modifying this contract only if every signer has signed for it.
if &c.contract == curr_contract {
if !all_signed {
return Err(AccError::NotEnoughSigners);
}
return Err(AccError::NotEnoughSigners);
}
c
}
Context::CreateContractHostFn(_) => return Err(AccError::InvalidContext),
// Allow creating new contracts only if every signer has signed for it.
Context::CreateContractHostFn(_) | Context::CreateContractWithCtorHostFn(_) => {
return Err(AccError::NotEnoughSigners);
}
};
// For the account control every signer must sign the invocation.

// Otherwise, we're only interested in functions that spend tokens.
// Besides the checks above we're only interested in functions that spend tokens.
if contract_context.fn_name != TRANSFER_FN
&& contract_context.fn_name != Symbol::new(env, "approve")
&& contract_context.fn_name != APPROVE_FN
&& contract_context.fn_name != BURN_FN
{
return Ok(());
}
Expand Down
18 changes: 10 additions & 8 deletions account/src/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use soroban_sdk::testutils::Address as _;
use soroban_sdk::testutils::AuthorizedFunction;
use soroban_sdk::testutils::AuthorizedInvocation;
use soroban_sdk::Val;
use soroban_sdk::Vec;
use soroban_sdk::{
auth::Context, testutils::BytesN as _, vec, Address, BytesN, Env, IntoVal, Symbol,
};
Expand All @@ -25,8 +26,8 @@ fn signer_public_key(e: &Env, signer: &Keypair) -> BytesN<32> {
signer.public.to_bytes().into_val(e)
}

fn create_account_contract(e: &Env) -> AccountContractClient {
AccountContractClient::new(e, &e.register_contract(None, AccountContract {}))
fn create_account_contract(e: &Env, signers: Vec<BytesN<32>>) -> AccountContractClient {
AccountContractClient::new(e, &e.register(AccountContract {}, (signers,)))
}

fn sign(e: &Env, signer: &Keypair, payload: &BytesN<32>) -> Val {
Expand All @@ -53,17 +54,18 @@ fn test_token_auth() {
let env = Env::default();
env.mock_all_auths();

let account_contract = create_account_contract(&env);

let mut signers = [generate_keypair(), generate_keypair()];
if signers[0].public.as_bytes() > signers[1].public.as_bytes() {
signers.swap(0, 1);
}
account_contract.init(&vec![
let account_contract = create_account_contract(
&env,
signer_public_key(&env, &signers[0]),
signer_public_key(&env, &signers[1]),
]);
vec![
&env,
signer_public_key(&env, &signers[0]),
signer_public_key(&env, &signers[1]),
],
);

let payload = BytesN::random(&env);
let token = Address::generate(&env);
Expand Down
Loading
Loading