Bitpanda Enterprise
  1. Tutorials
Bitpanda Enterprise
  • Bitpanda Enterprise
    • Getting Started
      • Overview
      • Authentication
      • Versioning and API Changes
      • Changelog
    • REST API Endpoints
      • Overview
      • Auth Tokens
        • Obtain a Refresh and Access Tokens
        • Revoke a Refresh Token
      • User Administration
        • Individual Users
          • Create new user
          • Get user list v2
          • Search for users
          • Get user details v2
          • Update an existing user
          • Get user details
          • Off-boarding user
          • Inactivate user
          • Get user accepted Terms & Conditions
          • Get user accepted Terms & Conditions v2
          • User verification files
          • Get account levels
        • Businesses
          • Get risk questions
          • Get a list of available businesses
          • Create new business
          • Get business details
          • Update an existing business
          • Create Authorized Individual
          • Get a list of Authorized Individuals
          • Get Authorized Individual details
          • Update Authorized Individual
          • Delete Authorized Individual
          • Create Shareholder
          • Get a list of Shareholders
          • Get Shareholder details
          • Update Shareholder
          • Delete Shareholder
          • Create Beneficial Owner
          • Get a list of Beneficial Owners
          • Get Beneficial Owner details
          • Update Beneficial Owner
          • Delete Beneficial Owner
          • Create Managing Director
          • Get a list of Managing Directors
          • Get Managing Director details
          • Update Managing Director
          • Delete Managing Director
          • Create Individual
          • Get a list of Individuals
          • Get Individual details
          • Update Individual
          • Delete Individual
        • User Files
          • Upload a file
          • Get file contents
          • Get file information
        • Legal & Regulatory
          • Get Terms & Conditions
          • Get Terms & Conditions v2
          • Get AML questions
          • Get appropriateness questions
          • Get client categorization questionnaire
          • Get DAC8 questionnaire
          • Get FATCA questionnaire
          • Get Legal Documents
          • Capture consent for User's final check
          • Retrieve Tax Identification Number Configuration
          • Get UK appropriateness questionnaire
          • Get appropriateness questionnaire for complex products
          • Get client categorization questionnaire
          • Get UK Risk Disclosure Warning
          • Acknowledge UK Risk Disclosure Warning
          • Get user compliance status
      • Asset Oversight
        • Available Assets
          • Get a list of available assets
          • Get a list of available assets v2
        • Asset Details
          • Get asset details
          • Get asset details v2
        • Asset History
          • Get asset history
          • Get asset history
        • Asset Info
          • Get asset information
          • Get asset information
        • Cryptocoin Details
          • Get cryptocoin details
          • Get cryptocoin details
        • Metal Details
          • Get metal details
          • Get metal details
        • Crypto Index Details
          • Get crypto index details
          • Get crypto index details
        • Stock Details
          • Get stock details
          • Get stock details
        • Equity Stock Details
          • Get equity stock details
          • Get equity stock details V2
        • ETF Details
          • Get ETF details
          • Get ETF details
        • Equity ETF Details
          • Get equity ETF details
          • Get equity ETF details V2
        • ETC Details
          • Get ETC details
          • Get ETC details
        • Equity ETC Details
          • Get Equity ETC details
          • Get Equity ETC details V2
        • Token Details
          • Get token details
          • Get token details
        • Asset ESG Data
          • Get asset ESG data
          • Get asset ESG data V2
        • List all available fiats per partner
        • Get the exchange rate for two assets
        • Get the swap exchange rate between two assets
        • Get assets under management
        • Get assets under management grouped by type
        • Get crypto index allocations
        • Get asset tags mapping
        • Get prices
        • Get prices V2
      • Trading Capabilities
        • Trades
          • Create a trade offer
          • Create a trade offer V2
          • [Deprecated] Accept a trade offer
          • Accept a trade offer V2
          • Accept a trade offer V3
          • Get a trade offer status
        • Swaps
          • Create a swap offer
          • Create a swap offer V2
          • Accept a swap offer
          • Accept a swap offer V2
        • Automated Orders
          • List automated orders
          • Get automated order price estimation
          • Create an automated order
          • Get an automated order details
          • Cancel an automated order
      • Portfolio Management
        • Returns the list of owned assets
        • Returns the list of owned asset groups
        • Portfolio performance based on timeframe
        • Returns the enhanced portfolio detail of an asset
        • Returns the list of owned assets
        • Returns the list of owned asset groups
        • Portfolio performance based on timeframe
        • Returns the enhanced portfolio detail of an asset
      • Transactions Timeline
        • All
          • Transaction timeline per user
        • Trades
          • List all trades per user
          • Get trade details
          • Get trades history for user using asset and fiat uuid
          • Search for trades
          • Lightweight Search for trades V2
        • Swaps
          • Search for swaps
          • Swap details by swap offer ID
          • Search for swaps V2
          • Swap details by swap offer ID V2
        • Crypto Transfers
          • List all crypto transfers per user
          • Search for crypto transfers
        • Non-User Initiated Transactions
          • Non-user initiated transaction details
          • List all non-user initiated transactions per partner or per user
          • List all non-user initiated transactions per partner or per user V2
        • Corporate Actions
          • List all corporate actions per partner or per user
          • Corporate action details
        • Crypto Actions
          • Crypto action details V2
          • Crypto action details
        • Staking Actions
          • List all staking actions per user
          • List all staking actions per user V2
      • Reports
        • Get all available report types per user
        • Get all generated reports per user
        • Create Account Statement Report
        • Download a specific report
      • Tax Insights
        • Get user’s tax eligibility status
        • Update user’s tax eligibility status
        • Get trade tax details
      • Notification Events
        • List all notification events per partner
      • Smart Investment Features
        • Crypto Transfers
          • List external addresses
          • Create deposit address
          • Update external address
          • Create withdrawal address
          • List of VASPs
          • Validate crypto address
          • Update tax declaration status for a crypto deposit transaction
          • Create a crypto withdrawal offer
          • Confirm a withdrawal offer
        • Crypto Staking
          • Get staking overview
          • Get bonded overview
          • Stake a crypto asset
          • Unstake a crypto asset
          • Stake a crypto asset V2
          • Unstake a crypto asset V2
          • Get a staking action status
        • Savings Plans
          • Create a savings plan
          • Search for savings plans
          • Cancel a savings plan
          • Cancel a savings plan V2
          • Confirm a savings plan transaction
          • Confirm a savings plan transaction V2
          • Create a savings plan V2
          • Search for savings plans V2
          • Get savings plan next recurrence date.
      • Settlements
        • List all available fiats per partner
        • Create a settlement deposit
        • Update the fiat stock
        • List all settlement transactions per partner
    • Webhooks
      • Overview
      • Setting Up Webhooks
      • Handling Webhooks Events
        • User Updates Notifications
          • User Updates Notifications
        • Corporate Actions Notifications
          • Corporate Actions Notifications
          • Corporate Actions Notifications
        • Crypto Transfers Notifications
          • Deposit or withdrawal notification
        • Settlement Notifications
          • Top-Up Request
          • Top-Up Request V2
          • Top-Up Success
          • Top-Up Success V2
          • Send Money
          • Send Money V2
          • Send Money Success
          • Send Money Success V2
        • Non-user Initiated Transactions Notifications
          • Non-user Initiated Transactions
          • Non-user Initiated Transactions V2
          • Non-user Initiated Transactions V3
        • Savings Plans Notifications
          • Savings Plan Upcoming Trade
          • Savings Plan Upcoming Trade v2
          • Savings Plan Successful Trade
          • Savings Plan Failed Trade
          • Savings Plan Auto Cancel
        • Crypto Actions Notifications
          • Crypto Actions Notifications
        • Reports Notifications
          • Reports Notifications
        • Automated Orders Notifications
          • Automated Orders Notifications
    • WebSocket
      • Overview
      • Setting a Websocket
      • Websocket Server Documentation
    • Glosary
      • Key Terms and Definitions
    • Schemas
      • 400
      • 401
      • 403
      • UserJourney
      • 404
      • trades-search-lightweight
      • 413
      • TradeDetails
      • 422
      • CreateOfferRequest
      • 500
      • CreateOfferUUIDRequest
      • AccessToken
      • ListOrderResponse
      • getTransactionResponse
      • CreateOrderRequest
      • getFiatsResponse
      • CreateOrderResponse
      • GetOrderResponse
      • 405
      • 406
      • 409
      • 410
      • 503
      • Term
      • PaginationMeta
      • PaginationLinks
      • TermV2Link
      • ComplexProductsAnswer
      • TermV2Text
      • ComplexProductsQuestion
      • AmlAnswerNested
      • AmlQuestionNested
      • AmlAnswer
      • AmlQuestion
      • QuestionnaireAnswer
      • QuestionnaireQuestion
      • ClientCategorizationNestedAnswer
      • ClientCategorizationNestedQuestion
      • ClientCategorizationAnswer
      • ClientCategorizationQuestion
      • UKRiskDisclosureContentLink
      • Dac8Answer
      • UKRiskDisclosureContent
      • Dac8Question
      • UKRiskDisclosureActions
      • FatcaAnswer
      • UKRiskDisclosure
      • FatcaQuestion
      • AccountLevel
      • GetUserList
      • SimpleCursorPaginationMeta
      • AmlQuestionAnswerRequest
      • AppropriatenessQuestionAnswerRequest
      • ClientCategorizationQuestionAnswerRequest
      • FatcaQuestionAnswerRequest
      • Dac8QuestionAnswerRequest
      • UserVerificationV2Request
      • UserTax
      • UserMultipleTax
      • UserExtCompliance
      • CreateUserV2RequestBody
      • UserSearch
      • GetUserV2
      • UpdateUserV2RequestBody
      • GetUser
      • UserOffBoardingRequestBody
      • UserAcceptedTerm
      • UserAcceptedTermV2Link
      • UserAcceptedTermV2Text
      • ComplianceDetails
      • UserVerificationFilesV2RequestBody
      • UserComplianceV2
      • LegalDocument
      • UserComplianceV2Response
      • TaxRules
      • Asset
      • AssetHistory
      • AssetInfo
      • CryptoIndexAllocation
      • CoinDetails
      • MetalDetails
      • CryptoIndexDetails
      • YearlyNetIncome
      • StockDetails
      • EquityStockDetails
      • ETFDetails
      • EquityETFDetails
      • ETCDetails
      • EquityETCDetails
      • TokenDetails
      • ESGData
      • ExchangeRate
      • SwapExchangeRate
      • Asset-V2
      • GetAssetsUnderManagement
      • GetAssetsUnderManagementTypeGroup
      • FiatV2
      • TagGroup
      • TagsMapping
      • Trade
      • TradeV2
      • TransactionTimelineItem
      • TradeSearchV2
      • NextPrevCursorPagination
      • CorporateActions
      • CorporateActionDetailsAsset
      • CorporateActionDetailsFiat
      • CorporateActionDetails
      • NonUserInitiatedTransactionsDetailsAsset
      • NonUserInitiatedTransactionDetailsFiat
      • NonUserInitiatedTransactionsDetails
      • CryptoActionDetailsAsset
      • CryptoActionDetailsFiat
      • CryptoActionDetails
      • CryptoActionDetailsAssetV2
      • CryptoActionTransaction
      • CryptoActionDetailsV2
      • Warnings
      • Offer
      • OfferUUID
      • Offer-Accept
      • Offer-Accept-Uuid
      • Overview
      • GroupOverview
      • Performance
      • AssetDetailsEnhancedWithStaking
      • OverviewV2
      • AssetDetailsEnhancedWithStakingV2
      • Fiat
      • CreateDomainDepositRequestBody
      • UpdateFiatStockRequestBody
      • TransactionSearch
      • CreateAccountStatement
      • AccountStatementReportResponse
      • ReportDetails
      • UploadFileRequestBody
      • FileInformation
      • OverviewResponse
      • BondedOverviewResponse
      • StakeRequest
      • StakeResponse
      • PendingStakeActionResponse
      • UnstakeRequest
      • UnstakeResponse
      • SearchResponse
      • SearchV2Response
      • PaginationMetaV2
      • StakeV2Request
      • StakeV2Response
      • UnstakeV2Request
      • UnstakeV2Response
      • GetStatusResponse
      • EventV2
      • NonUserInitiatedTransactions
      • NonUserInitiatedTransactionsV2
      • GetPricesResponse
      • GetPricesResponse-v2
      • GetTaxStatusResponse
      • OrderPriceEstimationResponse
      • UpdateTaxStatusRequest
      • UpdateTaxStatusResponse
      • GetTaxDetailsResponse
      • AddressResponse
      • CreateAddressRequest
      • DepositAddressResponse
      • UpdateExternalAddressRequest
      • CreateWithdrawalAddressRequest
      • VaspResponse
      • ValidateCryptoAddressRequest
      • ValidateCryptoAddressResponse
      • TransactionResponse
      • TaxDeclarationUpdateRequest
      • WithdrawalOfferRequest
      • WithdrawalOfferResponse
      • WithdrawalResponse
      • SearchSavingsPlanResponse
      • CreateSavingsPlanRequest
      • CreateSavingsPlanResponse
      • ModifySavingsPlanRequest
      • ModifySavingsPlanResponse
      • CancelSavingsPlanV2Response
      • ConfirmSavingsPlanTransactionResponse
      • ConfirmSavingsPlanTransactionV2Response
      • SearchSavingsPlanV2Response
      • CreateSavingsPlanV2Request
      • CreateSavingsPlanV2Response
      • GetSavingsPlanNextRecurrenceResponse
      • CreateSwapOfferRequest
      • CreateSwapOfferResponse
      • SwapTradesSearch
      • GetSwap
      • CreateSwapOfferRequestV2
      • CreateSwapOfferResponseV2
      • SwapTradesSearchV2
      • GetSwapV2
      • AcceptSwapOfferResponse
      • AcceptSwapOfferResponseV2
      • ResponseMeta
      • RiskAnswer
      • RiskQuestion
      • GeneralAddress
      • EntityTaxClassification
      • Business
      • RiskQuestionAnswerRequest
      • CreateBusinessRequestBody
      • BusinessDetails
      • UpdateBusinessRequestBody
      • AuthorizedIndividual
      • CreateAuthorizedIndividualRequestBody
      • UpdateAuthorizedIndividualRequestBody
      • Shareholder
      • CreateShareholderRequestBody
      • UpdateShareholderRequestBody
      • BeneficialOwnerType
      • BeneficialOwnerControllingPersonType
      • BeneficialOwner
      • CreateBeneficialOwnerRequestBody
      • UpdateBeneficialOwnerRequestBody
      • ManagingDirector
      • CreateManagingDirectorRequestBody
      • UpdateManagingDirectorRequestBody
      • Individual
      • CreateIndividualRequestBody
      • UpdateIndividualRequestBody
  • Custody
    • Introduction
    • Security
    • Getting Started
    • Changelog
    • Webhooks
    • Supported Assets
    • Glossary
    • Tutorials
      • API Onboarding
      • TrustVault Node.js SDK
      • Change Wallet Policy API
      • Create a Bitcoin Transaction
      • Create an Ethereum Transaction
      • Create Transaction (Unsupported EVM chain)
      • Create Ethereum Transaction GraphQL API
      • Calculating Transaction Fee
      • Decoding an Ethereum Transaction Webhook Payload
      • Get User Portfolio
      • Environments
    • APIs
      • Travel Rule API
      • Deprecations
      • Trust API
        • Authentication
          • TrustVault Public Keys
        • Query
          • User
            • User SubWallets - Details
            • User SubWallets - Portfolio
            • User SubWallets - Balances
            • Get Transactions
            • Get Transactions for a BTC Receive Address
            • Get All BTC Receive Addresses (With Transactions)
            • Get User Portfolio
            • csvPortfolio
          • Get Request Item
        • Mutations
          • Create Transactions
            • Create BTC Transaction
            • Create ETH
            • Create Transaction (EVM compatible chain)
            • Create Exchange Transfer
          • Create Change Policy Request
          • Create Bitcoin Receive Address
          • Add Signature
          • Cancel request
          • Create Sub Wallet
          • Create Eth Personal Sign
          • Create Eth Signed Typed Data
          • Create Radix Transaction
          • Create Xdc.Network Transaction
    • Under the Hood
      • Understanding Bitcoin
      • Supported Ethereum Decoded Data
  • Crypto Pay by Bitpanda
    • Overview
    • REST API Endpoints
      • Authentication
        • Obtain a Refresh and Access Tokens
        • Revoke a Refresh Token
      • Transactions
        • Get transaction details
        • Create a new transaction
        • Get transactions details
      • Get list of fiat currencies
    • Webhooks
      • Settlement Update Notifications
      • Transaction Update Notifications
    • Schemas
      • 400
      • 401
      • 403
      • 404
      • 413
      • 422
      • 500
      • AccessToken
      • getTransactionResponse
      • getFiatsResponse
  1. Tutorials

