Skip to main content

Disperse Payment Signature Structure

To authorize disperse payment operations the user must generate a cryptographic signature compliant with the EIP-191 standard.

The signature is created by signing a precisely formatted string message derived from the payment details, including a hash of the recipient data array.

Signed Message Format

The message is constructed by concatenating the following components as strings, separated by commas (,):

string.concat(
"ef83c1d6",
",",
AdvancedStrings.bytes32ToString(hashList),
",",
AdvancedStrings.addressToString(_token),
",",
Strings.toString(_amount),
",",
Strings.toString(_priorityFee),
",",
Strings.toString(_nonce),
",",
_priorityFlag ? "true" : "false",
",",
AdvancedStrings.addressToString(_executor)
);

Message Components

1. Function Selector (Hex String):

  • ef83c1d6: Identifies the dispersePay function

2. Hash List (String):

  • The result of AdvancedStrings.bytes32ToString(hashList)
  • Where hashList = sha256(abi.encode(toData))
  • Purpose: Ensures signature covers the specific recipient list and amounts

3. Token Address (String):

  • The result of AdvancedStrings.addressToString(_token)
  • Purpose: Identifies the token being distributed

4. Total Amount (String):

  • The result of Strings.toString(_amount)
  • Purpose: Specifies the total amount being distributed across all recipients

5. Priority Fee (String):

  • The result of Strings.toString(_priorityFee)
  • Purpose: Specifies the fee paid to fishers

6. Nonce (String):

  • The result of Strings.toString(_nonce)
  • Purpose: Provides replay protection for the transaction

7. Priority Flag (String):

  • "true": If _priorityFlag is true (asynchronous)
  • "false": If _priorityFlag is false (synchronous)
  • Purpose: Explicitly includes the execution mode in the signed message

8. Executor Address (String):

  • The result of AdvancedStrings.addressToString(_executor)
  • Purpose: Specifies the address authorized to submit this payment request
tip
  • addressToString converts an address to a lowercase string
  • Strings.toString converts a number to a string
  • _priority_boolean indicates whether the payment will be executed asynchronously (true) or synchronously (false)

Hash List Structure

The hashList component within the signature message is derived by ABI-encoding the entire toData array and then computing its sha256 hash:

bytes32 hashList = sha256(abi.encode(toData));

This ensures that the signature covers the specific recipient list and amounts.

Example

Here's a practical example of constructing a signature message for distributing 0.1 ETH to multiple recipients:

Scenario: User wants to distribute 0.1 ETH to three recipients using synchronous processing

Recipients (toData array):

DispersePayMetadata[] memory toData = new DispersePayMetadata[](3);
toData[0] = DispersePayMetadata({
amount: 30000000000000000, // 0.03 ETH
to_address: 0x742c7b6b472c8f4bd58e6f9f6c82e8e6e7c82d8c,
to_identity: ""
});
toData[1] = DispersePayMetadata({
amount: 50000000000000000, // 0.05 ETH
to_address: address(0),
to_identity: "alice"
});
toData[2] = DispersePayMetadata({
amount: 20000000000000000, // 0.02 ETH
to_address: 0x8e3f2b4c5d6a7f8e9c1b2a3d4e5f6c7d8e9f0a1b,
to_identity: ""
});

Parameters:

  • hashList: sha256(abi.encode(toData)) = 0x1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b
  • _token: address(0) (ETH)
  • _amount: 100000000000000000 (0.1 ETH total)
  • _priorityFee: 5000000000000000 (0.005 ETH)
  • _nonce: 25
  • _priorityFlag: false (synchronous)
  • _executor: address(0) (unrestricted)

Resulting message string:

ef83c1d6,0x1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b,0x0000000000000000000000000000000000000000,100000000000000000,5000000000000000,25,false,0x0000000000000000000000000000000000000000

Message breakdown:

  1. ef83c1d6 - Function selector for dispersePay
  2. 0x1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b - Hash of recipient data
  3. 0x0000000000000000000000000000000000000000 - Token address (ETH)
  4. 100000000000000000 - Total amount in wei (0.1 ETH)
  5. 5000000000000000 - Priority fee in wei (0.005 ETH)
  6. 25 - Nonce
  7. false - Priority flag (synchronous)
  8. 0x0000000000000000000000000000000000000000 - Executor (unrestricted)
tip
  • AdvancedStrings.addressToString converts an address to a lowercase hexadecimal string with "0x" prefix
  • AdvancedStrings.bytes32ToString converts a bytes32 hash to a hexadecimal string with "0x" prefix
  • Strings.toString converts a number to a string
  • _priorityFlag indicates whether the payment will be executed asynchronously (true) or synchronously (false)
  • The hashList must be calculated as sha256(abi.encode(toData)) to ensure signature integrity
  • Total _amount should equal the sum of all individual amounts in the toData array

DispersePayMetadata Struct

Defines the payment details for a single recipient within the toData array.

struct DispersePayMetadata {
uint256 amount;
address to_address;
string to_identity;
}
  • amount: The amount to send to this specific recipient
  • to_address: Direct address (use address(0) if using identity)
  • to_identity: Username/identity string (empty if using address)