Before Any Integration
Configure Your Policy: Before integrating Predicate, you must deploy a policy or use an existing one. The policy ID
must be stored in the ServiceManager
contract.
Access the Network: The Predicate labs entity maintains a free service (middleware) which has been optimized for
broadcasting tasks and aggregating signatures from the Operator Network.
Bridge Integration
This sample bridge contract inherits the Predicate Client, a library which provides necessary functions to enforce the
corresponding policy.
One such function is authorizeTransactions
, which verifies that the signatures nested in the authorization parameters
belong to registered Predicate Operators.
import {PredicateClient} from "@predicate/mixins/PredicateClient.sol";
contract Bridge is PredicateClient {
function dispatch(
uint32 destinationDomain,
bytes32 recipientAddress,
bytes calldata messageBody,
bytes calldata metadata,
PredicateMessage calldata predicateMessage
) public payable virtual returns (bytes32) {
bytes memory encodedSigAndArgs = abi.encodeWithSignature("_dispatch(uint32,bytes32,bytes,bytes)", receiver, amount);
require(_authorizeTransaction(predicateMessage, encodedSigAndArgs), "MetaCoin: unauthorized transaction");
return _dispatch(destinationDomain, recipientAddress, messageBody, metadata);
}
}
Before users submit a transaction to the above contract, the interface must fetch signatures from the Predicate Network.
Each Operator in the Predicate Network enforces and signs the transaction referencing the latest policy set by the
application owner (see the Predicate ServiceManager
contract).
To fetch these signatures, the front end makes an API call to the Predicate Middleware, which returns the signatures
alongside the transaction. The following is an example of how this is done.
import * as sdk from 'predicate-sdk'
const predicate = new sdk.PredicateClient({
apiUrl: PREDICATE_API_URL,
apiKey: PREDICATE_API_KEY,
});
const functionArgsPacked = sdk.packFunctionArgs("_dispatch(uint32,bytes32,bytes,bytes)",
[
destinationDomain,
recipientAddress,
messageBody,
metadata
]);
const predicateSignatures = await predicate.evaluatePolicy({
from: wallet.address,
to: contractAddress,
data: functionArgsPacked,
value: "0",
});
const predicateMessage = sdk.signaturesToBytes(result.data);
const tx: ethers.TransactionResponse = await contract[
"dispatch(uint32,bytes32,bytes,bytes,(string,uint256,address[],bytes[]))"
](destinationDomain,
recipientAddress,
messageBody,
metadata,
predicateMessage);
await tx.wait()