Decoding an Ethereum Transaction Webhook Payload

Who is this tutorial for:
Users receiving an Ethereum Webhook and those who want to use the co-signing-service example to write custom rules for signing transaction
Anyone interested in how to parse the Ethereum transaction payload

Introduction#

For this tutorial we will be looking at how we can pull apart an Ethereum transaction that a co-signing-service could use to implement specific rules. In this example our co-signing-service interacts with the Gnosis Safe (docs).

Setup Process#

Image a the following has been setup:
1.
You have a TrustVault account
2.
You have connected MetaMask to your TrustVault account
3.
You have setup a webhook
4.
You have an API key to interact with the TrustVault SDK
5.
You have registered your external private key to act as a signer on your wallet. This means that no transactions are sent from TrustVault unless your external key signs them
6.
You have defined some rules on which transactions to sign
7.
You have written your code and setup a co-signing-service of your own to listen to the webhook
8.
You have created a transaction in Metamask via any DApp (In this example we're using Gnosis Safe)
9.
Your co-signing-service has received a webhook from TrustVault informing you that a new transaction has been created
Once we receive the Webhook we can look deeper at what the payload would look like and how we can see what its trying to do. To see an example of the payload for a transaction would be see Sample Ethereum Transaction Created Event Object.
Our current Webhooks provide the full ethereum transaction data payload.
e.g.
{
  "version": "1.0.1",
  "type": "ETHEREUM_TRANSACTION_CREATED",
  "payload": {
    "assetSymbol": "ETH",
    "chain": "ETHEREUM",
    "signData": {
      "transaction": {
        "nonce": 10,
        "gasPrice": "172000000000",
        "gasLimit": "51303",
        "chainId": 3,
        "v": 3,
        "to": "0x7FC6F18fa1461189aB89732d2ECAaD988E1Be26A",
        "fromAddress": "0x6fe668915B32A1364FE63386b4E3cE919b267540",
        "value": "0",
        "data": "0xa9059cbb000000000000000000000000671e96593Ea93bfcb510375f4CeC111d0E5cf1b800000000000000000000000000000000000000000000000caf67003701680000",
        "decodedInput": {
          "id": "0xa9059cbb",
          "signature": "transfer(address to, uint256 amount)",
          "params": [
            {
              "name": "to",
              "type": "address",
              "value": "0x671e96593ea93bfcb510375f4cec111d0e5cf1b8"
            },
            {
              "name": "amount",
              "type": "uint256",
              "value": "0xcaf67003701680000"
            }
          ]
        }
      },
      "hdWalletPath": [
        "0x8000002c",
        "0x8000003c",
        "0x80000000",
        "0x0",
        "0x0"
      ],
      "unverifiedDigestData": {
        "transactionDigest": "7ebf00d9345b2f2217c125afc633f623d2253a2b092992032f0d6a5f9003a62a",
        "signData": "303f04207ebf00d9345b2f2217c125afc633f623d2253a2b092992032f0d6a5f9003a62a301b0205008000002c0205008000003c02050080000000020100020100",
        "shaSignData": "0bdb1e2b1c75e16c887c5186f734c6c049324f9a951aed7b43bc7c19138cce9c"
      }
    },
    "requestId": "25127cea-dbc7-6d89-ca6c-199fdaeb03c6",
    "subWalletId": {
      "type": "ETH",
      "index": 0,
      "id": "7a9e053c-47fc-489b-956f-2aafbe7d2ff0"
    },
    "trustId": "e7aac98f-d5c2-4adf-a47a-564aa05ce554",
    "subWalletIdString": "7a9e053c-47fc-489b-956f-2aafbe7d2ff0/ETH/0"
  },
  "messageId": "d913c151-f04b-47ca-a935-0949e4c27cb1",
  "timestamp": 1611935455856,
  "isoTimestamp": "2021-01-29T15:50:55.856Z"
}

Gnosis Safe#

In order to understand the contract call we need to understand how the Gnosis safe works.
The safe uses the Proxy Delegate pattern to invoke methods on a common contract shared by all Safe instances (to avoid the high gas cost associated with deploying the actual safe contract).
So to interact with the Safe you invoke methods on GnosisSafeProxy.sol that simply forwards these requests to a masterCopy using the delegatecall message call. This pattern basically treats the masterCopy as library code in the context of the proxy. The current masterCopy is v1.1.1 deployed on mainnet here.
To further complicate matters the multi-sig nature of the Gnosis Safe can be handled both on- and off-chain. Consider, for example, a simple 2-of-2 safe with keys A and B. There are a number of alternative ways in which a transaction execution can proceed:
1.
A and B both sign the transaction off-chain (the format can be generated directly or a call can be made to the smart contract to encode the data on the clients behalf). Some party is responsible for collating these two signatures and submitting the execTransaction call. This could be A or B, but doesn't necessarily have to be. The transaction could even be sent by a gas relay network as outlined in EIP-1613 with no direct involvement from A or B after they have signed
2.
A signs and forward their signature to B. B submits the execTransaction call directly and their signature is considered pre-validated as they signed the call directly
3.
A signs the transaction and uses the approveHash method to submit the signature on-chain. B then submits the execTransaction call with both A and B's addresses marked as pre-validated
(Theoretically both A and B can call approveHash and then someone else submit the transaction with pre-validated signatures for A and B, although I don't see a scenario where this would be of use as A or B can simply call execTransaction instead of approveHash and save some gas)
Here is an example Gnosis Safe invocation taken from etherscan (this field would also be present in a TrustVault Webhook for an ethereum transaction that needs signing. See: Sample Ethereum Transaction Created Event Object and look at the data field):
FieldValue
to0x5791b08b3f51e80903af7a694392b793dbd9ca38
value0x0
data0x6a761202000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec700000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000000000009f3c000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
0000000000001c00000000000000000000000000000000000000000000000000000000000000044a9059cbb000000000000000000000000ba339b8271afea71
3008314487dd98f8d941720f00000000000000000000000000000000000000000000000000000002540be400000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000000000000000000c3827868e9e02b2d7557db27cf7aef0b21e26a32b20b110c
814f853c5948c6ba9a5b576241b59280334f04ce5bc385e42eaf1320b5099643a73089f847c42ec46f1b000000000000000000000000ca14b0714e0e9e19bc4
a90c2af377d8000f0a113000000000000000000000000000000000000000000000000000000000000000001df862fe32b0bd3ff342134cb51570134168e1d81
271ad449d9b3df8a24075d9b407496c6a4ce22265fc0b8f273ac5c129ba20070948d8cf5e2c619df99aae0bf200000000000000000000000000000000000000
000000000000000000000
In this transaction the to address is the address of a Gnosis safe proxy contract. This proxy contract points to the 1.1.1 version of the masterCopy described above. There is no value for this call, but the data payload contains an execTransaction call that is forwarded to the masterCopy.
To break the arguments down further I've included a slightly more readable version of the data field and annotated the various arguments. (The arguments are encoded according to the Solidity Contract ABI Specification):
Function: execTransaction(address to, uint256 value, bytes data, uint8 operation, uint256 safeTxGas, uint256 dataGas, uint256 gasPrice, address gasToken, address refundReceiver, bytes signatures) ***

MethodID: 0x6a761202
[0]:  000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec7 <= to
[1]:  0000000000000000000000000000000000000000000000000000000000000000 <= value
[2]:  0000000000000000000000000000000000000000000000000000000000000140 v data (encoded later)
[3]:  0000000000000000000000000000000000000000000000000000000000000000 <= operation
[4]:  0000000000000000000000000000000000000000000000000000000000009f3c <= safeTxGas
[5]:  0000000000000000000000000000000000000000000000000000000000000000 <= gasPrice
[6]:  0000000000000000000000000000000000000000000000000000000000000000 <= gasToken
[7]:  0000000000000000000000000000000000000000000000000000000000000000 <= refundReceiver
[8]:  0000000000000000000000000000000000000000000000000000000000000000 <= dataGas
[9]:  00000000000000000000000000000000000000000000000000000000000001c0 v signatures (encoded later)
[10]: 0000000000000000000000000000000000000000000000000000000000000044 <= data
[11]: a9059cbb000000000000000000000000ba339b8271afea713008314487dd98f8
[12]: d941720f00000000000000000000000000000000000000000000000000000002
[13]: 540be40000000000000000000000000000000000000000000000000000000000
[14]: 00000000000000000000000000000000000000000000000000000000000000c3 <= signatures
[15]: 827868e9e02b2d7557db27cf7aef0b21e26a32b20b110c814f853c5948c6ba9a
[16]: 5b576241b59280334f04ce5bc385e42eaf1320b5099643a73089f847c42ec46f
[17]: 1b000000000000000000000000ca14b0714e0e9e19bc4a90c2af377d8000f0a1
[18]: 1300000000000000000000000000000000000000000000000000000000000000
[19]: 0001df862fe32b0bd3ff342134cb51570134168e1d81271ad449d9b3df8a2407
[20]: 5d9b407496c6a4ce22265fc0b8f273ac5c129ba20070948d8cf5e2c619df99aa
[21]: e0bf200000000000000000000000000000000000000000000000000000000000
Notice that the embedded data and signatures field are of variable length and so are included after the fixed size arguments.
To find out more about this safe we can find out it's owners by executing a call on the contract (0xa0e67e2b is the function selector for getOwners() - you can always validate this yourself):
{"jsonrpc":"2.0","id":1,"result":"0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000005000000000000000000000000ad8627895a7ea6b9fb8fe0b219d4eda3a6ce45f6000000000000000000000000fbc652036cee0bd4a70ad7993a0dcc217863b1990000000000000000000000009bdfd96efb2a24d87f13eef2770ed071a9373f9f000000000000000000000000ca14b0714e0e9e19bc4a90c2af377d8000f0a113000000000000000000000000c80b893cf169310c6dbe3e3245fb9fbb9dcf40a8"}
This response uses the same ABI encoding format. The first element of the result is of variable length (address[]) and so we encode the offset within the data to find the result (simple given that this is the only data in the result!), then the length of the array (5), followed by 5 distinct addresses.
I'll leave figuring out the threshold of this multi-sig as an exercise for the reader (hint, change 8 characters in the curl command above!).
Now we know this is a 3-of-5 multi-sig vault we can go back and look at the transaction arguments in more detail:
FieldValueDescription
to0xdac17f958d2ee523a2206206994597c13d831ec7This is the Tether USD ERC-20 contract
value0x0This transaction is sending no value
data0xa9059cbb
000000000000000000000000ba339b8271afea713008314487dd98f8d941720f
00000000000000000000000000000000000000000000000000000002540be4
An ABI encoded invocation to send to the Tether contract (in this case, to send 1,000,000,000
TUSD to address 0xba339b8271afea713008314487dd98f8d941720f)
operation0x00x0 = CALL, 0x1 = DELEGATECALL
safeTxGas
gasPrice
gasToken
refundReceiver
dataGas
0x9f3c
0x0
0x0
0x0
0x0
Can be used to pay senders in gas relay networks (see above)
signatures0x827868e9e02b2d7557db27cf7aef0b21e26a32b20b110c814f853c5948c6ba9a
5b576241b59280334f04ce5bc385e42eaf1320b5099643a73089f847c42ec46f
1b
000000000000000000000000ca14b0714e0e9e19bc4a90c2af377d8000f0a113
0000000000000000000000000000000000000000000000000000000000000000
01
df862fe32b0bd3ff342134cb51570134168e1d81271ad449d9b3df8a24075d9b
407496c6a4ce22265fc0b8f273ac5c129ba20070948d8cf5e2c619df99aae0bf
20
This request contains 3 signatures. The first and third are ECDSA signatures that would have
been collected offline. The second is a pre-validated signature of the sender,
0xca14b0714e0e9e19bc4a90c2af377d8000f0a113.
We can assume that the 3 signatures on the transaction satisfied the 3-of-5 multi-sig of the target safe and so the Tether transaction was correctly forwarded on to the ERC-20 contract and executed.

Summary#

Once we have understood the details of the transactions we can then use them in rules that a co-signing-service can use to decide whether or not to sign the transaction. We could use any one of the parameters against a set of rules to decide if we sign the transaction. Can we:
Only sign transactions to certain addresses? Yes
Only sign transactions to to certain method calls? Yes
Only sign transactions of a certain value? Yes
We get access to the full set of parameters and this opens up a whole new world of rules and rules configuration.
In our next tutorial we'll show how you can take this newly understood transaction and decide if we want to sign it based on some predefined rules.
Previous
Calculating Transaction Fee
Next
Get User Portfolio
Built with