co-signing-service could use to implement specific rules. In this example our co-signing-service interacts with the Gnosis Safe (docs).co-signing-service of your own to listen to the webhookco-signing-service has received a webhook from TrustVault informing you that a new transaction has been created{
"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"
}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.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 signedexecTransaction call directly and their signature is considered pre-validated as they signed the call directlyexecTransaction call with both A and B's addresses marked as pre-validated(Theoretically both A and B can call approveHashand 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 callexecTransactioninstead ofapproveHashand save some gas)
data field):| Field | Value |
|---|---|
| to | 0x5791b08b3f51e80903af7a694392b793dbd9ca38 |
| value | 0x0 |
| data | 0x6a761202000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec700000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000009f3c000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000001c00000000000000000000000000000000000000000000000000000000000000044a9059cbb000000000000000000000000ba339b8271afea71 3008314487dd98f8d941720f00000000000000000000000000000000000000000000000000000002540be400000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000000000000c3827868e9e02b2d7557db27cf7aef0b21e26a32b20b110c 814f853c5948c6ba9a5b576241b59280334f04ce5bc385e42eaf1320b5099643a73089f847c42ec46f1b000000000000000000000000ca14b0714e0e9e19bc4 a90c2af377d8000f0a113000000000000000000000000000000000000000000000000000000000000000001df862fe32b0bd3ff342134cb51570134168e1d81 271ad449d9b3df8a24075d9b407496c6a4ce22265fc0b8f273ac5c129ba20070948d8cf5e2c619df99aae0bf200000000000000000000000000000000000000 000000000000000000000 |
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.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]: e0bf200000000000000000000000000000000000000000000000000000000000data and signatures field are of variable length and so are included after the fixed size arguments.call on the contract (0xa0e67e2b is the function selector for getOwners() - you can always validate this yourself):{"jsonrpc":"2.0","id":1,"result":"0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000005000000000000000000000000ad8627895a7ea6b9fb8fe0b219d4eda3a6ce45f6000000000000000000000000fbc652036cee0bd4a70ad7993a0dcc217863b1990000000000000000000000009bdfd96efb2a24d87f13eef2770ed071a9373f9f000000000000000000000000ca14b0714e0e9e19bc4a90c2af377d8000f0a113000000000000000000000000c80b893cf169310c6dbe3e3245fb9fbb9dcf40a8"}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.| Field | Value | Description |
|---|---|---|
| to | 0xdac17f958d2ee523a2206206994597c13d831ec7 | This is the Tether USD ERC-20 contract |
| value | 0x0 | This transaction is sending no value |
| data | 0xa9059cbb 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) |
| operation | 0x0 | 0x0 = 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) |
| signatures | 0x827868e9e02b2d7557db27cf7aef0b21e26a32b20b110c814f853c5948c6ba9a 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. |
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: