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

Account

0x5780d32eef8Ba2c87aeA78b2E2D8d4450eEcc070E4e6d2550F828c412165801A0x5780...801A

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
0x1a403000504100301a445000ba49000032400481504100205d490000504100083240048220451300524510044a4400007cf30ca9e83e8b7e0d1e608fb6252d53a08144a65cd73031ff2fbc52614b8a6a00000000000002301bce3fd60567c32cd3505c5cddb13e6a94cc08b11b7ba1aa0bdd0e8cb725596a00000000000000023cde1cb504d0793e2eb3db82ee9ba8e728c35ab5ab3b28ad4a44d0a5f73d8b1e12e81b31a0a14f60dcfa7ed51474113f7c0ef513e1e57bbef9f3ba74e3f9419877c960337715b598feb92ac53b3f736ca9f87c88abc42bb02b763c738e69679a14f849df2eca7f13fa8baa8faa5478ef2fcdabe1bb7223dc9cd664940d60d0ff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000042414b4f000000003031323334353637383961626364656600000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000cccccccccccc00020000000000001b1000000000000019e000000000000019d8000000000000160000000000000015a8000000000000117800000000000010f80000000000001064000000000000103c0000000000000fa00000000000000c1c00000000000009080000000000000838