# Usage

### What You're Building <a href="#what-youre-building" id="what-youre-building"></a>

Think of `TargetBase` as your smart contract's security bouncer. It's a battle-tested foundation that gives you signature-based authorization, smart account enforcement, and all the protection you need for EIP-7702 delegated accounts—without having to reinvent the wheel.

This guide walks you through extending TargetBase to build your own secure contracts. We'll use the RealEstateInvestment contract as our real-world example because, well, nothing teaches better than actual code.

### What TargetBase Does For You <a href="#what-targetbase-does-for-you" id="what-targetbase-does-for-you"></a>

Here's what you get out of the box:

* **Signature-based authorization** – Only calls signed by your master key get through
* **Smart account validation** – Enforces EIP-7702 compliance (no random EOAs sneaking in)
* **Replay attack protection** – Nonces and hash tracking ensure each authorization works exactly once
* **Time-bound authorizations** – Set expiry timestamps so old signatures can't haunt you
* **Emergency recovery** – Because sometimes you need a backup plan
* **Multi-source execution chains** – Perfect for when you need to aggregate data from multiple sources

Think of it as a security framework that handles all the hard parts so you can focus on your business logic.

### The Core Building Blocks <a href="#the-core-building-blocks" id="the-core-building-blocks"></a>

#### AuthData <a href="#authdata-your-authorization-package" id="authdata-your-authorization-package"></a>

Every protected function needs one of these. It's like a VIP pass that proves the caller has permission:

```solidity
struct AuthData {
    uint256 nonce;              // Prevents replay attacks
    uint256 expiry;             // "This signature expires on..."
    bytes32 id;                 // Unique execution identifier
    Execution[] executions;     // For multi-step operations
    bytes result;               // The final data or parameters
    bool sponsorExecutionFee;   // Who pays the gas?
    bytes signature;            // The master key's signature
}
```

#### The Authorization Players <a href="#the-authorization-players" id="the-authorization-players"></a>

* **Master Key** – The VIP who signs everything. This is your authorization authority.
* **Recovery Key** – Your emergency contact. Can rotate the master key if things go wrong.
* **Owner** – The admin. Controls contract settings and upgrades.
* **DelegatedAccount** – The only type of account allowed to call your protected functions (EIP-7702 smart accounts only)

### How to Extend TargetBase (The Three-Step Implementation) <a href="#how-to-extend-targetbase-the-three-step-recipe" id="how-to-extend-targetbase-the-three-step-recipe"></a>

#### Step 1: Set Up Your Contract <a href="#step-1-set-up-your-contract" id="step-1-set-up-your-contract"></a>

Start by inheriting from TargetBase. You can mix in other contracts too—we're using ERC20 in our real estate example:

```solidity
contract YourContract is TargetBase, [OtherContracts] {
    constructor(
        address _authKey,
        address _recoveryKey,
        address _owner,
        address _delegatedAccountImpl,
        // your additional parameters
    ) TargetBase(_authKey, _recoveryKey, _owner, _delegatedAccountImpl) {
        // your initialization magic happens here
    }
}
```

{% hint style="info" %}
**Pro tip**: Pass those four addresses to TargetBase first, then handle your own initialization. Order matters!
{% endhint %}

#### Step 2: Define Your Data Structures <a href="#step-2-protect-your-functions" id="step-2-protect-your-functions"></a>

Before you do anything else, define the structs that will carry your data which is basically the result your are expected from the KRNL node as a part of the workflow execution. These are what you'll encode/decode in `authData.result`:

```solidity
// What your protected function will actually use
struct YourResponseStruct {
    uint256 someField;           // 0-100
    uint256 expectedAnnualYield;  // In basis points
    string investmentGrade;       // "A+", "A", "B+", etc.
    uint256 propertyValue;        // In USD
    string recommendation;        // "INVEST", "HOLD", or "PASS"
}
```

**Important**: The fields in your struct should be **alphabetically ordered** when you're working with external data sources. This ensures consistent encoding/decoding across different systems.

#### Step 2: Protect Your Functions <a href="#step-2-protect-your-functions" id="step-2-protect-your-functions"></a>

Now when you integrate KRNL to your smart contract, you use `requireAuth(authData)` modifier to do the basic validation check like your nonce, expiry, etc and make `AuthData` your first parameter:

```solidity
function yourProtectedFunction(
    AuthData calldata authData,  // Always first!
    // then your actual business parameters
) external requireAuth(authData) {
    // By the time this runs, TargetBase has already verified:
    // ✓ The caller is a legit EIP-7702 account
    // ✓ The signature is valid
    // ✓ The nonce is correct
    // ✓ It hasn't expired
    // ✓ It hasn't been used before
    
    // Your business logic here
}
```

#### Step 3: Decode Your Data (When You Need It) <a href="#step-3-decode-your-data-when-you-need-it" id="step-3-decode-your-data-when-you-need-it"></a>

If you're working with multi-source execution chains or need to extract data from the authorization:

```solidity
function submitData(AuthData calldata authData) 
    external requireAuth(authData) 
{
    // Unpack the final result from your execution chain
    YourResponseStruct memory response = 
        abi.decode(authData.result, (YourResponseStruct));
    
    // Now validate it
    require(response.someField > threshold, "Not good enough!");
    
    // And use it
    // ... your business logic
}
```

### Real-World Example: Tokenizing Real Estate <a href="#real-world-example-tokenizing-real-estate" id="real-world-example-tokenizing-real-estate"></a>

Let's look at how the RealEstateInvestment contract does it. This contract lets people buy fractional ownership of properties using USDC. It needs TargetBase because property analysis data comes from multiple sources (Zillow, Census data, AI analysis) and needs to be verified before allowing investments.

```solidity
contract RealEstateInvestment is TargetBase, ERC20 {

    // Step 1: Define the response struct for property analysis
    struct PropertyAnalysisResponse {
        uint256 confidence;           // Fields alphabetically ordered
        uint256 expectedAnnualYield;
        string investmentGrade;
        uint256 propertyValue;
        string recommendation;
    }
    
    // Step 2: Set up the constructor
    // Notice we're mixing TargetBase with ERC20—totally fine!
    constructor(
        address _authKey,
        address _recoveryKey, 
        address _owner,
        address _delegatedAccountImpl,
        address _usdcToken,
        string memory _propertyAddress
    ) TargetBase(_authKey, _recoveryKey, _owner, _delegatedAccountImpl) 
      ERC20("Real Estate Property Token", "REPT") {
        // Initialize our business-specific stuff
        usdc = IERC20(_usdcToken);
        property.propertyAddress = _propertyAddress;
    }

    // Step 3: Create a protected function that handles multi-source data
    function submitPropertyAnalysis(AuthData calldata authData) 
        external requireAuth(authData) 
    {
        // This data came from a chain of executions:
        // Zillow API → Census data → AI analysis
        // We decode the final aggregated result
        PropertyAnalysisResponse memory analysisResponse = 
            abi.decode(authData.result, (PropertyAnalysisResponse));
        
        // Always validate before trusting!
        if (analysisResponse.confidence < MIN_CONFIDENCE) {
            revert ConfidenceTooLow();
        }
        
        // Now we can safely use it
        property.totalValue = analysisResponse.propertyValue;
        property.investmentGrade = analysisResponse.investmentGrade;
        
        // Pro move: Emit events with authData context for audit trails
        emit PropertyAnalyzed(
            msg.sender,
            authData.nonce,
            authData.id,
            property.propertyAddress,
            analysisResponse.propertyValue,
            // ... more event params
        );
    }
    
    // Step 4: Another Protected function with business parameters
    function purchaseTokens(
        AuthData calldata authData,  // Auth first
        uint256 usdcAmount           // Then your params
    ) external requireAuth(authData) {
        // Authorization already verified, just do your thing
        require(usdcAmount >= MIN_INVESTMENT, "Need at least 1000 USDC");
        
        // Calculate tokens, transfer USDC, mint tokens, etc.
        // ... your business logic
    }
}
```

**What's happening here?**

* The constructor handles both TargetBase and ERC20 initialization
* `submitPropertyAnalysis` decodes complex multi-source data and validates it
* `purchaseTokens` combines authorization with business parameters
* Events include `authData.nonce` and `authData.id` for complete traceability

### Things to Avoid <a href="#the-rules-of-the-game" id="the-rules-of-the-game"></a>

#### When Setting Up Your Constructor <a href="#when-setting-up-your-constructor" id="when-setting-up-your-constructor"></a>

