VeChain Docs
  • Welcome to VeChain
  • Blockchain Basics
    • Introduction to blockchain
    • Introduction to digital property
    • The evolution of the internet
  • Introduction to VeChain
    • About the VeChain blockchain
      • Consensus Deep Dive
      • Governance
    • Dual-Token Economic Model
      • VeChain (VET)
      • VeThor (VTHO)
    • Acquire VeChain Assets
    • Sustainability
  • Core Concepts
    • Networks
      • Thor Solo Node
      • Testnet
      • Mainnet
    • Nodes
      • Node Rewards Programme
    • Blocks
      • Block Model
    • Transactions
      • Transaction Model
      • Transaction Fees
      • Transaction Calculation
      • Meta Transaction Features
        • Transaction Uniqueness
        • Controllable Transaction Lifecycle
        • Clauses (Multi-Task Transaction)
        • Fee Delegation
          • Multi-Party Payment (MPP)
          • Designated Gas Payer (VIP-191)
        • Transaction Dependency
    • Block Explorers
    • Wallets
      • VeWorld
        • User Guide
          • Setup
          • Wallet
          • Signing
          • Activities
          • Settings
        • FAQ
      • Sync2
        • User Guide
          • Setup
          • Wallet
          • Signing
          • Activities
          • Settings
        • FAQ
      • Sync
        • User Guide
          • Wallet
          • Ledger Device
          • Browser dApps and web
          • Interact with dApps
          • Activities
          • Settings
          • Report an Issue
          • Contributing
        • FAQ
    • EVM Compatibility
      • VeChain Modifications
      • Methodology
      • Test Coverage
        • Gas model
        • Raw transaction
        • hardhat specific
          • Ganache failures
          • evm_increaseTime
        • Failures in constructor
        • eth_sign
        • Contract address prediction
        • BadBeacon proxy address at 0x1
      • How to Recreate
      • Additional Information
        • Using Governance Contracts
        • ERC1820/ERC777 Testnet
        • Delegate Options
    • Account Abstraction
      • UserOperation
      • Bundler
      • EntryPoint Contract
      • Account Factory Contract
      • Paymaster Contract
    • Token Bound Accounts
  • How to run a node
    • Nodes
    • How to run a Thor Solo Node
    • Custom Network
    • Connect Sync2 to a Thor Solo Node
  • Developer Resources
    • Getting Started
    • How to build on VeChain
      • Connect to the Network
      • Read Data
        • Read Blocks
        • Read Transactions
        • Read Accounts
        • States & Views
        • Events & Logs
        • VET Transfers
      • Write Data
        • Transactions
        • Fee Delegation
      • Listen to Changes
        • Events
        • VET Transfers
        • Transactions
        • Blocks
        • Beats
      • Build with Hardhat
      • Utilities
        • BigInt and Unit-Handling
        • Name Service Lookups
    • Example dApps
      • Buy me a Coffee
      • Token Bound Accounts
      • PWA with Privy and Account Abstraction
    • EVM Compatibility for Developers
      • Key Architectural Differences and Optimizations
      • Practical Implications for Developers: Key Considerations
      • RPC Methods (Detailed Breakdown)
      • Frequently Asked Questions (FAQs)
      • VeChain Blockchain Specifications
      • Key Differences Between VeChain and Ethereum (Summary)
      • Best Practices for Developing on VeChainThor
    • How to verify Address-Ownership
      • Next.js Session Verification
    • Debug Reverted Transactions
    • Account Abstraction
    • VIP-191: Designated Gas Payer
      • How to Integrate VIP-191 (I)
      • How to Integrate VIP-191 (II)
      • How to Integrate VIP-191 (III)
    • Index with Graph Node
      • Setup with Docker
      • Index with OpenZeppelin
        • Create Subgraph Project
        • Configure Contracts
        • Deploy Subgraph and start Indexing
        • Track Subgraph Indexing
        • Access Subgraph
        • Update Subgraph
    • SDKs & Providers
      • SDK
        • Architecture
        • Accounts
        • Bloom Filter
        • Certificates
        • Contracts
        • Cryptography
        • Debug
        • Encoding
        • Polls
        • Subscriptions
        • Thor Client
        • Transactions
      • Thor DevKit
        • Installation
        • Usage
          • Cryptography
          • Accounts
          • Encoding
          • Transactions
          • Certificates
          • Bloom Filter
      • DApp Kit
        • v2
          • Installation
          • React
            • Installation
            • Usage
          • Vanilla JS
            • Installation
            • Usage
          • Core
            • Installation
            • Usage
          • Theme Variables
          • i18n
        • v1
          • Installation
          • React
            • Installation
            • Usage
          • Vanilla JS
            • Installation
            • Usage
          • Core
            • Installation
            • Usage
          • Theme Variables
          • i18n
          • Node Polyfills
          • V0 to V1
        • v0
          • Installation
          • Usage
          • React
            • Installation
            • Usage
          • Vanilla (UI)
            • Installation
            • Usage
          • Styles (UI)
          • i18n
      • DevPal
      • Web3-Providers-Connex
        • Installation
        • Usage
      • Connex
        • Installation
        • API Specification
    • Frameworks & IDEs
      • Hardhat
      • Remix
    • Built-in Contracts
    • VORJ
    • Useful Links
  • How to contribute
