Complete dapp in 1 week!
Welcome to my 1-Week-Aepp-Challange.
The goal is to develop complete decentralized application (dapp) with Aeternity blockchain (aepp).
I’m documenting the whole design and development process.
Feel free to follow the progress.
Day 5: client side of the aepp (Aeternity based dapp) overview, smart contract interactions, security concerns.
Day 4: https://www.mobycrypt.com/1-week-aepp-challange-day-4-aepp-sdk-js-and-communication-with-the-blockchain/
Centralised dapp client side
The ideal dapp is completely third party independent. It means there is no entity which is the middleman in the application logic flow, having the potential influence on the operations workflow. Blockchain gives the possibility of storing and processing data in the way that only authorised entities can do it. It also enables to implement immutable software which operates on the data.
Any application (mobile, web, desktop) has the UI. In case of web applications, the web browser renders the sources (html, js, css). It fetches the data from the web server, process it and presents as the visual result – the web page. In context of dapp – in most cases this part of the application will be delivered from the centralised third party servers. Why is that?
In general there is completely no point to store any part of the UI in the blockchain.
First of all the client is transparent. It means that it’s just fetched from the centralised server however whole processing is done in the client browser. It means that at least in theory we have control over it, no third party is included in the processing.
Secondly client is frequently changing – due to technology changes, content changes, marketing aspects and everything related to. Generally UI must support easy changes (this is why web became so popular, because of easy changes) instead of being immutable!
Summarising, even if the client side in most dapps will be provided by centralised party – it should have no big impact on the transparency of the dapp. Even if the processing rules are defined by the third party – these rules (application workflow, data access) are transparent and in the control of the client.
Aeternity smart contract deployment (with JS SDK)
In order to give possibility of interaction with smart contract in the client side we install Javascript SDK (described here). Having the SDK we can for example send transactions or invoke smart contracts method.
Logonity gives possibility to create logo commission. Every logo commission is the seperate smart contract existing in the blockchain. It is responsible for single commission only. The JS SDK gives possibility easily compile and deploy smart contract to the network.
Having the smart contract code defined like:
const smartContractCode = '<smart contract code>';
The code responsible for deployment smart contract to the network (blockchain) is given:
import Ae from '@aeternity/aepp-sdk/es/ae/universal'; const smartContractCode = '<smart contract code>'; Ae({ url: 'https://sdk-testnet.aepps.com', internalUrl: 'https://sdk-testnet.aepps.com', keypair: { secretKey: '02a9f1e976b83b5cdf34279e9068fc7f352a5b49144fd96e7546390ff20a7a14e256c3ecea141842c37f9686fa0558faf71388dc473f5d69891d9ea2ee2cb671', publicKey: 'ak_2igXQ7pQgH5YDv4zP9ciq1R3qW8pNaGgywqYnwRPrBhKhYxgeG' }, }).then((ae) => { return ae.contractCompile(smartContractCode); }).then(bytecode => { return bytecode.deploy({ initState: `("initArgument1", "initArgument2")`, options: { amount: 1000000000000000000 } }); }).then(deployed => { console.log(`Contract deployed at ${JSON.stringify(deployed)}`); });
The code compiles the contract code <smart contract code>
to the bytecode deployes it to the network (Aeternity blockchain). It initializes the contract state (the contract constructor) with 2 string arguments initArgument1
and initArgument2
. It also sends 1 Ae to the contract. When the contract will be successfully deployed – the callback with deployed
contract address will be invoked.
Smart contract interactions
Having the contract deployed to the network we can interact with it (invoke the public functions) with the JS SDK. Invoking the contract functions requires to provide contract address which is returned as the response on the contract deployment.
Smart contracts have mainly 2 types of functions:
- changing the state – in other words the functions which require to save data in blockchain (database), for example modyfiying some smart contract data;
- not chaning the state – the functions which simply read data from the blockchain;
Using the API – whenever we invoke changing the state functions – we must provide our public/private keys, in order to sign the transactions. Not changing the state functions invocations don’t require to provide keys using the API.
The code snippet below shows how to invoke the non changing the state function of the smart contract:
Ae({ url: this.properties.nodeUrl, internalUrl: this.properties.nodeUrl, }).then(async (ae) => { const rewardResult = await ae.contractCallStatic('<CONTRACT_ADDRESS>', 'sophia-address', 'getReward'); const decodedResult = await ae.contractDecodeData('int', rewardResult.result); console.log(`Got the value from smart contract ${decodedResult}`); });
The SDK function which calls the smart contract is contractCallStatic
. As the name suggests – dedicated only for non changing state functions. It requires to provide smart contract address as the first argument, then sophia-address
constant string value (don’t change it), then contract function name – in our case getReward
. Result returned by the function must be decoded. What’s the type of the result? Below is the function definition taken from smart contract:
public function getReward(): int = Contract.balance
As you see the contract returns reward as the int
type. This is why we decode it in client from the int
type.
Invoking the function which changes the contract state requires additionally providing the pub/private keys.
Ae({ url: this.properties.nodeUrl, internalUrl: this.properties.nodeUrl, keypair: { secretKey: '02a9f1e976b83b5cdf34279e9068fc7f352a5b49144fd96e7546390ff20a7a14e256c3ecea141842c37f9686fa0558faf71388dc473f5d69891d9ea2ee2cb671', publicKey: 'ak_2igXQ7pQgH5YDv4zP9ciq1R3qW8pNaGgywqYnwRPrBhKhYxgeG' }, }).then(async (ae) => { const result = await ae.contractCall('<CONTRACT_ADDRESS>', 'sophia-address', 'submitProposal', {args: `("argument1")`}); console.log(`Invoked function subitProposal with argument. Got the result ${result}`); });
The SDK function used to call smart contract is contractCall
. The given code invokes the function submitProposal
from the smart contract with argument argument1
. If you would need to provide more than one argument, you would define something like: {args: '("argument1", "argument2")'}
Security concerns
The SDK API can be implemented in the client side of the dapp, giving the possibility of interaction with blockchain and smart contracts. What security concerns may such architecture have?
From the security point of view it’s very important to provide safety keys usage (especially private keys) and the application architecture should provide maximum security in that field. In our examples we were using concrete values of private/public keys – which in general is not good approach. Dedicated solution (which will be delivered in future by Aeternity team for sure) would be based on dedicated wallet which would interact with SDK in secure way – not forcing developer to design the application where user must provide the private key.
I’ve described the code which is responsible for deploying the contract to the network. It’s worth to notice that since such code would be implemented in the client, it’s easy to modify it and deploy changed, even malicious code to the network. Imagine the client side deploys the contract which transfer tokens when particular condition is met. Attacker would change the condition to send the tokens to his (attacker) account even when condition is not met.
When our dapp architecutre is focused on client, where the smart contract is also deployed to the network – it’s important to provide security mechanism which would assure that the contract deployed to the network is the non modified and valid.
Of course there are plenty of security aspects (as well as the solutions) implied by decentralised architecture which must be considered. Many of them depend of the concrete application design.
The Logonity client side
The snippet below is taken from the Logonity (to prove that I develop it!).
The Logonity client gives possibility to upload logo commission to the network. In general blockchain stores the commission info (author, reward, logo description). Everyone can submit their own proposal of the logo. The smart contract will be updated whenever new proposal will be provided. The information of proposal saved in the blockchain will be minimal – just the ID of the logo and the author (Aeternity public address). What kind of ID? Generated by the centralised server side which stores the pictures data (generally files). When commission author chooses the best logo – the smart contract is invoked to transfer locked funds (reward) to the logo author. Commission gets closed and the commission principal can download the logo from centralised server.
All the interaction with smart contract are made from Logonity client side.
Summary
In dapps architecture the client side may contain crucial application logic, including interaction with blockchain. There are many security concerns in such approach which must be taken into consideration at the design stage.
Since the challange is almost over, the next article I will present the Logonity alpha version.