DMC access Guide

This guide aims to help understand the security considerations when integrating with DMC and how to prevent these security issues.

Exchange Deposit and Withdraw Access Solution

Basic Logic

Deposit: Users need to deposit funds into their accounts on the exchange. To do this, the exchange will generate a unique identifier that can be recognized within the platform. When depositing funds into the exchange account, the user needs to fill in the unique identifier generated by the exchange in the “memo” field of the transfer operation.

Withdraw: When a user initiates a withdrawal, thet need to provide their DMC account information. The exchange will transfer the amount of DMC requested for withdrawal to the account name provided by the user, thereby completing the withdrawal operation. In this process, the “memo” field may also be necessary, as the user may be withdrawing funds from one exchange to another.

Notes

DMC supports twi types of transfer methods, namely transfer andextransfer

The difference between them is that the transfer operation can only transefer tokens issued by the official, that is, tokens whose contract is @datamall, while extransfer can transfer any token.

Currently, the official tokens issued in DMC include DMC@datamall and PST@datamall,and only DMC@datamall is supported for transfer operation.

DMC@datamall has four decimal places, and the smallest unit is 0.0001 DMC

Instance

extransfer

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
{
account: 'dmc.token',
name: 'extransfer',
authorization: [{
actor: account,
permission: 'active',
}],
data: {
from: account,
to: to,
quantity: {
quantity: `${amount} DMC`,
contract: 'datamall'
}
memo: memo
}
}

The result returned on-chain:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
{
"transaction_id": "2b0e27e0b9c9d6c6ada6b09be5c267c7e2ce1926e6fa4bc7d3fae369d22175ca",
"processed": {
"id": "2b0e27e0b9c9d6c6ada6b09be5c267c7e2ce1926e6fa4bc7d3fae369d22175ca",
"block_num": 13111072,
"block_time": "2023-06-19T04:20:50.500",
"producer_block_id": null,
"receipt": {
"status": "executed",
"cpu_usage_us": 421,
"net_usage_words": 18
},
"elapsed": 421,
"net_usage": 144,
"scheduled": false,
"action_traces": [
{
"action_ordinal": 1,
"creator_action_ordinal": 0,
"closest_unnotified_ancestor_action_ordinal": 0,
"receipt": {
"receiver": "dmc.token",
"act_digest": "b238dc7fc3dd05f45fde4ecc48bb66fad2c1669f1f81af51fd3384866e881c6f",
"global_sequence": 13486942,
"recv_sequence": 390918,
"auth_sequence": [
[
"speakfool123",
211
]
],
"code_sequence": 37,
"abi_sequence": 37
},
"receiver": "dmc.token",
"act": {
"account": "dmc.token",
"name": "extransfer",
"authorization": [
{
"actor": "speakfool123",
"permission": "active"
}
],
"data": {
"from": "speakfool123",
"to": "asdasdqwdqwd",
"quantity": {
"quantity": "0.0001 DMC",
"contract": "datamall"
},
"memo": "test"
},
"hex_data": "304488942e6854c590b84ddc266c1236010000000000000004444d4300000000000000311a69b2490474657374"
},
"context_free": false,
"elapsed": 131,
"console": "",
"trx_id": "2b0e27e0b9c9d6c6ada6b09be5c267c7e2ce1926e6fa4bc7d3fae369d22175ca",
"block_num": 13111072,
"block_time": "2023-06-19T04:20:50.500",
"producer_block_id": null,
"account_ram_deltas": [],
"except": null,
"error_code": null,
"return_value_hex_data": "",
"inline_traces": []
}
],
"account_ram_delta": null,
"except": null,
"error_code": null
}
}

transfer

1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
"account": "dmc.token",
"name": 'transfer',
"authorization": [{
actor: from,
permission: 'active',
}],
"data": {
"from": from,
"to": to,
"quantity": `${amount} DMC`,
"memo": memo
}
}

