Cuenta Simple
Este ejemplo implementa la cuenta de contrato más pequeña posible contract account: cada llamada require_auth delega en una clave pública ed25519. Muestra cómo almacenar esa clave, ejecutar __check_auth y mostrar fallos de autorización. Usa esto como base antes de pasar al Ejemplo de Cuenta Compleja para firmas múltiples o aplicación de políticas.
Implementar una cuenta de contrato requiere un muy buen entendimiento de la autenticación y autorización y exige pruebas rigurosas y revisión. El ejemplo aquí no es un contrato de cuenta completo: úsalo solo como referencia de la API.
Aunque las cuentas de contrato son compatibles con el protocolo Stellar y el SDK Soroban, el soporte completo del cliente (como simulación de transacciones) aún está en desarrollo.
Ejecutar el Ejemplo
- Completa la lista de verificación de [Configuración] para instalar Stellar CLI, el objetivo Rust y las variables de entorno necesarias.
- Clona el repositorio
soroban-examplesen la etiquetav23.0.0:
git clone -b v23.0.0 https://github.com/stellar/soroban-examples
- Si prefieres no instalar nada localmente, lanza el repositorio en GitHub Codespaces o Codeanywhere.
Ejecuta las pruebas desde el directorio simple_account:
cd simple_account
cargo test
Salida esperada:
running 1 test
test test::test_account ... ok
Cómo Funciona
Abre simple_account/src/lib.rs. El contrato mantiene un único estado: la clave pública ed25519 del propietario.
Inicializar al propietario
#[contracttype]
#[derive(Clone)]
pub enum DataKey {
Owner,
}
#[contractimpl]
impl SimpleAccount {
pub fn init(env: Env, public_key: BytesN<32>) {
if env.storage().instance().has(&DataKey::Owner) {
panic!("owner is already set");
}
env.storage().instance().set(&DataKey::Owner, &public_key);
}
Llama a init una vez para guardar la clave pública del propietario. Llamadas posteriores causan un pánico para evitar reemplazar la clave.
Implementar __check_auth
#[allow(non_snake_case)]
pub fn __check_auth(
env: Env,
signature_payload: BytesN<32>,
signature: BytesN<64>,
_auth_context: Vec<Context>,
) {
let public_key: BytesN<32> = env
.storage()
.instance()
.get(&DataKey::Owner)
.unwrap();
env.crypto()
.ed25519_verify(&public_key, &signature_payload.into(), &signature);
}
}
__check_auth se ejecuta cada vez que otro contrato invoca require_auth en esta dirección de contrato. La implementación carga la clave almacenada, verifica la firma y provoca un pánico en caso de fallo para que la llamada upstream de require_auth sea rechazada. Cuando necesites múltiples claves o lógica de políticas, sigue el mismo patrón mostrado en la Cuenta Compleja.
Pruebas
Abre simple_account/src/test.rs. __check_auth no está expuesto como un punto de entrada regular, así que las pruebas llaman a env.try_invoke_contract_check_auth para emular el host de Soroban y ejecutar la misma ruta que Soroban usa durante require_auth.
#[test]
fn test_account() {
let env = Env::default();
let account_contract = SimpleAccountClient::new(&env, &env.register(SimpleAccount, ()));
let signer = Keypair::generate(&mut thread_rng());
account_contract.init(&signer.public.to_bytes().into_val(&env));
let payload = BytesN::random(&env);
env.try_invoke_contract_check_auth::<Error>(
&account_contract.address,
&payload,
sign(&env, &signer, &payload),
&vec![&env],
)
.unwrap();
assert!(env
.try_invoke_contract_check_auth::<Error>(
&account_contract.address,
&payload,
BytesN::<64>::random(&env).into(),
&vec![&env],
)
.is_err());
}
try_invoke_contract_check_auth simula la ruta del host para require_auth, permitiendo probar tanto el caso de éxito como un caso de fallo con bytes aleatorios.
Sigue la misma estructura para cualquier cuenta:
- crea un par de claves y guarda el firmante esperado (por ejemplo, con
init) - llama a
try_invoke_contract_check_authcon una firma válida y verifica que tenga éxito - llámalo de nuevo con una firma o carga inválida y verifica que falle
Compilar el Contrato
Para producir el ejecutable Wasm, ejecuta:
stellar contract build
# add --package soroban-simple-account-contract when building inside the soroban-examples workspace
El archivo compilado aparece en target/wasm32v1-none/release/simple_account.wasm (el nombre exacto depende del nombre de tu crate).
Lecturas Adicionales
- Ejemplo de cuenta compleja – añade soporte para multisig y límites de gasto.
- Contrato de firma BLS – demuestra esquemas de firma personalizados dentro de
__check_auth.