ress
issuer
=
5
;
// A flag indicating if this token is burnable.
bool
is_burnable
=
6
;
// A whitelist address list used to lock tokens.
repeated
aelf
.
Address
lock_white_list
=
7
;
// The chain id of the token.
int32
issue_chain_id
=
8
;
// The external information of the token.
ExternalInfo
external_info
=
9
;
// The address that owns the token.
aelf
.
Address
owner
=
10
;
}
message
SetPrimaryTokenSymbolInput
{
// The symbol of the token.
string
symbol
=
1
;
}
message
IssueInput
{
// The token symbol to issue.
string
symbol
=
1
;
// The token amount to issue.
int64
amount
=
2
;
// The memo.
string
memo
=
3
;
// The target address to issue.
aelf
.
Address
to
=
4
;
}
message
TransferInput
{
// The receiver of the token.
aelf
.
Address
to
=
1
;
// The token symbol to transfer.
string
symbol
=
2
;
// The amount to to transfer.
int64
amount
=
3
;
// The memo.
string
memo
=
4
;
}
message
LockInput
{
// The one want to lock his token.
aelf
.
Address
address
=
1
;
// Id of the lock.
aelf
.
Hash
lock_id
=
2
;
// The symbol of the token to lock.
string
symbol
=
3
;
// a memo.
string
usage
=
4
;
// The amount of tokens to lock.
int64
amount
=
5
;
}
message
UnlockInput
{
// The one want to un-lock his token.
aelf
.
Address
address
=
1
;
// Id of the lock.
aelf
.
Hash
lock_id
=
2
;
// The symbol of the token to un-lock.
string
symbol
=
3
;
// a memo.
string
usage
=
4
;
// The amount of tokens to un-lock.
int64
amount
=
5
;
}
message
TransferFromInput
{
// The source address of the token.
aelf
.
Address
from
=
1
;
// The destination address of the token.
aelf
.
Address
to
=
2
;
// The symbol of the token to transfer.
string
symbol
=
3
;
// The amount to transfer.
int64
amount
=
4
;
// The memo.
string
memo
=
5
;
}
message
ApproveInput
{
// The address that allowance will be increased.
aelf
.
Address
spender
=
1
;
// The symbol of token to approve.
string
symbol
=
2
;
// The amount of token to approve.
int64
amount
=
3
;
}
message
BatchApproveInput
{
repeated
ApproveInput
value
=
1
;
}
message
UnApproveInput
{
// The address that allowance will be decreased.
aelf
.
Address
spender
=
1
;
// The symbol of token to un-approve.
string
symbol
=
2
;
// The amount of token to un-approve.
int64
amount
=
3
;
}
message
BurnInput
{
// The symbol of token to burn.
string
symbol
=
1
;
// The amount of token to burn.
int64
amount
=
2
;
}
message
ChargeResourceTokenInput
{
// Collection of charge resource token, Symbol->Amount.
map
<
string
,
int64
>
cost_dic
=
1
;
// The sender of the transaction.
aelf
.
Address
caller
=
2
;
}
message
TransactionFeeBill
{
// The transaction fee dictionary, Symbol->fee.
map
<
string
,
int64
>
fees_map
=
1
;
}
message
TransactionFreeFeeAllowanceBill
{
// The transaction free fee allowance dictionary, Symbol->fee.
map
<
string
,
int64
>
free_fee_allowances_map
=
1
;
}
message
CheckThresholdInput
{
// The sender of the transaction.
aelf
.
Address
sender
=
1
;
// The threshold to set, Symbol->Threshold.
map
<
string
,
int64
>
symbol_to_threshold
=
2
;
// Whether to check the allowance.
bool
is_check_allowance
=
3
;
}
message
GetTokenInfoInput
{
// The symbol of token.
string
symbol
=
1
;
}
message
GetBalanceInput
{
// The symbol of token.
string
symbol
=
1
;
// The target address of the query.
aelf
.
Address
owner
=
2
;
}
message
GetBalanceOutput
{
// The symbol of token.
string
symbol
=
1
;
// The target address of the query.
aelf
.
Address
owner
=
2
;
// The balance of the owner.
int64
balance
=
3
;
}
message
GetAllowanceInput
{
// The symbol of token.
string
symbol
=
1
;
// The address of the token owner.
aelf
.
Address
owner
=
2
;
// The address of the spender.
aelf
.
Address
spender
=
3
;
}
message
GetAllowanceOutput
{
// The symbol of token.
string
symbol
=
1
;
// The address of the token owner.
aelf
.
Address
owner
=
2
;
// The address of the spender.
aelf
.
Address
spender
=
3
;
// The amount of allowance.
int64
allowance
=
4
;
}
message
CrossChainTransferInput
{
// The receiver of transfer.
aelf
.
Address
to
=
1
;
// The symbol of token.
string
symbol
=
2
;
// The amount of token to transfer.
int64
amount
=
3
;
// The memo.
string
memo
=
4
;
// The destination chain id.
int32
to_chain_id
=
5
;
// The chain id of the token.
int32
issue_chain_id
=
6
;
}
message
CrossChainReceiveTokenInput
{
// The source chain id.
int32
from_chain_id
=
1
;
// The height of the transfer transaction.
int64
parent_chain_height
=
2
;
// The raw bytes of the transfer transaction.
bytes
transfer_transaction_bytes
=
3
;
// The merkle path created from the transfer transaction.
aelf
.
MerklePath
merkle_path
=
4
;
}
message
IsInWhiteListInput
{
// The symbol of token.
string
symbol
=
1
;
// The address to check.
aelf
.
Address
address
=
2
;
}
message
SymbolToPayTxSizeFee
{
// The symbol of token.
string
token_symbol
=
1
;
// The charge weight of primary token.
int32
base_token_weight
=
2
;
// The new added token charge weight. For example, the charge weight of primary Token is set to 1.
// The newly added token charge weight is set to 10. If the transaction requires 1 unit of primary token,
// the user can also pay for 10 newly added tokens.
int32
added_token_weight
=
3
;
}
message
SymbolListToPayTxSizeFee
{
// Transaction fee token information.
repeated
SymbolToPayTxSizeFee
symbols_to_pay_tx_size_fee
=
1
;
}
message
ChargeTransactionFeesInput
{
// The method name of transaction.
string
method_name
=
1
;
// The contract address of transaction.
aelf
.
Address
contract_address
=
2
;
// The amount of transaction size fee.
int64
transaction_size_fee
=
3
;
// Transaction fee token information.
repeated
SymbolToPayTxSizeFee
symbols_to_pay_tx_size_fee
=
4
;
}
message
ChargeTransactionFeesOutput
{
// Whether the charge was successful.
bool
success
=
1
;
// The charging information.
string
charging_information
=
2
;
}
message
CallbackInfo
{
aelf
.
Address
contract_address
=
1
;
string
method_name
=
2
;
}
message
ExtraTokenListModified
{
option
(
aelf
.
is_event
)
=
true
;
// Transaction fee token information.
SymbolListToPayTxSizeFee
symbol_list_to_pay_tx_size_fee
=
1
;
}
message
GetLockedAmountInput
{
// The address of the lock.
aelf
.
Address
address
=
1
;
// The token symbol.
string
symbol
=
2
;
// The id of the lock.
aelf
.
Hash
lock_id
=
3
;
}
message
GetLockedAmountOutput
{
// The address of the lock.
aelf
.
Address
address
=
1
;
// The token symbol.
string
symbol
=
2
;
// The id of the lock.
aelf
.
Hash
lock_id
=
3
;
// The locked amount.
int64
amount
=
4
;
}
message
TokenInfoList
{
// List of token information.
repeated
TokenInfo
value
=
1
;
}
message
GetCrossChainTransferTokenContractAddressInput
{
// The chain id.
int32
chainId
=
1
;
}
message
CrossChainCreateTokenInput
{
// The chain id of the chain on which the token was created.
int32
from_chain_id
=
1
;
// The height of the transaction that created the token.
int64
parent_chain_height
=
2
;
// The transaction that created the token.
bytes
transaction_bytes
=
3
;
// The merkle path created from the transaction that created the transaction.
aelf
.
MerklePath
merkle_path
=
4
;
}
message
InitializeFromParentChainInput
{
// The amount of resource.
map
<
string
,
int32
>
resource_amount
=
1
;
// The token contract addresses.
map
<
int32
,
aelf
.
Address
>
registered_other_token_contract_addresses
=
2
;
// The creator the side chain.
aelf
.
Address
creator
=
3
;
}
message
UpdateCoefficientsInput
{
// The specify pieces gonna update.
repeated
int32
piece_numbers
=
1
;
// Coefficients of one single type.
CalculateFeeCoefficients
coefficients
=
2
;
}
enum
FeeTypeEnum
{
READ
=
0
;
STORAGE
=
1
;
WRITE
=
2
;
TRAFFIC
=
3
;
TX
=
4
;
}
message
CalculateFeePieceCoefficients
{
// Coefficients of one single piece.
// The first char is its type: liner / power.
// The second char is its piece upper bound.
repeated
int32
value
=
1
;
}
message
CalculateFeeCoefficients
{
// The resource fee type, like READ, WRITE, etc.
int32
fee_token_type
=
1
;
// Coefficients of one single piece.
repeated
CalculateFeePieceCoefficients
piece_coefficients_list
=
2
;
}
message
AllCalculateFeeCoefficients
{
// The coefficients of fee Calculation.
repeated
CalculateFeeCoefficients
value
=
1
;
}
message
TotalTransactionFeesMap
{
// Token dictionary that charge transaction fee, Symbol->Amount.
map
<
string
,
int64
>
value
=
1
;
// The hash of the block processing the transaction.
aelf
.
Hash
block_hash
=
2
;
// The height of the block processing the transaction.
int64
block_height
=
3
;
}
message
TotalResourceTokensMaps
{
// Resource tokens to charge.
repeated
ContractTotalResourceTokens
value
=
1
;
// The hash of the block processing the transaction.
aelf
.
Hash
block_hash
=
2
;
// The height of the block processing the transaction.
int64
block_height
=
3
;
}
message
ContractTotalResourceTokens
{
// The contract address.
aelf
.
Address
contract_address
=
1
;
// Resource tokens to charge.
TotalResourceTokensMap
tokens_map
=
2
;
}
message
TotalResourceTokensMap
{
// Resource token dictionary, Symbol->Amount.
map
<
string
,
int64
>
value
=
1
;
}
message
StringList
{
repeated
string
value
=
1
;
}
message
TransactionFeeDelegations
{
// delegation, symbols and its' amount
map
<
string
,
int64
>
delegations
=
1
;
// height when added
int64
block_height
=
2
;
//Whether to pay transaction fee continuously
bool
isUnlimitedDelegate
=
3
;
}
message
TransactionFeeDelegatees
{
map
<
string
,
TransactionFeeDelegations
>
delegatees
=
1
;
}
message
SetTransactionFeeDelegationsInput
{
// the delegator address
aelf
.
Address
delegator_address
=
1
;
// delegation, symbols and its' amount
map
<
string
,
int64
>
delegations
=
2
;
}
message
SetTransactionFeeDelegationsOutput
{
bool
success
=
1
;
}
message
RemoveTransactionFeeDelegatorInput
{
// the delegator address
aelf
.
Address
delegator_address
=
1
;
}
message
RemoveTransactionFeeDelegateeInput
{
// the delegatee address
aelf
.
Address
delegatee_address
=
1
;
}
message
GetTransactionFeeDelegationsOfADelegateeInput
{
aelf
.
Address
delegatee_address
=
1
;
aelf
.
Address
delegator_address
=
2
;
}
message
GetTransactionFeeDelegateesInput
{
aelf
.
Address
delegator_address
=
1
;
}
message
GetTransactionFeeDelegateesOutput
{
repeated
aelf
.
Address
delegatee_addresses
=
1
;
}
message
SetSymbolAliasInput
{
string
symbol
=
1
;
string
alias
=
2
;
}
// Events
message
Transferred
{
option
(
aelf
.
is_event
)
=
true
;
// The source address of the transferred token.
aelf
.
Address
from
=
1
[
(
aelf
.
is_indexed
)
=
true
]
;
// The destination address of the transferred token.
aelf
.
Address
to
=
2
[
(
aelf
.
is_indexed
)
=
true
]
;
// The symbol of the transferred token.
string
symbol
=
3
[
(
aelf
.
is_indexed
)
=
true
]
;
// The amount of the transferred token.
int64
amount
=
4
;
// The memo.
string
memo
=
5
;
}
message
Approved
{
option
(
aelf
.
is_event
)
=
true
;
// The address of the token owner.
aelf
.
Address
owner
=
1
[
(
aelf
.
is_indexed
)
=
true
]
;
// The address that allowance be increased.
aelf
.
Address
spender
=
2
[
(
aelf
.
is_indexed
)
=
true
]
;
// The symbol of approved token.
string
symbol
=
3
[
(
aelf
.
is_indexed
)
=
true
]
;
// The amount of approved token.
int64
amount
=
4
;
}
message
UnApproved
{
option
(
aelf
.
is_event
)
=
true
;
// The address of the token owner.
aelf
.
Address
owner
=
1
[
(
aelf
.
is_indexed
)
=
true
]
;
// The address that allowance be decreased.
aelf
.
Address
spender
=
2
[
(
aelf
.
is_indexed
)
=
true
]
;
// The symbol of un-approved token.
string
symbol
=
3
[
(
aelf
.
is_indexed
)
=
true
]
;
// The amount of un-approved token.
int64
amount
=
4
;
}
message
Burned
{
option
(
aelf
.
is_event
)
=
true
;
// The address who wants to burn token.
aelf
.
Address
burner
=
1
[
(
aelf
.
is_indexed
)
=
true
]
;
// The symbol of burned token.
string
symbol
=
2
[
(
aelf
.
is_indexed
)
=
true
]
;
// The amount of burned token.
int64
amount
=
3
;
}
message
ChainPrimaryTokenSymbolSet
{
option
(
aelf
.
is_event
)
=
true
;
// The symbol of token.
string
token_symbol
=
1
;
}
message
CalculateFeeAlgorithmUpdated
{
option
(
aelf
.
is_event
)
=
true
;
// All calculate fee coefficients after modification.
AllCalculateFeeCoefficients
all_type_fee_coefficients
=
1
;
}
message
RentalCharged
{
option
(
aelf
.
is_event
)
=
true
;
// The symbol of rental fee charged.
string
symbol
=
1
;
// The amount of rental fee charged.
int64
amount
=
2
;
// The payer of rental fee.
aelf
.
Address
payer
=
3
;
// The receiver of rental fee.
aelf
.
Address
receiver
=
4
;
}
message
RentalAccountBalanceInsufficient
{
option
(
aelf
.
is_event
)
=
true
;
// The symbol of insufficient rental account balance.
string
symbol
=
1
;
// The balance of the account.
int64
amount
=
2
;
}
message
TokenCreated
{
option
(
aelf
.
is_event
)
=
true
;
// The symbol of the token.
string
symbol
=
1
;
// The full name of the token.
string
token_name
=
2
;
// The total supply of the token.
int64
total_supply
=
3
;
// The precision of the token.
int32
decimals
=
4
;
// The address that has permission to issue the token.
aelf
.
Address
issuer
=
5
;
// A flag indicating if this token is burnable.
bool
is_burnable
=
6
;
// The chain id of the token.
int32
issue_chain_id
=
7
;
// The external information of the token.
ExternalInfo
external_info
=
8
;
// The address that owns the token.
aelf
.
Address
owner
=
9
;
}
message
Issued
{
option
(
aelf
.
is_event
)
=
true
;
// The symbol of issued token.
string
symbol
=
1
;
// The amount of issued token.
int64
amount
=
2
;
// The memo.
string
memo
=
3
;
// The issued target address.
aelf
.
Address
to
=
4
;
}
message
CrossChainTransferred
{
option
(
aelf
.
is_event
)
=
true
;
// The source address of the transferred token.
aelf
.
Address
from
=
1
;
// The destination address of the transferred token.
aelf
.
Address
to
=
2
;
// The symbol of the transferred token.
string
symbol
=
3
;
// The amount of the transferred token.
int64
amount
=
4
;
// The memo.
string
memo
=
5
;
// The destination chain id.
int32
to_chain_id
=
6
;
// The chain id of the token.
int32
issue_chain_id
=
7
;
}
message
CrossChainReceived
{
option
(
aelf
.
is_event
)
=
true
;
// The source address of the transferred token.
aelf
.
Address
from
=
1
;
// The destination address of the transferred token.
aelf
.
Address
to
=
2
;
// The symbol of the received token.
string
symbol
=
3
;
// The amount of the received token.
int64
amount
=
4
;
// The memo.
string
memo
=
5
;
// The destination chain id.
int32
from_chain_id
=
6
;
// The chain id of the token.
int32
issue_chain_id
=
7
;
// The parent chain height of the transfer transaction.
int64
parent_chain_height
=
8
;
// The id of transfer transaction.
aelf
.
Hash
transfer_transaction_id
=
9
;
}
message
TransactionFeeDelegationAdded
{
option
(
aelf
.
is_event
)
=
true
;
aelf
.
Address
delegator
=
1
[
(
aelf
.
is_indexed
)
=
true
]
;
aelf
.
Address
delegatee
=
2
[
(
aelf
.
is_indexed
)
=
true
]
;
aelf
.
Address
caller
=
3
[
(
aelf
.
is_indexed
)
=
true
]
;
}
message
TransactionFeeDelegationCancelled
{
option
(
aelf
.
is_event
)
=
true
;
aelf
.
Address
delegator
=
1
[
(
aelf
.
is_indexed
)
=
true
]
;
aelf
.
Address
delegatee
=
2
[
(
aelf
.
is_indexed
)
=
true
]
;
aelf
.
Address
caller
=
3
[
(
aelf
.
is_indexed
)
=
true
]
;
}
message
SymbolAliasAdded
{
option
(
aelf
.
is_event
)
=
true
;
string
symbol
=
1
[
(
aelf
.
is_indexed
)
=
true
]
;
string
alias
=
2
[
(
aelf
.
is_indexed
)
=
true
]
;
}
message
SymbolAliasDeleted
{
option
(
aelf
.
is_event
)
=
true
;
string
symbol
=
1
[
(
aelf
.
is_indexed
)
=
true
]
;
string
alias
=
2
[
(
aelf
.
is_indexed
)
=
true
]
;
}
Contract Reference State
Navigate to
src
.
create a
new file
ContractReferences.cs
.
The implementation of file
src/ContractRefefrence.cs
is as follows:
ContractReferences.cs
using
AElf
.
Contracts
.
MultiToken
;
namespace
AElf
.
Contracts
.
LotteryGame
{
public
partial
class
LotteryGameState
{
internal
TokenContractContainer
.
TokenContractReferenceState
TokenContract
{
get
;
set
;
}
}
}
Implement Lottery Game Smart Contract
Navigate to
src/LotteryGame.cs
LotteryGame.cs
using
AElf
.
Contracts
.
MultiToken
;
using
AElf
.
Sdk
.
CSharp
;
using
AElf
.
Types
;
using
Google
.
Protobuf
.
WellKnownTypes
;
namespace
AElf
.
Contracts
.
LotteryGame
{
// Contract class must inherit the base class generated from the proto file
public
class
LotteryGame
:
LotteryGameContainer
.
LotteryGameBase
{
private
const
string
TokenContractAddress
=
"ASh2Wt7nSEmYqnGxPPzp4pnVDU4uhj1XW9Se5VeZcX2UDdyjx"
;
// tDVW token contract address
private
const
string
TokenSymbol
=
"ELF"
;
private
const
long
MinimumPlayAmount
=
1_000_000
;
// 0.01 ELF
private
const
long
MaximumPlayAmount
=
1_000_000_000
;
// 10 ELF
// Initializes the contract
public
override
Empty
Initialize
(
Empty
input
)
{
// Check if the contract is already initialized
Assert
(
State
.
Initialized
.
Value
==
false
,
"Already initialized."
)
;
// Set the contract state
State
.
Initialized
.
Value
=
true
;
// Set the owner address
State
.
Owner
.
Value
=
Context
.
Sender
;
// Initialize the token contract
State
.
TokenContract
.
Value
=
Address
.
FromBase58
(
TokenContractAddress
)
;
return
new
Empty
(
)
;
}
// Plays the lottery game with a specified amount of tokens.
// The method checks if the play amount is within the limit.
// If the player wins, tokens are transferred from the contract to the sender and a PlayOutcomeEvent is fired with the won amount.
// If the player loses, tokens are transferred from the sender to the contract and a PlayOutcomeEvent is fired with the lost amount.
public
override
Empty
Play
(
Int64Value
input
)
{
var
playAmount
=
input
.
Value
;
// Check if input amount is within the limit
Assert
(
playAmount
is
>=
MinimumPlayAmount
and
<=
MaximumPlayAmount
,
"Invalid play amount."
)
;
// Check if the sender has enough tokens
var
balance
=
State
.
TokenContract
.
GetBalance
.
Call
(
new
GetBalanceInput
{
Owner
=
Context
.
Sender
,
Symbol
=
TokenSymbol
}
)
.
Balance
;
Assert
(
balance
>=
playAmount
,
"Insufficient balance."
)
;
// Check if the contract has enough tokens
var
contractBalance
=
State
.
TokenContract
.
GetBalance
.
Call
(
new
GetBalanceInput
{
Owner
=
Context
.
Self
,
Symbol
=
TokenSymbol
}
)
.
Balance
;
Assert
(
contractBalance
>=
playAmount
,
"Insufficient contract balance."
)
;
if
(
IsWinner
(
)
)
{
// Transfer the token from the contract to the sender
State
.
TokenContract
.
Transfer
.
Send
(
new
TransferInput
{
To
=
Context
.
Sender
,
Symbol
=
TokenSymbol
,
Amount
=
playAmount
}
)
;
// Emit an event to notify listeners about the outcome
Context
.
Fire
(
new
PlayOutcomeEvent
{
Amount
=
input
.
Value
,
Won
=
playAmount
}
)
;
}
else
{
// 프로젝트로 돌아가기