# DEP 0002: Smart Contract Composability

```
status: deprecated
```

## Current Situation

When creating the DAO, we needed to invent the concept of protocol
owned liquidity in DarkFi. Without this, in order to have on chain DAO
treasuries, the DarkFi blockchain would have to recognize funds held by
both the money and DAO contracts as valid. This introduces a security
risk if there is an error in the DAO contracts.

Additionally it means that liquidity could only be held by the DAO
contract, and any liquidity held by other contracts would have to be
recognized by the consensus as valid. This would restrict the protocols
that could work with on chain liquidity to a small hardcoded subset
due to security.

Motivated by the desire to enable protocol owned liquidity, we created
the concept in `money::transfer()` of the `spend_hook`.

Firstly a quick recap of how `money::transfer()` works. During the
mint phase of creating coins, we construct a coin
`C = hash(…, spend_hook, user_data)`. The `…` contains coin data such
as value, token ID and other attributes. During the burn phase we
produce a deterministic unlinkable nullifier.

This is a more general ZK concept of committing to several attributes,
and then later either full on revealing them or more specifically
applying constraints to the attributes. To enable protocol owned
liquidity, we introduced the coin attributes `spend_hook` and
`user_data`, motivated by these desires:

* Generalize protocol-owned liquidity enabling any third party to write
  contracts that own liquidity.
* Stronger security model for on chain liquidity by only depending on
  the money contract when composed with contracts like the DAO.

When a coin is spent, the `spend_hook` is revealed publicly. The
`money::transfer()` call enforces that the subsequent contract called
in the tx matches the `spend_hook`. In our example, `spend_hook = DAO`,
and then our tx will have two calls: `[money::transfer(), DAO::exec()]`.
When spending a coin where the `spend_hook = DAO`, then
`money::transfer()` will check the next contract in the tx will match
the `spend_hook`.

Now you might ask some questions:

* Here we are listing `DAO`, but actually we need a stricter check that
  the call is `DAO::exec()` and not some other DAO method call.
* We need to enforce which DAO we are operating on.

This is where the `user_data` is used. We can commit to several things
including which function is called in the contract. Since in the DAO,
only `DAO::exec()` can be composed, we just sidestep this and enforce
that when a tx has two calls, then the DAO one must be `DAO::exec()`.
We then use the `user_data` to store the DAO bulla.

## Motivation: Limitations of Current Approach

The current approach enables contracts to own liquidity, which is how
we can have DAO on chain treasuries. We have the ability for contracts
to directly call other contracts. However this calling mechanism is
static.

We desire now to generalize the DAO calling mechanism, so any contract
could be called. Currently `DAO::exec()` deserializes the
`money::transfer()` calldata, and then enforces its checks on it inside
wasm. These checks are hardcoded.

It would be very useful if instead this data or code were to be
dynamic. Therefore a DAO proposal could be called, not to call
`money::transfer()` but instead to call another contract. This system
would then be generic and usable with other contracts, such as an
algorithmic streaming contract making calls on a ZK NFT.

## Proposal: Introspective Params

The current `ContractCall` struct looks like:

```rust
pub struct ContractCall {
    /// ID of the contract invoked
    pub contract_id: ContractId,
    /// Call data passed to the contract
    pub data: Vec<u8>,
}
```

We propose to change the `data` field to this:

```rust
pub struct ContractCall {
    /// ID of the contract invoked
    pub contract_id: ContractId,
    /// Named call data passed to the contract
    pub data: HashMap<String, Vec<u8>>,
}
```

This way contracts can query each other's calldata in a dynamic
compatible way. Some part of the params for a contract may be specific
to that contract. Another part might be generic, which shares the same
struct with multiple other contracts. This enables contracts to query
an interface from another contract's calldata, deserialize that data
and work with it, without having to hardcode a dependency, e.g.
`DAO::exec()` hardcoding a dependency on `money::transfer()` params.

## Note on Auth Modules

An alternative approach is introducing the concept of auth modules. So
for example, with the DAO, a user could deploy their own contract on
chain with specific logic, then make a proposal to execute that
contract. We could also supply our own auth module with hardcoded
branching support for several common contract types.

However while this may be desirable in some cases where complex logic
in DAO proposals are required, it presents several downsides:

* The supplied auth module will hardcode support for a few contract
  types and not be properly generic.
* User deployed contracts could be expensive and error prone.
* For efficiency the DAO would probably end up hardcoding support for
  several contract types directly, as well as other composable contracts.
