# Is it possible to check what contract functions are called in a transaction from a predicate?

**URL:** <https://forum.fuel.network/t/is-it-possible-to-check-what-contract-functions-are-called-in-a-transaction-from-a-predicate/4061>\
**Category:** General\
**Created:** [January 26, 2024, 3:37pm UTC](https://forum.fuel.network/t/is-it-possible-to-check-what-contract-functions-are-called-in-a-transaction-from-a-predicate/4061 "2024-01-26T15:37:41Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![mpoplavkov](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.fuel.network/mpoplavkov/32/399_2.png) [@mpoplavkov](https://forum.fuel.network/u/mpoplavkov)\
**Post date:** [January 26, 2024, 3:37pm UTC](https://forum.fuel.network/t/is-it-possible-to-check-what-contract-functions-are-called-in-a-transaction-from-a-predicate/4061/1 "2024-01-26T15:37:41Z")

</div>

Let’s say, I have a deployed contract with the following ABI:

```auto
abi TestContract {
    #[storage(read, write)]
    fn one();

    #[storage(read)]
    fn two();

    #[storage(write)]
    fn three();
}

```

And I want to write a predicate that would check that a specific function of this contract was called within the transaction. Something like:

```auto
predicate;

fn check_function_called(contract_id: ContractId, function_name: String) -> bool {
  ???
}

fn main() -> bool {
    check_function_called(CONTRACT_ID, "two")
}

```

This predicate should return true if and only if the function “two” was called.

From my understanding of predicates, that should be possible to do, but I don’t understand how to implement it

---

<div class="post-metadata">

**Author:** ![david](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.fuel.network/david/32/32_2.png) [@david](https://forum.fuel.network/u/david)\
**Post date:** [January 26, 2024, 4:45pm UTC](https://forum.fuel.network/t/is-it-possible-to-check-what-contract-functions-are-called-in-a-transaction-from-a-predicate/4061/2 "2024-01-26T16:45:17Z")

</div>

You can enforce this by having a script that calls that function, then have the predicate check that it’s the same script by verifying the script hash.

This is the technique we’ve used in this project (still WIP):

> **[GitHub - dmihal/fuel-gasless-nfts](https://github.com/dmihal/fuel-gasless-nfts)**
>
> Contribute to dmihal/fuel-gasless-nfts development by creating an account on GitHub.

I’ll try to simplify the logic here, first create a script:

```rust
script;

use std::constants::ZERO_B256;
use shared::{Mint};

configurable {
    NFT_CONTRACT: ContractId = ContractId::from(ZERO_B256),
}

fn main(recipient: Address) {
    let nft_contract = abi(Mint, NFT_CONTRACT.into());
    let _out = nft_contract.mint(Identity::Address(recipient));
}

```

Then create a predicate that verifies the script:

```rust
predicate;

use std::{
    constants::ZERO_B256,
    tx::tx_script_bytecode_hash,
};

configurable {
    EXPECTED_SCRIPT_BYTECODE_HASH: b256 = ZERO_B256,
}

fn main() -> bool {
    tx_script_bytecode_hash() == EXPECTED_SCRIPT_BYTECODE_HASH
}

```

Then you just need to make sure your code generates the correct script & predicates, filling in the configurables. This is roughly how we implemented it:

```rust
    let configurables = NFTScriptConfigurables::new()
        .with_NFT_CONTRACT(nft);
    let script = NFTScript::new(account.clone(), "./nft_script/out/debug/nft_script.bin")
        .with_configurables(configurables);

    let mut hasher = Sha256::new();
    hasher.update(
        script
            .main(account.address())
            .script_call
            .script_binary,
    );
    let script_hash = Bits256(hasher.finalize().into());

    let configurables = GasPredicateConfigurables::new()
        .with_EXPECTED_SCRIPT_BYTECODE_HASH(script_hash);

    let predicate: Predicate =
        Predicate::load_from("../gas_predicate/out/debug/gas_predicate.bin")
            .unwrap()
            .with_configurables(configurables);

```

---

<div class="post-metadata">

**Author:** ![mpoplavkov](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.fuel.network/mpoplavkov/32/399_2.png) [@mpoplavkov](https://forum.fuel.network/u/mpoplavkov)\
**Post date:** [January 26, 2024, 5:07pm UTC](https://forum.fuel.network/t/is-it-possible-to-check-what-contract-functions-are-called-in-a-transaction-from-a-predicate/4061/3 "2024-01-26T17:07:01Z")

</div>

Awesome, thank you! I’ll try it out

---

<div class="post-metadata">

**Author:** ![mpoplavkov](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.fuel.network/mpoplavkov/32/399_2.png) [@mpoplavkov](https://forum.fuel.network/u/mpoplavkov)\
**Post date:** [January 26, 2024, 5:28pm UTC](https://forum.fuel.network/t/is-it-possible-to-check-what-contract-functions-are-called-in-a-transaction-from-a-predicate/4061/4 "2024-01-26T17:28:24Z")

</div>

That’s only valid if the entire transaction is predefined, right? Is it possible to check if a specific function was called in case it’s only one step in the transaction (eg a multicall transaction).

Modifying your example, I can have two scripts:

```auto
script;

use std::constants::ZERO_B256;
use shared::{Mint};

configurable {
    NFT_CONTRACT: ContractId = ContractId::from(ZERO_B256),
}

fn main(recipient: Address) {
    let nft_contract = abi(Mint, NFT_CONTRACT.into());
    let _out = nft_contract.mint(Identity::Address(recipient));
}

```

and

```auto
script;

use std::constants::ZERO_B256;
use shared::{Mint};

configurable {
    NFT_CONTRACT: ContractId = ContractId::from(ZERO_B256),
}

fn main(recipient: Address, recipient2: Address) {
    let nft_contract = abi(Mint, NFT_CONTRACT.into());
    let _out = nft_contract.mint(Identity::Address(recipient));
    nft_contract.transfer(_out.tokenId, Identity::Address(recipient2));
}

```

Both calling the same function `nft_contract.mint`.  
Can I check that this function was called from within a predicate for any of these scripts?

---

<div class="post-metadata">

**Author:** ![david](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.fuel.network/david/32/32_2.png) [@david](https://forum.fuel.network/u/david)\
**Post date:** [January 29, 2024, 1:01pm UTC](https://forum.fuel.network/t/is-it-possible-to-check-what-contract-functions-are-called-in-a-transaction-from-a-predicate/4061/5 "2024-01-29T13:01:32Z")

</div>

It’s theoretically possible, you could introspect the script bytecode and just try to validate _part_ of it. But it would be a bit complicated, it’s not something we have an example for yet.

Also there would be ways to “trick” the validation, by inserting bytecode into the script that gets skipped over.
