Skip to content

tjdragon/DFNS-CallPol

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

🛡️ DFNS Service Accounts & Smart Contract Operations

This guide explains the concept of Service Accounts within the DFNS ecosystem and demonstrates how they can be used to programmatically approve or reject smart contract operations based on custom on-chain data decoding.


🤖 What is a Service Account?

In traditional systems, policies are often evaluated based on static rules (e.g., "Is the transaction amount under $1000?"). However, interacting with Web3 and Smart Contracts requires a deeper level of dynamic evaluation.

When a user initiates a transaction to a smart contract, the actual details of what that transaction is doing (who gets tokens, which admin function is called, etc.) are buried inside an ABI-encoded data payload.

A Service Account acts as an automated, programmatic "Checker" in a Maker/Checker workflow. It allows you to:

  1. Intercept a pending policy approval.
  2. Decode the complex on-chain transaction data (the ABI payload).
  3. Evaluate custom business logic against the decoded parameters.
  4. Decide autonomously to either Approve or Deny the transaction.

By granting a Service Account the right to approve transactions within a Policy, you create a powerful, automated middle-tier for risk management and compliance.

Tip

Production Best Practice In a true Maker/Checker production environment, the initiatorCanApprove flag on the policy should be set to false, ensuring that the human initiating the transaction cannot bypass the automated checks enforced by the Service Account.


🛠️ How SCApproveOrReject.ts Works

The script SCApproveOrReject.ts is a concrete implementation of an automated Service Account. It pulls pending approvals, unpacks the Ethereum transaction payload, applies business rules, and automatically registers a decision with the DFNS API.

Here is the step-by-step breakdown of its workflow:

1. Fetching Pending Approvals

The script leverages the DFNS SDK to query the policy engine for any approvals currently waiting in a Pending state.

const approvals = await dfnsApi.policies.listApprovals({
  query: { status: 'Pending' }
});

2. Loading the Contract ABI

To understand what the transaction is trying to do, the script needs the "dictionary" for the smart contract. It loads the StableCoin.json artifact (generated by Hardhat) to retrieve the ABI (Application Binary Interface).

const artifactPath = path.join(__dirname, '../artifacts/contracts/StableCoin.sol/StableCoin.json');
const artifact = JSON.parse(fs.readFileSync(artifactPath, 'utf8'));
const { abi } = artifact;

3. Validating the Target Contract

Before attempting to decode anything, the script first verifies that the transaction is actually destined for the correct smart contract address. If not, the transaction is rejected or ignored.

const toAddress = requestBody.to;
if (toAddress != '0x007cb8aafaa9eb5b411ebece99f1671a286d2ee8') {
  console.log("This is the wrong smart contract address. Rejecting")
  continue;
}

4. 🧩 ABI Decoding (The Core Logic)

This is where the magic happens. The script uses the viem library to take the raw hex string from requestBody.data and decode it using the previously loaded ABI.

const decoded = decodeFunctionData({
  abi,
  data: requestBody.data as `0x${string}`
});

If the transaction was a call to the mint(address to, uint256 amount) function, decodeFunctionData transforms the unreadable hex into structured data:

  • decoded.functionName: "mint"
  • decoded.args: ["0x126b39aFd4c1027168bf936B68C4d011793E7609", 9000000n]

5. Applying Business Rules

With the data decoded into usable TypeScript variables, the Service Account can now enforce complex business logic.

In this specific script, the rules are:

  1. Is it the mint function?
  2. Is the destination address whitelisted? (e.g., must be 0x126b39aFd4c1027168bf936B68C4d011793E7609).
  3. Is the amount within safe limits? (e.g., amount must be $\le$ 10,000,000).
if (decoded.functionName === 'mint') {
  const [destinationAddress, amount] = decoded.args as [string, bigint];
  
  // Rule 1 Check: Destination Address
  if (destinationAddress != '0x126b39aFd4c1027168bf936B68C4d011793E7609') {
     await reject(approval.id)
  } else {
     // Rule 2 Check: Amount Limit
     if (amount <= 10000000) {
        await approve(approval.id)
     } else {
        await reject(approval.id) // Too large!
     }
  }
}

6. Executing the Decision

Finally, the script calls back to the DFNS API, acting as the Service Account user, to officially register the Approved or Denied decision on the policy.

await dfnsApi.policies.createApprovalDecision({
  approvalId,
  body: {
    value: 'Approved', // or 'Denied'
    reason: 'Verified transaction details with finance team'
  }
})

🚦 Summary

By combining DFNS Policy Approvals with ABI Decoding, SCApproveOrReject.ts demonstrates a robust, automated pipeline. It prevents malicious or erroneous smart contract interactions before they ever reach the blockchain, all without requiring manual human intervention for every single transaction.

About

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors