En résumé
L’API Smart Contracts de Blockradar vous permet d’interagir avec n’importe quel smart contract directement depuis votre portefeuille, sans avoir à gérer vous-même les endpoints RPC, les flux de signature ou le déploiement de contrats.
Prérequis
Avant d’utiliser l’API Smart Contracts, assurez-vous de disposer de :
Clé API
Obtenez votre clé API depuis le Dashboard Blockradar . Rendez-vous dans Developers pour en générer une.
Portefeuille créé
Créez un portefeuille via l’API Create Wallet ou le dashboard. Vous aurez besoin du walletId pour toutes les opérations sur les smart contracts.
Solde en monnaie native
Approvisionnez votre portefeuille en monnaie native (ETH, BNB, MATIC, etc.) pour couvrir les frais de gas. Utilisez le endpoint Network Fee pour estimer les coûts avant d’exécuter.
Blockchains prises en charge
L’API Smart Contracts prend en charge toutes les blockchains compatibles EVM ainsi que Tron disponibles sur Blockradar. Consultez Integrations pour la liste complète des réseaux pris en charge et les liens vers les faucets.
Solana n’est pas pris en charge pour les interactions avec les smart contracts. L’API Smart Contracts fonctionne uniquement avec les chaînes compatibles EVM et Tron.
Commencez par utiliser des testnets pendant le développement afin d’éviter de dépenser des fonds réels.
Introduction
L’API Smart Contracts transforme Blockradar d’une infrastructure de portefeuilles en une couche d’exécution programmable. Vous pouvez lire l’état d’un contrat, exécuter des fonctions de contrats, estimer les frais de gas et signer des transactions, le tout via une surface API unifiée.
Opérations de lecture Récupérez les données de n’importe quel smart contract sur les blockchains prises en charge.
Opérations d'écriture Exécutez les fonctions de smart contracts avec une gestion complète des transactions.
Estimation des frais Calculez les coûts de gas avant l’exécution pour vous assurer de disposer de fonds suffisants.
Opérations groupées Exécutez plusieurs appels de contrat dans une seule requête API.
Cas d’usage
L’API Smart Contracts débloque des capacités puissantes pour les développeurs fintech :
Intégration DeFi : Connectez-vous à des protocoles tels qu’Uniswap, Aave ou Compound pour la gestion du rendement et de la liquidité
Opérations de trésorerie : Automatisez la gestion de trésorerie au sein de votre plateforme fintech
Actifs tokenisés : Intégrez des actifs du monde réel dans vos flux produit
Règlements programmables : Exécutez des contrôles de conformité et des règlements automatisés
Actifs personnalisés : Gérez des actifs personnalisés, des systèmes de récompense et des programmes de fidélité
Master Wallet vs Child Address
L’API Smart Contracts est disponible à deux niveaux :
Master Wallet Exécutez les opérations de contrat directement depuis votre master wallet. Idéal pour les opérations de trésorerie et la gestion centralisée des fonds.
Child Address Exécutez les opérations de contrat à partir de child addresses individuelles. Parfait pour les opérations spécifiques aux utilisateurs et la gestion séparée des fonds.
Endpoints Master Wallet
Opération Endpoint Description Lecture POST /v1/wallets/{walletId}/contracts/readRécupère les données des smart contracts Écriture POST /v1/wallets/{walletId}/contracts/writeExécute les fonctions des smart contracts Network Fee POST /v1/wallets/{walletId}/contracts/network-feeEstime les coûts de gas Sign Only POST /v1/wallets/{walletId}/contracts/write/signSigne sans diffuser
Endpoints Child Address
Opération Endpoint Description Lecture POST /v1/wallets/{walletId}/addresses/{addressId}/contracts/readRécupère les données des smart contracts Écriture POST /v1/wallets/{walletId}/addresses/{addressId}/contracts/writeExécute les fonctions des smart contracts Network Fee POST /v1/wallets/{walletId}/addresses/{addressId}/contracts/network-feeEstime les coûts de gas Sign Only POST /v1/wallets/{walletId}/addresses/{addressId}/contracts/write/signSigne sans diffuser
Structure de la requête
Toutes les requêtes de smart contracts nécessitent ces paramètres :
Paramètre Type Requis Description addressstring Oui L’adresse du smart contract sur la blockchain methodstring Oui Le nom de la fonction à appeler parametersarray Oui Arguments dans l’ordre défini par l’ABI de la fonction abiarray Oui L’Application Binary Interface du contrat referencestring Non Votre identifiant interne de suivi de la transaction metadataobject Non Paires clé-valeur personnalisées pour des détails supplémentaires de transaction
Les champs reference et metadata ne s’appliquent qu’aux opérations d’écriture. Les opérations de lecture ne prennent pas en charge ces champs.
Comprendre les ABIs
L’ABI (Application Binary Interface) définit la manière d’interagir avec un smart contract. Vous pouvez obtenir des ABIs depuis :
Block explorers : Etherscan, BscScan, PolygonScan (contrats vérifiés)
Documentation des protocoles : Documentation officielle des protocoles DeFi
Code source du contrat : Compilez à partir du code source Solidity
Lecture des données du contrat
Utilisez l’endpoint de lecture pour interroger l’état du contrat sans modifier la blockchain.
Exemple de lecture avec Master Wallet
curl --request POST \
--url https://api.blockradar.co/v1/wallets/{walletId}/contracts/read \
--header 'Content-Type: application/json' \
--header 'x-api-key: <api-key>' \
--data '{
"address": "0x337610d27c682E347C9cD60BD4b3b107C9d34dDd",
"method": "balanceOf",
"parameters": ["0x947514e4B803e312C312da0F1B41fEDdbe15ae7a"],
"abi": [{
"constant": true,
"inputs": [{"name": "account", "type": "address"}],
"name": "balanceOf",
"outputs": [{"name": "", "type": "uint256"}],
"stateMutability": "view",
"type": "function"
}]
}'
const response = await fetch (
`https://api.blockradar.co/v1/wallets/ ${ walletId } /contracts/read` ,
{
method: 'POST' ,
headers: {
'Content-Type' : 'application/json' ,
'x-api-key' : '<api-key>'
},
body: JSON . stringify ({
address: '0x337610d27c682E347C9cD60BD4b3b107C9d34dDd' ,
method: 'balanceOf' ,
parameters: [ '0x947514e4B803e312C312da0F1B41fEDdbe15ae7a' ],
abi: [{
constant: true ,
inputs: [{ name: 'account' , type: 'address' }],
name: 'balanceOf' ,
outputs: [{ name: '' , type: 'uint256' }],
stateMutability: 'view' ,
type: 'function'
}]
})
}
);
Exemple de lecture avec Child Address
curl --request POST \
--url https://api.blockradar.co/v1/wallets/{walletId}/addresses/{addressId}/contracts/read \
--header 'Content-Type: application/json' \
--header 'x-api-key: <api-key>' \
--data '{
"address": "0x337610d27c682E347C9cD60BD4b3b107C9d34dDd",
"method": "balanceOf",
"parameters": ["0x947514e4B803e312C312da0F1B41fEDdbe15ae7a"],
"abi": [{
"constant": true,
"inputs": [{"name": "account", "type": "address"}],
"name": "balanceOf",
"outputs": [{"name": "", "type": "uint256"}],
"stateMutability": "view",
"type": "function"
}]
}'
const response = await fetch (
`https://api.blockradar.co/v1/wallets/ ${ walletId } /addresses/ ${ addressId } /contracts/read` ,
{
method: 'POST' ,
headers: {
'Content-Type' : 'application/json' ,
'x-api-key' : '<api-key>'
},
body: JSON . stringify ({
address: '0x337610d27c682E347C9cD60BD4b3b107C9d34dDd' ,
method: 'balanceOf' ,
parameters: [ '0x947514e4B803e312C312da0F1B41fEDdbe15ae7a' ],
abi: [{
constant: true ,
inputs: [{ name: 'account' , type: 'address' }],
name: 'balanceOf' ,
outputs: [{ name: '' , type: 'uint256' }],
stateMutability: 'view' ,
type: 'function'
}]
})
}
);
Réponse de lecture
{
"message" : "Contract read successfully" ,
"statusCode" : 200 ,
"data" : "10052335235393043"
}
Réponses d’erreur de lecture
Adresse de contrat invalide
{
"message" : "Invalid contract address" ,
"statusCode" : 400 ,
"error" : "BAD_REQUEST"
}
{
"message" : "Method 'balanceOf' not found in ABI" ,
"statusCode" : 400 ,
"error" : "ABI_METHOD_NOT_FOUND"
}
Exécution du contrat annulée
{
"message" : "Contract execution reverted" ,
"statusCode" : 400 ,
"error" : "EXECUTION_REVERTED" ,
"data" : {
"reason" : "ERC20: balance query for zero address"
}
}
{
"message" : "Parameter count mismatch. Expected 1, got 2" ,
"statusCode" : 400 ,
"error" : "INVALID_PARAMETERS"
}
Écriture sur les contrats
Exécutez des fonctions modifiant l’état des smart contracts.
Exemple d’écriture avec Master Wallet
curl --request POST \
--url https://api.blockradar.co/v1/wallets/{walletId}/contracts/write \
--header 'Content-Type: application/json' \
--header 'x-api-key: <api-key>' \
--data '{
"address": "0xYOUR_TOKEN_CONTRACT",
"method": "approve",
"parameters": ["0xYOUR_SPENDER_ADDRESS", "1000000000000000000"],
"abi": [{
"inputs": [
{"name": "spender", "type": "address"},
{"name": "amount", "type": "uint256"}
],
"name": "approve",
"outputs": [{"name": "", "type": "bool"}],
"stateMutability": "nonpayable",
"type": "function"
}]
}'
const response = await fetch (
`https://api.blockradar.co/v1/wallets/ ${ walletId } /contracts/write` ,
{
method: 'POST' ,
headers: {
'Content-Type' : 'application/json' ,
'x-api-key' : '<api-key>'
},
body: JSON . stringify ({
address: '0xYOUR_TOKEN_CONTRACT' ,
method: 'approve' ,
parameters: [ '0xYOUR_SPENDER_ADDRESS' , '1000000000000000000' ],
abi: [{
inputs: [
{ name: 'spender' , type: 'address' },
{ name: 'amount' , type: 'uint256' }
],
name: 'approve' ,
outputs: [{ name: '' , type: 'bool' }],
stateMutability: 'nonpayable' ,
type: 'function'
}]
})
}
);
Exemple d’écriture avec Child Address
curl --request POST \
--url https://api.blockradar.co/v1/wallets/{walletId}/addresses/{addressId}/contracts/write \
--header 'Content-Type: application/json' \
--header 'x-api-key: <api-key>' \
--data '{
"address": "0xYOUR_TOKEN_CONTRACT",
"method": "approve",
"parameters": ["0xYOUR_SPENDER_ADDRESS", "1000000000000000000"],
"abi": [{
"inputs": [
{"name": "spender", "type": "address"},
{"name": "amount", "type": "uint256"}
],
"name": "approve",
"outputs": [{"name": "", "type": "bool"}],
"stateMutability": "nonpayable",
"type": "function"
}]
}'
const response = await fetch (
`https://api.blockradar.co/v1/wallets/ ${ walletId } /addresses/ ${ addressId } /contracts/write` ,
{
method: 'POST' ,
headers: {
'Content-Type' : 'application/json' ,
'x-api-key' : '<api-key>'
},
body: JSON . stringify ({
address: '0xYOUR_TOKEN_CONTRACT' ,
method: 'approve' ,
parameters: [ '0xYOUR_SPENDER_ADDRESS' , '1000000000000000000' ],
abi: [{
inputs: [
{ name: 'spender' , type: 'address' },
{ name: 'amount' , type: 'uint256' }
],
name: 'approve' ,
outputs: [{ name: '' , type: 'bool' }],
stateMutability: 'nonpayable' ,
type: 'function'
}]
})
}
);
Réponse d’écriture
{
"message" : "Contract write initiated" ,
"statusCode" : 200 ,
"data" : {
"id" : "tx-uuid" ,
"hash" : "0x..." ,
"status" : "PENDING"
}
}
Les opérations d’écriture sont asynchrones. La réponse initiale affiche le statut PENDING. Écoutez le webhook custom-smart-contract.success pour confirmer la finalisation de la transaction.
Réponses d’erreur d’écriture
{
"message" : "Insufficient native token balance for gas" ,
"statusCode" : 400 ,
"error" : "INSUFFICIENT_GAS" ,
"data" : {
"required" : "0.005" ,
"available" : "0.001" ,
"token" : "ETH"
}
}
{
"message" : "Insufficient token balance" ,
"statusCode" : 400 ,
"error" : "INSUFFICIENT_BALANCE" ,
"data" : {
"required" : "1000000000000000000" ,
"available" : "500000000000000000"
}
}
{
"message" : "Transaction would revert" ,
"statusCode" : 400 ,
"error" : "EXECUTION_REVERTED" ,
"data" : {
"reason" : "ERC20: transfer amount exceeds allowance"
}
}
{
"message" : "Invalid ABI format" ,
"statusCode" : 400 ,
"error" : "INVALID_ABI" ,
"data" : {
"details" : "Missing 'inputs' field in ABI definition"
}
}
{
"message" : "Wallet not found" ,
"statusCode" : 404 ,
"error" : "NOT_FOUND"
}
Estimation des frais réseau
Estimez toujours les frais avant d’exécuter des opérations d’écriture afin de vous assurer que votre portefeuille dispose d’une quantité suffisante de monnaie native.
Estimation des frais avec Master Wallet
curl --request POST \
--url https://api.blockradar.co/v1/wallets/{walletId}/contracts/network-fee \
--header 'Content-Type: application/json' \
--header 'x-api-key: <api-key>' \
--data '{
"address": "0xYOUR_TOKEN_CONTRACT",
"method": "approve",
"parameters": ["0xYOUR_SPENDER_ADDRESS", "1000000000000000000"],
"abi": [{
"inputs": [
{"name": "spender", "type": "address"},
{"name": "amount", "type": "uint256"}
],
"name": "approve",
"outputs": [{"name": "", "type": "bool"}],
"stateMutability": "nonpayable",
"type": "function"
}]
}'
Estimation des frais avec Child Address
curl --request POST \
--url https://api.blockradar.co/v1/wallets/{walletId}/addresses/{addressId}/contracts/network-fee \
--header 'Content-Type: application/json' \
--header 'x-api-key: <api-key>' \
--data '{
"address": "0xYOUR_TOKEN_CONTRACT",
"method": "approve",
"parameters": ["0xYOUR_SPENDER_ADDRESS", "1000000000000000000"],
"abi": [{
"inputs": [
{"name": "spender", "type": "address"},
{"name": "amount", "type": "uint256"}
],
"name": "approve",
"outputs": [{"name": "", "type": "bool"}],
"stateMutability": "nonpayable",
"type": "function"
}]
}'
Réponse de frais
{
"message" : "Network fee retrieved" ,
"statusCode" : 200 ,
"data" : {
"networkFee" : "0.00001247904" ,
"networkFeeInUSD" : "0.01" ,
"nativeBalance" : "0.5" ,
"nativeBalanceInUSD" : "450.00" ,
"estimatedArrivalTime" : 30
}
}
Exemple pratique : échange d’actifs sur Uniswap
Cette section présente deux approches pour exécuter un échange d’actifs : sans opérations groupées (appels séquentiels) et avec opérations groupées (appel API unique).
Exemple 1 : échange d’actifs SANS opérations groupées
Cette approche effectue des appels API individuels pour chaque étape. Utilisez-la lorsque vous avez besoin d’un contrôle précis sur chaque transaction ou lorsque les opérations dépendent des résultats d’appels précédents.
Étape 1 : vérifier le solde de l’actif
const balanceOfAbi = {
constant: true ,
inputs: [{ name: 'account' , type: 'address' }],
name: 'balanceOf' ,
outputs: [{ name: '' , type: 'uint256' }],
stateMutability: 'view' ,
type: 'function'
};
const balance = await fetch (
`https://api.blockradar.co/v1/wallets/ ${ walletId } /contracts/read` ,
{
method: 'POST' ,
headers: { 'Content-Type' : 'application/json' , 'x-api-key' : apiKey },
body: JSON . stringify ({
address: TOKEN_ADDRESS ,
method: 'balanceOf' ,
parameters: [ walletAddress ],
abi: [ balanceOfAbi ]
})
}
). then ( r => r . json ());
console . log ( 'Asset Balance:' , balance . data );
Étape 2 : approuver la dépense de l’actif
const approveAbi = {
inputs: [
{ name: 'spender' , type: 'address' },
{ name: 'amount' , type: 'uint256' }
],
name: 'approve' ,
outputs: [{ name: '' , type: 'bool' }],
stateMutability: 'nonpayable' ,
type: 'function'
};
const approval = await fetch (
`https://api.blockradar.co/v1/wallets/ ${ walletId } /contracts/write` ,
{
method: 'POST' ,
headers: { 'Content-Type' : 'application/json' , 'x-api-key' : apiKey },
body: JSON . stringify ({
address: TOKEN_ADDRESS ,
method: 'approve' ,
parameters: [ UNISWAP_ROUTER , amountIn ],
abi: [ approveAbi ]
})
}
). then ( r => r . json ());
console . log ( 'Approval TX:' , approval . data . hash );
// IMPORTANT: Wait for webhook confirmation before proceeding
Attendez toujours le webhook custom-smart-contract.success confirmant que la transaction d’approbation a été minée avant d’exécuter le swap.
Étape 3 : estimer les frais du swap
const swapAbi = {
inputs: [
{ name: 'amountIn' , type: 'uint256' },
{ name: 'amountOutMin' , type: 'uint256' },
{ name: 'path' , type: 'address[]' },
{ name: 'to' , type: 'address' },
{ name: 'deadline' , type: 'uint256' }
],
name: 'swapExactTokensForTokens' ,
outputs: [{ name: 'amounts' , type: 'uint256[]' }],
stateMutability: 'nonpayable' ,
type: 'function'
};
const fees = await fetch (
`https://api.blockradar.co/v1/wallets/ ${ walletId } /contracts/network-fee` ,
{
method: 'POST' ,
headers: { 'Content-Type' : 'application/json' , 'x-api-key' : apiKey },
body: JSON . stringify ({
address: UNISWAP_ROUTER ,
method: 'swapExactTokensForTokens' ,
parameters: [
amountIn ,
amountOutMin ,
[ TOKEN_A , TOKEN_B ],
walletAddress ,
deadline
],
abi: [ swapAbi ]
})
}
). then ( r => r . json ());
console . log ( 'Estimated Fee:' , fees . data . networkFee );
Étape 4 : exécuter le swap
const swap = await fetch (
`https://api.blockradar.co/v1/wallets/ ${ walletId } /contracts/write` ,
{
method: 'POST' ,
headers: { 'Content-Type' : 'application/json' , 'x-api-key' : apiKey },
body: JSON . stringify ({
address: UNISWAP_ROUTER ,
method: 'swapExactTokensForTokens' ,
parameters: [
amountIn ,
amountOutMin ,
[ TOKEN_A , TOKEN_B ],
walletAddress ,
deadline
],
abi: [ swapAbi ]
})
}
). then ( r => r . json ());
console . log ( 'Swap TX:' , swap . data . hash );
Exemple 2 : échange d’actifs AVEC opérations groupées
Cette approche combine approve + swap en un seul appel API en utilisant le tableau calls. Utilisez-la pour plus d’efficacité lorsque vous souhaitez mettre en file plusieurs opérations à la fois.
Les opérations groupées s’exécutent séquentiellement. Chaque opération est soumise comme une transaction distincte, mais vous n’avez besoin que d’un seul appel API.
Requête groupée : approve + swap en un seul appel
const approveAbi = {
inputs: [
{ name: 'spender' , type: 'address' },
{ name: 'amount' , type: 'uint256' }
],
name: 'approve' ,
outputs: [{ name: '' , type: 'bool' }],
stateMutability: 'nonpayable' ,
type: 'function'
};
const swapAbi = {
inputs: [
{ name: 'amountIn' , type: 'uint256' },
{ name: 'amountOutMin' , type: 'uint256' },
{ name: 'path' , type: 'address[]' },
{ name: 'to' , type: 'address' },
{ name: 'deadline' , type: 'uint256' }
],
name: 'swapExactTokensForTokens' ,
outputs: [{ name: 'amounts' , type: 'uint256[]' }],
stateMutability: 'nonpayable' ,
type: 'function'
};
const batchSwap = await fetch (
`https://api.blockradar.co/v1/wallets/ ${ walletId } /contracts/write` ,
{
method: 'POST' ,
headers: { 'Content-Type' : 'application/json' , 'x-api-key' : apiKey },
body: JSON . stringify ({
calls: [
{
address: TOKEN_ADDRESS ,
method: 'approve' ,
parameters: [ UNISWAP_ROUTER , amountIn ],
abi: [ approveAbi ],
reference: 'approve-tx' ,
metadata: { step: 'approval' }
},
{
address: UNISWAP_ROUTER ,
method: 'swapExactTokensForTokens' ,
parameters: [
amountIn ,
amountOutMin ,
[ TOKEN_A , TOKEN_B ],
walletAddress ,
deadline
],
abi: [ swapAbi ],
reference: 'swap-tx' ,
metadata: { step: 'swap' }
}
]
})
}
). then ( r => r . json ());
console . log ( 'Batch Result:' , batchSwap . data );
Réponse groupée
{
"message" : "Batch contract write initiated successfully" ,
"statusCode" : 200 ,
"data" : {
"success" : [
{
"index" : 0 ,
"id" : "tx-uuid-1" ,
"hash" : "0xapprove..." ,
"status" : "PENDING" ,
"reference" : "approve-tx"
},
{
"index" : 1 ,
"id" : "tx-uuid-2" ,
"hash" : "0xswap..." ,
"status" : "PENDING" ,
"reference" : "swap-tx"
}
],
"errors" : []
}
}
Gestion des échecs partiels dans un lot
const result = await batchSwap . json ();
// Check for successful operations
result . data . success . forEach ( tx => {
console . log ( `✓ ${ tx . reference } : ${ tx . hash } ` );
});
// Check for failed operations
result . data . errors . forEach ( error => {
console . error ( `✗ Operation ${ error . index } ( ${ error . method } ): ${ error . error } ` );
});
Règles des opérations groupées
Règle Valeur Taille maximale du lot 20 opérations Ordre d’exécution Séquentiel Gestion des erreurs Succès partiel (les échecs n’arrêtent pas les opérations suivantes)
Quand utiliser chaque approche
Scénario Approche recommandée Vérifier les résultats entre les étapes Sans lot Paramètres dynamiques basés sur des résultats précédents Sans lot Schémas simples approve + action Avec lot Plusieurs opérations indépendantes Avec lot Minimiser les appels API Avec lot
Événements Webhook
Les opérations de smart contracts déclenchent des notifications webhook :
Événement Description custom-smart-contract.successOpération de contrat terminée avec succès custom-smart-contract.failedOpération de contrat échouée
Payload du Webhook
{
"event" : "custom-smart-contract.success" ,
"data" : {
"id" : "tx-uuid" ,
"hash" : "0x..." ,
"status" : "SUCCESS" ,
"method" : "approve" ,
"contractAddress" : "0x..." ,
"blockchain" : {
"name" : "ethereum" ,
"network" : "mainnet"
}
}
}
Bonnes pratiques
Sécurité
Vérifiez les adresses des contrats : Vérifiez toujours deux fois les adresses des contrats avant d’interagir
Utilisez des ABIs de confiance : Obtenez les ABIs de sources vérifiées comme les block explorers
Définissez des limites raisonnables : Utilisez la protection contre le slippage et les plafonds de montant pour les opérations DeFi
Gestion du gas
Estimez avant d’exécuter : Appelez toujours d’abord l’endpoint network-fee
Surveillez le solde natif : Assurez-vous d’avoir suffisamment d’ETH/BNB/MATIC pour les frais de gas
Utilisez les opérations groupées : Réduisez le surcoût en groupant les opérations liées
Gestion des erreurs
Implémentez des écouteurs de webhook : Ne vous fiez pas uniquement aux réponses API
Gérez les échecs partiels : Vérifiez à la fois les tableaux success et errors dans les réponses groupées
Réessayez avec backoff : Implémentez un backoff exponentiel pour les échecs transitoires
Référence API
Endpoints Master Wallet
Endpoint Description Read Contract Lit l’état du contrat Write Contract Exécute les fonctions du contrat Network Fee Estime les coûts de gas Sign Only Signe sans diffuser
Endpoints Child Address
Endpoint Description Read Contract Lit l’état du contrat Write Contract Exécute les fonctions du contrat Network Fee Estime les coûts de gas Sign Only Signe sans diffuser
Support
L’API Smart Contracts vous permet de créer des intégrations blockchain sophistiquées sans gérer la complexité de l’infrastructure. Commencez par des opérations de lecture simples et intégrez progressivement des opérations d’écriture à mesure que vous vous familiarisez avec le système.