Powered by GitBook
On this page
  • Building clauses
  • Transfer VET and VTHO clauses
  • Deploying a Smart Contract Clause
  • Calling a Contract Function Clause
  • Steps:
  • Multi-Clause Contract Interaction
  • Multiple Clauses in a Single Transaction
  • Commenting Contract Invocations
  • Specifying Revisions in Read Functions
  • Delegating a Contract Call

Was this helpful?

  1. Developer Resources
  2. SDKs & Providers
  3. SDK

Contracts

The following sections provide detailed information on interacting with VeChain smart contracts using the VeChain SDK.

Building clauses

VeChain uses clauses to interact with smart contracts. A clause is a single operation that can be executed on the blockchain. The VeChain SDK provides a ClauseBuilder class to create clauses for various operations.

⚠️ Warning: To execute the clauses, you need to build a transaction and sign it with a wallet. The signed transaction can then be sent to the blockchain. This process is covered ahead in the documentation.

Transfer VET and VTHO clauses

The following example shows you how to build clauses to transfer the two main token of VeChain, the token VET and the energy token VTHO (the one used to pay for transaction fees)

import {
    Address,
    Clause,
    Units,
    VET,
    VTHO,
    VTHO_ADDRESS
} from '@vechain/sdk-core';

// build some example clauses

// 1. Transfer vet

const transferVetClause = Clause.transferVET(
    Address.of('0xf02f557c753edf5fcdcbfe4c1c3a448b3cc84d54'),
    VET.of(300n, Units.wei)
);

// 2. Transfer VTHO

const transferVTHOClause = Clause.transferVTHOToken(
    Address.of('0xf02f557c753edf5fcdcbfe4c1c3a448b3cc84d54'),
    VTHO.of(300n, Units.wei)
);

Deploying a Smart Contract Clause

Steps:

  1. Clause Construction: Use clauseBuilder.deployContract from @vechain/sdk-core to construct a deployment clause.

  2. Smart Contract Bytecode: Pass the compiled contract's bytecode to deploy it.

  3. Clause Building: create the deployment clause

// 1 - Init contract bytecode to deploy

const contractBytecode = HexUInt.of(
    '0x608060405234801561000f575f80fd5b506101438061001d5f395ff3fe608060405234801561000f575f80fd5b5060043610610034575f3560e01c806360fe47b1146100385780636d4ce63c14610054575b5f80fd5b610052600480360381019061004d91906100ba565b610072565b005b61005c61007b565b60405161006991906100f4565b60405180910390f35b805f8190555050565b5f8054905090565b5f80fd5b5f819050919050565b61009981610087565b81146100a3575f80fd5b50565b5f813590506100b481610090565b92915050565b5f602082840312156100cf576100ce610083565b5b5f6100dc848285016100a6565b91505092915050565b6100ee81610087565b82525050565b5f6020820190506101075f8301846100e5565b9291505056fea2646970667358221220427ff5682ef89b62b910bb1286c1028d32283512122854159ad59f1c71fb6d8764736f6c63430008160033'
);

// 2 - Create a clause to deploy the contract
const clause = Clause.deployContract(contractBytecode);

Calling a Contract Function Clause

Steps:

  1. Understand the ABI: The ABI (JSON format) defines contract functions and parameters.

  2. Clause Creation: Use clauseBuilder.functionInteraction to create a clause for function calls.

  3. Clause Building: Build the clause, e.g., calling setValue(123) to modify the contract state.

