---
title: Call Contract Method
slug: signum/call-contract-method
createdAt: 2022-09-08T12:36:07.000Z
---

It is possible to write contracts with an additional set of callable methods. If a method is exposed by the Smart Contract, it can be executed when sending a transaction with an attached hexdecimal message.&#x20;

:::hint{type="warning"}
Note that Smart Contracts cannot read encrypted messages.
:::

## Anatomy of callable methods

A method call consists of at maximum four parameters with each 8 bytes.&#x20;

![](https://api.archbee.com/api/optimize/l2AIpSUU6srSQmG1-K2bb/C_8Yd1I9EoR2fCD9bIRAc_image.png)

A method call can have 0 to 3 additional arguments, which needs to be converted into hexdecimal representation respecting Big Endian Byte Order. The way how method calls are handled in the Smart Contracts is not defined. This is especially true for the method identifier

### Methods in SmartJ

The method identifiers in SmartJ are long numbers (int64) and a hashed variant of a methods signature. On compilation the compiler shows the related method hashes in the development console.&#x20;

::Image[]{src="https://api.archbee.com/api/optimize/l2AIpSUU6srSQmG1-K2bb/Gp29Qo9nuKcc00t5AXxsM_image.png" size="68" width="763" height="704" caption="Method Hashes provided by SmartJ" position="center" showCaption="true"}



Intuitively, publicly callable methods in SmartJ need to be public, as this reflects the expected behavior in Java.

### Methods in SmartC

SmartC does not implicitely define how methods can be called and it is up to the developer to define the behavior. This can be either a numeric or alphabetical identifier. A pattern to deal with "public" methods can be found [here](https://github.com/deleterium/SmartC/blob/main/samples/PublicMethodsOnSmartC.md). This proposal considers compatibility to SmartJ public method calls.&#x20;

## SignumJS Example

Finally, time to show some code. It's actually pretty simple, as SignumJS does most of the black magic behind the scenes.

```javascript
const {Address} = require("@signumjs/core");
const {generateMasterKeys} = require("@signumjs/crypto");
const {Amount} = require("@signumjs/util");

const LedgerHostUrls = {
    'TestNet': 'https://europe3.testnet.signum.network',
    'MainNet': 'https://europe.signum.network',
}

/**
 * This is an example of mapping between the hashes (generated on compilation with SmartJ)
 * and more readable names. Of course, this depends on each contract
 *
 * Using constants is a good practice.
 */
const ContractMethods = {
    TransferRoyalties: '7174296962751784077',
    Transfer: '-8011735560658290665',
    PutForAuction: '4465321042251021641',
    SetNotForSale: '-1462395320800038545',
    PutForSale: '483064598096680683',
}
/**
 * This advanced example shows how to interact with smart contracts, i.e. how to call methods
 */
async function callMethodOfContract(params) {
    try {

        const {ledger: ledgerType, passphrase, contract, amount, method, arg1 = 0, arg2 = 0, arg3 = 0} = params;

        const ledger = LedgerClientFactory.create({
            nodeHost: LedgerHostUrls[ledgerType])
        }
        const contractId = Address.create(contract).getNumericId()
        const senderKeys = generateMasterKeys(passphrase);
        
        // finally, we call the contracts method
        // as you can see it's pretty easy, just use the method hash and add the args as array
        const {transaction} = await ledger.contract.callContractMethod({
            contractId,
            amountPlanck: Amount.fromSigna(amount).getPlanck(),
            senderPublicKey: senderKeys.publicKey,
            senderPrivateKey: senderKeys.signPrivateKey,
            feePlanck: Amount.fromSigna(0.01).getPlanck(),
            methodHash: ContractMethods[method],
            methodArgs: [arg1, arg2, arg3]
        }
)
        console.info('Call successful - tx id:', transaction)
    } catch (e) {
        console.error(e)
    }
}

(async () => {
    await callMethodOfContract({
        ledger: 'TestNet',
        contract: '12355673...',
        amount: 0.5,
        method: 'SetNotForSale',
        arg1: Amount.fromSigna(50_000),getPlanck(),
    });
})();
```

### Alphanumeric method names in SmartC

If you use SmartC and want to use alphanumeric names within your code, please consider the correct conversion for the `methodHash` argument

In the following example the contract uses the abbreviated command `cthzth` as method identifier

:::CodeblockTabs
```javascript
const {convertHexStringToDecString, convertHexEndianess, convertStringToHexString} = require("@signumjs/util");

// This way it is possible to convert short alphanumeric strings into
// correct values
function convertMethodCommand(text) {
  if (text.length > 8) {
    throw new Error('Text Argument cannot be larger than 8 bytes')
  }

  return convertHexStringToDecString(
    convertHexEndianess(
      convertStringToHexString(text)
    )
  );
}  
  
// ... 

ledger.contract.callContractMethod({
    feePlanck: Amount.fromSigna(0.01).getPlanck(),
    amountPlanck: Amount.fromSigna(ActivationFee).getPlanck(),
    senderPublicKey: keys.publicKey,
    senderPrivateKey: keys.signPrivateKey,
    contractId: ContractId,
    methodHash: convertMethodCommand('cthzth'),
    methodArgs: [ChainValue.create(1).setCompound(amount).getAtomic()]
})
```

contract.c

```cpp
/*
This is an excerpt from the real world contract, showing
how to process commands/method calls
*/

// ...

void main(void) {
    while ((currentTX.txId = getNextTx()) != 0) {
        currentTX.sender = getSender(currentTX.txId);
        currentTX.amount = getAmount(currentTX.txId);

        if(!isAlive){
            sendAmount(currentTX.amount, currentTX.sender);
            return;
        }

        readMessage(currentTX.txId, 0, currentTX.message);
        switch(currentTX.message[0]){
            case 'die':
                deactivate();
                break;
            case 'cthsig':
                changeSignaThreshold(currentTX.message[1]);
                break;
            case 'cthzth':
                changeZTHThreshold(currentTX.message[1]);
                break;
            default:
                txReceived();
        }
    }
}

// ...
```
:::
