bitpro가 원문에서 글자만 모은 내용이에요. 표·그림·수식은 빠지거나 깨질 수 있어요. 전체 41쪽 중 13쪽
Transfer the token from the sender to the contract
State
.
TokenContract
.
TransferFrom
.
Send
(
new
TransferFromInput
{
From
=
Context
.
Sender
,
To
=
Context
.
Self
,
Symbol
=
TokenSymbol
,
Amount
=
playAmount
}
)
;
// Emit an event to notify listeners about the outcome
Context
.
Fire
(
new
PlayOutcomeEvent
{
Amount
=
input
.
Value
,
Won
=
-
playAmount
}
)
;
}
return
new
Empty
(
)
;
}
// Withdraws a specified amount of tokens from the contract.
// This method can only be called by the owner of the contract.
// After the tokens are transferred, a WithdrawEvent is fired to notify any listeners about the withdrawal.
public
override
Empty
Withdraw
(
Int64Value
input
)
{
AssertIsOwner
(
)
;
// Transfer the token from the contract to the sender
State
.
TokenContract
.
Transfer
.
Send
(
new
TransferInput
{
To
=
Context
.
Sender
,
Symbol
=
TokenSymbol
,
Amount
=
input
.
Value
}
)
;
// Emit an event to notify listeners about the withdrawal
Context
.
Fire
(
new
WithdrawEvent
{
Amount
=
input
.
Value
,
From
=
Context
.
Self
,
To
=
State
.
Owner
.
Value
}
)
;
return
new
Empty
(
)
;
}
// Deposits a specified amount of tokens into the contract.
// This method can only be called by the owner of the contract.
// After the tokens are transferred, a DepositEvent is fired to notify any listeners about the deposit.
public
override
Empty
Deposit
(
Int64Value
input
)
{
AssertIsOwner
(
)
;
// Transfer the token from the sender to the contract
State
.
TokenContract
.
TransferFrom
.
Send
(
new
TransferFromInput
{
From
=
Context
.
Sender
,
To
=
Context
.
Self
,
Symbol
=
TokenSymbol
,
Amount
=
input
.
Value
}
)
;
// Emit an event to notify listeners about the deposit
Context
.
Fire
(
new
DepositEvent
{
Amount
=
input
.
Value
,
From
=
Context
.
Sender
,
To
=
Context
.
Self
}
)
;
return
new
Empty
(
)
;
}
// Transfers the ownership of the contract to a new owner.
// This method can only be called by the current owner of the contract.
public
override
Empty
TransferOwnership
(
Address
input
)
{
AssertIsOwner
(
)
;
// Set the new owner address
State
.
Owner
.
Value
=
input
;
return
new
Empty
(
)
;
}
// A method that read the contract's play amount limit
public
override
PlayAmountLimitMessage
GetPlayAmountLimit
(
Empty
input
)
{
// Wrap the value in the return type
return
new
PlayAmountLimitMessage
{
MinimumAmount
=
MinimumPlayAmount
,
MaximumAmount
=
MaximumPlayAmount
}
;
}
// A method that read the contract's current balance
public
override
Int64Value
GetContractBalance
(
Empty
input
)
{
// Get the balance of the contract
var
balance
=
State
.
TokenContract
.
GetBalance
.
Call
(
new
GetBalanceInput
{
Owner
=
Context
.
Self
,
Symbol
=
TokenSymbol
}
)
.
Balance
;
// Wrap the value in the return type
return
new
Int64Value
{
Value
=
balance
}
;
}
// A method that read the contract's owner
public
override
StringValue
GetOwner
(
Empty
input
)
{
return
State
.
Owner
.
Value
==
null
?
new
StringValue
(
)
:
new
StringValue
{
Value
=
State
.
Owner
.
Value
.
ToBase58
(
)
}
;
}
// Determines if the player is a winner.
// This method generates a random number based on the current block height and checks if it's equal to 0.
// If the random number is 0, the player is considered a winner.
private
bool
IsWinner
(
)
{
var
randomNumber
=
Context
.
CurrentHeight
%
2
;
return
randomNumber
==
0
;
}
// This method is used to ensure that only the owner of the contract can perform certain actions.
// If the context sender is not the owner, an exception is thrown with the message "Unauthorized to perform the action."
private
void
AssertIsOwner
(
)
{
Assert
(
Context
.
Sender
==
State
.
Owner
.
Value
,
"Unauthorized to perform the action."
)
;
}
}
}
Building Smart Contract
Build the new code with the following commands inside
src
folder:
Terminal
dotnet build
You should see
LotteryGame.dll.patched
in the directory
lottery_game/src/bin/Debug/net.6.0
Step 3 - Deploy Smart Contract
Create A Wallet
To send transactions on the aelf blockchain, you must have a wallet.
Run this command to create aelf wallet.
Terminal
aelf-command create
You will be prompted to save your account, please do
save
your account as shown below:
Terminal
? Save account info into a file?
(
Y/n
)
Y
Make sure to choose Y to save your account information.
tip
ℹ️ Note: If you do not save your account information (by selecting n or N), do not export the wallet password. Only
proceed to the next
step if you have saved your account information.
Next, enter and confirm your password. Then export your wallet password as shown below:
Linux and macOs
Windows
Terminal
export
WALLET_PASSWORD
=
"YOUR_WALLET_PASSWORD"
Command Prompt
$env
:WALLET_PASSWORD
=
"YOUR_WALLET_PASSWORD"
Acquire Testnet Tokens (Faucet) for Development
To deploy smart contracts or execute on-chain transactions on aelf, you'll require testnet ELF tokens.
Get ELF Tokens
Go to
https://faucet-ui.aelf.dev
Enter your address and click
Get Tokens
.
Deploy Smart Contract:
The smart contract needs to be deployed on the chain before users can interact with it.
Run the following command to deploy a contract. Remember to export the path of LotteryGame.dll.patched to CONTRACT_PATH.
Linux and macOs
Windows
Terminal
export
CONTRACT_PATH
=
$(
find
~+
.
-path
"*patched*"
|
head
-n
1
)
Terminal
aelf-deploy
-a
$WALLET_ADDRESS
-p
$WALLET_PASSWORD
-c
$CONTRACT_PATH
-e
https://tdvw-test-node.aelf.io/
Command Prompt
$CONTRACT_PATH
=
Get-ChildItem
-Recurse
-Filter
"*patched*"
|
Select-Object
-First
1
-ExpandProperty
FullName
$env
:CONTRACT_PATH
=
$CONTRACT_PATH
Command Prompt
aelf-deploy
-a
$env
:WALLET_ADDRESS
-p
$env
:WALLET_PASSWORD
-c
$env
:CONTRACT_PATH
-e
https://tdvw-test-node.aelf.io/
Please wait for approximately 1 to 2 minutes. If the deployment is successful, it will provide you with the contract address.
Copy the smart contract address from the
address
field
Export your smart contract address:
Linux and macOs
Windows
Terminal
export
CONTRACT_ADDRESS
=
"YOUR_SMART_CONTRACT_ADDRESS e.g. 2LUmicHyH4RXrMjG4beDwuDsiWJESyLkgkwPdGTR8kahRzq5XS"
Command Prompt
$env
:CONTRACT_ADDRESS
=
"YOUR_SMART_CONTRACT_ADDRESS e.g. 2LUmicHyH4RXrMjG4beDwuDsiWJESyLkgkwPdGTR8kahRzq5XS"
tip
ℹ️ Note: You are to copy the smart contract address as we will be referencing it in the next steps!
info
🎉 You have successfully deployed your dApp smart contract on the aelf testnet! In the next steps, we will be building the frontend components that allow us to interact with our deployed smart contract!
Step 4 - Interact with Your Deployed Smart Contract
Approving Smart Contract Spending
Terminal
aelf-command send ASh2Wt7nSEmYqnGxPPzp4pnVDU4uhj1XW9Se5VeZcX2UDdyjx
-a
$WALLET_ADDRESS
-p
$WALLET_PASSWORD
-e
https://tdvw-test-node.aelf.io Approve
tip
ℹ️ Note:
ASh2Wt7nSEmYqnGxPPzp4pnVDU4uhj1XW9Se5VeZcX2UDdyjx
is the contract address of
Multitoken Contract
on aelf Testnet dAppChain (tDVW).
When prompted, enter the following parameters to approve the spending of 90 ELF tokens:
Terminal
Enter the params one by one, type `Enter` to skip optional param:
? Enter the required param <spender>: "INSERT_YOUR_CONTRACT_ADDRESS_HERE"
? Enter the required param <symbol>: ELF
? Enter the required param <amount>: 9000000000
Initializing Lottery Game Contract
Terminal
aelf-command send
$CONTRACT_ADDRESS
-a
$WALLET_ADDRESS
-p
$WALLET_PASSWORD
-e
https://tdvw-test-node.aelf.io Initialize
Output:
Depositing funds into the Lottery Game Contract
Terminal
aelf-command send
$CONTRACT_ADDRESS
-a
$WALLET_ADDRESS
-p
$WALLET_PASSWORD
-e
https://tdvw-test-node.aelf.io Deposit
You will be prompted for the following:
Terminal
Enter the params one by one, type `Enter` to skip optional param:
? Enter the required param <value>: 20000
Output:
Playing the Lottery Game
Terminal
aelf-command send
$CONTRACT_ADDRESS
-a
$WALLET_ADDRESS
-p
$WALLET_PASSWORD
-e
https://tdvw-test-node.aelf.io Play
Let's check the
balance
Terminal
aelf-command call ASh2Wt7nSEmYqnGxPPzp4pnVDU4uhj1XW9Se5VeZcX2UDdyjx
-a
$WALLET_ADDRESS
-p
$WALLET_PASSWORD
-e
https://tdvw-test-node.aelf.io GetBalance
You will be prompted for the following:
Terminal
Enter the required param <symbol>: ELF
Enter the required param <owner>: $WALLET_ADDRESS
Understanding Inter-Contract Calls in aelf
In this section, we'll explore how inter-contract calls work in the aelf blockchain using the lottery game example from the tutorial. This will help you understand how different smart contracts can interact to perform complex operations.
1.
Smart Contract Overview
Lottery Contract
: Manages the game, including buying tickets, drawing winners, and distributing prizes.
Token Contract
: Handles the token transactions needed for buying lottery tickets.
2.
Ticket Purchase Process
Initiating Purchase
: When a user wants to buy a lottery ticket, they interact with the Lottery Contract.
Token Transfer Requirement
: The Lottery Contract must verify that the user has enough tokens and transfer those tokens to the lottery’s account to complete the purchase.
3.
Initializing Contract Reference State
Setting Contract Address
: The Lottery Contract must first initialize its reference to the Token Contract by setting the correct contract address in its state.
4.
Making an Inter-Contract Call
Calling Token Contract
: The Lottery Contract needs to interact with the Token Contract to transfer tokens.
Method Invocation
: It calls a method in the Token Contract, such as
Transfer
.
Parameters
: The call includes details like the sender’s address, the recipient’s address (the lottery account), and the amount of tokens.
Encoding and Sending
: The parameters are encoded into a transaction format and sent to the Token Contract.
5.
Processing in the Token Contract
Token Transfer
: The Token Contract processes the transfer request by deducting tokens from the user’s account and adding them to the lottery account.
Return Response
: The Token Contract then returns a result indicating whether the transfer was successful or if it failed.
6.
Handling the Response
Lottery Contract’s Role
: Once the Lottery Contract receives the response from the Token Contract, it checks if the transfer was successful.
Next Steps
: If successful, the Lottery Contract updates the user's lottery ticket entries and continues with the game logic.
7.
Authorization and Security
Permission Checks
: Ensures that the Lottery Contract is authorized to invoke methods in the Token Contract.
Secure Transactions
: Ensures that token transfers are secure and correctly authorized.
8.
Error Handling
Failure Management
: If the token transfer fails (e.g., due to insufficient funds), the Lottery Contract handles the error by potentially reverting the transaction or notifying the user.
By following these steps, you can see how inter-contract calls in aelf allow different contracts to work together smoothly. This modular approach helps in building complex applications like a lottery game by ensuring secure and authorized interactions between contracts.
🎯 Conclusion
🎊 Congratulations!
You've completed the Lottery Game Contract tutorial! Well done for mastering the steps and complexities involved. 🌟
📚 What You've Learned
In this tutorial, you've explored:
🛠️ Setting up your development environment for aelf blockchain.
🎲 Developing a smart contract for a basic lottery game with state management and random number generation.
🚀 Deploying and interacting with your Lottery Game Contract on the aelf network.
🔍 Final Output
By now, you should have:
📜 Successfully deployed your Lottery Game Contract on the aelf blockchain.
🎉 Deposited funds and played the lottery game using smart contract interactions.
Ensure you've seen your ELF balance updated after playing the game to verify the contract's functionality.
➡️ What's Next?
Now that you've tackled the Lottery Game Contract, consider exploring more advanced topics or other tutorials to expand your aelf blockchain development skills.
🚀 Keep innovating and building awesome decentralized applications!
Happy coding! 😊
Step 1 - Setting up your development environment
Step 2 - Develop Smart Contract
Start Your Smart Contract Project
Adding Your Smart Contract Code
Building Smart Contract
Step 3 - Deploy Smart Contract
Step 4 - Interact with Your Deployed Smart Contract
Approving Smart Contract Spending
Initializing Lottery Game Contract
Depositing funds into the Lottery Game Contract
Playing the Lottery Game
Understanding Inter-Contract Calls in aelf
1.
Smart Contract Overview
2.
Ticket Purchase Process
3.
Initializing Contract Reference State
4.
Making an Inter-Contract Call
5.
Processing in the Token Contract
6.
Handling the Response
7.
Authorization and Security
8.
Error Handling
🎯 Conclusion
## /quick-start/developers/dao-dapp
On this page
Description
: This is the slightly more complex dApp in this guide. It covers mechanisms of a decentralized autonomous organization (DAO) dApp including creating a proposal, vote on a proposal, fetch all proposals, security considerations, and advanced data structures to ensure a fair and transparent DAO processes.
Purpose
: To teach you about complex logic implementation, security best
practices, and efficient data management in smart contracts.
Difficulty Level
: Difficult
Step 1 - Setting up your development environment
Local
Codespaces
Basic knowledge of terminal commands
IDE
- Install
VS Code
Install Required Packages
Install dotnet 6.0 SDK
Install aelf contract templates
Terminal
dotnet new
--install
AElf.ContractTemplates
AELF.ContractTemplates contains various predefined templates for the ease of developing smart contracts on the aelf blockchain.
Install aelf deploy tool
Terminal
dotnet tool
install
--global
aelf.deploy
aelf.deploy is a utility tool for deploying smart contracts on the aelf blockchain.
Please remember to export PATH after installing aelf.deploy.
Install Node.js and Yarn
Install Node.js
Install Yarn
Install aelf-command
Linux and macOs
Windows
Terminal
sudo
npm
i
-g
aelf-command
Command Prompt
npm
i
-g
aelf-command
aelf-command is a CLI tool for interacting with the aelf blockchain, enabling tasks like creating wallets and managing transactions.
Provide required permissions while installing aelf-command globally.
Install Git
Install Git
As we will be using a ready made project, we will require git to clone from the project.
Visit
aelf-devcontainer-template
.
Click the
Use this template
button. Choose
Create a new repository
.
Enter a suitable repository name. Click
Create repository
.
Within the GitHub interface of your new repository, click on
Code
.
Select
Codespaces
.
Click on the
+
sign to create a new Codespace.
After some time, your workspace will load with the contents of the repository.
You can now continue your development using GitHub Codespaces.
Step 2 - Develop Smart Contract
Project Setup
Open your
Terminal
.
Enter the following command to create a new project folder:
Terminal
mkdir
capstone_aelf
cd
capstone_aelf
Enter this command to create the capstone project.
Terminal
dotnet new aelf
-n
BuildersDAO
Adding Your Smart Contract Code
Open your project in your favorite IDE (like VSCode).
Rename the
src/Protobuf/contract/hello_world_contract.proto
file to
BuildersDAO.proto
.
After renaming the file, your working directory should look like this.
That's it! Your project is now set up and ready to go 🚀
Defining Methods and Messages
Let's add the RPC methods and message definitions to our Voting dApp.
Open
src/Protobuf/contract/BuildersDAO.proto
Replace its contents with this code snippet.
src/Protobuf/contract/BuildersDAO.proto
syntax
=
"proto3"
;
import
"aelf/core.proto"
;
import
"aelf/options.proto"
;
import
"google/protobuf/empty.proto"
;
import
"Protobuf/reference/acs12.proto"
;
// The namespace of this class
option
csharp_namespace
=
"AElf.Contracts.BuildersDAO"
;
service
BuildersDAO
{
// The name of the state class the smart contract is going to use to access
// blockchain state
option
(
aelf
.
csharp_state
)
=
"AElf.Contracts.BuildersDAO.BuildersDAOState"
;
option
(
aelf
.
base
)
=
"Protobuf/reference/acs12.proto"
;
// Actions -> Methods that change state of smart contract
// This method sets up the initial state of our StackUpDAO smart contract
rpc
Initialize
(
google
.
protobuf
.
Empty
)
returns
(
google
.
protobuf
.
Empty
)
;
// This method allows a user to become a member of the DAO by taking in their
// address as an input parameter
rpc
JoinDAO
(
aelf
.
Address
)
returns
(
google
.
protobuf
.
Empty
)
;
// This method allows a user to create a proposal for other users to vote on.
// The method takes in a "CreateProposalInput" message which comprises of an
// address, a title, description and a vote threshold (i.e how many votes
// required for the proposal to pass)
rpc
CreateProposal
(
CreateProposalInput
)
returns
(
Proposal
)
;
// This method allows a user to vote on proposals towards a specific proposal.
// This method takes in a "VoteInput" message which takes in the address of
// the voter, specific proposal and a boolean which represents their vote
rpc
VoteOnProposal
(
VoteInput
)
returns
(
Proposal
)
;
// Views -> Methods that does not change state of smart contract
// This method allows a user to fetch a list of proposals that had been
// created by members of the DAO
rpc
GetAllProposals
(
google
.
protobuf
.
Empty
)
returns
(
ProposalList
)
{
option
(
aelf
.
is_view
)
=
true
;
}
// aelf requires explicit getter methods to access the state value,
// so we provide these three getter methods for accessing the state
// This method allows a user to fetch a proposal by proposalId
rpc
GetProposal
(
google
.
protobuf
.
StringValue
)
returns
(
Proposal
)
{
option
(
aelf
.
is_view
)
=
true
;
}
// This method allows a user to fetch the member count that joined DAO
rpc
GetMemberCount
(
google
.
protobuf
.
Empty
)
returns
(
google
.
protobuf
.
Int32Value
)
{
option
(
aelf
.
is_view
)
=
true
;
}
// This method allows a user to check whether this member is exist by address
rpc
GetMemberExist
(
aelf
.
Address
)
returns
(
google
.
protobuf
.
BoolValue
)
{
option
(
aelf
.
is_view
)
=
true
;
}
}
// Message definitions
message
Member
{
aelf
.
Address
address
=
1
;
}
message
Proposal
{
string
id
=
1
;
string
title
=
2
;
string
description
=
3
;
repeated
aelf
.
Address
yesVotes
=
4
;
repeated
aelf
.
Address
noVotes
=
5
;
string
status
=
6
;
// e.g., "IN PROGRESS", "PASSED", "DENIED"
int32
voteThreshold
=
7
;
}
message
CreateProposalInput
{
aelf
.
Address
creator
=
1
;
string
title
=
2
;
string
description
=
3
;
int32
voteThreshold
=
4
;
}
message
VoteInput
{
aelf
.
Address
voter
=
1
;
string
proposalId
=
2
;
bool
vote
=
3
;
// true for yes, false for no
}
message
MemberList
{
repeated
Member
members
=
1
;
}
message
ProposalList
{
repeated
Proposal
proposals
=
1
;
}
Understanding the Code
1.
Define Syntax & Imports
proto3
version.
Import necessary Protobuf definitions and libraries.
2.
RPC Methods
Initialize
: Set up initial state
JoinDAO
: User joins DAO. User's
address
is the function parameter.
CreateProposal
: User creates a proposal. User's
address
,
title
,
description
,
vote threshold
are the function parameter.
VoteOnProposal
: User votes on a proposal. User's
address
,
proposal
vote
is the function parameter.
GetAllProposals
: Fetch list of proposals
3.
Getter Metho프로젝트로 돌아가기