Points Program: Earn rewards and contribute to the Fuel Network.Learn more →

Account

0x7Ae5C24c33916dBb050503C13a3485BBBE6D2DA67f212415668E3De0dea93b7B0x7Ae5...3b7B

Bako Safe
The Bako Safe is a multi-signature wallet that supports Fuel native wallets and passkeys.

Source Code
predicate;

use std::{b512::B512, tx::{GTF_WITNESS_DATA, tx_id, tx_witnesses_count}};

use libraries::{
    constants::{
        BYTE_WITNESS_TYPE_FUEL,
        BYTE_WITNESS_TYPE_WEBAUTHN,
        EMPTY_SIGNERS,
        INVALID_ADDRESS,
        MAX_SIGNERS,
    },
    entities::{
        SignatureType,
        WebAuthnHeader,
    },
    recover_signature::{
        fuel_verify,
        webauthn_verify,
    },
    utilities::{
        b256_to_ascii_bytes,
    },
    validations::{
        check_duplicated_signers,
        check_signer_exists,
        verify_prefix,
    },
    webauthn_digest::{
        get_webauthn_digest,
    },
};

configurable {
    SIGNERS: [b256; 10] = EMPTY_SIGNERS,
    SIGNATURES_COUNT: u64 = 0,
    #[allow(dead_code)]
    HASH_PREDICATE: b256 = b256::zero(),
}

fn main() -> bool {
    let mut i_witnesses = 0;
    let mut verified_signatures: Vec<Address> = Vec::with_capacity(MAX_SIGNERS);

    while i_witnesses < tx_witnesses_count() {
        let mut witness_ptr = __gtf::<raw_ptr>(i_witnesses, GTF_WITNESS_DATA);
        if (verify_prefix(witness_ptr)) {
            let tx_bytes = b256_to_ascii_bytes(tx_id()); // are used 
            witness_ptr = witness_ptr.add_uint_offset(4); // skip bako prefix
            let signature = witness_ptr.read::<SignatureType>();
            witness_ptr = witness_ptr.add_uint_offset(__size_of::<u64>()); // skip enum size
            let pk: Address = match signature {
                SignatureType::WebAuthn(signature_payload) => {
                    let data_ptr = witness_ptr.add_uint_offset(__size_of::<WebAuthnHeader>());

                    webauthn_verify(
                        get_webauthn_digest(signature_payload, data_ptr, tx_bytes),
                        signature_payload,
                    )
                },
                SignatureType::Fuel(_) => {
                    let signature = witness_ptr.read::<B512>();

                    fuel_verify(signature, tx_bytes)
                },
                _ => INVALID_ADDRESS,
            };

            let is_valid_signer = check_signer_exists(pk, SIGNERS);
            check_duplicated_signers(is_valid_signer, verified_signatures);
        }

        i_witnesses += 1;
    }

    return verified_signatures.len() >= SIGNATURES_COUNT;
}
Bytecode
0x1a403000504100301a445000ba49000032400481504100205d490000504100083240048220451300524510044a4400007cf30ca9e83e8b7e0d1e608fb6252d53a08144a65cd73031ff2fbc52614b8a6a00000000000002303acff2fcb9ba9ef41fa22ec3af90402c824fc601325a56b8870bd344f9b1007f0000000000000001e49c40ba0898aea55ef5a19bc9e30afbb3857c1d0561b1d9f5cfe8133b64aee000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000042414b4f000000003031323334353637383961626364656600000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000cccccccccccc00020000000000001b1000000000000019e000000000000019d8000000000000160000000000000015a8000000000000117800000000000010f80000000000001064000000000000103c0000000000000fa00000000000000c1c00000000000009080000000000000838