Solidity Basics for JavaScript Devs Part 3

I wanted to publish the third part of this series after I finished my first Solidity project alongside the source code of that project.

Sadly, I got a few issues connecting the frontend to the Hardhat local network.

Anyway, I figured I could still publish it unfinished; at least all the tests pass, haha.

Here is the link to the repo. The examples from the book Hands-On Smart Contract Development with Solidity and Ethereum but rewritten for Hardhat and TypeScript. Again, the frontend doesn’t work; I started one with Preact but had some issues with the local network and didn’t find the time to solve this.

Maybe, some of you might figure out how to get the frontend connected to the local network?

Anyway, here are the last three Solidity tips for you, my fellow JavaScript users!



Contracts have a receive/fallback Function

The EVM calls two special functions when someone sends transactions to your contract that no other functions could handle. They don’t need the function keyword and must be external payable.

contract MyContract 

    fallback() external payable 
        // called when none of the contract's functions
        // match the called function signature
    

    receive() external payable 
        // called when the call data is empty
    



The Fallback Function

You can use the fallback function to delegate calls to different contracts. Since contracts deployed on the Ethereum blockchain are immutable, you need some indirection if you want to upgrade them over time. This can be done with a contract that only implements the fallback function that will relay calls to any function to a contract address. You can change this address and, in turn, indirectly change the implementation of the contract.



The Receive Function

You can use the receive function to handle calls only concerned with Ether and nothing else. For example, when you want to store a token amount into the smart contract’s balance.



Solidity Variables are Initialized by Default

Because solidity uses static typing, the language knows what type every variable at compile time. Each of these types has an initial value the EVM will use when it executes.



Initial Values

  • address: 0x0
  • array (dynamic): []
  • array (fixed): fixed-size array with initial values
  • boolean: false
  • enum: first enum element
  • function (external): a function that always throws an error
  • function (internal): a function that returns initial values if a return is defined
  • int: 0
  • mapping: empty mapping
  • string: ""
  • struct: a struct where all members are set to initial values
  • uint: 0



Requesting a Wallet Account Requires a Manual Call of eth_requestAccounts

Browser extension wallets usually block access to the accounts they manage from websites. The user has to allow the website to access it manually.

Somehow Ethers.js doesn’t ask for permissions automatically when you want to use a wallet account. You have to manually send a request to the wallet before you can use an account/signer.

const provider = new ethers.providers.Web3Provider(
  window.ethereum,
  chainId
)

await provider.send("eth_requestAccounts", [])

const account =  provider.getSigner()

The call to the asynchronous send method will block until the user accepted the request.



Conclusion

With this article I finished my first steps into Solidity, smart contract development, and web3 in general.

I hope, I could clear things up for you and my project helps you to get started!

I saw thousands of views on this series, so I pursuing more ideas in that direction this year. So if you’re a web2 JavaScript developer who wants to learn more about web3, stay tuned!


Source link

How To Deploy Cost Effective Smart Contracts

When people think about smart contracts, you tend to think about Ehereum However. Many ecosystems are building or have built support for the distributed computing that smart contracts allow for. Hedera recently announced their support for Smart Contracts 2.0 that will allow the contracts to run with all the native costs, security, and speeds of the Hedera network, which are pretty impressive.

This post will show you how to deploy a smart contract to the Hedera network with the JavaScrip SDK. We will first compile our smart contract into byte code. Then we will store the byte-code to the Hedera File Service, deploy our contact, and modify the state variable of our contract.



Compiling Your Smart Contract

You will first need to compile your smart contract into byte-code. There are a few different ways you can do this, recommend using remix. Remix will output a file usually called simple_storage.json. If you copy this file into your IDE, you will be able to initialize it in JavaScript like this: let json = require('./compiledSmartContract.json').



Storing the byte-code on the Hedera File Service

We need the fileID of its byte code stored on the Hedera file service to deploy our contract. We can get this by using the FileCreateTransaction API from the hedera JS SDK and passing it the byte-code.

    const compiled = json['data']['bytecode']['object'];
    // Store Contact in file service. Different from eth. Transaction size is smaller on hedera for security 
    const mycontract = await new FileCreateTransaction()
        .setContents(compiled)
        .setKeys([PrivateKey.fromString(myPrivateKey)])
        // The default max fee of 1 HBAR is not enough to make a file ( starts around 1.1 HBAR )
        .setMaxTransactionFee(new Hbar(2)) // 2 HBAR
        .execute(client);

    const TransactionReceipt  = await mycontract.getReceipt(client);
    const fileid =  new FileId(TransactionReceipt.fileId);
    console.log("file ID: " + fileid);

Afterward, we can get the FileID from the FileCreateTransaction receipt, as shown in the example above.



Deploying

Once you have a fileId of the byte-code from your contract, you can pass the fileId from the previous step to the ContractCreateTransaction() API call.

    // Deploy Contract
    const deploy = await new ContractCreateTransaction()
        .setGas(300)
        .setBytecodeFileId(fileid)
        .execute(client);

    const receipt = await deploy.getReceipt(client); //Get the new contract 
    const newContractId = receipt.contractId;        
    console.log("The contract ID is " + newContractId);

After deploying the contract you can await the receipt to get the contract ID.



Calling the Smart Contract Functions

When calling the smart contract functions, you have to know whether or not the function you want to call is modifying the state variables of the contract. If you are changing state variables, you will use the ContractExecuteTransaction() endpoint. Otherwise, you will use the ContractCallQuery() endpoint. You can think of this a doing reads vs doing writes.



Modifying State

For example, I am calling the set function in the contract outlined in the solidity documentation, I am modifying the storedData state variable.

Using the Hedera API to call this function would look something like this.

    const setter = await new ContractExecuteTransaction()
        .setContractId(newContractId)
        .setGas(400000)
        .setFunction("set", new ContractFunctionParameters().addUint256(7))
        .setMaxTransactionFee(new Hbar(3))


    const contractCallResult = await setter.execute(client);
    const testing = await contractCallResult.getRecord(client);
    console.log("Status Code:", testing.status)



!Modifying State

The call to the corresponding getter would look something like this

    const getter = await new ContractCallQuery() // 
        .setContractId(newContractId)
        .setFunction("get")
        .setGas(300000)
        .setMaxQueryPayment(new Hbar(1)) // defaults to 1, if requires more than one need change
    // set should be around at least 3-5k gas
    const contractGetter = await getter.execute(client);
    const message = await contractGetter.getUint256(0);
    console.log("contract message: " + message);

Source link