The result returned on-chain:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
{
"transaction_id": "eeaa563d937e26dafa39cbe306faf47fa7a55d75ea558aa34148d206eecd0a86",
"processed": {
"id": "eeaa563d937e26dafa39cbe306faf47fa7a55d75ea558aa34148d206eecd0a86",
"block_num": 13110171,
"block_time": "2023-06-19T04:13:20.000",
"producer_block_id": null,
"receipt": {
"status": "executed",
"cpu_usage_us": 356,
"net_usage_words": 17
},
"elapsed": 356,
"net_usage": 136,
"scheduled": false,
"action_traces": [
{
"action_ordinal": 1,
"creator_action_ordinal": 0,
"closest_unnotified_ancestor_action_ordinal": 0,
"receipt": {
"receiver": "dmc.token",
"act_digest": "75efa22efa51fc67e8379ca04d92b2dbdc4fef20652ad21995e4cd34226d2a36",
"global_sequence": 13486018,
"recv_sequence": 390897,
"auth_sequence": [
[
"speakfool123",
208
]
],
"code_sequence": 37,
"abi_sequence": 37
},
"receiver": "dmc.token",
"act": {
"account": "dmc.token",
"name": "transfer",
"authorization": [
{
"actor": "speakfool123",
"permission": "active"
}
],
"data": {
"from": "speakfool123",
"to": "asdasdqwdqwd",
"quantity": "0.0001 DMC",
"memo": "test"
},
"hex_data": "304488942e6854c590b84ddc266c1236010000000000000004444d43000000000474657374"
},
"context_free": false,
"elapsed": 152,
"console": "",
"trx_id": "eeaa563d937e26dafa39cbe306faf47fa7a55d75ea558aa34148d206eecd0a86",
"block_num": 13110171,
"block_time": "2023-06-19T04:13:20.000",
"producer_block_id": null,
"account_ram_deltas": [],
"except": null,
"error_code": null,
"return_value_hex_data": "",
"inline_traces": []
}
],
"account_ram_delta": null,
"except": null,
"error_code": null
}
}

For parameter details, please refer to the API documentation

“Fake coins” deposit

It needs to be identified and only accepts transfers of DMC@datamall. Transfers of other tokens are considered invalid transactions.

For transfer,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
"act": {
"account": "dmc.token",
"name": "transfer",
"authorization": [
{
"actor": "speakfool123",
"permission": "active"
}
],
"data": {
"from": "speakfool123",
"to": "asdasdqwdqwd",
"quantity": "0.0001 DMC",
"memo": "test"
},
"hex_data": "304488942e6854c590b84ddc266c1236010000000000000004444d43000000000474657374"
}

Please note:

For extransfer,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
"act": {
"account": "dmc.token",
"name": "extransfer",
"authorization": [
{
"actor": "speakfool123",
"permission": "active"
}
],
"data": {
"from": "speakfool123",
"to": "asdasdqwdqwd",
"quantity": {
"quantity": "0.0001 DMC",
"contract": "datamall"
},
"memo": "test"
},
"hex_data": "304488942e6854c590b84ddc266c1236010000000000000004444d4300000000000000311a69b2490474657374"
}

Please note:

Transaction status confirmation

Irreversible Height Determination

As DMC adopts the PoSS consensus mechanism, when judging a transaction, it is necessary to ensure that the transaction has been confirmed and inclued in an irreversible block. The irresversible height refers to the height that has reached consensus in the current DMC node network, and blocks below this height cannot be rolled back. This means that transactions within this height have been sufficiently confirmed and will not be tampered with or reversed.

For the DMC network, if the block height of a transaction is greater than the irreversible height, the transaction is still reversible and may be affected by blockchain reorganization or other attacks. However, if the block height of a transaction is less than or equal to the irresversible height, we can confirm that the transaction has been confirmed by enough BP nodes and has entered an irreversible state and will not be rolled back.

Hard-failed status attack

There are muitiple execution states for DMC on-chain transactions, one of which is hard-failed. Transactions in this state have not been executed successfully but still leave a record on chain. Attackeds can use this transaction feature of DMC to threaten businesses and conduct invalid transactions. The prevention method for this security threat is to judge the transaction status based on the irreversible height. If the transaction status is hard-failed , it is considered an illegal transaction.

