← Digital Assets

Stellar and Soroban signing policies

Set rules for Stellar operations and Soroban contract calls before signing.

Stellar operations

Choose which operation types your key may sign. Check amounts, source accounts, fees, and the combined value of a payment batch.

Integration guide
Edict exampleshowcase-xlm.edict
authority "showcase-xlm" {
    intent = "xlm.transaction"
    version = "1"

    config {
        networkPassphrase = "Public Global Stellar Network ; September 2015"
    }

    let XLM = 10000000

    approver treasury {
        type = "reference"
        id = "treasury"
        ref = "treasury@sha256:<digest>"
    }

    approver security {
        type = "reference"
        id = "security"
        ref = "security@sha256:<digest>"
    }

    fn nativePaymentTotal(operations: List<Operation>): Integer {
        var total = 0

        for (op in operations) {
            if (op.type != "payment" or op.explicitSource or op.transfer == null) {
                return -1
            }

            if (op.transfer.type != "native.transfer" or op.transfer.amount <= 0) {
                return -1
            }

            total = total + op.transfer.amount
        }

        return total
    }

    policy "reviewed-payments" {
        let total = nativePaymentTotal(transaction.operations)

        allow when {
            transaction.type == "v1"
            transaction.fee > 0
            transaction.fee <= 1000
            transaction.operations.count() <= 5
            total > 0
            total <= 1000 * XLM
        }

        require 2 of [treasury, security]
    }
}

Soroban contract calls

Declare Soroban contracts and methods. Check decoded arguments, set rules across all calls in a transaction, and choose which calls need approval.

Integration guide
Edict exampleshowcase-soroban.edict
authority "showcase-soroban" {
    intent = "xlm.transaction"
    version = "1"

    config {
        networkPassphrase = "Public Global Stellar Network ; September 2015"
    }

    contract token: soroban {
        address = "CADAMBQGAYDAMBQGAYDAMBQGAYDAMBQGAYDAMBQGAYDAMBQGAYDAMSST"

        fn approve(
            from: address,
            spender: address,
            amount: i128,
            live_until_ledger: u32
        )
    }

    let tokenUnit = 10000000

    approver treasury {
        type = "reference"
        id = "treasury"
        ref = "treasury@sha256:<digest>"
    }

    approver security {
        type = "reference"
        id = "security"
        ref = "security@sha256:<digest>"
    }

    policy "reviewed-allowances" {
        allow when {
            transaction.fee > 0
            transaction.fee <= 1000000
            token.approve.count() == 1
            token.approve.all(call -> call.from == transaction.sourceAccount)
            token.approve.all(call -> call.amount >= 0)
            token.approve.sum(call -> call.amount) <= 1000 * tokenUnit
        }

        require security if (token.approve.any(call -> call.amount > 0))
    }
}