Skip to main content

Develop an Aspect

This section guides you in building a dApp on Artela with a sample Aspect. This Aspect functions as a native extension, co-process with smart contract, and can be injected throughout the transaction lifecycle. In this example, we'll show how Aspect can identify and revert a specific transaction.

Pre-requisites:

1. Setting up a new project​

Make sure you have a recent version of Node.js and npm installed, Start by installing the aspect-tool:

npm install -g @artela/aspect-tool

Project Initialization, to kick off your project with aspect-tool, follow these steps:

# Create a new directory and navigate into it
mkdir my-first-aspect && cd my-first-aspect

# Set up the npm project with aspect-tool
aspect-tool init

# Install the necessary dependencies
npm install

This will create a project directory with the following structure:

.
β”œβ”€β”€ README.md
β”œβ”€β”€ asconfig.json
β”œβ”€β”€ aspect <-- Your aspect code resides here
β”‚Β Β  └── index.ts <-- Entry functions for the aspect
β”œβ”€β”€ contracts <-- Place your smart contracts here
β”œβ”€β”€ package.json
β”œβ”€β”€ project.config.json
β”œβ”€β”€ scripts <-- Utility scripts, including deploying, binding and etc.
β”‚Β Β  β”œβ”€β”€ aspect-deploy.cjs
β”‚Β Β  β”œβ”€β”€ bind.cjs
β”‚Β Β  β”œβ”€β”€ contract-call.cjs
β”‚Β Β  β”œβ”€β”€ contract-deploy.cjs
β”‚Β Β  β”œβ”€β”€ contract-send.cjs
β”‚Β Β  └── create-account.cjs
β”œβ”€β”€ tests
└── tsconfig.json

2. Deploy a smart contract​

2.1. Add a Smart Contract​

Within the contracts directory of your project, create your smart contract source files with a .sol extension.

For example, create a HelloWorld.sol file:

// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.8.2 <0.9.0;

contract HelloWorld {
address private owner;
constructor() {
owner = msg.sender;
}
function isOwner(address user) external view returns (bool result) {
return user == owner;
}

// print hello message
function hello() public pure returns (string memory) {
return "hello";
}

// print world message
function world() public pure returns (string memory) {
return "world";
}
}

2.2. Compile the Smart Contract​

This step relies on solc, first check if solc is installed correctly

solc --version

Compile your contract using:

npm run contract:build

βœ… Successful compilation will generate HelloWorld.abi and HelloWorld.bin files in the build/contract directory.

2.3. Deploy the Smart Contract​

2.3.1 Update project.config.json​

Update the project.config.json in the root directory with the appropriate network configuration:

{
"node": "https://betanet-rpc1.artela.network"
}
πŸ’‘

For more details regarding development environment setup, please refer to artela devnet

2.3.2 Create a blockchain account (optional).​

Execute the following command under the my-first-aspect folder to create an account if you haven't already done so:

npm run account:create

βœ… If an account gets created successfully, its private key will be dumped as privateKey.txt in the current directory.

πŸ’‘

For more detailed usage information about this command, please refer to the create-account command documentation.

If your account lacks test tokens, join Discord,and request some in testnet-faucet channel.

2.3.4 Deploy your contract​

Execute the following command within the my-first-aspect folder, using the provided script:

npm run contract:deploy --  --abi ./build/contract/HelloWorld.abi \
--bytecode ./build/contract/HelloWorld.bin

βœ… Upon successful deployment, the terminal will display the contract address.

πŸ’‘

For more detailed usage information about this command, please refer to the deploy-contract command documentation.

2.4 Call Contract​

Execute the following command within the my-first-aspect folder, call the Contract

2.4.1 call hello method​

npm run contract:call -- --contract {smart-contract-address}  \
--abi ./build/contract/HelloWorld.abi \
--method hello
  • replace the placeholder {smart-contract-address} with the information obtained from step 2 3 deploy the smart contract.

βœ… Upon successful, the terminal will display call result.

πŸ’‘

For more detailed usage information about this command, please refer to the contract-call command documentation.

2.4.2 call world method​

npm run contract:call -- --contract {smart-contract-address}  \
--abi ./build/contract/HelloWorld.abi \
--method world

βœ… If the world string is returned, it means that we have successfully deployed the HelloWorld contract.

3. Create your Aspect​

3.1. Implements an Aspect​

The Aspect source files can be found in aspect/index.ts.

For example, to add logic after a smart contract call execution, open index.ts, locate the postContractCall function, and insert your logic:

postContractCall(input:PostContractCallInput):void {
// Implement me...
}
πŸ’‘

For detailed instructions, refer to the Aspect Doc.

3.2. Access State Changes of Smart Contract​

To integrate the state of the HelloWorld contract with your Aspect, follow these steps:

In aspect/index.ts, add your Aspect to check the transaction, if world function is called, then revert:

import {
allocate,
entryPoint,
execute,
IPostContractCallJP,
PostContractCallInput,
sys,
uint8ArrayToHex,
} from "@artela/aspect-libs";

// 1. implement IPostContractCallJP
class Aspect implements IPostContractCallJP {

isOwner(sender: Uint8Array): bool {
// implement me
// if return false,bind、unbind、upgrade Aspect will be block
return true;
}
/**
* postContractCall is a join-point which will be invoked after a contract call has finished.
*
* @param input input to the current join point
*/
postContractCall(input: PostContractCallInput): void {

let txData = uint8ArrayToHex(input.call!.data);

// if call `world` function then revert, 30b67baa is method signature of `world`
if (txData.startsWith("30b67baa")) {
sys.revert("the function `world` not available");
}
}
}

// 2.register aspect Instance
const aspect = new Aspect();
entryPoint.setAspect(aspect);

// 3.must export it
export {execute, allocate};

3.3. Compile the Aspect​

Build your Aspect:

npm run aspect:build 

βœ… The resulting release.wasm in the build folder contains the necessary WASM bytecode.

3.4. Deploy the Aspect​

Deploy your compiled Aspect:

npm run aspect:deploy -- --wasm ./build/release.wasm --joinPoints PostContractCall

βœ… Upon successful execution, the terminal will display the Aspect address. It is essential to make a note of this address as it will be useful later on.

πŸ’‘

For more detailed usage information about this command, please refer to the deploy-aspect command documentation.

4. Bind the Smart Contract and Aspect​

Deploying the Aspect doesn't automatically activate it. To make it functional, bind it to a smart contract:

npm run contract:bind -- --contract {smart-contract-address} \
--abi ./build/contract/HelloWorld.abi \
--aspectId {aspect-Id}
  • replace the placeholder {smart-contract-address} with the information obtained from step 2 3 deploy the smart contract.
  • replace the placeholder {aspect-Id} with the information obtained from step 3.4. Deploy the Aspect.

βœ… The binding process has been successful, and the transaction receipt has been printed.

πŸ’‘

For more detailed usage information about this command, please refer to the bind-aspect command documentation.

5. Test the Smart Contract and Aspect Integration​

Now that the HelloWorld contract and Aspect are bound, call world to test.

npm run contract:call -- --contract {smart-contract-address}  \
--abi ./build/contract/HelloWorld.abi \
--method world
  • replace the placeholder {smart-contract-address} with the information obtained from step 2 3 deploy the smart contract.

βœ… Due to Aspect interception, the transaction is reverted.

img.svg

Congratulations! You've learned the basics of Aspect development. For a deeper dive, refer to our comprehensive Aspect Doc.