# Syndicate Smart RPC with Shield3 Previous demo link: https://hackmd.io/@shield3/HypAXccXT ## Summary This demo shows an example implementation of Shield3's policy engine & RPC to support the gas subsidized transaction use case with Syndicate. The goal is to determine whether or not a subsidized user transaction, and a corresponding subsidy transaction should be submitted based on a set of rules provided by Syndicate. An account has been configured with the following policies: 1. Allow subsidized transactions to specific contracts only 2. Allow value transfers below a max subsidy amount 3. Allow subsidy transactions for 'fresh' accounts (nonce < x) - NOTE this is an optional alternative to tracking how many subsidies a wallet has received. If the wallet has been used a certain amount of times we could assume they can get some gas for themselves to continue transacting 4. Block subsidy recipients if the recipient has a balance > X (If they have the funds to pay the gas fees don't need to subsidy probably) 5. Block specific addresses from receiving subsidy transactions (custom block list and compliance based lists) *Note on IP address based policies* - If the transactions come directly to Shield3 first this would be feasible to implement blocklists, but if they are coming from Syndicate backend with the simulate call they would probably have to pass the original IP address along with the tx. Also IP based rate limiting for subsidies is a bit more involved but not impossible. The main issue is keeping track of this in a way that it can be referenced in policies. The state policies refer to is mostly on chain. ## Suggested implementation with bundle simulation Bundle simulation has been added to the Shield3 RPC. This allows both the subsidy transaction & the subsidized transaction to be submitted in one call and receive the policy results. ### Example API Request & Response In this example request the user is calling a valid subsidized contract. The subsidy sender is in a group of authorized subsidy senders and is sending a small value transaction to the user. In the API response ```javascript subsidizedContractAddress = '0xbEc332E1eb3EE582B36F979BF803F98591BB9E24' subsidySenderExample = '0x2000000000000000000000000000000000000002' userSenderExample = '0x3000000000000000000000000000000000000003' ``` #### Request Params contains `[[serializedUserTx, userAddress], [serializedSubsidyTx, subsidySenderAddress]]` ```json { "jsonrpc": "2.0", "method": "eth_simulateTransactionBundle", "params": [ [ "0xe8808512a05f20008307a12094bec332e1eb3ee582b36f979bf803f98591bb9e248080830138818080", "0x3000000000000000000000000000000000000003" ], [ "0xf0278512a05f20008307a12094400000000000000000000000000000000000000488016345785d8a000080830138818080", "0x2000000000000000000000000000000000000002" ] ], "id": 42 } ``` #### Response The response contains an array with results for both transaction. The top level field `decision` indicates the overall result for the transaction. For a bundle to be allowed both items should have an `Allow` result. Individual policy information is included to describe the detailed reason why a transaction is or is not allowed. ```json= { "jsonrpc": "2.0", "result": [ { "transaction": { "id": "3070a8b8-7eb6-42ec-a068-d269f6d39e21", "team_id": "466ad3c1-f971-4d21-b983-1e8450d56510", "network": "0x013881", "tx_status": "Simulated", "decoded_type": "unknown", "tx_context": { "raw_tx": "0xe8808512a05f20008307a12094bec332e1eb3ee582b36f979bf803f98591bb9e248080830138818080", "validated_tx": { "r": "0x0000000000000000000000000000000000000000000000000000000000000000", "s": "0x0000000000000000000000000000000000000000000000000000000000000000", "v": 0, "to": "0xbEc332E1eb3EE582B36F979BF803F98591BB9E24", "data": "0x", "from": "0x3000000000000000000000000000000000000003", "type": null, "nonce": 0, "value": { "hex": "0x00", "type": "BigNumber" }, "chainId": 80001, "network": "0x013881", "gasLimit": { "hex": "0x07a120", "type": "BigNumber" }, "gasPrice": { "hex": "0x12a05f2000", "type": "BigNumber" } } }, "policies_triggered": 5, "workflow_results": { "policyResults": [ { "name": "Account Balance Limit", "result": { "errors": [], "reasons": [ { "invoked": true, "policy_id": "policy1", "annotations": { "name": "Account Balance Restriction", "message": "Allow subsidized transactions for accounts with balance less than 1" } }, { "invoked": false, "policy_id": "policy0", "annotations": { "name": "Allow Subsidy Transactions", "message": "Allow subsidy senders to send transactions to any address", "dependency": "verified_addresses:2de656ef-a0b5-423a-b975-1356a59f3ee6" } } ], "decision": "Allow" }, "policyId": "bdcedc62-faa0-4d00-baa8-9700ae281541", "policySource": "Team", "policyDecision": "Allow" }, { "name": "Native value threshold", "result": { "errors": [], "reasons": [ { "invoked": true, "policy_id": "policy1", "annotations": { "name": "Base Permit" } }, { "invoked": true, "policy_id": "policy0", "annotations": { "name": "Allow Native Transfers Under Threshold", "message": "Allow Native Transfers Under Threshold" } }, { "invoked": false, "policy_id": "policy2", "annotations": { "name": "Block Native Transfers Over Threshold", "message": "Block Native Transfers Over Threshold" } } ], "decision": "Allow" }, "policyId": "6d99cb11-1a12-491a-b29a-fb316160faa6", "policySource": "Team", "policyDecision": "Allow" }, { "name": "Sender Nonce Limit", "result": { "errors": [], "reasons": [ { "invoked": true, "policy_id": "policy0", "annotations": { "name": "Account Nonce Restriction", "message": "Allow subsidized transactions for accounts with nonce less than 5" } }, { "invoked": false, "policy_id": "policy1", "annotations": { "name": "Allow Subsidy Transactions", "message": "Allow subsidy senders to send transactions to any address", "dependency": "verified_addresses:2de656ef-a0b5-423a-b975-1356a59f3ee6" } } ], "decision": "Allow" }, "policyId": "cf63a026-68fc-45fe-9d2f-fc95237a5e99", "policySource": "Team", "policyDecision": "Allow" }, { "name": "Subsidized Contract Group", "result": { "errors": [], "reasons": [ { "invoked": true, "policy_id": "policy1", "annotations": { "name": "Allow Subsidized Transactions", "message": "Restrict subsidized transactions to list of contracts", "dependency": "verified_apps:fa85abea-68a5-454a-8970-ae040d7d1f46" } }, { "invoked": false, "policy_id": "policy0", "annotations": { "name": "Allow Subsidy Transactions", "message": "Allow subsidy senders to send transactions to any address", "dependency": "verified_addresses:2de656ef-a0b5-423a-b975-1356a59f3ee6" } } ], "decision": "Allow" }, "policyId": "9b814006-71de-4355-9f74-8ac2f0b2f620", "policySource": "Team", "policyDecision": "Allow" }, { "name": "OFAC SDN block native and ERC20 transactions", "result": { "errors": [], "reasons": [ { "invoked": false, "policy_id": "policy5", "annotations": { "name": "Standard ERC20 TransferFrom Block OFAC - Specially Designated Nationals List", "message": "Allow ERC20 transfer from unless blocked sender or recipient", "dependency": "shared_addresses:0312e487-e4c5-4c6d-8364-12da10853d99" } }, { "invoked": false, "policy_id": "policy1", "annotations": { "name": "Standard ERC20 TransferFrom Block OFAC - Specially Designated Nationals List", "message": "Allow ERC20 transfer from unless blocked sender or recipient", "dependency": "shared_addresses:0312e487-e4c5-4c6d-8364-12da10853d99" } }, { "invoked": false, "policy_id": "policy4", "annotations": { "name": "Non-Standard ERC20 Transfer Block OFAC - Specially Designated Nationals List", "message": "Allow ERC20 transfer unless blocked sender or recipient", "dependency": "shared_addresses:0312e487-e4c5-4c6d-8364-12da10853d99" } }, { "invoked": true, "policy_id": "policy3", "annotations": { "name": "Address or Contract Block OFAC - Specially Designated Nationals List", "message": "Allow transactions unless blocked sender or recipient or contract", "dependency": "shared_addresses:0312e487-e4c5-4c6d-8364-12da10853d99" } }, { "invoked": false, "policy_id": "policy0", "annotations": { "name": "Non-Standard ERC20 Approve Block OFAC - Specially Designated Nationals List", "message": "Allow ERC20 approve unless blocked sender or recipient", "dependency": "shared_addresses:0312e487-e4c5-4c6d-8364-12da10853d99" } }, { "invoked": false, "policy_id": "policy6", "annotations": { "name": "Standard ERC20 Approve Block OFAC - Specially Designated Nationals List", "message": "Allow ERC20 approve unless blocked sender or spender", "dependency": "shared_addresses:0312e487-e4c5-4c6d-8364-12da10853d99" } }, { "invoked": false, "policy_id": "policy2", "annotations": { "name": "Standard ERC20 Transfer Block OFAC - Specially Designated Nationals List", "message": "Allow ERC20 transfer unless blocked sender or recipient", "dependency": "shared_addresses:0312e487-e4c5-4c6d-8364-12da10853d99" } } ], "decision": "Allow" }, "policyId": "5df5f234-bb93-42d5-82b8-a1f11db9eaa2", "policySource": "Shared", "policyDecision": "Allow" } ], "routingDecision": "Allow" }, "created_at": "2024-03-01T19:06:34.413Z", "updated_at": "2024-03-01T19:06:35.285Z" }, "decision": "Allow" }, { "transaction": { "id": "1419ac05-2b3f-4898-88f9-a92c5d0b26a8", "team_id": "466ad3c1-f971-4d21-b983-1e8450d56510", "network": "0x013881", "tx_status": "Simulated", "decoded_type": "unknown", "tx_context": { "raw_tx": "0xf0278512a05f20008307a12094400000000000000000000000000000000000000488016345785d8a000080830138818080", "validated_tx": { "r": "0x0000000000000000000000000000000000000000000000000000000000000000", "s": "0x0000000000000000000000000000000000000000000000000000000000000000", "v": 0, "to": "0x4000000000000000000000000000000000000004", "data": "0x", "from": "0x2000000000000000000000000000000000000002", "type": null, "nonce": 39, "value": { "hex": "0x016345785d8a0000", "type": "BigNumber" }, "chainId": 80001, "network": "0x013881", "gasLimit": { "hex": "0x07a120", "type": "BigNumber" }, "gasPrice": { "hex": "0x12a05f2000", "type": "BigNumber" } } }, "policies_triggered": 5, "workflow_results": { "policyResults": [ { "name": "Account Balance Limit", "result": { "errors": [], "reasons": [ { "invoked": true, "policy_id": "policy1", "annotations": { "name": "Account Balance Restriction", "message": "Allow subsidized transactions for accounts with balance less than 1" } }, { "invoked": true, "policy_id": "policy0", "annotations": { "name": "Allow Subsidy Transactions", "message": "Allow subsidy senders to send transactions to any address", "dependency": "verified_addresses:2de656ef-a0b5-423a-b975-1356a59f3ee6" } } ], "decision": "Allow" }, "policyId": "bdcedc62-faa0-4d00-baa8-9700ae281541", "policySource": "Team", "policyDecision": "Allow" }, { "name": "Native value threshold", "result": { "errors": [], "reasons": [ { "invoked": true, "policy_id": "policy0", "annotations": { "name": "Allow Native Transfers Under Threshold", "message": "Allow Native Transfers Under Threshold" } }, { "invoked": true, "policy_id": "policy1", "annotations": { "name": "Base Permit" } }, { "invoked": false, "policy_id": "policy2", "annotations": { "name": "Block Native Transfers Over Threshold", "message": "Block Native Transfers Over Threshold" } } ], "decision": "Allow" }, "policyId": "6d99cb11-1a12-491a-b29a-fb316160faa6", "policySource": "Team", "policyDecision": "Allow" }, { "name": "Sender Nonce Limit", "result": { "errors": [], "reasons": [ { "invoked": false, "policy_id": "policy0", "annotations": { "name": "Account Nonce Restriction", "message": "Allow subsidized transactions for accounts with nonce less than 5" } }, { "invoked": true, "policy_id": "policy1", "annotations": { "name": "Allow Subsidy Transactions", "message": "Allow subsidy senders to send transactions to any address", "dependency": "verified_addresses:2de656ef-a0b5-423a-b975-1356a59f3ee6" } } ], "decision": "Allow" }, "policyId": "cf63a026-68fc-45fe-9d2f-fc95237a5e99", "policySource": "Team", "policyDecision": "Allow" }, { "name": "Subsidized Contract Group", "result": { "errors": [], "reasons": [ { "invoked": true, "policy_id": "policy0", "annotations": { "name": "Allow Subsidy Transactions", "message": "Allow subsidy senders to send transactions to any address", "dependency": "verified_addresses:2de656ef-a0b5-423a-b975-1356a59f3ee6" } }, { "invoked": false, "policy_id": "policy1", "annotations": { "name": "Allow Subsidized Transactions", "message": "Restrict subsidized transactions to list of contracts", "dependency": "verified_apps:fa85abea-68a5-454a-8970-ae040d7d1f46" } } ], "decision": "Allow" }, "policyId": "9b814006-71de-4355-9f74-8ac2f0b2f620", "policySource": "Team", "policyDecision": "Allow" }, { "name": "OFAC SDN block native and ERC20 transactions", "result": { "errors": [], "reasons": [ { "invoked": false, "policy_id": "policy1", "annotations": { "name": "Standard ERC20 TransferFrom Block OFAC - Specially Designated Nationals List", "message": "Allow ERC20 transfer from unless blocked sender or recipient", "dependency": "shared_addresses:0312e487-e4c5-4c6d-8364-12da10853d99" } }, { "invoked": false, "policy_id": "policy2", "annotations": { "name": "Standard ERC20 Transfer Block OFAC - Specially Designated Nationals List", "message": "Allow ERC20 transfer unless blocked sender or recipient", "dependency": "shared_addresses:0312e487-e4c5-4c6d-8364-12da10853d99" } }, { "invoked": false, "policy_id": "policy4", "annotations": { "name": "Non-Standard ERC20 Transfer Block OFAC - Specially Designated Nationals List", "message": "Allow ERC20 transfer unless blocked sender or recipient", "dependency": "shared_addresses:0312e487-e4c5-4c6d-8364-12da10853d99" } }, { "invoked": false, "policy_id": "policy5", "annotations": { "name": "Standard ERC20 TransferFrom Block OFAC - Specially Designated Nationals List", "message": "Allow ERC20 transfer from unless blocked sender or recipient", "dependency": "shared_addresses:0312e487-e4c5-4c6d-8364-12da10853d99" } }, { "invoked": false, "policy_id": "policy0", "annotations": { "name": "Non-Standard ERC20 Approve Block OFAC - Specially Designated Nationals List", "message": "Allow ERC20 approve unless blocked sender or recipient", "dependency": "shared_addresses:0312e487-e4c5-4c6d-8364-12da10853d99" } }, { "invoked": false, "policy_id": "policy6", "annotations": { "name": "Standard ERC20 Approve Block OFAC - Specially Designated Nationals List", "message": "Allow ERC20 approve unless blocked sender or spender", "dependency": "shared_addresses:0312e487-e4c5-4c6d-8364-12da10853d99" } }, { "invoked": true, "policy_id": "policy3", "annotations": { "name": "Address or Contract Block OFAC - Specially Designated Nationals List", "message": "Allow transactions unless blocked sender or recipient or contract", "dependency": "shared_addresses:0312e487-e4c5-4c6d-8364-12da10853d99" } } ], "decision": "Allow" }, "policyId": "5df5f234-bb93-42d5-82b8-a1f11db9eaa2", "policySource": "Shared", "policyDecision": "Allow" } ], "routingDecision": "Allow" }, "created_at": "2024-03-01T19:06:35.299Z", "updated_at": "2024-03-01T19:06:35.959Z" }, "decision": "Allow" } ], "id": "1" } ```