Skip to content

Commit

Permalink
feat: Argent Cairo 1 account contract support
Browse files Browse the repository at this point in the history
  • Loading branch information
xJonathanLEI committed Sep 15, 2023
1 parent 05ebd12 commit 430f46e
Show file tree
Hide file tree
Showing 6 changed files with 111 additions and 46 deletions.
22 changes: 11 additions & 11 deletions 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 Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ serde = { version = "1.0.164", features = ["derive"] }
serde_json = { version = "1.0.99", features = ["preserve_order"] }
serde_with = "2.3.3"
shellexpand = "3.1.0"
starknet = { git = "https://github.com/xJonathanLEI/starknet-rs", rev = "a5e23d08c6ec8cac4dbedb1d291aa5a8e4b3ba64" }
starknet = { git = "https://github.com/xJonathanLEI/starknet-rs", rev = "f16271877c9dbf08bc7bf61e4fc72decc13ff73d" }
tempfile = "3.8.0"
thiserror = "1.0.40"
tokio = { version = "1.28.2", default-features = false, features = ["macros", "rt-multi-thread"] }
Expand Down
73 changes: 52 additions & 21 deletions src/account.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,22 +20,27 @@ use crate::path::ExpandedPathbufParser;

const BRAAVOS_SIGNER_TYPE_STARK: FieldElement = FieldElement::ONE;

pub const KNOWN_ACCOUNT_CLASSES: [KnownAccountClass; 3] = [
pub const KNOWN_ACCOUNT_CLASSES: [KnownAccountClass; 4] = [
KnownAccountClass {
class_hash: felt!("0x048dd59fabc729a5db3afdf649ecaf388e931647ab2f53ca3c6183fa480aa292"),
variant: AccountVariantType::OpenZeppelin,
description: "OpenZeppelin account contract v0.6.1 compiled with cairo-lang v0.11.0.2",
},
KnownAccountClass {
class_hash: felt!("0x025ec026985a3bf9d0cc1fe17326b245dfdc3ff89b8fde106542a3ea56c5a918"),
variant: AccountVariantType::Argent,
description: "Argent X official proxy account",
variant: AccountVariantType::ArgentLegacy,
description: "Argent X legacy (Cairo 0) proxy account",
},
KnownAccountClass {
class_hash: felt!("0x03131fa018d520a037686ce3efddeab8f28895662f019ca3ca18a626650f7d1e"),
variant: AccountVariantType::Braavos,
description: "Braavos official proxy account",
},
KnownAccountClass {
class_hash: felt!("0x01a736d6ed154502257f02b1ccdf4d9d1089f80811cd6acad48e6b6a9d1f2003"),
variant: AccountVariantType::Argent,
description: "Argent X official account",
},
];

#[derive(Debug, Clone, Parser)]
Expand Down Expand Up @@ -79,8 +84,9 @@ pub struct KnownAccountClass {

pub enum AccountVariantType {
OpenZeppelin,
Argent,
ArgentLegacy,
Braavos,
Argent,
}

#[serde_as]
Expand All @@ -97,10 +103,13 @@ pub struct OzAccountConfig {
#[derive(Serialize, Deserialize)]
pub struct ArgentAccountConfig {
pub version: u64,
#[serde_as(as = "Option<UfeHex>")]
#[serde(default, skip_serializing_if = "Option::is_none")]
pub implementation: Option<FieldElement>,
#[serde_as(as = "UfeHex")]
pub implementation: FieldElement,
#[serde_as(as = "UfeHex")]
pub signer: FieldElement,
// Old account files use `signer`
#[serde(alias = "signer")]
pub owner: FieldElement,
#[serde_as(as = "UfeHex")]
pub guardian: FieldElement,
}
Expand Down Expand Up @@ -223,18 +232,33 @@ impl AccountConfig {
&[oz.public_key],
FieldElement::ZERO,
)),
AccountVariant::Argent(argent) => Ok(get_contract_address(
undeployed_status.salt,
undeployed_status.class_hash,
&[
argent.implementation, // implementation
selector!("initialize"), // selector
FieldElement::TWO, // calldata_len
argent.signer, // calldata[0]: signer
argent.guardian, // calldata[1]: guardian
],
FieldElement::ZERO,
)),
AccountVariant::Argent(argent) => match argent.implementation {
Some(implementation) => {
// Legacy Cairo 0 account deployment
Ok(get_contract_address(
undeployed_status.salt,
undeployed_status.class_hash,
&[
implementation, // implementation
selector!("initialize"), // selector
FieldElement::TWO, // calldata_len
argent.owner, // calldata[0]: signer
argent.guardian, // calldata[1]: guardian
],
FieldElement::ZERO,
))
}
None => {
// Cairo 1 account deployment without using proxy
Ok(get_contract_address(
undeployed_status.salt,
undeployed_status.class_hash,
&[argent.owner, argent.guardian],
FieldElement::ZERO,
))
}
},

AccountVariant::Braavos(braavos) => {
if !matches!(braavos.multisig, BraavosMultisigConfig::Off) {
anyhow::bail!("Braavos accounts cannot be deployed with multisig on");
Expand Down Expand Up @@ -279,7 +303,13 @@ impl AccountVariant {
ExecutionEncoding::New
}
}
AccountVariant::Argent(_) => ExecutionEncoding::Legacy,
AccountVariant::Argent(argent) => {
if argent.implementation.is_some() {
ExecutionEncoding::Legacy
} else {
ExecutionEncoding::New
}
}
AccountVariant::Braavos(_) => ExecutionEncoding::Legacy,
}
}
Expand All @@ -306,8 +336,9 @@ impl Display for AccountVariantType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
AccountVariantType::OpenZeppelin => write!(f, "OpenZeppelin"),
AccountVariantType::Argent => write!(f, "Argent X"),
AccountVariantType::ArgentLegacy => write!(f, "Legacy Argent X (Cairo 0)"),
AccountVariantType::Braavos => write!(f, "Braavos"),
AccountVariantType::Argent => write!(f, "Argent X"),
}
}
}
Expand Down
12 changes: 5 additions & 7 deletions src/subcommands/account/argent/init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,8 @@ use crate::{
};

