Approved Calls

Overview

This policy provides an additional security layer, by having the sender first submit the transaction's data for off-chain validation before it can be sent your protocol's smart contract.

Protected Attack Vector

This policy protects against attacks that are difficult (or impossible) to detect on-chain by integrating advanced off-chain security checks. One such example is detecting a transaction that will cause a bridge imbalance across two (or more) separate networks.

How It Works

  1. Before sending a transaction to the blockchain, your DApp needs to send the transaction data to a Signer API.

  2. If the transaction passes all checks performed by the Signer API, a secure signature will be returned.

  3. The DApp can now submit this signature to the policy by calling the approveCallsViaSignature() method.

  4. Finally, the DApp can now submit the original transaction and it will be allowed to go through.

Coming Soon: We're building a DApp SDK to make this integration seamless for DApps.

Setup Instructions

  1. Deploy your own version of this policy (see Source Code).

  2. Add the newly deployed policy to the Firewall (you can do this Globally or Per-Method, see Policy Administration).

  3. That's it!

If you're just getting started, we recommend you use Ironblocks' Signer API

Step By Step Example

  1. Before submitting your transaction to the blockchain, send it to a Signer API to get a secure signature:

const to = RECIPIENT_CONTRACT_ADDRESS;

const from = YOUR_WALLET_ADDRESS;

const approvingPolicyAddress = POLICY_ADDRESS

const chainId = 56 // BNB Smart Chain

const data = yourSmartContractInterface.encodeFunctionData('deposit()'); // 0x3B9ACA00

const value = '0x1';

const payload = {approvingPolicyAddress, chainId, to, from, data, value};

const response = await axios.post(
    'https://api.ironblocks.com/services/firewall/sign',
    payload
);

  1. The response object has the following interface:

interface Response {
     requestId: string;
     status:  "approved" | "rejected";
     message: string;
     
     data: {
          callHashes: string[];
          expiration: number;
          txOrigin: Web3Address;
          nonce: number;
          signature: string;
     };
}

NOTE: Your response will have a Status Code 200 whether it's approved or rejected , as long as it was validly transmitted and received.

  1. Once you receive the signature you can register your signature with the policy, which will allow the original transaction to pass when submitted on-chain. You do this by calling the approveCallsViaSignature() method on the policy.

Properties

Name
Type
Description

approvedCalls

mapping

(address => bytes32[])

maps a sender (tx.origin) to it's signed call hashes

approvedCallsExpiration

mapping

(address => uint256)

maps a sender to most recent timestamp of an approved call

Methods

approveCallsViaSignature()

function approveCallsViaSignature(bytes32[] calldata _callHashes, uint256 expiration, address txOrigin, uint nonce, bytes memory signature)

Approves a call via a secure signature (from the Signer API)

Parameter Name
Type
Description

_callHashes

bytes32[] calldata

the call hashes to approve

expiration

uint256

the expiration time of these approved calls

txOrigin

address

the transaction origin of the approved hashes

nonce

uint

used internally to prevent replay attacks

signature

bytes memory

the signature of the signer with the above parameters

Security Lifecycle

This policy runs during the Firewall's Pre-Execution hook.

Source Code

On our GitHub repository: ApprovedCallsPolicy.sol

Last updated