# Source Chain Smart Contracts

{% hint style="danger" %}
Please note that all information and code snippets provided in this section are for educational purposes only and not to be directly deployed in production.
{% endhint %}

## What is a Source Chain Smart Contract?

A source chain smart contract is a contract living on a client chain such as <img src="https://1740410107-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FVp3bVdljVxZuwysnIzZ1%2Fuploads%2FzN7KJNKew9VX4QvOd1zI%2Feth-diamond-purple.7929ed26.png?alt=media&#x26;token=6acf48bb-010a-4feb-a563-d91e4ebcfe7f" alt="" data-size="line"> `Ethereum` that is supported by the <img src="https://1740410107-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FVp3bVdljVxZuwysnIzZ1%2Fuploads%2FNAKy4UUXIWbarZjUxJIV%2Fcreditcoin-CTC-logo.png?alt=media&#x26;token=acf9a8d0-310e-49be-a7cd-17bb73895786" alt="" data-size="line"> `Creditcoin` Oracle. Source chain contracts have two main responsibilities:

1. Support any source chain logic required by their Universal DApp.
2. Emit events that contain the data their DApp needs to verify and process on Creditcoin

Let's focus on these one by one.

### Source chain logic

Most logic and data for Universal DApps should live in contracts on Creditcoin (the execution chain) rather than the source chain. Keep source chain logic minimal—typically just enough to handle asset movements (e.g., burning tokens, locking assets) and emit events.

**Best practices:**

* Minimize source chain logic to reduce gas costs and complexity
* Keep business logic on Creditcoin where it can leverage the oracle's verification capabilities
* Use source chain contracts primarily for emitting events that trigger cross-chain actions

### Emitting Events

This is the way by which the *source chain* will communicate with the *execution chain*. When a source chain contract emits an event, it becomes part of the transaction's receipt logs, which can be cryptographically verified on Creditcoin. Imagine that you want a simple DApp which burns ERC20 tokens on Ethereum and mints corresponding ERC20 tokens on Creditcoin. Then you would want your [source chain smart contract](https://docs.creditcoin.org/usc/infrastructure-overview#source-chain-smart-contract) to emit an event such as `TokensBurned`.

**Event design considerations:**

* Use `indexed` parameters for efficient filtering (up to 3 indexed parameters)
* Include all data the DApp needs in the event parameters
* Keep event signatures consistent to simplify parsing in USC contracts

### Example Source chain contract

The following example shows a simple ERC20 contract that supports a token bridge DApp. When tokens are "burned" (transferred to a burn address), a custom `TokensBurned` event is emitted, which can be verified on Creditcoin to trigger token minting.

**Key features:**

* Emits a custom `TokensBurned` event for easy filtering by [offchain workers](https://docs.creditcoin.org/usc/dapp-builder-infrastructure/offchain-oracle-workers)
* Uses a burn address (`0x...01`) to represent token burning
* The `TokensBurned` event includes all necessary data (`from`, `value`)
* Workers can easily filter for this specific event signature and then generate proofs to submit to the USC contract

```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";

contract TestERC20 is ERC20 {
    address public constant BURN_ADDRESS = address(1); // 0x...01

    /// @notice Emitted when tokens are burned (sent to the burn address).
    /// @param from The address burning their tokens
    /// @param value The amount of tokens burned
    event TokensBurned(address indexed from, uint256 value);

    constructor() ERC20("Burn Test", "TEST") {
        // Mint sender initial supply
        _mint(msg.sender, 1_000_000 ether);
    }

    /// @notice "Burn" by transferring tokens to the 0x...01 sink address.
    /// @dev This does NOT reduce totalSupply; it only makes tokens inaccessible.
    /// @param amount The amount of tokens to burn
    /// @return success Whether the transfer succeeded
    function burn(uint256 amount) external returns (bool) {
        _transfer(msg.sender, BURN_ADDRESS, amount);
        emit TokensBurned(msg.sender, amount);
        return true;
    }
}
```

## Next Steps

[universal-smart-contracts](https://docs.creditcoin.org/usc/dapp-builder-infrastructure/universal-smart-contracts "mention")

*Check out* [*this tutorial*](https://github.com/gluwa/usc-testnet-bridge-examples) *for an example of how to use the Creditcoin stack to set up a decentralized trustless bridge.*
