How to make sure every party agrees to protocol

Hi - I’ve been playing around with the IOU starter example. Let’s say I want to instantiate a protocol between Alice, the issuer on the IOU, and Bob, the payee. Strangely, I can deploy such a protocol by using Bob’s access token on /npl/objects/iou/Iou/ and pass on Alice’s claims as an issuer. But Alice could not agree to owe anything to Bob. How do you make sure this is not possible? Thanks

Welcome to our forum!

Right now it is indeed not directly possible to prohibit this.

The usual workaround is to not annotate the constructor with @api and instead use a factory protocol to ensure the IOU is created with the appropriate party bindings.

We recognize that this is not ideal, so we’re working hard on a new feature which allows you to declaratively prevent such assignments. I don’t know the exact timeline, but is should land soon.

To add to this, we could implement ways to make sure every party interacts with a protocol before actions can be taken, or restrict the claims that can be used for protocol creation to the ones in the JWT or any other combination. For your use-case of financial agreement, it may be an easy win.

Yet this would very quickly become a constraint for building applications generally. When it is not possible to use a ruleset for automated party assignment and enforcement, modelling the interaction you seek in NPL is best.

For your specific use-case, two additional states will give you the certainty to only have ‘unpaid’ IOUs that actually need to be unpaid. Other implementation may work too.

@api
protocol[issuer, payee] FullyAgreedIou(var forAmount: Number) {
    require(forAmount > 0, "Initial amount must be strictly positive");

    initial state requested;
    state issuerApproved;
    state payeeApproved;
    state unpaid;
    final state paid;
    final state forgiven;

    @api
    permission[issuer] issuerApprove() | requested, payeeApproved {
        if (activeState().getOrFail() == FullyAgreedIou.States.requested) {
            become issuerApproved;
        } else {
            become unpaid;
        };
    };

    @api
    permission[payee] payeeApprove() | requested, issuerApproved {
        if (activeState().getOrFail() == FullyAgreedIou.States.requested) {
            become payeeApproved;
        } else {
            become unpaid;
        };
    }
    // everything else being equall
}

This problem can now be solved using Party Automation