Easily Calling Arbitrary Smart Contract Functions on Ethereum Part 2 - The How?
In Part 1 of this blog series, we discussed how a crucial step of the Asset Tokenization value chain (investor address whitelisting and token distribution), can be automated using Upvest’s new Complex Transaction (CxTx) endpoint. In this article, we dive deeper into the workings of the CxTx, with a practical example of a transfer transaction, which we will then extend to batch sending, used for token distribution. By the end of this article, you will be able to call any Ethereum smart contract function yourself, using CxTx.
A CxTx “Transfer” Transaction
First, we need to instantiate the Upvest Clientele API with the right authentication parameters in order to make valid function calls. For this, the function main is defined as asynchronous, and hence can have await expressions that frees up the processor while waiting for the function itself to return a value. The JSON values of the authentication parameters can be seen in this example configuration file. We prepare this with the following code:
In the next step, an Ethereum transfer transaction can be prepared. The JSON values of the CxTx payload is also found in the same configuration file. The payload of the transfer transaction is seen here:
The parameters of the payload are as follows:
- The type of CxTx you want to call: in this case, it's clearly an ethereum function call. Upvest also offers a “raw” function call that can include the payload in binary. Only these two types are accepted by the CxTx API.
- The to destination: Ethereum address of the smart contract on which the function gets called, in EIP 55 mixed-case checksum encoding, including a "0x" prefix.
- The Ether value to be transferred: if required for a `payable` function, some Ether can be sent along with the function call. But this should be set to `0` for `non-payable` functions.
- The desired gas_limit: take into account the maximum amount of gas the client is willing to spend for this transaction for Gas Limit. You will need to know the approximate amount of Gas required for the function call you are trying to make.
- The desired gas_price in Wei: this is the price you are willing to pay per Gas "unit". This determines the likelihood with which miners will choose to include this transaction in one of the next blocks. An example of how to calculate this is found here.
- The CxTx endpoint then takes the abi of any (single) smart contract function. This is a JSON object describing exactly how to call this function. Since we call only one function here, only the ABI of that specific function has to be included, and not the ABI of the whole contract (which is also usually a JSON array).
- The function call’s parameters: in the above code example, the smart contract address and Ether value. A JSON array listing all values to be used, for each call parameter. This list has to match with the list of types in the abi field.
Note: It is mandatory to send the above integers (value, gas_limit, gas_price) rendered as base-10 strings (e.g: “12345”), to ensure safe transport of up to 256-bit numbers used in Ethereum.
After the transfer transaction has been defined, we need to define who’s going to pay the network Gas fee for this transaction. For this, the fund boolean in the above snippet decides if the auxiliary Upvest funding service should cover the transaction fee. If true, it's covered by the funding service, the funding amount will be the product of contract’s Gas Limit multiplied by the Gas Price. If this boolean is false, then the wallet must contain Ether in order to pay the transaction Gas fee. Upvest can also perform the nonce management for these transactions, however also allows a specific nonce value to be provided as a parameter in the payload, should you wish to manage nonces yourself.
We then call the createComplex function from the Clientele API library with the walletId, user password, the transaction payload (tx), and the fund boolean. We then call the main function, thereby executing the ‘async’ wrapper function.
A polling function can be used to retrieve the transaction hash (txhash), as shown in the lower half of the snippet. This is optional. If included, the polling function returns the status of the transaction being processed. When the actual status changes to ‘Confirmed’, we can be sure that the transaction has been mined (i.e. included in a block on the blockchain). The various transaction statuses are defined here. Upvest advocates using webhooks instead of polling. In the future, Upvest will also provide a dedicated webhook API for all customer wallets managed by Upvest. This is what a response looks like:
A batch transfer would then involve calling the above formulated transfer transaction in a loop, with a list of wallet addresses and a list of token amounts to be transferred. This achieves the intended purpose of automating the token sale process, for whitelisting of investor addresses and transferring the tokens to them.
If Part 2 of this series resonated with you, sign up for a free account, browse our documentation, and start experimenting with the Upvest API. In the upcoming Part 3, we will discuss what we learned from implementing the CxTx endpoint and what's in store for its future.
Any questions? Send us a tweet, or join our Discord channel to engage with the Upvest developer community. Keep up-to-date with Upvest developments here.