Withdrawal using VEM
There are several ways to initiate withdrawals on the Ethereum network using the Staking API by retrieving the Validator Exit Message (VEM):
- Off-chain signature.
- On-chain signature.
Request examples are provided using cURL.
Off-chain signature
-
Generate an Elliptic Curve Diffie-Hellman (ECDH) key pair. Retain the private key securely for future steps, as you'll need it to decrypt the VEM.
We use keys on the
NIST P-256
curve (akasecp256r11
akaprime256v1
) for ECDH algorithm inside ECIES encryption scheme. The client should keep their private key secret and discard it when it’s not needed anymore. Also, the client should send his public key when making the initial request.Those public keys have to be base64 encoded string of PEM block with x509 SPKI (aka PKIX) formatted public key on P-256 curve, so they should look smth like this:
1. "ecdhPublicKey":"LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUZrd0V3WUhLb1pJemowQ0FRWUlLb1pJemowREFRY0RRZ0FFNWgwcmRaSEZaZWNSbWIxR2RqQis3T0dUMnovegozMG1TRnZhWTdQaTltek5HT3J6SjZVbS9GbUMwb2lXMVFBT1FhOVFldGFpZm1EMU0zc09iU0JwV3N3PT0KLS0tLS1FTkQgUFVCTElDIEtFWS0tLS0tCg=="
base64 decoded version:
-----BEGIN PUBLIC KEY----- MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE5h0rdZHFZecRmb1GdjB+7OGT2z/z 30mSFvaY7Pi9mzNGOrzJ6Um/FmC0oiW1QAOQa9QetaifmD1M3sObSBpWsw== -----END PUBLIC KEY-----
Those keys (client’s ECDH public key) will be used to produce ECDH shared secret inside the ECIES scheme by our server. The server’s ECDH public key is encoded in the first N bytes (65 in case of p-256 curve) as it is required in SEC 1 v2.
-
Prepare
id
that is an arbitrary UUID. Generate it in one of the following ways: -
Prepare the JSON
vem_request
structure embedding the validators'pubkeys
for withdrawal andecdh_client_pubkey
.Example
vem_request
structure:{ "action": "vem_request", "pubkeys": [ "0x867a9f95287decd74e076b8fefca3022fcb2c3c37de246e950ade0cc3609c74d4badda62657a64c2c4009f1b6625c647", "0x93e298f6ac5fb8f262a23450d1638aec1c45f77fd1ac86beb19b696b3b84fef3694e9b2166b337783911a3d7df13fbf1" ], "ecdh_client_pubkey": "LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUZrd0V3WUhLb1pJemowQ0FRWUlLb1pJemowREFRY0RRZ0FFNWgwcmRaSEZaZWNSbWIxR2RqQis3T0dUMnovegozMG1TRnZhWTdQaTltek5HT3J6SjZVbS9GbUMwb2lXMVFBT1FhOVFldGFpZm1EMU0zc09iU0JwV3N3PT0KLS0tLS1FTkQgUFVCTElDIEtFWS0tLS0tCg==" }
action
— The action type to be requested, here specified as a VEM request.pubkeys
— An array of public keys identifying the validators you are withdrawing from.ecdh_client_pubkey
— Your ECDH public key for secure communication.
-
To authorize the withdrawal process, the
vem_request
must be digitally signed using the Ethereum private key associated with yourwithdrawalAddress
orcontrollerAddress
.vem_request_signature
is a 0x prefixed hex encoded signature of Keccak256 hash of thevem_request
field done using the private key of either thewithdrawalAddress
orcontrollerAddress
. This private key should be a standard Ethereum key on the secp256k1 curve and use the standard Ethereum extended ECDSA signature algorithm.The signature verifies that the requestor has the authority to perform the transaction and is an essential security measure to prevent unauthorized withdrawals.
-
Submit the VEM request by sending a POST request to /api/v1/eth/staking/direct/vem/create. Use https://api-test.p2p.org for testing or https://api.p2p.org for production.
Example request:
curl --request POST \ --url https://api.p2p.org/api/v1/eth/staking/direct/vem/create \ --header 'accept: application/json' \ --header 'authorization: Bearer <token>' \ --header 'content-type: application/json' \ --data ' { "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "type": "off_chain", "vemRequest": "{\"action\": \"vem_request\",\"pubkeys\": [\"0x867a9f95287decd74e076b8fefca3022fcb2c3c37de246e950ade0cc3609c74d4badda62657a64c2c4009f1b6625c647\", \"0x93e298f6ac5fb8f262a23450d1638aec1c45f77fd1ac86beb19b696b3b84fef3694e9b2166b337783911a3d7df13fbf1\"],\"ecdh_client_pubkey\": \"LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUZrd0V3WUhLb1pJemowQ0FRWUlLb1pJemowREFRY0RRZ0FFNWgwcmRaSEZaZWNSbWIxR2RqQis3T0dUMnovegozMG1TRnZhWTdQaTltek5HT3J6SjZVbS9GbUMwb2lXMVFBT1FhOVFldGFpZm1EMU0zc09iU0JwV3N3PT0KLS0tLS1FTkQgUFVCTElDIEtFWS0tLS0tCg==\"}", "vemRequestSignature": "0x.....", "vemRequestSignedBy": "0x....." } '
id
— UUID to identify VEM set-up request.type
— VEM request type used. We support two types:off_chain
andon_chain
.vemRequest
— This parameter should be a JSON formatted string that represents the VEM request.vemRequestSignature
— The digital signature of the request.vemRequestSignedBy
— The Ethereum address that signed the request, providing a linkage to the withdrawal or controller account.
Example response:
{ "result": true }
-
Check the request status and retrieve the signed VEM by sending a GET request to /api/v1/eth/staking/direct/vem/status/{id}.
Example request:
curl --request GET \ --url https://api.p2p.org/api/v1/eth/staking/direct/vem/status/3fa85f64-5717-4562-b3fc-2c963f66afa6 \ --header 'accept: application/json' \ --header 'authorization: Bearer <token>' \
id
— UUID that was specified in the VEM set-up request.
Example response:
{ "error": null, "result": { "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "status": "processing", "type": "off_chain", "vemRequest": "{\"action\": \"vem_request\",\"pubkeys\": [\"0x867a9f95287decd74e076b8fefca3022fcb2c3c37de246e950ade0cc3609c74d4badda62657a64c2c4009f1b6625c647\", \"0x93e298f6ac5fb8f262a23450d1638aec1c45f77fd1ac86beb19b696b3b84fef3694e9b2166b337783911a3d7df13fbf1\"],\"ecdh_client_pubkey\": \"LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUZrd0V3WUhLb1pJemowQ0FRWUlLb1pJemowREFRY0RRZ0FFNWgwcmRaSEZaZWNSbWIxR2RqQis3T0dUMnovegozMG1TRnZhWTdQaTltek5HT3J6SjZVbS9GbUMwb2lXMVFBT1FhOVFldGFpZm1EMU0zc09iU0JwV3N3PT0KLS0tLS1FTkQgUFVCTElDIEtFWS0tLS0tCg==\"}", "vemRequestSignature": "0x.....", "vemRequestSignedBy": "0x.....", "error": "", "vemResult": "" } }
id
— UUID that was specified in the VEM set-up request.status
— VEM request status.type
— VEM request type used. We support two types:off_chain
andon_chain
.vemRequest
— The base64 encoded VEM request.vemRequestSignature
— The digital signature of the request.vemRequestSignedBy
— The Ethereum address that signed the request, providing a linkage to the withdrawal or controller account.error
— error message (if exists)vemResult
— encrypted vem results
Upon receipt of the vemResult
, you should use your private ECDH key to decrypt the message using the ECIES scheme and retrieve the signed VEM for your staked Ethereum.
What's Next?
- Getting Started.
- Staking API reference.
Updated 8 days ago