Skip to content

Commit

Permalink
add 27-token-interface-inference.md
Browse files Browse the repository at this point in the history
  • Loading branch information
tomasavola authored Sep 12, 2024
1 parent c0d468e commit 1e09b19
Showing 1 changed file with 97 additions and 0 deletions.
97 changes: 97 additions & 0 deletions docs/docs/detectors/27-token-interface-inference.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
# Token interface inference

## Description

- Category: `Best practices`
- Severity: `Enhancement`
- Detector: [`token-interface-inference`](https://github.com/CoinFabrik/scout-soroban/tree/main/detectors/token-interface-inference)
- Test Cases: [`token-interface-inference-1`](https://github.com/CoinFabrik/scout-soroban/tree/main/test-cases/token-interface-inference/token-interface-inference-1)

In Rust, the use of tokens requires strictly following a set of specifications. If any of these are not met, the contract will have errors and fail. Therefore, the use of the `soroban_sdk::token::TokenInterface` trait is really useful because it warns if any of the specifications are not being fulfilled.

## Why is this bad?

Not using the `soroban_sdk::token::TokenInterface` trait makes it more difficult to comply with the token interface.

## Issue example

Consider the following `Soroban` contract:

```rust

#[contract]
pub struct TokenInterfaceInference;

#[contractimpl]
impl TokenInterfaceInference {
pub fn initialize(
env: Env,
admin: Address,
decimals: u32,
name: String,
symbol: String,
) -> Result<(), TIIError> {
let current_token_metadata: Option<TokenMetadata> =
env.storage().instance().get(&DataKey::TokenMetadata);
if current_token_metadata.is_some() {
return Err(TIIError::AlreadyInitialized);
} else {
env.storage().instance().set(
&DataKey::TokenMetadata,
&TokenMetadata {
decimals,
name,
symbol,
admin,
},
);
}

Ok(())
}

```


In this example, the trait `soroban_sdk::token::TokenInterface` is not implemented; instead, a contract named "TokenInterfaceInference" is implemented.

The code example can be found [here](https://github.com/CoinFabrik/scout-soroban/tree/main/test-cases/token-interface-inference/token-interface-inference-1/vulnerable-example).


## Remediated example

Consider the following `Soroban` contract:

```rust

#[contractimpl]
impl token::TokenInterface for TokenInterfaceEvents {
fn allowance(env: Env, from: Address, spender: Address) -> i128 {
let allowance = Self::get_allowance(env.clone(), from, spender);
if allowance.expiration_ledger < env.ledger().sequence() {
0
} else {
allowance.amount
}
}

```

In this example, the trait `soroban_sdk::token::TokenInterface` is implemented on a contract called "TokenInterfaceEvents".

The remediated code example can be found [here](https://github.com/CoinFabrik/scout-soroban/tree/main/test-cases/token-interface-inference/token-interface-inference-1/remediated-example).

## How is it detected?

Checks if token handling is being implemented in the contract and warns if the trait `soroban_sdk::token::TokenInterface` is not being used.











0 comments on commit 1e09b19

Please sign in to comment.