EVM Partition
Alphabill implements an EVM (Ethereum Virtual Machine) Partition as a system-defined partition that enables developers to deploy Solidity programs. However, this partition is not shardable. To enhance scalability, the Alphabill architecture supports multiple EVM Partition instances running in parallel. Smart contracts deployed in different EVM Partitions do not share memory and cannot call each other directly. Interoperability between partitions is achieved through exchanging proofs that can be verified due to a common root of trust.
This tutorial shows you how to deploy and execute smart contracts implemented in Solidity on the Alphabill EVM Partition using the Alphabill CLI wallet.
Prerequisites
Before you begin, make sure you meet the following prerequisites:
- You have set up an Alphabill CLI wallet.
- Your wallet is funded with testnet ALPHA, and it has enough fee credit to cover transaction fees when interacting with the EVM Partition.
- Recommended: command-line Solidity compiler (version 0.8.x) is installed on your system.
Compile Solidity Source Code
Using Command-Line Solidity Compiler
The smart contract that you will deploy on the Alphabill EVM Partition implements a counter. The counter keeps its value in the state and provides functions for reading the current value (get()
), incrementing the value by one (increment()
), and setting the value to an arbitrary 256-bit integer (set()
). The value of the counter is initialized to zero.
-
Copy the following source code and save it in a file named
Counter.sol
in thealphabill-wallet/build
directory.Counter.sol// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract Counter {
uint256 value = 0;
event Increment(uint256 indexed newValue);
function get() public view returns (uint256) {
return value;
}
function increment() public returns (uint256) {
unchecked { // let the value wrap to zero instead of failing
value++;
}
emit Increment(value);
return value;
}
function set(uint256 n) public {
value = n;
}
} -
Before deployment, you need to compile the source code into EVM bytecode using a Solidity compiler. Go to the
alphabill-wallet/build
directory and run the following command:solc --evm-version berlin --hashes --bin -o counter Counter.sol
ImportantMake sure to specify the
--evm-version berlin
command-line option; otherwise, the compiler may default to generating instructions that are not yet supported in the EVM partition.If the compilation is successful, you should see the following output from the compiler:
Compiler run successful. Artifact(s) can be found in directory "counter".
-
Verify that the artifacts
Counter.bin
andCounter.signatures
exist in thealphabill-wallet/build/counter
directory. The contents of the files should look like those shown below.-
The
Counter.bin
file contains EVM bytecode needed to deploy the smart contract:counter/Counter.bin60806040526000805534801561001457600080fd5b506101c3806100246000396000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c806360fe47b1146100465780636d4ce63c14610062578063d09de08a14610080575b600080fd5b610060600480360381019061005b9190610136565b61009e565b005b61006a6100a8565b6040516100779190610172565b60405180910390f35b6100886100b1565b6040516100959190610172565b60405180910390f35b8060008190555050565b60008054905090565b600080600081548092919060010191905055506000547f51af157c2eee40f68107a47a49c32fbbeb0a3c9e5cd37aa56e88e6be92368a8160405160405180910390a2600054905090565b600080fd5b6000819050919050565b61011381610100565b811461011e57600080fd5b50565b6000813590506101308161010a565b92915050565b60006020828403121561014c5761014b6100fb565b5b600061015a84828501610121565b91505092915050565b61016c81610100565b82525050565b60006020820190506101876000830184610163565b9291505056fea2646970667358221220567c7e5fdc6353f0e1c8cf1771cb6d9a4e91532d997c577f52a72f3027b62de464736f6c63430008150033
-
The
Counter.signatures
file contains a list of encoded function selectors that are needed to invoke functions with the Alphabill CLI wallet.counter/Counter.signaturesFunction signatures:
6d4ce63c: get()
d09de08a: increment()
60fe47b1: set(uint256)
Event signatures:
51af157c2eee40f68107a47a49c32fbbeb0a3c9e5cd37aa56e88e6be92368a81: Increment(uint256)
When both files are present and have the expected content, you are all set to deploy the smart contract.
-
Using Remix Online IDE
Alternatively, you can compile the same source code using the Remix Online IDE, which is a no-setup tool with a GUI for developing smart contracts.
-
Open your browser and go to the Remix Online IDE website using the following link: https://remix.ethereum.org
-
Click the Start Coding button to create a default project based on a basic workspace template.
-
In the File Explorer panel, create a new file under the
contracts
folder, name it4_Counter.sol
, and open it.Initially, the
contracts
folder contains three smart contracts named1_Storage.sol
,2_Owner.sol
and3_Ballot.sol
. You can also use any of the three pre-written contracts that are already in the mixer with the generation of the templates. The steps will be similar, but for simplicity, this tutorial is based on4_Counter.sol
. -
In the editor, paste the following source code into the file you just created:
4_Counter.sol// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract Counter {
uint256 value = 0;
event Increment(uint256 indexed newValue);
function get() public view returns (uint256) {
return value;
}
function increment() public returns (uint256) {
unchecked { // let the value wrap to zero instead of failing
value++;
}
emit Increment(value);
return value;
}
function set(uint256 n) public {
value = n;
}
} -
You will then get a warning about pasting code into the editor. Since you will be using it in a test environment and this is a simple "Hello world!" style contract that allows for only incrementing an integer and asking for current value of the integer, then it's safe to click OK.
-
Select the
4_Counter.sol
contract (if not already selected) and compile the contract by pressing the green Compile button. -
The following figures show you how to access the bytecode and function hashes of the contract that are needed later when invoking
get()
,increment()
andset()
functions:-
Open the Solidity compiler tab.
-
Click the Compilation Details button to access all necessary information about the contract, including function hashes, ABI, and more.
-
Bytecode and function hashes are necessary for later use. The hashes are required to call and execute the functions, while the bytecode is needed to deploy the contract. You can copy the entire bytecode and function hashes by clicking the small Copy buttons, as shown in the figure below.
-
Deploy the Counter Smart Contract
-
Go to the
build
directoy where you have the Alphabill CLI binary and run the following command to deploy the smart contract. The bytecode to be deployed is specified via the--data
option.-
If you used the command-line Solidity compiler, the bytecode is in the
Counter.bin
file and you can use the command substitution../abwallet wallet evm deploy \
--alphabill-api-uri https://evm-partition.testnet.alphabill.org \
--data $(< counter/Counter.bin) \
--max-gas 300000 -
If you compiled the contract with the Remix online IDE, copy the bytecode from Remix IDE, and paste it behind the
--data
option.
infoAlphabill EVM Partition inherits the concept of gas from Ethereum. Currently, the cost of gas is fixed at 0.021 tema for one unit of gas. Once you start deploying larger smart contracts you may need to increase the value of
--max-gas
option. Make sure to keep the value smaller than the block gas limit which is currently set to 15 000 000. -
-
After the deployment transaction succeeds, you should see output similar to this:
Evm transaction succeeded
Evm transaction processing fee: 0.000'032'09
Deployed smart contract address: ac241e528f6c303d6d5816bd381aef19b6a04b1a
Evm execution returned: 608060405234801561001057600080FD5B50600436106100415760003560E01C806360FE47B1146100465780636D4CE63C14610062578063D09DE08A14610080575B600080FD5B610060600480360381019061005B9190610136565B61009E565B005B61006A6100A8565B6040516100779190610172565B60405180910390F35B6100886100B1565B6040516100959190610172565B60405180910390F35B8060008190555050565B60008054905090565B600080600081548092919060010191905055506000547F51AF157C2EEE40F68107A47A49C32FBBEB0A3C9E5CD37AA56E88E6BE92368A8160405160405180910390A2600054905090565B600080FD5B6000819050919050565B61011381610100565B811461011E57600080FD5B50565B6000813590506101308161010A565B92915050565B60006020828403121561014C5761014B6100FB565B5B600061015A84828501610121565B91505092915050565B61016C81610100565B82525050565B60006020820190506101876000830184610163565B9291505056FEA2646970667358221220567C7E5FDC6353F0E1C8CF1771CB6D9A4E91532D997C577F52A72F3027B62DE464736F6C63430008150033Congratulations! You have deployed your first smart contract on Alphabill EVM Partition. Now, let's try to use it.
importantTake note of the address of your smart contract shown on the line beginning with "Deployed smart contract address". In the commands given below, replace the placeholder
CONTRACT_ADDRESS
with the actual address. The address will be unique every time you deploy your contract.
Invoke Smart Contract Functions
Read-Only Calls
First, try reading the value of the counter. For read-only queries, the EVM Partition provides a call
interface that executes the called function immediately without recording the transaction and its effects in the ledger. No fee has to be paid for call
requests (although you still need to specify the --max-gas
option) because the call function of the CLI tool executes the contract immediately without creating a transaction on the blockchain.
Execute the following command after replacing the placeholder with the address of your smart contract and verifying that the value of --data
option matches the get()
function signature.
-
If you compiled the contract using the command-line Solidity compiler, the signature is in your
Counter.signatures
file../abwallet wallet evm call \
--alphabill-api-uri https://evm-partition.testnet.alphabill.org \
--address CONTRACT_ADDRESS \
--data 6d4ce63c \
--max-gas 300000 -
If you used Remix IDE, you can find the
get()
function signature under Compliation Details.
This is the expected output, indicating that the value of the counter is zero (represented as a 256-bit integer):
Evm transaction succeeded
Evm transaction processing fee: 0.000'000'00
Evm execution returned: 0000000000000000000000000000000000000000000000000000000000000000
Executing Transactions
To increment the value, you need to execute a transaction and pay a transaction fee. When a transaction is executed, the transaction is permanently recorded in the journal of transactions, and the effects of the transaction are reflected in the state of the ledger.
Increment the counter with the following command (again, make sure the --data
option corresponds to the signature of the increment()
function and substituting the contract address):
./abwallet wallet evm execute \
--alphabill-api-uri https://evm-partition.testnet.alphabill.org \
--address CONTRACT_ADDRESS \
--data d09de08a \
--max-gas 300000
Example output (note that the "Evm log" line will differ):
Evm transaction succeeded
Evm transaction processing fee: 0.000'009'43
Evm log 0 : &{{} 0xAc241E528F6c303D6d5816Bd381Aef19b6a04b1a [0x51af157c2eee40f68107a47a49c32fbbeb0a3c9e5cd37aa56e88e6be92368a81 0x0000000000000000000000000000000000000000000000000000000000000001] []}
Evm execution returned: 0000000000000000000000000000000000000000000000000000000000000001
The last line contains the returned value of the counter as a 256-bit integer, and it equals to one as expected.
Providing Arguments to Functions
Finally, set the counter to a specific value to see how to specify arguments in function calls. The set()
function expects a 256-bit integer argument. You can provide the argument by appending a hex-encoded value at the end of the function signature specified in the --data
option.
To set the counter to the maximum value, use the following command:
./abwallet wallet evm execute \
--alphabill-api-uri https://evm-partition.testnet.alphabill.org \
--address CONTRACT_ADDRESS \
--data 60fe47b1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF \
--max-gas 300000
Expected output:
Evm transaction succeeded
Evm transaction processing fee: 0.000'005'66
After setting the counter to the maximum value, as an exercise, try to increment the value of the counter once. What do you think will happen? After incrementing, check the value with the get()
call.