chain/get_transaction_status

The following operation requires the corresponding request node to have the configuration item transaction-finality-status-max-storage-size-gb configured. If it involves financial matters, it is recommended to maintain your own synchronized node.

1
2
3
4
5
curl --location '${RPC_ENDPOINT}/v1/chain/get_transaction_status' \
--header 'Content-Type: application/json' \
--data '{
"id": "TRX_ID"
}'

If the request is correct, the following result will be returned:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{
"state": "IRREVERSIBLE",
"block_number": 14899444,
"block_id": "00e358f4f8906b140aff2db43ed991aea50255223eb0660e87e6c84861c2dbbc",
"block_timestamp": "2023-07-06T09:27:05.000",
"expiration": "2023-07-06T09:27:29.000",
"head_number": 14899540,
"head_id": "00e3595421070003362eb53f66808cfc9a1dd84e66c6fd63f23faa35493b8b31",
"head_timestamp": "2023-07-06T09:27:53.000",
"irreversible_number": 14899493,
"irreversible_id": "00e35925187869c08d4fba75234066fd4e203ada79b0d923adab4ecfcd116806",
"irreversible_timestamp": "2023-07-06T09:27:29.500",
"earliest_tracked_block_id": "00e35341164012efb8685db89045bd88164adf21d8a7386c399437b8d644cd26",
"earliest_tracked_block_number": 14897985
}

Notes:

1.If the state is IRREVERSIBLE it means that the transaction has been confirmed by an irreversible block and will not be rolled back.
2.Records are kept for a default duration of 3 minutes. If the time exceeds this duration, the state will become UNKNOWN . If there is a need for additional time to modify the parameter transaction-finality-status-success-duration-sec which has a default value of 180 seconds.

trace_api/get_block

The following operations requires the corresponding request node to have loaded the trace_api_plugin. If it involves fund issues, it is recommended to maintain a synchronized node.

1
2
3
4
5
curl --location '${RPC_ENDPOINT}/v1/trace_api/get_block' \
--header 'Content-Type: application/json' \
--data '{
"block_num": ${block_num}
}'

If the request is correct, the following result will be returned.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
{
"id": "00f433cc28f34dc4a80e0bcfb6d935d0bf06f1d57210c76485bef6126b6de87e",
"number": 16004044,
"previous_id": "00f433cb0997beac31ea8977415b62fd0ac565aa4eba8a1959fbf7bd7e897e98",
"status": "irreversible",
"timestamp": "2023-05-17T02:47:36.000Z",
"producer": "dmcrc1bppa11",
"transaction_mroot": "0000000000000000000000000000000000000000000000000000000000000000",
"action_mroot": "ea58ff5ff979f865869ebc38606017291950aeb9d67181e884e6722d048cce04",
"schedule_version": 4,
"transactions": [
{
"id": "a2d14ce284e5b3ad6ac708a5744cc8a771a643a0d69cbbf96d4223e40a879a39",
"block_num": 16004044,
"block_time": "2023-05-17T02:47:36.000",
"producer_block_id": "00f433cc28f34dc4a80e0bcfb6d935d0bf06f1d57210c76485bef6126b6de87e",
"actions": [
..
],
"status": "executed",
"cpu_usage_us": 100,
"net_usage_words": 0,
"signatures": [],
"transaction_header": {
"expiration": "2023-05-17T02:47:36",
"ref_block_num": 13259,
"ref_block_prefix": 2005527089,
"max_net_usage_words": 0,
"max_cpu_usage_ms": 0,
"delay_sec": 0
}
}
]
}

Note:

  1. Confirm status is irreversible,which proves that the blck is no longer reversible.
  2. Traversetransactions[] to confirm that the searched transaction is in the block.
  3. Comfirm thattransactions[i].status is in the executedstate.

Node Security

For a trading platform’s proprietary API nodes, it is strongly advised to deactivate external network RPC access. Should the node necessitate RPC interaction, it is recommended to employ internal network HTTP. The corresponding configuration example code is provided below:

1
2
3
chain.load("http", {
"http-server-address": "127.0.0.1:8870",
});