Contract Calling and Execution
Caduceus smart contracts are implemented on the Caduceus EVM. Therefore, it is easy to use widely available libraries such as Web3.js and Ether.js to call deployed contracts.
We will look at three possibilities when calling or executing.
Web3.JS Example
First you must include Web3.js in your Javascript code. You can include it from a CDN such as Cloudflare as in the following example:
<script src="https://cdnjs.cloudflare.com/ajax/libs/web3/3.0.0-rc.5/web3.min.js"></script>
Calling to Read
This is the simplest type of contract call. We see an example using the popular Metamask wallet below:
// Solidity
contract MyContract {
function myFunction() returns(uint256 myNumber, string myString) {
return (23456, "Hello!%");
}
}
const web3 = new Web3(window.ethereum); //web3 served by Metamask
// web3.js
var MyContract = new web3.eth.Contract(abi, address);
MyContract.methods.myFunction().call()
.then(console.log);
> Result {
myNumber: '23456',
myString: 'Hello!%',
0: '23456', // these are here as fallbacks if the name is not know or given
1: 'Hello!%'
}
Creating a transaction to alter state
This is equivalent to writing to the Caduceus blockchain. A smart contract's methods may accept parametes such as integers, strings and booleans. These valuse will be persisted to the blockchain state upon a successful write.
// using the callback
//.methodName represents the function name in the smart contract
//123 represents the parameter that is set
myContract.methods.methodName(123).send({from: '0xde0B295669a9FD93d5F28D9Ec85E40f4cb697BAe'}, function(error, transactionHash){
...
});
// using the promise
myContract.methods.methodName(123).send({from: '0xde0B295669a9FD93d5F28D9Ec85E40f4cb697BAe'})
.then(function(receipt){
// receipt can also be a new contract instance, when coming from a "contract.deploy({...}).send()"
});
Creating a transaction to send CMP tokens
Creating a transaction to send CMP involves first converting the amount to Wei, and then converting the Wei to a Hex value.
The ethereum.request object is available when Metamask is active for the user.
In this example, we have an error catcher within the function.
async function sendCMP() {
input_value = $('#htmlbox').val() //jquery based user input
console.log(input_value);
if (input_value.trim() == '') {
input_value = 0
}
if (!isNaN(input_value)) {
input_value = parseInt(input_value)
}
var starting = String(input_value);
var amountWei = web3.utils.toWei(starting, 'ether');
var finalvalue = web3.utils.toHex(amountWei);
ethereum
.request({
method: 'eth_sendTransaction',
params: [{
from: currentAccount,
to: contactAddress,
value: finalvalue,
//gasPrice: '0x09184e72a000',
// gas: '0x2710',
}, ],
})
.then((txHash) => {
console.log(txHash);
ethereum
.request({
method: 'eth_getTransactionReceipt',
params: [txHash]
})
.then((transactionReceiptResult) => {
console.log("transaction receipt result fired");
console.log(transactionReceiptResult);
})
})
.catch((error) => {
console.log("reached error");
console.log(error);
});
}
Ether JS
Ether.JS is a another popular package that is used to connect to smart contracts on EVM compatible blockchains.
Calling to read
Let's look at an example of a contract read action, using metamask.
const ethereum = (window as any).ethereum;
const accounts = await ethereum.request({
method: "eth_requestAccounts",
});
const provider = new ethers.providers.Web3Provider(ethereum)
const walletAddress = accounts[0] // first account in MetaMask
const signer = provider.getSigner(walletAddress)
const abi = [
"function name() public view returns (string)",
"function symbol() public view returns (string)",
"function decimals() public view returns (uint8)",
"function totalSupply() public view returns (uint256)",
"function approve(address _spender, uint256 _value) public returns (bool success)"]
const USDTContract = new ethers.Contract("0xdAC17F958D2ee523a2206206994597C13D831ec7", abi, signer)
const name = await USDTContract.name()
const symbol = await USDTContract.symbol()
const decimals = await USDTContract.decimals()
const totalSupply = await USDTContract.totalSupply()
console.log(`${symbol} (${name}) total supply is ${ethers.utils.formatUnits(totalSupply, decimals)}`)
Creating a transaction to alter state:
Suppose a Solidity function is named buy. We would call it as follows through Javascript:
<script
src="https://cdn.ethers.io/lib/ethers-5.0.umd.min.js"
type="application/javascript"
></script>
//sending data to write to blockchain state
await contract.buy(inputAmount, { value: ethersValue });
//sending tokens
function send_token(
contract_address,
send_token_amount,
to_address,
send_account,
private_key
) {
let wallet = new ethers.Wallet(private_key)
let walletSigner = wallet.connect(window.ethersProvider)
window.ethersProvider.getGasPrice().then((currentGasPrice) => {
let gas_price = ethers.utils.hexlify(parseInt(currentGasPrice))
console.log(`gas_price: ${gas_price}`)
if (contract_address) {
// general token send
let contract = new ethers.Contract(
contract_address,
send_abi,
walletSigner
)
// How many tokens?
let numberOfTokens = ethers.utils.parseUnits(send_token_amount, 18)
console.log(`numberOfTokens: ${numberOfTokens}`)
// Send tokens
contract.transfer(to_address, numberOfTokens).then((transferResult) => {
console.dir(transferResult)
alert("sent token")
})
} // ether send
else {
const tx = {
from: send_account,
to: to_address,
value: ethers.utils.parseEther(send_token_amount),
nonce: window.ethersProvider.getTransactionCount(
send_account,
"latest"
),
gasLimit: ethers.utils.hexlify(gas_limit), // 100000
gasPrice: gas_price,
}
console.dir(tx)
try {
walletSigner.sendTransaction(tx).then((transaction) => {
console.dir(transaction)
alert("Send finished!")
})
} catch (error) {
alert("failed to send!!")
}
}
})
}