diff --git a/examples/README.md b/examples/README.md index c24eff814..c42cd66ba 100644 --- a/examples/README.md +++ b/examples/README.md @@ -33,7 +33,6 @@ See the table below for the detailed examples description. | [storage](storage) | The contract implements API for basic operations with a contract storage. It shows hos to use `storage` interop package. See the `storage` [package documentation](../pkg/interop/storage/storage.go). | | [timer](timer) | The idea of the contract is to count `tick` method invocations and destroy itself after the third invocation. It shows how to use `contract.Call` interop function to call, update (migrate) and destroy the contract. Please, refer to the `contract.Call` [function documentation](../pkg/interop/contract/contract.go) | | [token](token) | This contract implements NEP-17 token standard (like NEO and GAS tokens) with all required methods and operations. See the NEP-17 token standard [specification](https://github.com/neo-project/proposals/pull/126) for details. | -| [token-sale](token-sale) | The contract represents a token with `allowance`. It means that the token owner should approve token withdrawing before the transfer. The contract demonstrates how interop packages can be combined to work together. | ## Compile diff --git a/examples/token-sale/go.mod b/examples/token-sale/go.mod deleted file mode 100644 index 58e2026c0..000000000 --- a/examples/token-sale/go.mod +++ /dev/null @@ -1,5 +0,0 @@ -module github.com/nspcc-dev/neo-go/examples/token-sale - -go 1.16 - -require github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220321144137-d5a9af5860af diff --git a/examples/token-sale/go.sum b/examples/token-sale/go.sum deleted file mode 100644 index d6c936018..000000000 --- a/examples/token-sale/go.sum +++ /dev/null @@ -1,2 +0,0 @@ -github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220321144137-d5a9af5860af h1:QO3pU/jSYyX3EHBX8BPO01oRkVhGBXPrQaQEhn+4fv8= -github.com/nspcc-dev/neo-go/pkg/interop v0.0.0-20220321144137-d5a9af5860af/go.mod h1:QBE0I30F2kOAISNpT5oks82yF4wkkUq3SCfI3Hqgx/Y= diff --git a/examples/token-sale/token_sale.go b/examples/token-sale/token_sale.go deleted file mode 100644 index 8593e9a04..000000000 --- a/examples/token-sale/token_sale.go +++ /dev/null @@ -1,279 +0,0 @@ -package tokensale - -import ( - "github.com/nspcc-dev/neo-go/pkg/interop" - "github.com/nspcc-dev/neo-go/pkg/interop/runtime" - "github.com/nspcc-dev/neo-go/pkg/interop/storage" - "github.com/nspcc-dev/neo-go/pkg/interop/util" -) - -const ( - decimals = 8 - multiplier = decimals * 10 -) - -var ( - owner = util.FromAddress("NbrUYaZgyhSkNoRo9ugRyEMdUZxrhkNaWB") - trigger byte - token TokenConfig - ctx storage.Context -) - -// TokenConfig holds information about the token we want to use for the sale. -type TokenConfig struct { - // Name of the token. - Name string - // 3 letter abbreviation of the token. - Symbol string - // How decimals this token will have. - Decimals int - // Address of the token owner. This is the Uint160 hash. - Owner []byte - // The total amount of tokens created. Notice that we need to multiply the - // amount by 100000000. (10^8) - TotalSupply int - // Initial amount is number of tokens that are available for the token sale. - InitialAmount int - // How many NEO will be worth 1 token. For example: - // Lets say 1 euro per token, where 1 NEO is 60 euro. This means buyers - // will get (60 * 10^8) tokens for 1 NEO. - AmountPerNEO int - // How many Gas will be worth 1 token. This is the same calculation as - // for the AmountPerNEO, except Gas price will have a different value. - AmountPerGas int - // The maximum amount you can mint in the limited round. For example: - // 500 NEO/buyer * 60 tokens/NEO * 10^8 - MaxExchangeLimitRound int - // When to start the token sale. - SaleStart int - // When to end the initial limited round if there is one. For example: - // SaleStart + 10000 - LimitRoundEnd int - // The prefix used to store how many tokens there are in circulation. - CirculationKey []byte - // The prefix used to store how many tokens there are in the limited round. - LimitRoundKey []byte - // The prefix used to store the addresses that are registered with KYC. - KYCKey []byte -} - -// newTokenConfig returns the initialized TokenConfig. -func newTokenConfig() TokenConfig { - return TokenConfig{ - Name: "My awesome token", - Symbol: "MAT", - Decimals: decimals, - Owner: owner, - TotalSupply: 10000000 * multiplier, - InitialAmount: 5000000 * multiplier, - AmountPerNEO: 60 * multiplier, - AmountPerGas: 40 * multiplier, - MaxExchangeLimitRound: 500 * 60 * multiplier, - SaleStart: 75500, - LimitRoundEnd: 75500 + 10000, - CirculationKey: []byte("in_circulation"), - LimitRoundKey: []byte("r1"), - KYCKey: []byte("kyc_ok"), - } -} - -// getIntFromDB is a helper that checks for nil result of storage.Get and returns -// zero as the default value. -func getIntFromDB(ctx storage.Context, key []byte) int { - var res int - val := storage.Get(ctx, key) - if val != nil { - res = val.(int) - } - return res -} - -// InCirculation returns the amount of total tokens that are in circulation. -func InCirculation() int { - return getIntFromDB(ctx, token.CirculationKey) -} - -// addToCirculation sets the given amount as "in circulation" in the storage. -func addToCirculation(amount int) bool { - if amount < 0 { - return false - } - supply := getIntFromDB(ctx, token.CirculationKey) - supply += amount - if supply > token.TotalSupply { - return false - } - storage.Put(ctx, token.CirculationKey, supply) - return true -} - -// AvailableAmount returns the total amount of available tokens left -// to be distributed. -func AvailableAmount() int { - inCirc := getIntFromDB(ctx, token.CirculationKey) - return token.TotalSupply - inCirc -} - -// init initializes runtime trigger, TokenConfig and storage context before any -// other contract method is called -func init() { - trigger = runtime.GetTrigger() - token = newTokenConfig() - ctx = storage.GetContext() -} - -// checkOwnerWitness is a helper function which checks whether the invoker is the -// owner of the contract. -func checkOwnerWitness() bool { - // This is used to verify if a transfer of system assets (NEO and Gas) - // involving this contract's address can proceed. - if trigger == runtime.Application { - // Check if the invoker is the owner of the contract. - return runtime.CheckWitness(token.Owner) - } - return false -} - -// Decimals returns the token decimals -func Decimals() int { - if trigger != runtime.Application { - panic("invalid trigger") - } - return token.Decimals -} - -// Symbol returns the token symbol -func Symbol() string { - if trigger != runtime.Application { - panic("invalid trigger") - } - return token.Symbol -} - -// TotalSupply returns the token total supply value -func TotalSupply() int { - if trigger != runtime.Application { - panic("invalid trigger") - } - return getIntFromDB(ctx, token.CirculationKey) -} - -// BalanceOf returns the amount of token on the specified address -func BalanceOf(holder interop.Hash160) int { - if trigger != runtime.Application { - panic("invalid trigger") - } - return getIntFromDB(ctx, holder) -} - -// Transfer transfers specified amount of token from one user to another -func Transfer(from, to interop.Hash160, amount int, _ interface{}) bool { - if trigger != runtime.Application { - return false - } - if amount <= 0 || len(to) != 20 || !runtime.CheckWitness(from) { - return false - } - amountFrom := getIntFromDB(ctx, from) - if amountFrom < amount { - return false - } - if amountFrom == amount { - storage.Delete(ctx, from) - } else { - diff := amountFrom - amount - storage.Put(ctx, from, diff) - } - amountTo := getIntFromDB(ctx, to) - totalAmountTo := amountTo + amount - if totalAmountTo != 0 { - storage.Put(ctx, to, totalAmountTo) - } - return true -} - -// TransferFrom transfers specified amount of token from one user to another. -// It differs from Transfer in that it use allowance value to store the amount -// of token available to transfer. -func TransferFrom(from, to []byte, amount int) bool { - if trigger != runtime.Application { - return false - } - if amount <= 0 { - return false - } - availableKey := append(from, to...) - if len(availableKey) != 40 { - return false - } - availableTo := getIntFromDB(ctx, availableKey) - if availableTo < amount { - return false - } - fromBalance := getIntFromDB(ctx, from) - if fromBalance < amount { - return false - } - toBalance := getIntFromDB(ctx, to) - newFromBalance := fromBalance - amount - newToBalance := toBalance + amount - storage.Put(ctx, to, newToBalance) - storage.Put(ctx, from, newFromBalance) - - newAllowance := availableTo - amount - if newAllowance == 0 { - storage.Delete(ctx, availableKey) - } else { - storage.Put(ctx, availableKey, newAllowance) - } - return true -} - -// Approve stores token transfer data if the owner has enough token to send. -func Approve(owner, spender []byte, amount int) bool { - if !checkOwnerWitness() || amount < 0 { - return false - } - if len(spender) != 20 { - return false - } - toSpend := getIntFromDB(ctx, owner) - if toSpend < amount { - return false - } - approvalKey := append(owner, spender...) - if amount == 0 { - storage.Delete(ctx, approvalKey) - } else { - storage.Put(ctx, approvalKey, amount) - } - return true -} - -// Allowance returns allowance value for specified sender and receiver. -func Allowance(from, to []byte) interface{} { - if trigger != runtime.Application { - return false - } - key := append(from, to...) - return getIntFromDB(ctx, key) -} - -// Mint initial supply of tokens -func Mint(to []byte) bool { - if trigger != runtime.Application { - return false - } - if !checkOwnerWitness() { - return false - } - minted := storage.Get(ctx, []byte("minted")) - if minted != nil && minted.(bool) == true { - return false - } - - storage.Put(ctx, to, token.TotalSupply) - storage.Put(ctx, []byte("minted"), true) - addToCirculation(token.TotalSupply) - return true -} diff --git a/examples/token-sale/token_sale.yml b/examples/token-sale/token_sale.yml deleted file mode 100644 index 979bbc4a2..000000000 --- a/examples/token-sale/token_sale.yml +++ /dev/null @@ -1,13 +0,0 @@ -name: "My awesome token" -sourceurl: https://github.com/nspcc-dev/neo-go/ -supportedstandards: ["NEP-17"] -safemethods: ["balanceOf", "decimals", "symbol", "totalSupply"] -events: -- name: Transfer - parameters: - - name: from - type: Hash160 - - name: to - type: Hash160 - - name: amount - type: Integer