* **No zero addresses** – TargetBase will reject them. Every address parameter matters.
* **DelegatedAccount must be real** – It needs to be an actual deployed contract with code. No empty addresses or EOAs.
* **Order matters** – Pass the four TargetBase parameters first, in order: `_authKey, _recoveryKey, _owner, _delegatedAccountImpl`

#### When Writing Protected Functions <a href="#when-writing-protected-functions" id="when-writing-protected-functions"></a>

* **AuthData always comes first** – It's not just convention, it's how the pattern works. `function myFunc(AuthData calldata authData, ...)`
* **Use the modifier** – Don't forget `requireAuth(authData)`. That's where all the magic happens.
* **Include context in events** – Always emit `authData.nonce` and `authData.id` in your events. Future you will thank present you when debugging!

#### The Security Guarantees <a href="#the-security-guarantees" id="the-security-guarantees"></a>

Here's what TargetBase enforces automatically:

* **EIP-7702 only** – No EOAs allowed. Only properly delegated smart accounts get through.
* **Sequential nonces** – Can't skip ahead or go backward. If Alice is on nonce 5, her next call must use nonce 5, then 6, then 7...
* **Expiry matters** – That timestamp isn't just for show. Expired = rejected.
* **One-time use** – Each authorization is like a ticket. Once it's used, it's burned. No replays, no exceptions.

### Best Practices <a href="#smart-moves-best-practices" id="smart-moves-best-practices"></a>

**Emit meaningful events**\
Include `authData.nonce` and `authData.id` in every event. Six months from now when you're debugging a production issue, you'll want that audit trail. Trust me.

**Validate everything**\
Just because data made it through authorization doesn't mean it's correct. Always validate decoded results before using them. Check ranges, verify checksums, enforce business rules.

**Use custom errors**\
TargetBase uses them for a reason—they're gas-efficient and more descriptive. `revert InsufficientFunds()` beats `require(balance > 0, "Insufficient funds")` every time.

**Protect against reentrancy**\
TargetBase includes `nonReentrant` protection. Use it on any function that changes state or moves value around.

**Keep view functions simple**\
Don't use `requireAuth` on view or pure functions. They don't change state, so they don't need authorization. Save the gas.

**Use Ownable for admin stuff**\
TargetBase inherits from Ownable, so you get `onlyOwner` for free. Use it for administrative functions that shouldn't go through the auth flow.

### Three Common Patterns You Can Use <a href="#three-common-patterns-youll-use" id="three-common-patterns-youll-use"></a>

#### Pattern 1: Simple Authorization (Just Verify, No Data) <a href="#pattern-1-simple-authorization-just-verify-no-data" id="pattern-1-simple-authorization-just-verify-no-data"></a>

```solidity
function simpleAction(AuthData calldata authData) 
    external requireAuth(authData) 
{
    // No data decoding needed
    // Just verify the caller is authorized and execute
    someState = true;
}
```

#### Pattern 2: Multi-Source Data Pipeline <a href="#pattern-2-multi-source-data-pipeline" id="pattern-2-multi-source-data-pipeline"></a>

```solidity
function complexAction(AuthData calldata authData) 
    external requireAuth(authData) 
{
    // Decode the aggregated result from your execution chain
    FinalResult memory result = abi.decode(authData.result, (FinalResult));
    
    // Validate it
    require(result.confidence >= MIN_CONFIDENCE, "Low confidence");
    
    // Use it
    processResult(result);
}
```

#### Pattern 3: Authorization + Business Parameters <a href="#pattern-3-authorization--business-parameters" id="pattern-3-authorization--business-parameters"></a>

```solidity
function businessAction(
    AuthData calldata authData,
    uint256 amount,
    address recipient
) external requireAuth(authData) {
    // Combine authorization with your own parameters
    // Auth is verified, now validate your business logic
    require(amount > 0, "Amount must be positive");
    require(recipient != address(0), "Invalid recipient");
    
    // Do your thing
    transfer(recipient, amount);
}
```

**When to use each:**

* **Pattern 1**: Permission changes, state toggles, simple actions
* **Pattern 2**: External data validation, multi-API aggregation, complex analysis
* **Pattern 3**: Most common! Authorized actions with user-provided parameters

<br>
