Skip to content

DeadmanXXXII/Aptos_tests

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 

Repository files navigation

Aptos smart contract security tests:

module secret_vault::vault {
    use std::signer;
    use std::string::{Self, String};
    use aptos_framework::event;
    #[test_only]
    use std::debug;

    /// Error codes
    const NOT_OWNER: u64 = 1;

    struct Vault has key {
        secret: String
    }

    // events
    #[event]
    struct SetNewSecret has drop, store {}

    // --- ENTRY ---
    public entry fun set_secret(caller: &signer, secret: vector<u8>) {
        let secret_vault = Vault { secret: string::utf8(secret) };
        move_to(caller, secret_vault);
        event::emit(SetNewSecret {});
    }

    // --- VIEW ---
    #[view]
    public fun get_secret(caller: address): String acquires Vault {
        assert!(caller == @owner, NOT_OWNER);
        let vault = borrow_global<Vault>(@owner);
        vault.secret
    }

    // ================
    // Tests
    // ================
    // Happy path: set and read by inspecting the resource directly
    #[test(owner = @0xcc, user = @0x123)]
    fun test_secret_vault(owner: &signer, user: &signer) acquires Vault {
        use aptos_framework::account;

        // Set up accounts (ok to call in tests)
        account::create_account_for_test(signer::address_of(owner));
        account::create_account_for_test(signer::address_of(user));

        let secret = b"i'm a secret";
        set_secret(owner, secret);

        let o = signer::address_of(owner);
        let vault = borrow_global<Vault>(o);
        assert!(vault.secret == string::utf8(secret), 100);

        debug::print(&b"All tests passed!");
    }

    // Calling view with a non-owner address should abort with NOT_OWNER
    #[test(owner = @0xcc, user = @0x123)]
    #[expected_failure(abort_code = NOT_OWNER)]
    fun test_unauthorized_access(owner: &signer, user: &signer) acquires Vault { 
      use aptos_framework::account;
        account::create_account_for_test(signer::address_of(owner));
        account::create_account_for_test(signer::address_of(user));

        set_secret(owner, b"top secret");
        // get_secret asserts caller == @owner; passing user's address should abort
        let _ = get_secret(signer::address_of(user));
    }

    // Setting twice should abort because the resource already exists at owner
    #[test(owner = @0xcc)]
    #[expected_failure] // don't pin code; second move_to will fail
    fun test_double_set_fails(owner: &signer) {
        use aptos_framework::account;
        account::create_account_for_test(signer::address_of(owner));

        set_secret(owner, b"first");
        // second publish of the same resource should abort at VM level
        set_secret(owner, b"second");
    }

    // After a successful set, the value remains what we stored
    #[test(owner = @0xcc)]
    fun test_value_persists_after_set(owner: &signer) acquires Vault {
        use aptos_framework::account;
        account::create_account_for_test(signer::address_of(owner));

        let s1 = b"persist me";
        set_secret(owner, s1);

        let v = borrow_global<Vault>(signer::address_of(owner));
        assert!(v.secret == string::utf8(s1), 100);
    }

    #[test(owner = @0xcc, user = @0x123)]
    fun test_value_persists_after_set(owner: &signer) acquires Vault {
        use aptos_framework::account;
        account::create_account_for_test(signer::address_of(owner));

        let s1 = b"persist me";
        set_secret(owner, s1);

        let v = borrow_global<Vault>(signer::address_of(owner));
        assert!(v.secret == string::utf8(s1), 100);
    }

    #[test(owner = @0xcc, user = @0x123)]
    fun test_view_function_vulnerability(owner: &signer, user: &signer) acquires Vault {
    use aptos_framework::account;
        use std::signer;

    // Set up accounts
        account::create_account_for_test(signer::address_of(owner));
        account::create_account_for_test(signer::address_of(user));

    // Owner sets a secret
        let secret = b"my_super_secret";
        set_secret(owner, secret);

    // Assert that the user is not the owner to prove the test setup is correct
        assert!(signer::address_of(user) != signer::address_of(owner), 101);

    // Call the view function from the user's context, but pass the owner's address as the 'caller'
        let retrieved_secret = get_secret(signer::address_of(owner));

    // Assert that the retrieved secret matches the one set by the owner
    // This will cause the test to pass, proving the vulnerability
        assert!(retrieved_secret == string::utf8(secret), 102);

    }

    #[test(owner = @0xcc, attacker = @0x456)] 
    #[expected_failure(abort_code = NOT_OWNER)] 
    fun test_attacker_cannot_read_secret(owner: &signer, attacker: &signer) acqui>
    use aptos_framework::account;
    use std::signer;

    account::create_account_for_test(signer::address_of(owner));
    account::create_account_for_test(signer::address_of(attacker));

    set_secret(owner, b"top secret");
      // The attacker calls the get_secret function with a spoofed address
    // The test expects this to fail with NOT_OWNER.
    let _ = get_secret(signer::address_of(owner));

    }

    #[test(owner = @0xcc, attacker = @0x456)]  
    fun test_view_function_exploit(owner: &signer, attacker: &signer) acquires Vault {
    use aptos_framework::account;
    use std::signer;
    use std::debug; // You might need to add this line

    // Create accounts for the owner and the attacker.
    account::create_account_for_test(signer::address_of(owner));
    account::create_account_for_test(signer::address_of(attacker));

    // The owner sets the secret.
    let secret = b"my_super_secret";
    set_secret(owner, secret);

    // The attacker attempts to read the secret by providing the owner's addr>
    let stolen_secret = get_secret(signer::address_of(owner));

    // Print the stolen secret to the console.
    debug::print(&stolen_secret);

    // Assert that the attacker was able to retrieve the correct secret.
    // This will cause the test to pass, proving the vulnerability.
    assert!(stolen_secret == string::utf8(secret), 101);

    

    }


}

About

Smart contract security tests

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published