// 1 - Init a simple contract ABI
const contractABI = [
    {
        constant: false,
        inputs: [
            {
                name: 'value',
                type: 'uint256'
            }
        ],
        name: 'setValue',
        outputs: [],
        payable: false,
        stateMutability: 'nonpayable',
        type: 'function'
    },
    {
        constant: true,
        inputs: [],
        name: 'getValue',
        outputs: [
            {
                name: '',
                type: 'uint256'
            }
        ],
        payable: false,
        stateMutability: 'view',
        type: 'function'
    }
] as const;

// 2 - Create a clause to call setValue(123)
const clause = Clause.callFunction(
    Address.of('0x7567d83b7b8d80addcb281a71d54fc7b3364ffed'), // just a sample deployed contract address
    ABIContract.ofAbi(contractABI).getFunction('setValue'),
    [123]
);

or you can load the contract using the thor client and then you can build the clause using the contract object.

// 1 - Build the thor client and load the contract

const thorSoloClient = ThorClient.at(THOR_SOLO_URL);

const contract = thorSoloClient.contracts.load(
    '0x7567d83b7b8d80addcb281a71d54fc7b3364ffed',
    contractABI
);

// 2 - Create a clause to call setValue(123)
const setValueClause = contract.clause.setValue(123);

Multi-Clause Contract Interaction

Now that we have seen how to build clauses, let's see how to send it to the blockchain. VeChain allows multiple clauses in a single transaction, enabling interactions with multiple contracts or operations.

Multiple Clauses in a Single Transaction

In the following example we will see how to execute multiple read operations to get information regarding a deployed ERC20 token contract.

// Reading data from multiple clauses in a single call
const multipleClausesResult =
    await thorSoloClient.contracts.executeMultipleClausesCall([
        contract.clause.totalSupply(),
        contract.clause.name(),
        contract.clause.symbol(),
        contract.clause.decimals()
    ]);

expect(multipleClausesResult[0]).toEqual({
    success: true,
    result: {
        plain: expectedBalance,
        array: [expectedBalance]
    }
});
expect(multipleClausesResult[1]).toEqual({
    success: true,
    result: {
        plain: 'SampleToken',
        array: ['SampleToken']
    }
});
expect(multipleClausesResult[2]).toEqual({
    success: true,
    result: {
        plain: 'ST',
        array: ['ST']
    }
});
expect(multipleClausesResult[3]).toEqual({
    success: true,
    result: {
        plain: 18,
        array: [18]
    }
});

⚠️ Warning: The example above shows a multi clause read call. It's also possible to execute multi clause transactions with the method executeMultipleClausesTransaction, but you need to build a signer first. Please refer to the signer section for more information

Commenting Contract Invocations

Add comments to operations when using wallets, helping users understand transaction details during signing.

// Transfer tokens to another address with a comment

await contract.transact.transfer(
    { comment: 'Transferring 100 ERC20 tokens' },
    '0x9e7911de289c3c856ce7f421034f66b6cde49c39',
    Units.parseEther('100').bi
);

Specifying Revisions in Read Functions

You can specify revisions (best or finalized) for read functions, similar to adding comments.

Delegating a Contract Call

VeChain supports delegated contract calls where fees are paid by the gas-payer.

const thorSoloClient = ThorClient.at(THOR_SOLO_URL);
const provider = new VeChainProvider(
    thorSoloClient,
    new ProviderInternalBaseWallet([deployerAccount], {
        gasPayer: {
            gasPayerPrivateKey: gasPayerAccount.privateKey
        }
    }),
    true
);
const signer = await provider.getSigner(deployerAccount.address);

// Defining a function for deploying the ERC20 contract
const setupERC20Contract = async (): Promise<Contract<typeof ERC20_ABI>> => {
    const contractFactory = thorSoloClient.contracts.createContractFactory(
        ERC20_ABI,
        erc20ContractBytecode,
        signer
    );

    // Deploying the contract
    await contractFactory.startDeployment();

    // Waiting for the contract to be deployed
    return await contractFactory.waitForDeployment();
};

// Setting up the ERC20 contract and getting its address
const contract = await setupERC20Contract();

// Transferring 10000 tokens to another address with a delegated transaction
const transferResult = await contract.transact.transfer(
    '0x9e7911de289c3c856ce7f421034f66b6cde49c39',
    10000n
);

// Wait for the transfer transaction to complete and obtain its receipt
const transactionReceiptTransfer = await transferResult.wait();

// Asserting that the transaction has not been reverted
expect(transactionReceiptTransfer.reverted).toEqual(false);
PreviousCertificatesNextCryptography

Last updated 1 month ago

Was this helpful?