/// Official hashes used as of extension version 5.7.0
const ARGENT_PROXY_CLASS_HASH: FieldElement =
felt!("0x025ec026985a3bf9d0cc1fe17326b245dfdc3ff89b8fde106542a3ea56c5a918");
const ARGENT_IMPL_CLASS_HASH: FieldElement =
felt!("0x033434ad846cdd5f23eb73ff09fe6fddd568284a0fb7d1be20ee482f044dabe2");
const ARGENT_CLASS_HASH: FieldElement =
felt!("0x01a736d6ed154502257f02b1ccdf4d9d1089f80811cd6acad48e6b6a9d1f2003");

#[derive(Debug, Parser)]
pub struct Init {
Expand Down Expand Up @@ -56,12 +54,12 @@ impl Init {
version: 1,
variant: AccountVariant::Argent(ArgentAccountConfig {
version: 1,
implementation: ARGENT_IMPL_CLASS_HASH,
signer: signer.get_public_key().await?.scalar(),
implementation: None,
owner: signer.get_public_key().await?.scalar(),
guardian: FieldElement::ZERO,
}),
deployment: DeploymentStatus::Undeployed(UndeployedStatus {
class_hash: ARGENT_PROXY_CLASS_HASH,
class_hash: ARGENT_CLASS_HASH,
salt,
context: None,
}),
Expand Down
13 changes: 10 additions & 3 deletions src/subcommands/account/deploy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,19 +100,26 @@ impl Deploy {
)
}
AccountVariant::Argent(argent_config) => {
// It's probably not worth it to continue to support legacy account deployment.
// Users can always deploy with an old Starkli version.
if argent_config.implementation.is_some() {
anyhow::bail!(
"deployment of legacy Argent X (Cairo 0) accounts is no longer supported"
);
}

// Makes sure we're using the right key
if signer_public_key != argent_config.signer {
if signer_public_key != argent_config.owner {
anyhow::bail!(
"public key mismatch. Expected: {:#064x}; actual: {:#064x}.",
argent_config.signer,
argent_config.owner,
signer_public_key
);
}

AnyAccountFactory::Argent(
ArgentAccountFactory::new(
undeployed_status.class_hash,
argent_config.implementation,
chain_id,
FieldElement::ZERO,
signer.clone(),
Expand Down
35 changes: 32 additions & 3 deletions src/subcommands/account/fetch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ impl Fetch {
legacy: true,
})
}
AccountVariantType::Argent => {
AccountVariantType::ArgentLegacy => {
let implementation = provider
.call(
FunctionCall {
Expand Down Expand Up @@ -138,8 +138,8 @@ impl Fetch {

AccountVariant::Argent(ArgentAccountConfig {
version: 1,
implementation,
signer,
implementation: Some(implementation),
owner: signer,
guardian,
})
}
Expand Down Expand Up @@ -211,6 +211,35 @@ impl Fetch {
signers,
})
}
AccountVariantType::Argent => {
let owner = provider
.call(
FunctionCall {
contract_address: address,
entry_point_selector: selector!("get_owner"),
calldata: vec![],
},
BlockId::Tag(BlockTag::Pending),
)
.await?[0];
let guardian = provider
.call(
FunctionCall {
contract_address: address,
entry_point_selector: selector!("get_guardian"),
calldata: vec![],
},
BlockId::Tag(BlockTag::Pending),
)
.await?[0];

AccountVariant::Argent(ArgentAccountConfig {
version: 1,
implementation: None,
owner,
guardian,
})
}
};

let account = AccountConfig {
Expand Down

0 comments on commit 430f46e

Please sign in to comment.