From 13a3da6dad3e1995ef056e0c6cb4d38990dc0e80 Mon Sep 17 00:00:00 2001 From: Joshua Hannan Date: Wed, 3 Jun 2020 15:13:12 -0500 Subject: [PATCH] update dependencies and use example token instead of flow token (#20) * updating dependencies and using example token instead of flow token * updating dependencies * fixing README and example transactions * using better string templating * go mod tidy * make generate contracts --- README.md | 33 ++- contracts/contracts.go | 32 ++ contracts/contracts_test.go | 12 + contracts/go.mod | 10 +- contracts/go.sum | 72 ++++- contracts/internal/assets/assets.go | 34 +-- src/contracts/CustodialDeposit.cdc | 110 ------- src/contracts/ExampleToken.cdc | 198 +++++++++++++ src/transactions/burn_tokens.cdc | 21 +- src/transactions/create_minter.cdc | 25 -- src/transactions/custodial_deposit.cdc | 52 ---- src/transactions/mint_tokens.cdc | 34 +-- src/transactions/setup_account.cdc | 22 +- src/transactions/transfer_tokens.cdc | 8 +- test/go.mod | 7 +- test/go.sum | 60 ++-- test/templates.go | 141 +++++---- test/test.go | 2 +- test/token_test.go | 394 ++++++++----------------- 19 files changed, 634 insertions(+), 633 deletions(-) delete mode 100644 src/contracts/CustodialDeposit.cdc create mode 100644 src/contracts/ExampleToken.cdc delete mode 100644 src/transactions/create_minter.cdc delete mode 100644 src/transactions/custodial_deposit.cdc diff --git a/README.md b/README.md index d9f4a81d..ae6cef4f 100644 --- a/README.md +++ b/README.md @@ -45,9 +45,12 @@ The feedback we are looking for is: ## Basics of the Standard: -The code for the standard is in `src/contracts/FungibleToken.cdc`. An example implementation of the standard that simulates what a simple FlowToken would be like is in `src/contracts/FlowToken.cdc`. +The code for the standard is in `src/contracts/FungibleToken.cdc`. An example implementation of the standard that simulates what a simple token would be like is in `src/contracts/ExampleToken.cdc`. + +The exact smart contract that is used for the official Flow Network Token is in `src/contracts/FlowToken.cdc` Example transactions that users could use to interact with fungible tokens are located in the `src/transactions/` directory. +Go transaction templates are in the `test/templates.go` file. These templates are mostly generic and can be used with any fungible token implementation by providing the correct addresses, names, and values. The standard consists of a contract interface called `FungibleToken` that requires implementing contracts to define a `Vault` resource that represents the tokens that an account owns. Each account that owns tokens will have a `Vault` stored in its account storage. Users call functions on each other's `Vault`s to send and receive tokens. @@ -60,7 +63,7 @@ Right now we are using unsigned 64-bit fixed point numbers `UFix64` as the type - `pub var totalSupply: UFix64` - The only required field of the contract. It would be incremented when new tokens are minted and decremented when they are destroyed. - Event that gets emitted when the contract is initialized - - `pub event FungibleTokenInitialized(initialSupply: UFix64)` + - `pub event TokensInitialized(initialSupply: UFix64)` 2- Retrieving the token fields of a `Vault` in an account that owns tokens. @@ -71,7 +74,7 @@ Right now we are using unsigned 64-bit fixed point numbers `UFix64` as the type 3- Withdrawing a specific amount of tokens *amount* using the *withdraw* function of the owner's `Vault` - Provider interface - - `pub fun withdraw(amount: UFix64): @Vault` + - `pub fun withdraw(amount: UFix64): @FungibleToken.Vault` - Conditions - the returned Vault's balance must equal the amount withdrawn - The amount withdrawn must be less than or equal to the balance @@ -81,12 +84,12 @@ Right now we are using unsigned 64-bit fixed point numbers `UFix64` as the type - Indicates how much was withdrawn and from what account the `Vault` is stored in. If the `Vault` is not in account storage when the event is emitted, `from` will be `nil`. - - `pub event withdraw(amount: UFix64, from: Address?)` + - `pub event TokensWithdrawn(amount: UFix64, from: Address?)` 4 - Depositing a specific amount of tokens *from* using the *deposit* function of the recipient's `Vault` - `Receiver` interface - - `pub fun deposit(from: @Vault)` + - `pub fun deposit(from: @FungibleToken.Vault)` - Conditions - `from` balance must be non-zero - The resulting balance must be equal to the initial balance + the balance of `from` @@ -94,16 +97,20 @@ Right now we are using unsigned 64-bit fixed point numbers `UFix64` as the type - Indicates how much was deposited and to what account the `Vault` is stored in. If the `Vault` is not in account storage when the event is emitted, `to` will be `nil`. - - `pub event Deposit(amount: UFix64, to: Address?)` -- Users could create custom `Receiver`s to trigger special code when transfers to them happen. + - `pub event TokensDeposited(amount: UFix64, to: Address?)` +- Users could create custom `Receiver`s to trigger special code when transfers to them happen, like forwarding the tokens + to another account, splitting them up, and much more. + +- **ATTENTION**: It is VITALLY important that if you are making your own implementation of the fungible token interface that + you cast the input to `deposit` as the type of your token. + `let vault <- from as! @ExampleToken.Vault` + Because the interface specifies the argument as `@FungibleToken.Vault`, any resource that satisfies this can be sent to the deposit function. If you do not cast it as the type of your token, others could deposit different tokens into your Vault maliciously to change the balance. 5 - Creating an empty Vault resource -- `pub fun createEmptyVault(): @Vault` -- Currently have no event -- Defined in the contract, but not in the `Vault` resource. - This means that to create an empty `Vault`, - the caller would always have to call the function in the contract. +- `pub fun createEmptyVault(): @FungibleToken.Vault` +- Defined in the contract + To create an empty `Vault`, the caller calls the function in the contract and stores the Vault in their storage. - Conditions: - the balance of the returned Vault must be 0 @@ -173,7 +180,7 @@ A standard for token metadata is still an unsolved problem in the general blockc To use the Flow Token contract as is, you need to follow these steps: 1. Deploy the `FungibleToken` definition to account `0x02` -2. Deploy the `FlowToken` definition to account `0x03` +2. Deploy the `ExampleToken` definition to account `0x03` 3. You can use the `get_balance.cdc` or `get_supply.cdc` scripts to read the balance of a user's `Vault` or the total supply of all tokens, respectively. 4. Use the `setupAccount.cdc` on any account to set up the account to be able to diff --git a/contracts/contracts.go b/contracts/contracts.go index 8f10199f..363d3573 100644 --- a/contracts/contracts.go +++ b/contracts/contracts.go @@ -11,7 +11,9 @@ import ( const ( fungibleTokenFilename = "FungibleToken.cdc" flowTokenFilename = "FlowToken.cdc" + exampleTokenFilename = "ExampleToken.cdc" defaultFungibleTokenAddress = "02" + tokenForwardingFilename = "TokenForwarding.cdc" ) // FungibleToken returns the FungibleToken contract interface. @@ -33,3 +35,33 @@ func FlowToken(fungibleTokenAddr string) []byte { return []byte(code) } + +// ExampleToken returns the ExampleToken contract. +// +// The returned contract will import the FungibleToken contract from the specified address. +func ExampleToken(fungibleTokenAddr string) []byte { + code := assets.MustAssetString(exampleTokenFilename) + + code = strings.ReplaceAll( + code, + "0x"+defaultFungibleTokenAddress, + "0x"+fungibleTokenAddr, + ) + + return []byte(code) +} + +// TokenForwarding returns the TokenForwarding contract. +// +// The returned contract will import the FungibleToken contract from the specified address. +func TokenForwarding(fungibleTokenAddr string) []byte { + code := assets.MustAssetString(tokenForwardingFilename) + + code = strings.ReplaceAll( + code, + "0x"+defaultFungibleTokenAddress, + "0x"+fungibleTokenAddr, + ) + + return []byte(code) +} diff --git a/contracts/contracts_test.go b/contracts/contracts_test.go index b11f54bd..0a23315e 100644 --- a/contracts/contracts_test.go +++ b/contracts/contracts_test.go @@ -21,3 +21,15 @@ func TestFlowTokenContract(t *testing.T) { assert.NotNil(t, contract) assert.Contains(t, string(contract), addrA.Hex()) } + +func TestExampleTokenContract(t *testing.T) { + contract := contracts.ExampleToken(addrA.Hex()) + assert.NotNil(t, contract) + assert.Contains(t, string(contract), addrA.Hex()) +} + +func TestTokenForwardingContract(t *testing.T) { + contract := contracts.TokenForwarding(addrA.Hex()) + assert.NotNil(t, contract) + assert.Contains(t, string(contract), addrA.Hex()) +} diff --git a/contracts/go.mod b/contracts/go.mod index e91e90b0..a6b7a4f2 100644 --- a/contracts/go.mod +++ b/contracts/go.mod @@ -3,7 +3,15 @@ module github.com/onflow/flow-ft/contracts go 1.14 require ( + github.com/ethereum/go-ethereum v1.9.13 // indirect github.com/kevinburke/go-bindata v3.21.0+incompatible // indirect - github.com/onflow/flow-go-sdk v0.3.0-beta1 + github.com/onflow/cadence v0.4.0 // indirect + github.com/onflow/flow-go-sdk v0.4.0 + github.com/pkg/errors v0.9.1 // indirect github.com/stretchr/testify v1.5.1 + golang.org/x/crypto v0.0.0-20200429183012-4b2356b1ed79 // indirect + golang.org/x/lint v0.0.0-20200130185559-910be7a94367 // indirect + golang.org/x/sys v0.0.0-20200501145240-bc7a7d42d5c3 // indirect + golang.org/x/tools v0.0.0-20200323144430-8dcfad9e016e // indirect + gopkg.in/yaml.v2 v2.2.8 // indirect ) diff --git a/contracts/go.sum b/contracts/go.sum index b668fc4a..8ed99557 100644 --- a/contracts/go.sum +++ b/contracts/go.sum @@ -25,13 +25,16 @@ github.com/antlr/antlr4 v0.0.0-20191217191749-ff67971f8580/go.mod h1:T7PbCXFs94r github.com/antlr/antlr4 v0.0.0-20200503195918-621b933c7a7f h1:0cEys61Sr2hUBEXfNV8eyQP01oZuBgoMeHunebPirK8= github.com/antlr/antlr4 v0.0.0-20200503195918-621b933c7a7f/go.mod h1:T7PbCXFs94rrTttyxjbyT5+/1V8T2TYDejxUfHJjw1Y= github.com/aristanetworks/goarista v0.0.0-20170210015632-ea17b1a17847/go.mod h1:D/tb0zPVXnP7fmsLZjtdUhSsumbK/ij54UXjjVgMGxQ= +github.com/aws/aws-sdk-go v1.25.48/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/btcsuite/btcd v0.0.0-20171128150713-2e60448ffcc6/go.mod h1:Dmm/EzmjnCiweXmzRIAiUWCInVmPgjkzgv5k4tVyXiQ= github.com/c-bata/go-prompt v0.2.3/go.mod h1:VzqtzE2ksDBcdln8G7mk2RX9QyGjH+OVqOCSiVIqS34= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s= +github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.0.1-0.20190104013014-3767db7a7e18/go.mod h1:HD5P3vAIAh+Y2GAxg0PrPN1P8WkepXGpjbUPDHJqqKM= +github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cloudflare/cloudflare-go v0.10.2-0.20190916151808-a80f83b9add9/go.mod h1:1MxXX1Ux4x6mqPmjkUgTP1CdXIBXKX7T+Jk9Gxrmx+U= @@ -44,7 +47,9 @@ github.com/davecgh/go-xdr v0.0.0-20161123171359-e6a2ba005892/go.mod h1:CTDl0pzVz github.com/deckarep/golang-set v0.0.0-20180603214616-504e848d77ea/go.mod h1:93vsz/8Wt4joVM7c2AVqh+YRMiUSc14yDtF28KmMOgQ= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= +github.com/dlclark/regexp2 v1.2.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= github.com/docker/docker v1.4.2-0.20180625184442-8e610b2b55bf/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/dop251/goja v0.0.0-20200219165308-d1232e640a87/go.mod h1:Mw6PkjjMXWbTj+nnj4s3QPXq1jaT0s5pC0iFD4+BOAA= github.com/edsrzf/mmap-go v0.0.0-20160512033002-935e0e8a636c/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= github.com/elastic/gosigar v0.8.1-0.20180330100440-37f05ff46ffa/go.mod h1:cdorVVzy1fhmEqmtgqkoE3bYtCfSCkVyjTyCIo22xvs= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= @@ -52,15 +57,20 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/ethereum/go-ethereum v1.9.9 h1:jnoBvjH8aMH++iH14XmiJdAsnRcmZUM+B5fsnEZBVE0= github.com/ethereum/go-ethereum v1.9.9/go.mod h1:a9TqabFudpDu1nucId+k9S8R9whYaHnGBLKFouA5EAo= +github.com/ethereum/go-ethereum v1.9.13 h1:rOPqjSngvs1VSYH2H+PMPiWt4VEulvNRbFgqiGqJM3E= +github.com/ethereum/go-ethereum v1.9.13/go.mod h1:qwN9d1GLyDh0N7Ab8bMGd0H9knaji2jOBm2RrMGjXls= github.com/fatih/color v1.3.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fjl/memsize v0.0.0-20180418122429-ca190fb6ffbc/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fxamacker/cbor/v2 v2.2.0 h1:6eXqdDDe588rSYAi1HfZKbx6YYQO4mxQ9eC6xYpU/JQ= github.com/fxamacker/cbor/v2 v2.2.0/go.mod h1:TA1xS00nchWmaBnEIxPSE5oHLuJBAVvqrtAnWBwBCVo= github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8= +github.com/go-sourcemap/sourcemap v2.1.2+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/go-test/deep v1.0.5 h1:AKODKU3pDH1RzZzm6YZu77YWtEAq6uh1rLIAQlay2qc= github.com/go-test/deep v1.0.5/go.mod h1:QV8Hv/iy04NyLBxAdO9njL0iVPN1S4d/A3NVv1V36o8= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= @@ -70,6 +80,7 @@ github.com/golang/protobuf v1.3.2-0.20190517061210-b285ee9cfc6c/go.mod h1:6lQm79 github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= +github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= @@ -81,19 +92,21 @@ github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpO github.com/huin/goupnp v0.0.0-20161224104101-679507af18f3/go.mod h1:MZ2ZmwcBpvOoJ22IJsc7va19ZwoheaBk43rKg12SKag= github.com/influxdata/influxdb v1.2.3-0.20180221223340-01288bdb0883/go.mod h1:qZna6X/4elxqT3yI9iZYdZrWWdeFOOprn86kgg4+IzY= github.com/jackpal/go-nat-pmp v1.0.2-0.20160603034137-1fa385a6f458/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= +github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/julienschmidt/httprouter v1.1.1-0.20170430222011-975b5c4c7c21/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/karalabe/usb v0.0.0-20190919080040-51dc0efba356/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU= github.com/kevinburke/go-bindata v3.21.0+incompatible h1:baK7hwFJDlAHrOqmE9U3u8tow1Uc5ihN9E/b7djcK2g= github.com/kevinburke/go-bindata v3.21.0+incompatible/go.mod h1:/pEEZ72flUW2p0yi30bslSp9YqD9pysLxunQDdb2CPM= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= +github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/lithammer/dedent v1.1.0/go.mod h1:jrXYCQtgg0nJiN+StA2KgR7w6CiQNv9Fd/Z9BP0jIOc= github.com/logrusorgru/aurora v0.0.0-20200102142835-e9ef32dff381 h1:bqDmpDG49ZRnB5PcgP0RXtQvnMSgIF14M7CBd2shtXs= github.com/logrusorgru/aurora v0.0.0-20200102142835-e9ef32dff381/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4= -github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/mattn/go-colorable v0.1.0/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= @@ -108,31 +121,32 @@ github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzp github.com/mattn/go-runewidth v0.0.6/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-tty v0.0.3/go.mod h1:ihxohKRERHTVzN+aSVRwACLCeqIoZAWpoICkkvrWyR0= +github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/naoina/go-stringutil v0.1.0/go.mod h1:XJ2SJL9jCtBh+P9q5btrd/Ylo8XwT/h1USek5+NqSA0= github.com/naoina/toml v0.1.2-0.20170918210437-9fafd6967416/go.mod h1:NBIhNtsFMo3G2szEBne+bO4gS192HuIYRqfvOWb4i1E= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= github.com/olekukonko/tablewriter v0.0.2-0.20190409134802-7e037d187b0c/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= -github.com/onflow/cadence v0.0.0-20200419191218-7825e473e791 h1:V6ilrhMhM1OlXPo2P/cadoDRDmngn/xTqRMQ2CQIeg8= -github.com/onflow/cadence v0.0.0-20200419191218-7825e473e791/go.mod h1:T2EWFkpigNIK4Kwn0zWcQbDXrVpjstyRXML/lK8qltY= -github.com/onflow/cadence v0.3.0-beta1 h1:hvCoaDfGRCWbS+M6S+5uyh9CRjd7uGJvOtuPB4oYrh4= -github.com/onflow/cadence v0.3.0-beta1/go.mod h1:GaLQ7IsJi5bqpH66GprNs8uoQtperK/xbXXIOq11nZw= -github.com/onflow/flow-go-sdk v0.1.1 h1:+B3boX2msebZc9JnuS0VjaYHG0+USu4dngM+njj1bHQ= -github.com/onflow/flow-go-sdk v0.1.1/go.mod h1:ShDDEC0Nb1PXtb3sGhwnFnbu+Hmib5uDfuC8H383PNE= -github.com/onflow/flow-go-sdk v0.3.0-beta1 h1:HmAqosPHLoNmYfhUECsSFpvSD4kWIkJ+Xs8LAJijKDc= -github.com/onflow/flow-go-sdk v0.3.0-beta1/go.mod h1:8v6vcYGh5/PtYcM3IXflLcCb00I91WDbnNF8SjirnlI= -github.com/onflow/flow/protobuf/go/flow v0.1.3/go.mod h1:kRugbzZjwQqvevJhrnnCFMJZNmoSJmxlKt6hTGXZojM= -github.com/onflow/flow/protobuf/go/flow v0.1.4/go.mod h1:kRugbzZjwQqvevJhrnnCFMJZNmoSJmxlKt6hTGXZojM= +github.com/onflow/cadence v0.4.0-beta1 h1:0f4CMnddT++5OYY53OPFuv5JTb85qDg/nygLV4Bk3Z8= +github.com/onflow/cadence v0.4.0-beta1/go.mod h1:gaPtSctdMzT5NAoJgzsRuwUkdgRswVHsRXFNNmCTn3I= +github.com/onflow/cadence v0.4.0 h1:oAKY/HclZZhc5wJgJwdPjWXJuC5IjuuHHVAAq3S7AHI= +github.com/onflow/cadence v0.4.0/go.mod h1:gaPtSctdMzT5NAoJgzsRuwUkdgRswVHsRXFNNmCTn3I= +github.com/onflow/flow-go-sdk v0.4.0 h1:ZNEE8HQ6xTyr4+RmlxZ2+U/BjKtQDsAB54I+D8AJpZA= +github.com/onflow/flow-go-sdk v0.4.0/go.mod h1:MHn8oQCkBNcl2rXdYSm9VYYK4ogwEpyrdM/XK/czdlM= +github.com/onflow/flow/protobuf/go/flow v0.1.5-0.20200601215056-34a11def1d6b/go.mod h1:kRugbzZjwQqvevJhrnnCFMJZNmoSJmxlKt6hTGXZojM= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/opentracing/opentracing-go v1.1.0 h1:pWlfV3Bxv7k65HYwkikxat0+s3pV4bsqf19k25Ur8rU= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/pborman/uuid v0.0.0-20170112150404-1b00554d8222/go.mod h1:VyrYX9gd7irzKovcSS6BIIEwPRkP2Wm2m9ufcdFSJ34= github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7/go.mod h1:CRroGNssyjTd/qIG2FyxByd2S8JEAZXBl4qUrZf8GS0= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/term v0.0.0-20190109203006-aa71e9d9e942/go.mod h1:eCbImbZ95eXtAUIbLAuAVnBnwf83mjf6QIVH8SHYwqQ= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -172,23 +186,39 @@ github.com/syndtr/goleveldb v1.0.1-0.20190923125748-758128399b1d/go.mod h1:9OrXJ github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/wsddn/go-ecdh v0.0.0-20161211032359-48726bab9208/go.mod h1:IotVbo4F+mw0EzQ08zFqg7pK3FebNXpaMsRy2RT+Ees= +github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= +github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +go.uber.org/goleak v1.0.0 h1:qsup4IcBdlmsnGfqyLl4Ntn3C2XCCuKAE7DwHpScyUo= +go.uber.org/goleak v1.0.0/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20200117160349-530e935923ad h1:Jh8cai0fqIK+f6nG0UgPW5wFk8wmiMhM3AyciDBdtQg= -golang.org/x/crypto v0.0.0-20200117160349-530e935923ad/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200311171314-f7b00557c8c4/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200423211502-4bdfaf469ed5 h1:Q7tZBpemrlsc2I7IyODzhtallWRSm4Q0d09pL6XbQtU= golang.org/x/crypto v0.0.0-20200423211502-4bdfaf469ed5/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200429183012-4b2356b1ed79 h1:IaQbIIB2X/Mp/DKctl6ROxz1KyMlKp4uyvL6+kQ7C88= +golang.org/x/crypto v0.0.0-20200429183012-4b2356b1ed79/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20200130185559-910be7a94367 h1:0IiAsCRByjO2QjX7ZPkw5oU9x+n1YqRL802rjC0c3Aw= +golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.2.0 h1:KU7oHjnv3XNWfa5COkzUifxZmxp1TyI7ImMXqFxLwvQ= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200301022130-244492dfa37a h1:GuSPYbZzB5/dcLNCwLQLsg3obCJtX9IJhpXkvY7kzk0= +golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -204,7 +234,11 @@ golang.org/x/sys v0.0.0-20190712062909-fae7ac547cb7/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae h1:/WDfKMnPU+m5M4xB+6x4kaepxRw6jWvR5iDRdvjHgy8= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200501145240-bc7a7d42d5c3 h1:5B6i6EAiSYyejWfvc5Rc9BbI3rzIsrrXfAQBWnYfn+w= +golang.org/x/sys v0.0.0-20200501145240-bc7a7d42d5c3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= @@ -214,6 +248,14 @@ golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGm golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200323144430-8dcfad9e016e h1:ssd5ulOvVWlh4kDSUF2SqzmMeWfjmwDXM+uGw/aQjRE= +golang.org/x/tools v0.0.0-20200323144430-8dcfad9e016e/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -226,10 +268,12 @@ google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKa gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce/go.mod h1:5AcXVHNjg+BDxry382+8OKon8SEWiKktQR07RKPsv1c= gopkg.in/olebedev/go-duktape.v3 v3.0.0-20190213234257-ec84240a7772/go.mod h1:uAJfkITjFhyEEuUfm7bsmCZRbW5WRq8s9EY8HZ6hCns= +gopkg.in/olebedev/go-duktape.v3 v3.0.0-20200316214253-d7b0ff38cac9/go.mod h1:uAJfkITjFhyEEuUfm7bsmCZRbW5WRq8s9EY8HZ6hCns= gopkg.in/sourcemap.v1 v1.0.5/go.mod h1:2RlvNNSMglmRrcvhfuzp4hQHwOtjxlbjX7UPY/GXb78= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/urfave/cli.v1 v1.20.0/go.mod h1:vuBzUtMdQeixQj8LVd+/98pzhxNGQoyuPBlsXHOQNO0= @@ -237,6 +281,8 @@ gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/contracts/internal/assets/assets.go b/contracts/internal/assets/assets.go index 855c4ada..ed2dd425 100644 --- a/contracts/internal/assets/assets.go +++ b/contracts/internal/assets/assets.go @@ -1,6 +1,6 @@ // Code generated by go-bindata. DO NOT EDIT. // sources: -// ../src/contracts/CustodialDeposit.cdc (3.533kB) +// ../src/contracts/ExampleToken.cdc (7.102kB) // ../src/contracts/FlowToken.cdc (7.074kB) // ../src/contracts/FungibleToken.cdc (7.306kB) // ../src/contracts/TokenForwarding.cdc (1.954kB) @@ -73,23 +73,23 @@ func (fi bindataFileInfo) Sys() interface{} { return nil } -var _custodialdepositCdc = "\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xa4\x56\x4b\x6f\xe3\x36\x10\xbe\xeb\x57\x0c\x50\xa0\xb0\x03\xdb\x5a\xb4\x45\x0f\x81\xbb\xe8\x6b\x03\xec\x6d\xd1\x4d\xd3\x33\x2d\x8d\x24\x22\x32\x29\x90\x23\x3f\x1a\xe4\xbf\x17\x43\x52\x12\x29\xdb\xdb\xb4\xeb\x43\xec\x48\x9c\x6f\xbe\xf9\xe6\xc5\xfc\xee\x2e\xcb\xbe\x81\xc7\x06\xe1\xb7\xde\x92\x2e\xa5\x68\xe1\x77\xec\xb4\x95\x04\x78\x12\xfb\xae\x45\x28\xb4\x22\x23\x0a\xca\xb2\x5f\xd4\xc5\x43\xa8\xb4\x01\x51\x14\xd8\x91\x54\x35\x94\xde\xd6\x42\x65\xf4\x1e\x84\x3a\x43\x6f\xd1\x64\x56\x03\x35\x82\x40\x40\x31\xba\xb1\x68\x0e\xb2\x60\xa4\xbe\x2d\xa1\x30\x58\x4a\x02\xe2\x83\x28\x1d\xa4\xee\x15\x6d\xb2\xec\xb1\x91\x16\xa4\x05\x31\x39\x97\xfc\x77\x8f\x8a\x04\x49\xad\x40\x57\x20\x22\xfe\x06\x0b\x94\x07\x34\x13\xf1\x0b\xdf\x01\x1d\x8e\x92\x1a\x06\xd6\x55\xb5\x2e\x1a\x21\x15\x88\xae\x83\x42\x28\xa6\xcd\x64\x7c\x64\x59\x1a\x16\x9e\x08\x8d\x9a\x60\x98\xdb\x14\x41\x83\xfb\x10\x06\x18\x6c\xf1\x20\x14\x65\x2c\xc2\xe8\x74\x74\x96\x65\x77\x79\x96\xc9\x7d\xa7\x0d\xc1\x43\xaf\x6a\xb9\x6b\xf1\x51\x3f\xa3\xf2\x7e\xde\x9d\xde\x7d\x37\xbe\x6e\xf5\x31\x7d\xf5\x7d\x96\x75\xfd\x6e\x4a\xc4\x28\xc0\x90\xbf\x97\x2c\x03\x00\xc8\x73\xf8\x70\x40\x45\x3e\x03\xd2\x02\xee\x25\x11\x96\x70\x6c\x50\x39\x9a\x23\x84\xb4\x1c\x85\x20\x2c\x9d\x25\xc3\xa3\x33\xfd\xa8\x24\x49\xd1\xca\xbf\xb1\x5c\x48\xff\xfb\x73\xdf\x75\xed\xf9\x1e\xfe\x7c\x90\xa7\x1f\x7f\x58\xbe\xc9\x17\xf3\xb7\x20\x0c\x3a\xe1\x4b\x23\x8e\x21\x1c\x01\x4f\xa2\x6f\x69\xe6\xf5\xaf\x70\x68\x21\xf6\x2c\xdc\xff\xf5\x15\x92\x87\xa5\x4b\xe8\x55\x4f\x8f\xa2\xae\xb1\x0c\xc2\xcd\xdc\xad\x80\x44\x7d\x0f\x9f\xc9\x48\x55\x07\xdf\x6c\x69\xd0\xea\xde\x14\x08\x52\x11\x9a\x4a\x14\x38\x74\xce\xa7\x7e\xd7\xca\x02\x5e\xdc\xd1\xe1\x78\xd5\x2b\x06\x8a\xdc\x70\xe4\xf7\xf0\x73\x92\xf8\x8d\x63\x37\x73\xc9\x10\xaf\x57\x1c\x07\xa0\x3f\xc2\xff\xf7\x69\x0d\x6d\x3e\x19\x7d\x90\x25\x9a\xd5\x05\xaf\x91\x58\x9e\xc3\x83\xc4\xd6\x29\xd3\x68\xfe\x6e\x10\x0e\x4c\xc1\xab\xca\xcf\xac\x7b\x18\xf4\x74\x4f\x3b\xd4\xdc\x85\x41\xd7\x24\xca\x16\xc9\xdb\x73\x60\x43\xc9\xfa\xa0\x12\xaf\x89\x12\xd1\x8b\x84\x59\xaf\x0a\xd7\xdf\xce\xe9\xd8\x82\x21\x83\x2c\xbb\xef\x32\x4b\xda\x60\x19\xe5\x35\xd8\x73\x53\x72\x4d\xf8\xd1\xe1\xf2\xec\xfa\xdd\x85\x23\x6a\x37\xb9\xf8\xb7\x9b\x50\x57\x28\x7c\x5d\xd6\xa2\xf4\xf3\x87\x89\xdc\x28\x33\x46\xdc\xec\x44\x2b\x54\x81\x01\x83\x44\x48\xfb\xf0\xb1\xd8\x56\x1b\x27\xec\xa6\x4c\x88\x6c\xd7\xfc\x3d\x1d\x7e\x4d\x64\x1e\xda\xec\x4d\x0a\x93\x78\x46\xa7\x15\x17\x74\xcd\x03\xcb\x11\x04\xe1\x1e\x0a\x53\xf7\x3c\x72\xe7\x0a\x0f\x2e\x42\x6d\x04\x1b\xd7\xd5\x2c\xae\x53\x66\x13\x1b\x7d\xa4\x30\x64\x38\x95\x0a\x8f\x40\xc8\x23\x4e\x98\x73\x48\xec\xd0\xcf\xbd\xc5\xb1\x30\x93\xda\x69\x10\xf6\x5a\xe1\x79\x3c\xb9\x43\xde\x3d\x64\x84\xb2\x15\x1a\x83\xe5\x86\xbd\x18\xa4\xde\x28\x5f\xbe\x0a\x8f\xed\x39\x06\x09\x73\x6e\x70\xa9\xc7\x41\x88\xa7\xc0\xa0\x10\x6d\x8b\x25\x58\x0d\x92\xdc\x4a\xd8\x45\xa3\x24\x86\xc2\xd6\xe2\xb1\x41\x83\x9b\x2f\x55\xd1\xf1\xc6\x30\xbb\x5e\x4b\xd7\xaa\xe7\x62\x1c\xfa\xef\xb4\x50\x7c\xd0\xb0\x5d\x47\x15\x73\xe1\x7a\x6e\x98\x16\x4d\x8d\xf4\xab\xaf\xc6\x1b\x65\x13\x0b\x1b\xea\x96\x77\xf0\xcd\x5e\x1c\x24\x98\x80\x17\xcb\x21\xfe\x59\xa0\x81\x7e\x44\x7e\x37\xa3\x12\x71\xe5\x4d\xe4\xd6\xd1\xd3\xf5\x89\x33\xef\xc1\x09\x15\xb6\x6b\x18\x0d\xaf\x41\x97\x68\xc9\xe8\xf3\x62\x0e\x11\x9e\x47\x50\x91\x75\x84\xc1\xf7\x06\x6b\x17\x7c\x6c\xe9\x62\x97\xe3\x06\x9d\x4d\xed\xc5\x8d\x71\x19\x7b\xe6\xa9\x3a\x08\xfd\x13\xa4\xba\x64\x49\x74\xc3\xb5\xc9\x8a\x03\x2e\x12\xe6\xdb\xb5\x2f\xf9\xf9\xd6\x88\x05\xdc\xae\x1d\xf6\x72\x95\x58\x92\xbe\x87\x9c\x13\x2b\x6a\xcc\xcb\xd4\x7a\x3c\xb8\xbc\x41\xa4\x95\xea\x79\xfb\xed\x4b\xb2\x81\x5e\xdf\xa7\xd4\xf2\xce\x3d\x9e\x63\xfb\xc3\x33\x2e\xc2\xd4\x48\xff\x8d\x8f\x6b\x9e\x2f\xdc\x60\x82\x92\xc9\x9e\xcd\x73\x77\x29\xe6\x93\x9c\x3e\x3f\x25\xd3\xb1\x25\x95\xa5\xb8\xf4\x67\xba\x8e\x6b\x7a\xc0\xe3\x61\xe9\xda\xc3\xf2\x40\xe1\xab\x66\xb8\x0f\x86\x50\x56\x7c\x71\xa1\x06\x0d\x68\x03\x4a\xd3\xb8\xe8\x2e\x80\x5a\x83\xa2\x3c\x03\x9e\xa4\x25\xcb\x48\x01\x21\x1b\x9b\x62\x39\x5b\xf2\x8f\x3a\x2a\xc0\x6b\x6c\x57\xe9\x72\x7e\xc6\x8b\x6e\x06\xdd\xf3\xd5\x75\xf0\xe5\xc2\xe1\x4b\xb2\xa4\xc4\x56\x1b\x90\x15\x28\x1d\x6e\x11\xd2\x06\x90\x55\x50\x2f\x88\x87\xfb\x8e\xce\xfe\x4c\xd4\xcf\x95\xab\x74\x6f\xf0\x34\xf4\x69\x5a\x4e\x5a\x94\xdb\x79\xab\xbc\x0f\xbb\x70\x2c\x8a\x6a\x78\x7f\x7b\x0c\xfc\x6b\x3f\x6e\xd7\x11\x8f\x68\x54\xba\x71\x3f\x43\x64\xd6\x0a\x8f\x1f\x38\xa8\x81\xf7\xc4\xd1\x07\x3e\xbd\x5c\x5c\x59\xed\x6f\xa0\x93\x38\x58\x5e\x8c\x9d\xd7\xec\x9f\x00\x00\x00\xff\xff\x01\xf1\xcd\x08\xcd\x0d\x00\x00" +var _exampletokenCdc = "\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xb4\x59\xcd\x72\x23\xb7\x11\xbe\xeb\x29\x3a\x3e\x24\x54\x59\xa2\x98\x54\x2a\x07\x95\xd6\x5e\x6d\xa2\xad\xf2\x21\xae\x94\xb3\x49\xae\xc2\xcc\x34\x49\x44\x33\x00\x0b\xc0\x90\xa2\x55\x7a\x77\x57\x37\x7e\x06\x18\x0e\x29\xc9\xda\xdd\x83\xbd\x1c\xa0\x7f\xd0\xfd\x75\xf7\x07\xac\xec\x36\xda\x38\xf8\xdc\xab\x95\xac\x5a\xfc\xa2\x1f\x50\xc1\xd2\xe8\x0e\x16\x8f\x8b\xbf\x9c\x9d\x6d\xfa\x0a\x6a\xad\x9c\x11\xb5\x83\xbb\x47\xd1\x6d\xc2\xa6\xeb\x91\xcc\xd3\xd9\x19\x00\xc0\xd5\x15\x7c\xd1\x4e\xb4\x60\xfb\xcd\xa6\xdd\x83\x5e\x16\x52\x16\xa4\x02\x7c\x94\xd6\xa1\xaa\x91\x25\xc8\xc2\x56\x18\x70\x24\xf6\x6f\x96\xba\x86\xff\x7c\x96\x8f\x7f\xfb\x6b\x52\x79\xb7\x45\xe5\xc0\xad\x85\x03\x69\x01\x3b\xe9\x1c\x36\xb0\x5b\xa3\x02\xb7\xc6\xc1\x41\x69\xa1\x36\x28\x1c\x36\x49\x35\xb2\xa8\x37\xfe\x93\x92\x4e\x8a\x56\xfe\x8a\xcd\x4c\xfa\xbf\x97\x06\xcf\x5f\x65\xd1\x1f\x44\x18\x84\x9d\x74\xeb\xc6\x88\x5d\x08\x99\x80\xff\x8a\xbe\x75\x93\xb6\xff\x17\xb7\xce\x44\xa7\x7b\xe5\xa2\xc9\x0b\x16\xbd\x86\xdb\xa6\x31\x68\xed\x8f\x6f\x75\xa1\xc1\x8d\xb6\x92\x56\x9c\x3e\xe9\xc0\x3f\xe2\xc6\x03\x07\x9c\x7e\xa3\x79\x85\xbb\xdc\x85\x4e\xaa\x63\x11\xff\x27\x2f\x8d\x2c\xbe\xfd\x88\xd6\x19\xbd\x3f\x62\xe2\x53\x6f\xd4\xef\x33\x21\xf8\x20\xec\xbd\x01\x83\x56\xf7\xa6\xc6\xe3\x18\xe2\xb3\x98\xbf\xfb\xb5\x99\x68\x5b\xbd\xc3\xe6\xf6\xf7\x9a\xad\xc8\xed\xd7\x98\xe5\xf3\x25\xb3\x83\x85\x21\xd3\x57\x57\xc9\xaa\xa8\xd7\xd0\x5b\x34\x60\x9d\x36\x68\x41\x28\x90\xca\x3a\xa1\x6a\xa4\x52\xd4\xaa\xdd\x73\xc5\xb0\x30\xd5\xa2\x5b\xa3\xf4\xbb\xc5\x0a\x53\x05\xaf\x11\x96\xbd\xaa\x9d\xd4\xbe\x62\x07\x11\xa1\x1a\x58\xe9\x2d\x52\xcc\xa1\xf2\xca\x36\x06\xf9\xfb\x46\x5b\x47\xb5\xd8\x48\x16\x8c\xda\xa4\x1a\xb5\x8a\x58\xb7\x7b\xce\x6e\x2d\xda\x16\x9b\x79\x6e\xbb\x5e\x63\xfd\x60\x61\x2d\x36\x1b\x8a\x97\x03\xd3\x2b\x27\x3b\x64\x49\xdc\xa2\x01\x91\xfc\xe3\xc0\x15\x2a\xa2\xa6\x5f\x42\x68\x69\x5d\xf9\xa3\x57\x18\x83\x1c\x4f\x45\xad\x03\x1f\x1d\x05\xa7\xe8\x24\x9c\x39\xf2\x31\x6a\xf3\x40\x5c\x4a\xc5\xb2\x17\x60\x35\x2d\x1b\x4e\x9c\xd2\xb0\x13\x7b\x58\x6a\x72\xac\x13\xad\xac\xa5\xee\xad\x4f\x84\xd3\xc1\xa4\x0f\x60\x8a\x8a\xee\x83\x51\xa9\x40\x48\x33\x87\x5b\xb0\x1b\xac\xa5\x68\x03\xd0\x06\x68\x28\xc4\xc6\x92\xa2\x6a\x70\xc1\x69\x06\x6e\xd4\x36\x54\x64\x11\x05\x42\x51\x52\xc3\xf6\x47\x6d\x7b\xfe\x2f\xa3\xb7\xb2\x41\x73\x31\xfa\xfe\x0b\xd6\x28\xb7\x87\xdf\x3f\x89\x96\xc1\x14\xda\x7d\x30\xbf\xd6\x2d\x79\xb8\x46\xa8\xc2\xba\x5e\x82\xe0\x00\xd8\xe0\x57\xda\x1e\xfb\x7d\xd8\x59\xf6\xfa\x04\x99\xd8\xa8\x0b\xa5\x84\x84\x78\x1a\x0e\x2a\xe5\x9f\x80\x91\x64\x49\x70\x36\xd2\x7c\x0e\x4f\x69\x9d\xfe\x58\x6c\x97\xf3\xa8\xf2\x43\x54\x9e\xb6\x3c\x17\x9e\xc4\x0e\x9f\x7d\xcb\x97\x3f\x47\x14\x7a\xbc\x88\x87\x58\x73\x0e\x57\x04\x53\xee\x0e\x20\xf8\xa3\x30\xab\xbe\xc3\x90\xb3\x88\x2a\xd5\x24\x13\xd6\x2b\x09\x32\x3c\x50\x52\xdd\xcd\x73\xa1\x9f\x5c\x80\x94\x0d\xbd\xc4\x21\x4d\x71\x61\xf6\xa1\x48\x63\xdb\xe9\xad\x47\x0a\xa5\x27\x57\x40\x6a\x3b\xad\x70\x9f\x76\x56\x28\xd5\x0a\x9c\x11\xca\x2e\xd1\x18\x6c\xe6\x64\xc5\xa0\xeb\x8d\xf2\x89\x55\xb8\x6b\xf7\xb9\x92\x58\x48\xc1\xa4\x2e\xca\x89\xf5\xfa\xb2\xa4\x4a\x91\x8e\x6b\xb0\xca\xc6\x55\xae\x0a\x5b\x8b\x3b\x2a\xa6\xf9\x54\x98\x09\x30\xcb\x5e\xa5\x38\x8d\x5b\xfd\x35\x7c\x2c\x31\xea\x3d\x3a\x99\xf4\xe2\xe7\x65\x88\x79\x21\x40\x2d\xfb\xe8\xe8\xf6\xff\x8f\xa3\x9b\x95\xe9\x9d\x42\xf3\xe3\x5c\xf8\x39\x7a\x5e\xe8\xf2\x71\x84\x9b\xcb\xbc\x13\x0c\x30\xf5\xda\xce\x8f\x20\x30\x44\xec\x2d\x00\x0c\x39\xd1\xd5\xff\xb1\x1e\xa3\x8f\x21\x27\x9a\xc6\x16\xf5\xe6\x6c\x2a\xb2\x90\xc9\xac\x90\xe9\x27\x1f\xcf\x4e\x83\x51\x5a\x08\xd3\x90\x84\xc3\xb4\x66\x29\x4b\x06\xbd\x33\x15\xd6\xa2\xb7\x38\x40\xba\xa8\x32\xf2\x31\x83\x31\x01\x16\x4d\xb4\x1d\x1a\x1b\x8f\x06\x16\xfd\xd3\xe0\xed\x5a\x14\x07\xa9\x10\x15\x81\xd0\xf6\x1d\x36\x7c\x54\x6e\xd2\x4b\xcd\x83\x26\x20\x30\xb0\x89\xf9\x01\xc2\x42\xa8\x67\x3e\xad\x53\xa8\x1a\xf7\x92\x16\x1d\x6c\xf9\x7c\x37\x97\x81\x03\xda\x3f\xc0\xc7\x9c\xf2\xce\xcb\xd3\xbe\x04\xc6\xef\xbd\xbe\xf9\xb8\x2d\x8d\x30\x79\xc8\xe6\x0a\x31\x4f\xea\x5e\x04\x66\x21\x03\x1f\x60\x31\x5f\x14\xeb\x31\x97\xdb\xe2\x08\x19\x3e\xc3\x86\xd9\x38\x2e\x45\x00\x32\x66\x0f\x1f\x8e\x2f\x5d\x16\x81\xc8\xac\x65\x36\x53\xdf\xb9\xeb\x36\x6e\x3f\x45\x81\xca\x82\x28\xfb\xa4\x47\x22\xf5\x11\x10\x39\xc0\x7f\x45\xa3\xd3\x9c\x57\x4d\xea\x7b\x72\xe8\x6b\xa2\x6d\xa9\x43\x86\xfe\x46\xd3\x9a\xa7\x7b\xd7\x5b\xdf\xe7\x68\x90\xdb\x44\x4a\x72\x65\xcc\xc4\x58\x89\x57\x9b\x5a\xe6\x98\x7d\xd1\x07\x6d\x1a\xcf\x19\xb8\xa0\xfc\x7a\x52\x56\xd7\x3c\x19\x3c\x11\x10\x55\xcb\xb5\x6a\xfc\xa0\x8e\xd8\xb5\x81\x54\x84\xb1\x0b\x6e\xbf\xc1\x03\x4a\x40\x58\x1f\x87\x71\xf6\x72\x1f\x7d\xa1\x8d\x2d\xe6\x8b\xf3\x3c\x57\x05\xf9\xb8\x6d\x3a\xa9\xa4\x75\x46\x38\x6d\x32\x9d\x29\xa1\x3f\xe3\xce\xf3\x9e\x57\x35\xba\x94\xd7\x2c\x5b\x93\x74\xfe\xd4\x40\x19\x19\x3e\x42\xe9\xaf\xe1\x63\x20\x64\x4f\x87\xc5\x78\xf2\x4e\x50\xfc\x3c\x3d\x11\xa6\x3d\x38\xa2\xa0\x9c\x0f\xe9\x14\xfe\xa2\xf0\xce\xf0\x8d\xae\x25\xaf\x0a\x9f\x37\xcc\x00\xf2\x7f\x9d\x8a\xd4\xf8\x1a\x73\x2a\x1a\x51\xe1\xd1\x1e\x90\x21\xe5\x90\xef\xc7\xb9\xe7\x27\x22\x57\x81\x20\xf4\xc5\x02\xf2\xf7\x01\x1a\x31\x91\x45\xbf\x8a\x3e\x27\x10\x8c\x99\x54\x20\x6c\x54\x77\xfe\xce\x1a\xef\x0e\x11\x8b\xe5\x7c\x4c\xb4\x1d\x32\x32\x3c\x09\xbd\xc2\x12\x89\x7d\x29\x99\xf4\xa9\x0c\xd3\x76\x9b\x9d\xeb\x82\x67\x3e\x79\xd5\xc5\x9e\xe6\xb2\x77\x9a\x8b\x31\x29\xcd\xa8\x5f\x77\xac\x09\x9e\x02\xc7\xe0\xee\x04\x5d\x3b\x1c\x8f\x23\xc4\xd0\x8d\xb2\xfc\x42\x7f\x42\xa0\x7f\x08\x9a\x66\x8b\xf3\x6b\xf8\xce\x87\x2c\xbc\x41\xf8\x7e\x5c\x21\xac\x18\x48\x86\x62\xa1\xb8\xbd\x7f\x77\x4c\xdb\x4d\x98\xbf\xa3\x0c\x1c\xd1\xdb\xa2\xb5\x5e\x29\x67\x3e\x64\xd5\xab\x2a\x4d\x3c\xbf\x7b\x1e\x7e\x3f\x45\x4b\x0f\x7d\x85\xa9\x03\xbc\xc8\x69\x47\x0f\x33\x63\x0a\x0a\xef\x62\xad\x7c\x0b\x9b\xee\xa6\x53\xb4\x7c\x7c\x9c\xe2\xf7\x41\x0f\xa0\xff\xc6\x92\xcf\x5a\xde\x7b\xfb\x00\x35\xbe\x17\x7b\x40\x6a\x6f\x05\xe7\xec\x8d\x7a\x43\x65\x06\xca\x34\xd0\xf4\xf8\x40\x73\x01\xb8\x5c\x62\xed\xe4\x16\xdb\x3d\x6b\xe5\x3b\xd9\x40\x80\x8f\xa8\xff\x59\x3b\xbc\xf6\x9c\xdd\xd3\x8b\xec\xe9\x4c\xf4\x4e\x77\xc2\x49\x2a\xdd\x3d\xd8\xbe\xe2\xd7\x0d\x6c\x86\xeb\x65\xd1\xcd\xf2\x97\xdb\xe2\xd9\x87\x9d\xee\x6b\xa7\xcd\xc9\xaa\x1f\x42\xf1\xcd\x39\x34\x49\x89\x88\x98\xe3\x94\x79\x9a\xc1\x8e\x8a\x61\xf4\x84\x78\x88\xec\x0c\xdf\x8c\xed\xfc\x08\x0c\xe1\xb2\xa4\xff\xbc\x58\x10\x93\xce\x43\xeb\x07\x5f\x16\x51\x66\xa1\xe3\x36\x9c\x0d\x11\xa6\x8e\x62\x8b\x44\x42\xa5\x2a\x5e\xe8\x46\xc1\x2f\xe2\x37\x5d\xab\x63\x1f\xcf\x4b\xef\x43\x41\xcc\xc9\xde\xec\xe6\x92\x95\xf9\x1b\xc4\x55\xb0\x7b\x85\x59\x36\x7c\x16\xa7\x8e\x27\x08\x09\xad\xac\xa1\x16\x1b\x51\xc9\x56\xba\x7d\x1c\x1e\x4c\x83\x9b\xfc\x81\x82\x5f\xe4\xf0\x71\xa3\x2d\xda\xf1\x4c\xbd\x0f\x74\xf6\x1e\x3a\x74\x6b\x4d\xd7\x38\xa3\xfb\x95\x8f\xd8\x7d\x7c\x9c\xba\xe7\x87\x16\xb3\x14\xd3\x44\xa5\x38\x5b\x2b\xd5\xc3\xcd\x1f\x0f\x41\xf5\x34\xfd\xee\xf5\xfc\xc3\xac\x40\xcb\x95\x3f\x58\x11\x87\xf4\x46\x56\xec\x74\xc2\xac\xd0\x9d\x0a\x5d\xda\xfe\x8d\x63\x18\xd2\x7f\x0f\x4b\x89\xed\x28\x84\x9f\xe2\xda\x57\x8f\x60\xd0\xfc\x9a\x00\x86\xad\x5f\x23\x7e\xdc\x0e\xb8\xbb\x0f\x45\x50\xdc\x39\x66\xa7\x31\xcf\xb2\x27\x30\xcf\xba\xca\x7c\xdd\x51\x03\x11\x2a\x3c\xd3\x73\x3a\xec\x5a\xef\x32\xfe\x97\x5e\x93\x77\xc2\x66\x6f\x9a\xc3\xdb\x57\xd6\x83\x4e\xfc\xdb\xd4\x74\xf5\x3e\x9f\x3d\x9f\xfd\x16\x00\x00\xff\xff\xfb\x0f\xed\xda\xbe\x1b\x00\x00" -func custodialdepositCdcBytes() ([]byte, error) { +func exampletokenCdcBytes() ([]byte, error) { return bindataRead( - _custodialdepositCdc, - "CustodialDeposit.cdc", + _exampletokenCdc, + "ExampleToken.cdc", ) } -func custodialdepositCdc() (*asset, error) { - bytes, err := custodialdepositCdcBytes() +func exampletokenCdc() (*asset, error) { + bytes, err := exampletokenCdcBytes() if err != nil { return nil, err } - info := bindataFileInfo{name: "CustodialDeposit.cdc", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x50, 0x8f, 0x1d, 0xd1, 0xe0, 0xbd, 0x34, 0x85, 0x2e, 0x3e, 0x2d, 0xd9, 0xde, 0xcf, 0xbc, 0xf5, 0xd8, 0x7f, 0xd5, 0x71, 0xd7, 0xba, 0x2c, 0x43, 0xbf, 0xad, 0xaf, 0xbc, 0xfb, 0x8, 0xd4, 0x3b}} + info := bindataFileInfo{name: "ExampleToken.cdc", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x5c, 0x9a, 0xe0, 0x98, 0x98, 0xe6, 0xb7, 0x48, 0xb4, 0x7b, 0x7f, 0xe7, 0xb2, 0x8e, 0xb2, 0x4e, 0x7f, 0xb3, 0xf2, 0x97, 0x88, 0xe7, 0xd3, 0xdd, 0xb5, 0x76, 0x32, 0xd1, 0x47, 0x6c, 0x2b, 0x55}} return a, nil } @@ -244,10 +244,10 @@ func AssetNames() []string { // _bindata is a table, holding each asset generator, mapped to its name. var _bindata = map[string]func() (*asset, error){ - "CustodialDeposit.cdc": custodialdepositCdc, - "FlowToken.cdc": flowtokenCdc, - "FungibleToken.cdc": fungibletokenCdc, - "TokenForwarding.cdc": tokenforwardingCdc, + "ExampleToken.cdc": exampletokenCdc, + "FlowToken.cdc": flowtokenCdc, + "FungibleToken.cdc": fungibletokenCdc, + "TokenForwarding.cdc": tokenforwardingCdc, } // AssetDebug is true if the assets were built with the debug flag enabled. @@ -294,10 +294,10 @@ type bintree struct { } var _bintree = &bintree{nil, map[string]*bintree{ - "CustodialDeposit.cdc": &bintree{custodialdepositCdc, map[string]*bintree{}}, - "FlowToken.cdc": &bintree{flowtokenCdc, map[string]*bintree{}}, - "FungibleToken.cdc": &bintree{fungibletokenCdc, map[string]*bintree{}}, - "TokenForwarding.cdc": &bintree{tokenforwardingCdc, map[string]*bintree{}}, + "ExampleToken.cdc": &bintree{exampletokenCdc, map[string]*bintree{}}, + "FlowToken.cdc": &bintree{flowtokenCdc, map[string]*bintree{}}, + "FungibleToken.cdc": &bintree{fungibletokenCdc, map[string]*bintree{}}, + "TokenForwarding.cdc": &bintree{tokenforwardingCdc, map[string]*bintree{}}, }} // RestoreAsset restores an asset under the given directory. diff --git a/src/contracts/CustodialDeposit.cdc b/src/contracts/CustodialDeposit.cdc deleted file mode 100644 index 92f18f93..00000000 --- a/src/contracts/CustodialDeposit.cdc +++ /dev/null @@ -1,110 +0,0 @@ -/** - -# The Custodial Deposit example contract - -An example contract for accepting deposits from any user -so that a custodial service could credit to their account. - -This is an example implementation of a Custodial receiver contract -that a custodial account with an off-chain app can use to accept -deposits from external accounts and credit them to the relevant -user account off-chain - -*/ - -import FungibleToken from 0x02 -import FlowToken from 0x03 - -pub contract CustodialDeposit { - - // Event that is emitted when the contract is created - pub event Initialized(initialSupply: UFix64) - - // Event that is emitted when tokens are withdrawn from a Vault - pub event Withdraw(amount: UFix64) - - // Event that is emitted when tokens are deposited to a Vault - pub event TaggedDeposit(amount: UFix64, tag: String) - - pub resource interface DepositPublic { - pub fun taggedDeposit(from: @FungibleToken.Vault, tag: String) - } - - pub resource DepositResource: FungibleToken.Provider, DepositPublic { - - // Field to hold the vault that holds the tokens that people deposit - pub let vault: @FlowToken.Vault - - // taggedDeposit - // - // Function that deposits a Vault into the stored Vault - // and emits an event with the tag for the user - // - pub fun taggedDeposit(from: @FungibleToken.Vault, tag: String) { - emit TaggedDeposit(amount: from.balance, tag: tag) - self.vault.deposit(from: <-from) - } - - // withdraw - // - // Function that takes an integer amount as an argument - // and withdraws that amount from the Vault. - // It creates a new temporary Vault that is used to hold - // the money that is being transferred. It returns the newly - // created Vault to the context that called so it can be deposited - // elsewhere. - // - pub fun withdraw(amount: UFix64): @FungibleToken.Vault { - emit Withdraw(amount: amount) - return <-self.vault.withdraw(amount: amount) - } - - // getBalance - // - // returns the balance of the stored Vault - pub fun getBalance(): UFix64 { - return self.vault.balance - } - - init(initVault: @FlowToken.Vault) { - self.vault <- initVault - } - - destroy() { - destroy self.vault - } - } - - access(self) fun initializeDepositResource(vault: @FlowToken.Vault) { - let balance = vault.balance - - self.account.save( - <-create DepositResource(initVault: <-vault), - to: /storage/depositResource - ) - - self.account.link<&{DepositPublic}>( - /public/depositResourcePublic, - target: /storage/depositResource - ) - - emit Initialized(initialSupply: balance) - } - - // The init function creates a new instance of the DepositResource resource - // and stores it in account storage, whether or not a Vault resource - // already exists in storage - init() { - - // To initialize the DepositResource, - // take the stored Vault out of storage and use it, - // or if no vault is stored, create a new empty vault - - if let storedVault <- self.account.load<@FlowToken.Vault>(from: /storage/flowTokenVault) { - self.initializeDepositResource(vault: <-storedVault) - } else { - let newEmptyVault <-FlowToken.createEmptyVault() - self.initializeDepositResource(vault: <-newEmptyVault) - } - } -} diff --git a/src/contracts/ExampleToken.cdc b/src/contracts/ExampleToken.cdc new file mode 100644 index 00000000..a95f2de6 --- /dev/null +++ b/src/contracts/ExampleToken.cdc @@ -0,0 +1,198 @@ +import FungibleToken from 0x02 + +pub contract ExampleToken: FungibleToken { + + // Total supply of ExampleTokens in existence + pub var totalSupply: UFix64 + + // Event that is emitted when the contract is created + pub event TokensInitialized(initialSupply: UFix64) + + // Event that is emitted when tokens are withdrawn from a Vault + pub event TokensWithdrawn(amount: UFix64, from: Address?) + + // Event that is emitted when tokens are deposited to a Vault + pub event TokensDeposited(amount: UFix64, to: Address?) + + // Event that is emitted when new tokens are minted + pub event TokensMinted(amount: UFix64) + + // Event that is emitted when tokens are destroyed + pub event TokensBurned(amount: UFix64) + + // Event that is emitted when a new minter resource is created + pub event MinterCreated(allowedAmount: UFix64) + + // Event that is emitted when a new burner resource is created + pub event BurnerCreated() + + // Vault + // + // Each user stores an instance of only the Vault in their storage + // The functions in the Vault and governed by the pre and post conditions + // in FungibleToken when they are called. + // The checks happen at runtime whenever a function is called. + // + // Resources can only be created in the context of the contract that they + // are defined in, so there is no way for a malicious user to create Vaults + // out of thin air. A special Minter resource needs to be defined to mint + // new tokens. + // + pub resource Vault: FungibleToken.Provider, FungibleToken.Receiver, FungibleToken.Balance { + + // holds the balance of a users tokens + pub var balance: UFix64 + + // initialize the balance at resource creation time + init(balance: UFix64) { + self.balance = balance + } + + // withdraw + // + // Function that takes an integer amount as an argument + // and withdraws that amount from the Vault. + // It creates a new temporary Vault that is used to hold + // the money that is being transferred. It returns the newly + // created Vault to the context that called so it can be deposited + // elsewhere. + // + pub fun withdraw(amount: UFix64): @FungibleToken.Vault { + self.balance = self.balance - amount + emit TokensWithdrawn(amount: amount, from: self.owner?.address) + return <-create Vault(balance: amount) + } + + // deposit + // + // Function that takes a Vault object as an argument and adds + // its balance to the balance of the owners Vault. + // It is allowed to destroy the sent Vault because the Vault + // was a temporary holder of the tokens. The Vault's balance has + // been consumed and therefore can be destroyed. + pub fun deposit(from: @FungibleToken.Vault) { + let vault <- from as! @ExampleToken.Vault + self.balance = self.balance + vault.balance + emit TokensDeposited(amount: vault.balance, to: self.owner?.address) + vault.balance = 0.0 + destroy vault + } + + destroy() { + ExampleToken.totalSupply = ExampleToken.totalSupply - self.balance + } + } + + // createEmptyVault + // + // Function that creates a new Vault with a balance of zero + // and returns it to the calling context. A user must call this function + // and store the returned Vault in their storage in order to allow their + // account to be able to receive deposits of this token type. + // + pub fun createEmptyVault(): @FungibleToken.Vault { + return <-create Vault(balance: 0.0) + } + + pub resource Administrator { + // createNewMinter + // + // Function that creates and returns a new minter resource + // + pub fun createNewMinter(allowedAmount: UFix64): @Minter { + emit MinterCreated(allowedAmount: allowedAmount) + return <-create Minter(allowedAmount: allowedAmount) + } + + // createNewBurner + // + // Function that creates and returns a new burner resource + // + pub fun createNewBurner(): @Burner { + emit BurnerCreated() + return <-create Burner() + } + } + + // Minter + // + // Resource object that token admin accounts can hold to mint new tokens. + // + pub resource Minter { + + // the amount of tokens that the minter is allowed to mint + pub var allowedAmount: UFix64 + + // mintTokens + // + // Function that mints new tokens, adds them to the total supply, + // and returns them to the calling context. + // + pub fun mintTokens(amount: UFix64): @ExampleToken.Vault { + pre { + amount > UFix64(0): "Amount minted must be greater than zero" + amount <= self.allowedAmount: "Amount minted must be less than the allowed amount" + } + ExampleToken.totalSupply = ExampleToken.totalSupply + amount + self.allowedAmount = self.allowedAmount - amount + emit TokensMinted(amount: amount) + return <-create Vault(balance: amount) + } + + init(allowedAmount: UFix64) { + self.allowedAmount = allowedAmount + } + } + + // Burner + // + // Resource object that token admin accounts can hold to burn tokens. + // + pub resource Burner { + + // burnTokens + // + // Function that destroys a Vault instance, effectively burning the tokens. + // + // Note: the burned tokens are automatically subtracted from the + // total supply in the Vault destructor. + // + pub fun burnTokens(from: @FungibleToken.Vault) { + let vault <- from as! @ExampleToken.Vault + let amount = vault.balance + destroy vault + emit TokensBurned(amount: amount) + } + } + + init() { + self.totalSupply = 1000.0 + + // Create the Vault with the total supply of tokens and save it in storage + // + let vault <- create Vault(balance: self.totalSupply) + self.account.save(<-vault, to: /storage/exampleTokenVault) + + // Create a public capability to the stored Vault that only exposes + // the `deposit` method through the `Receiver` interface + // + self.account.link<&ExampleToken.Vault{FungibleToken.Receiver}>( + /public/exampleTokenReceiver, + target: /storage/exampleTokenVault + ) + + // Create a public capability to the stored Vault that only exposes + // the `balance` field through the `Balance` interface + // + self.account.link<&ExampleToken.Vault{FungibleToken.Balance}>( + /public/exampleTokenBalance, + target: /storage/exampleTokenVault + ) + + let admin <- create Administrator() + self.account.save(<-admin, to: /storage/exampleTokenAdmin) + + // Emit an event that shows that the contract was initialized + emit TokensInitialized(initialSupply: self.totalSupply) + } +} diff --git a/src/transactions/burn_tokens.cdc b/src/transactions/burn_tokens.cdc index fe8b40f3..01dfe937 100644 --- a/src/transactions/burn_tokens.cdc +++ b/src/transactions/burn_tokens.cdc @@ -5,29 +5,32 @@ // The burning amount would be a parameter to the transaction import FungibleToken from 0x02 -import FlowToken from 0x03 +import ExampleToken from 0x03 transaction { // Vault resource that holds the tokens that are being burned let vault: @FungibleToken.Vault - let mintAndBurn: &FlowToken.MintAndBurn + let admin: &ExampleToken.Administrator prepare(signer: AuthAccount) { // Withdraw 10 tokens from the admin vault in storage - self.vault <- signer.borrow<&FlowToken.Vault>(from: /storage/flowTokenVault)! - .withdraw(amount: 10.0) + self.vault <- signer.borrow<&ExampleToken.Vault>(from: /storage/exampleTokenVault)! + .withdraw(amount: UFix64(10.0)) - // Create a reference to the admin MintAndBurn resource in storage - self.mintAndBurn = signer.borrow<&FlowToken.MintAndBurn>(from: /storage/flowTokenMintAndBurn) - ?? panic("Could not borrow a reference to the Burn resource") + // Create a reference to the admin admin resource in storage + self.admin = signer.borrow<&ExampleToken.Administrator>(from: /storage/exampleTokenAdmin) + ?? panic("Could not borrow a reference to the admin resource") } execute { - // burn the withdrawn tokens - self.mintAndBurn.burnTokens(from: <-self.vault) + let burner <- self.admin.createNewBurner() + + burner.burnTokens(from: <-self.vault) + + destroy burner } } \ No newline at end of file diff --git a/src/transactions/create_minter.cdc b/src/transactions/create_minter.cdc deleted file mode 100644 index a4f74ed7..00000000 --- a/src/transactions/create_minter.cdc +++ /dev/null @@ -1,25 +0,0 @@ -// This transaction is a template for a transaction that could be used -// by an admin account to create a new MintAndBurn resource -// and store it in another account -// -// Both accounts need to sign the transaction because the transaction needs -// to be able to access both accounts' storage - -import FungibleToken from 0x02 -import FlowToken from 0x03 - -transaction { - - prepare(existingAdmin: AuthAccount, newAdmin: AuthAccount) { - - // Get a reference to the existing admin's MintAndBurn resource in storage - let existingMintAndBurn = existingAdmin.borrow<&FlowToken.MintAndBurn>(from: /storage/flowTokenMintAndBurn)! - - // Use the existing admin's MintAndBurn resource to create a new one - - let newMintAndBurn <- existingMintAndBurn.createNewMinter(allowedAmount: 10.0) - - // Store the new MintAndBurn resource in the new admin's account's storage - newAdmin.save(<-newMintAndBurn, to: /storage/flowTokenMintAndBurn) - } -} diff --git a/src/transactions/custodial_deposit.cdc b/src/transactions/custodial_deposit.cdc deleted file mode 100644 index 7684c9ec..00000000 --- a/src/transactions/custodial_deposit.cdc +++ /dev/null @@ -1,52 +0,0 @@ - -// This transaction is a template for a transaction that could be -//used by anyone to deposit their tokens into a central contract that is -// controlled by a custodial entity like an exchange. -// They would specify a user ID in the transaction so that -// the deposit would emit an event that indicates which account -// should be credited. -// -// The custodial service would simply create this transaction from a -// template, filling in the necessary fields, and have the user -// sign the transaction to deposit their funds. -// -// The withdraw amount and the account from getAccount -// would be the parameters to the transaction - -import FungibleToken from 0x02 -import FlowToken from 0x03 -import CustodialDeposit from 0x04 - -transaction { - - // Vault resource that holds the tokens that are being transferred - var sentVault: @FlowToken.Vault - - prepare(signer: AuthAccount) { - - // Get a reference to the signer's stored vault - let storedVault = signer.borrow<&FlowToken.Vault>(from: /storage/flowTokenVault)! - - // Withdraw 10 tokens from the signer's stored vault - self.sentVault <- storedVault.withdraw(amount: 10.0) - } - - execute { - // Get the custodial service's public account object - let recipient = getAccount(0x04) - - // Get the custodial service's public reference to the resource - // that emits events when deposits happen - - let receiver = recipient - .getCapability(/public/depositResourcePublic)! - .borrow<&{CustodialDeposit.DepositPublic}>() - ?? panic("Could not borrow deposit reference from capability") - - // Deposit the withdrawn tokens to the recipient's Receiver. - // Include a tag for the event that is emitted - // - receiver.taggedDeposit(from: <-self.sentVault, tag: "1234") - } -} - \ No newline at end of file diff --git a/src/transactions/mint_tokens.cdc b/src/transactions/mint_tokens.cdc index cb108b86..412e34cc 100644 --- a/src/transactions/mint_tokens.cdc +++ b/src/transactions/mint_tokens.cdc @@ -7,34 +7,30 @@ // would be the parameters to the transaction import FungibleToken from 0x02 -import FlowToken from 0x03 +import ExampleToken from 0x03 transaction { - - // Vault resource that holds the tokens that are being minted - var vault: @FlowToken.Vault + let tokenAdmin: &ExampleToken.Administrator + let tokenReceiver: &ExampleToken.Vault{FungibleToken.Receiver} prepare(signer: AuthAccount) { - - // Get a reference to the signer's MintAndBurn resource in storage - let mintAndBurn = signer.borrow<&FlowToken.MintAndBurn>(from: /storage/flowTokenMintAndBurn) - ?? panic("Couldn't borrow MintAndBurn reference from storage") - - // Mint 10 new tokens - self.vault <- mintAndBurn.mintTokens(amount: 10.0) + self.tokenAdmin = signer + .borrow<&ExampleToken.Administrator>(from: /storage/exampleTokenAdmin) + ?? panic("Signer is not the token admin") + + self.tokenReceiver = getAccount(0x04) + .getCapability(/public/exampleTokenReceiver)! + .borrow<&ExampleToken.Vault{FungibleToken.Receiver}>() + ?? panic("Unable to borrow receiver reference") } execute { - // Get the recipient's public account object - let recipient = getAccount(0x03) + let minter <- self.tokenAdmin.createNewMinter(allowedAmount: 100.0) + let mintedVault <- minter.mintTokens(amount: 10) - // Get a reference to the recipient's Receiver - let receiver = recipient.getCapability(/public/flowTokenReceiver)! - .borrow<&FlowToken.Vault{FungibleToken.Receiver}>() - ?? panic("Couldn't borrow receiver reference from the recipient") + self.tokenReceiver.deposit(from: <-mintedVault) - // Deposit the newly minted token in the recipient's Receiver - receiver.deposit(from: <-self.vault) + destroy minter } } \ No newline at end of file diff --git a/src/transactions/setup_account.cdc b/src/transactions/setup_account.cdc index 38a7d832..6b41fcfd 100644 --- a/src/transactions/setup_account.cdc +++ b/src/transactions/setup_account.cdc @@ -1,31 +1,31 @@ // This transaction is a template for a transaction // to add a Vault resource to their account -// so that they can use the FlowTokens +// so that they can use the exampleToken import FungibleToken from 0x02 -import FlowToken from 0x03 +import ExampleToken from 0x03 transaction { prepare(signer: AuthAccount) { - if signer.borrow<&FlowToken.Vault>(from: /storage/flowTokenVault) != nil { - // Create a new FlowToken Vault and put it in storage - signer.save(<-FlowToken.createEmptyVault(), to: /storage/flowTokenVault) + if signer.borrow<&ExampleToken.Vault>(from: /storage/exampleTokenVault) != nil { + // Create a new exampleToken Vault and put it in storage + signer.save(<-ExampleToken.createEmptyVault(), to: /storage/exampleTokenVault) // Create a public capability to the Vault that only exposes // the deposit function through the Receiver interface - signer.link<&FlowToken.Vault{FungibleToken.Receiver}>( - /public/flowTokenReceiver, - target: /storage/flowTokenVault + signer.link<&ExampleToken.Vault{FungibleToken.Receiver}>( + /public/exampleTokenReceiver, + target: /storage/exampleTokenVault ) // Create a public capability to the Vault that only exposes // the balance field through the Balance interface - signer.link<&FlowToken.Vault{FungibleToken.Balance}>( - /public/flowTokenBalance, - target: /storage/flowTokenVault + signer.link<&ExampleToken.Vault{FungibleToken.Balance}>( + /public/exampleTokenBalance, + target: /storage/exampleTokenVault ) } } diff --git a/src/transactions/transfer_tokens.cdc b/src/transactions/transfer_tokens.cdc index 915f9103..7251ce88 100644 --- a/src/transactions/transfer_tokens.cdc +++ b/src/transactions/transfer_tokens.cdc @@ -6,7 +6,7 @@ // would be the parameters to the transaction import FungibleToken from 0x02 -import FlowToken from 0x03 +import ExampleToken from 0x03 transaction { @@ -16,7 +16,7 @@ transaction { prepare(signer: AuthAccount) { // Get a reference to the signer's stored vault - let storedVault = signer.borrow<&FlowToken.Vault>(from: /storage/flowTokenVault) + let storedVault = signer.borrow<&ExampleToken.Vault>(from: /storage/exampleTokenVault) ?? panic("Unable to borrow a reference to the sender's Vault") // Withdraw 10 tokens from the signer's stored vault @@ -30,8 +30,8 @@ transaction { // Get a reference to the recipient's Receiver let receiver = recipient - .getCapability(/public/flowTokenReceiver)! - .borrow<&FlowToken.Vault{FungibleToken.Receiver}>() + .getCapability(/public/exampleTokenReceiver)! + .borrow<&ExampleToken.Vault{FungibleToken.Receiver}>() ?? panic("Unable to borrow receiver reference for recipient") // Deposit the withdrawn tokens in the recipient's receiver diff --git a/test/go.mod b/test/go.mod index 4d4632d2..40397ec8 100644 --- a/test/go.mod +++ b/test/go.mod @@ -3,8 +3,9 @@ module github.com/onflow/flow-ft/test go 1.13 require ( - github.com/dapperlabs/flow-emulator v1.0.0-alpha.7.0.20200522225230-51e97f42cb03 - github.com/onflow/cadence v0.3.0-beta4.0.20200524043105-6b94cabe6a65 - github.com/onflow/flow-go-sdk v0.3.0-beta1 + github.com/dapperlabs/flow-emulator v0.4.0 + github.com/onflow/cadence v0.4.0 + github.com/onflow/flow-ft/contracts v0.0.0-20200525235630-0e8024a483ce + github.com/onflow/flow-go-sdk v0.4.0 github.com/stretchr/testify v1.5.1 ) diff --git a/test/go.sum b/test/go.sum index 48c13034..e700caf6 100644 --- a/test/go.sum +++ b/test/go.sum @@ -59,7 +59,6 @@ github.com/antlr/antlr4 v0.0.0-20200503195918-621b933c7a7f/go.mod h1:T7PbCXFs94r github.com/aristanetworks/goarista v0.0.0-20170210015632-ea17b1a17847/go.mod h1:D/tb0zPVXnP7fmsLZjtdUhSsumbK/ij54UXjjVgMGxQ= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/aws/aws-sdk-go v1.25.48/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= -github.com/axw/gocov v1.0.0/go.mod h1:LvQpEYiwwIb2nYkXY2fDWhg9/AsYqkhmrCshjlUJECE= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= @@ -68,6 +67,7 @@ github.com/btcsuite/btcd v0.0.0-20171128150713-2e60448ffcc6/go.mod h1:Dmm/EzmjnC github.com/btcsuite/btcd v0.0.0-20190213025234-306aecffea32/go.mod h1:DrZx5ec/dmnfpw9KyYoQyYo7d0KEvTkk/5M/vbZjAr8= github.com/btcsuite/btcd v0.0.0-20190523000118-16327141da8c/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI= github.com/btcsuite/btcd v0.0.0-20190824003749-130ea5bddde3/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI= +github.com/btcsuite/btcd v0.20.1-beta h1:Ik4hyJqN8Jfyv3S4AGBOmyouMsYE3EdYODkMbQjwPGw= github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/btcutil v0.0.0-20190207003914-4c204d697803/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= @@ -91,6 +91,7 @@ github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMn github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cloudflare/cloudflare-go v0.10.2-0.20190916151808-a80f83b9add9/go.mod h1:1MxXX1Ux4x6mqPmjkUgTP1CdXIBXKX7T+Jk9Gxrmx+U= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd h1:qMd81Ts1T2OTKmB4acZcyKaMtRnY5Y44NuXGX2GFJ1w= github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= @@ -102,15 +103,15 @@ github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfc github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/dapperlabs/flow-emulator v1.0.0-alpha.7.0.20200522225230-51e97f42cb03 h1:p72Hc7Ju5zVctDYsDrgg4O03q/FeSC6OFYaPE7+du7g= -github.com/dapperlabs/flow-emulator v1.0.0-alpha.7.0.20200522225230-51e97f42cb03/go.mod h1:c2n0nG7Wikp17yPuaAer9xaJLzjGcOCfEKiM29MQia4= -github.com/dapperlabs/flow-go v0.3.2-0.20200520200337-3476e94b144b h1:ZBwPx8vlkkotdxh0UO/vlmx0lIT7PDaJJ0FGCcAMSyY= -github.com/dapperlabs/flow-go v0.3.2-0.20200520200337-3476e94b144b/go.mod h1:qdTB1Q5uKj4uRq2ztmCMV9tggmkFUfE2HXOZVsD6PpM= -github.com/dapperlabs/flow-go v0.3.2-0.20200524173840-eafdd749ee5d h1:VS2qNkzIUTG7lWKlSe5bRWda/nGJe14nhEUnejiXILI= -github.com/dapperlabs/flow-go v0.3.2-0.20200524173840-eafdd749ee5d/go.mod h1:HmZLRcKPTgbuyoJm/U7OnCCH1xmRVVm2T9YzwIupJ6E= +github.com/dapperlabs/flow-core-contracts/contracts v0.0.0-20200526041238-ad2360621a1a h1:8qta1Pfh3RbkcvRVOvO6/ACpZmP0W5sIaaoCUF8JOQM= +github.com/dapperlabs/flow-core-contracts/contracts v0.0.0-20200526041238-ad2360621a1a/go.mod h1:6SQ2GUde3Wj3EIRFq9Vu12IhSx3PiY3nVxLOEVehlmY= +github.com/dapperlabs/flow-emulator v0.4.0 h1:Si9ENHgeEJswW3JdVb4D+k2/5gL3rj+Yeh4JYJEfc9g= +github.com/dapperlabs/flow-emulator v0.4.0/go.mod h1:ZYHi97htOwLrNpdmCze39JXPcNtfnh85lLU2nc+WuOw= +github.com/dapperlabs/flow-go v0.4.1-0.20200602235543-7c086e054cc3 h1:+UKAlUn9FfYp/MFV6ff5EcQAk68DuIusbVPMfOTTto8= +github.com/dapperlabs/flow-go v0.4.1-0.20200602235543-7c086e054cc3/go.mod h1:/BdLWfMxQzG/RX+OhdkgmolAMkVnT2tO92VVevlSS6U= github.com/dapperlabs/flow-go/crypto v0.3.2-0.20200312195452-df4550a863b7/go.mod h1:6UyHoekg86OJnzTz9hp3Ubzp2ZkrDMFg2krGbVEiloU= -github.com/dapperlabs/flow-go/crypto v0.3.2-0.20200505040645-6043e0fe5246 h1:Do+yDKdrWcyFGvDdhQ7SthDADpHgoD47D8xB2Vyz7yc= -github.com/dapperlabs/flow-go/crypto v0.3.2-0.20200505040645-6043e0fe5246/go.mod h1:DtpZLXm4h787U0fkDZ6F9/S3vpRr/JT8xFNJ9mfKzXw= +github.com/dapperlabs/flow-go/crypto v0.3.2-0.20200602194037-af8844481849 h1:2KFSBau3NqjwKA5kJ8uzlV0Ma0B0NAnW3tlAoeBtTNI= +github.com/dapperlabs/flow-go/crypto v0.3.2-0.20200602194037-af8844481849/go.mod h1:9RLfdwwRI3FVD/tm4Y8E9aqViRnCiXTcGgcmB8CsEVQ= github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= @@ -152,7 +153,6 @@ github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/ github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fxamacker/cbor/v2 v2.2.0 h1:6eXqdDDe588rSYAi1HfZKbx6YYQO4mxQ9eC6xYpU/JQ= github.com/fxamacker/cbor/v2 v2.2.0/go.mod h1:TA1xS00nchWmaBnEIxPSE5oHLuJBAVvqrtAnWBwBCVo= -github.com/gammazero/deque v0.0.0-20200310222745-50fa758af896/go.mod h1:D90+MBHVc9Sk1lJAbEVgws0eYEurY4mv2TDso3Nxh3w= github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclKsC9YodN5RgxqK/VD9HM9JsCSh7rNhMZE98= @@ -160,11 +160,14 @@ github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9 github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.9.0 h1:wDJmvq38kDhkVxi50ni9ykkdUr1PKgqKOoi01fa0Mdk= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= +github.com/go-logfmt/logfmt v0.4.0 h1:MP4Eh7ZCb31lleYCFuwm0oe4/YGak+5l1vA2NOE80nA= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8= github.com/go-sourcemap/sourcemap v2.1.2+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= +github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-test/deep v1.0.5 h1:AKODKU3pDH1RzZzm6YZu77YWtEAq6uh1rLIAQlay2qc= github.com/go-test/deep v1.0.5/go.mod h1:QV8Hv/iy04NyLBxAdO9njL0iVPN1S4d/A3NVv1V36o8= @@ -182,6 +185,7 @@ github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfb github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.3 h1:GV+pQPG/EUUbkh47niozDcADz6go/dUwhVzdUQHIVRw= github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a1/R87v0= @@ -227,7 +231,9 @@ github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgf github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/gxed/hashland/keccakpg v0.0.1/go.mod h1:kRzw3HkwxFU1mpmPP8v1WyQzwdGfmKFJ6tItnhQ67kU= github.com/gxed/hashland/murmur3 v0.0.1/go.mod h1:KjXop02n4/ckmZSnY2+HKcLud/tcmvhST0bie/0lS48= +github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-multierror v1.0.0 h1:iVjPR7a6H0tWELX5NxNe7bYopibicUzc7uPribsnS6o= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= github.com/hashicorp/golang-lru v0.0.0-20160813221303-0a025b7e63ad/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= @@ -284,6 +290,7 @@ github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7V github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= github.com/kami-zh/go-capturer v0.0.0-20171211120116-e492ea43421d/go.mod h1:P2viExyCEfeWGU259JnaQ34Inuec4R38JCyBx2edgD0= github.com/karalabe/usb v0.0.0-20190919080040-51dc0efba356/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU= +github.com/kevinburke/go-bindata v3.21.0+incompatible/go.mod h1:/pEEZ72flUW2p0yi30bslSp9YqD9pysLxunQDdb2CPM= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= @@ -291,6 +298,7 @@ github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6 github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/koron/go-ssdp v0.0.0-20191105050749-2e1c40ed0b5d/go.mod h1:5Ky9EC2xfoUKUor0Hjgi2BJhCSXJfMOFlmyYrVKGQMk= +github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515 h1:T+h1c/A9Gawja4Y9mFVWj2vyii2bbUNDw3kt9VxK2EY= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= @@ -437,16 +445,20 @@ github.com/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXW github.com/olekukonko/tablewriter v0.0.2-0.20190409134802-7e037d187b0c/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= github.com/onflow/cadence v0.3.0-beta1 h1:hvCoaDfGRCWbS+M6S+5uyh9CRjd7uGJvOtuPB4oYrh4= github.com/onflow/cadence v0.3.0-beta1/go.mod h1:GaLQ7IsJi5bqpH66GprNs8uoQtperK/xbXXIOq11nZw= -github.com/onflow/cadence v0.3.0-beta3 h1:muvmL9o0iqyUVL8XCAlhzAiJsX42syvk9GmEkt3+m4M= -github.com/onflow/cadence v0.3.0-beta3/go.mod h1:GaLQ7IsJi5bqpH66GprNs8uoQtperK/xbXXIOq11nZw= -github.com/onflow/cadence v0.3.0-beta3.0.20200522221348-6e99c1cc6bc8 h1:hSdP8PyuFn61VzrQN9XU01pZvBbvPqoryPOXUKDAaOA= -github.com/onflow/cadence v0.3.0-beta3.0.20200522221348-6e99c1cc6bc8/go.mod h1:GaLQ7IsJi5bqpH66GprNs8uoQtperK/xbXXIOq11nZw= -github.com/onflow/cadence v0.3.0-beta4.0.20200524043105-6b94cabe6a65 h1:1ZqKddG0CVWgxJiFmo23eaN0bcIBRu29QFjYLGWdNE0= -github.com/onflow/cadence v0.3.0-beta4.0.20200524043105-6b94cabe6a65/go.mod h1:GaLQ7IsJi5bqpH66GprNs8uoQtperK/xbXXIOq11nZw= +github.com/onflow/cadence v0.4.0-beta1 h1:0f4CMnddT++5OYY53OPFuv5JTb85qDg/nygLV4Bk3Z8= +github.com/onflow/cadence v0.4.0-beta1/go.mod h1:gaPtSctdMzT5NAoJgzsRuwUkdgRswVHsRXFNNmCTn3I= +github.com/onflow/cadence v0.4.0 h1:oAKY/HclZZhc5wJgJwdPjWXJuC5IjuuHHVAAq3S7AHI= +github.com/onflow/cadence v0.4.0/go.mod h1:gaPtSctdMzT5NAoJgzsRuwUkdgRswVHsRXFNNmCTn3I= +github.com/onflow/flow v0.1.4-0.20200601215056-34a11def1d6b/go.mod h1:lzyAYmbu1HfkZ9cfnL5/sjrrsnJiUU8fRL26CqLP7+c= +github.com/onflow/flow-ft/contracts v0.0.0-20200525235630-0e8024a483ce h1:I8SaLOFlQN7Jr+aU1mZB0mnsq2qlaaJPeji4PmkTWfA= +github.com/onflow/flow-ft/contracts v0.0.0-20200525235630-0e8024a483ce/go.mod h1:KwzrK5thiLObKHTHaHf9lrvOS3HLr9jntNEZUQ4yJgw= github.com/onflow/flow-go-sdk v0.3.0-beta1 h1:HmAqosPHLoNmYfhUECsSFpvSD4kWIkJ+Xs8LAJijKDc= github.com/onflow/flow-go-sdk v0.3.0-beta1/go.mod h1:8v6vcYGh5/PtYcM3IXflLcCb00I91WDbnNF8SjirnlI= +github.com/onflow/flow-go-sdk v0.4.0 h1:ZNEE8HQ6xTyr4+RmlxZ2+U/BjKtQDsAB54I+D8AJpZA= +github.com/onflow/flow-go-sdk v0.4.0/go.mod h1:MHn8oQCkBNcl2rXdYSm9VYYK4ogwEpyrdM/XK/czdlM= github.com/onflow/flow/protobuf/go/flow v0.1.4 h1:xRdLYCxR/V6lq03ElK3g0T/F8pCIpLrKs2IHQTYr9rM= github.com/onflow/flow/protobuf/go/flow v0.1.4/go.mod h1:kRugbzZjwQqvevJhrnnCFMJZNmoSJmxlKt6hTGXZojM= +github.com/onflow/flow/protobuf/go/flow v0.1.5-0.20200601215056-34a11def1d6b/go.mod h1:kRugbzZjwQqvevJhrnnCFMJZNmoSJmxlKt6hTGXZojM= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= @@ -492,6 +504,7 @@ github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsT github.com/prometheus/procfs v0.0.8 h1:+fpWZdT24pJBiqJdAwYBjPSk+5YmQzYNPYzQsdzLkt8= github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= github.com/prometheus/tsdb v0.6.2-0.20190402121629-4f204dcbc150/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= +github.com/prometheus/tsdb v0.7.1 h1:YZcsG11NqnK4czYLrWd9mpEuAJIHVQLwdrleYfszMAA= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/psiemens/graceland v1.0.0/go.mod h1:1Tof+vt1LbmcZFE0lzgdwMN0QBymAChG3FRgDx8XisU= github.com/psiemens/sconfig v0.0.0-20190623041652-6e01eb1354fc/go.mod h1:+MLKqdledP/8G3rOBpknbLh0IclCf4WneJUtS26JB2U= @@ -557,6 +570,7 @@ github.com/uber/jaeger-lib v2.2.0+incompatible/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6 github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= +github.com/vektra/mockery v1.1.2/go.mod h1:VcfZjKaFOPO+MpN4ZvwPjs4c48lkq1o3Ym8yHZJu0jU= github.com/vmihailenco/msgpack v4.0.4+incompatible h1:dSLoQfGFAo3F6OoNhwUmLwVgaUXK79GlxNBwueZn0xI= github.com/vmihailenco/msgpack v4.0.4+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk= github.com/vmihailenco/msgpack/v4 v4.3.11 h1:Q47CePddpNGNhk4GCnAx9DDtASi2rasatE0cd26cZoE= @@ -576,6 +590,7 @@ github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= +github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= @@ -586,6 +601,8 @@ go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.5.1 h1:rsqfU5vBkVknbhUGbAUwQKR2H4ItV8tjJ+6kJX4cxHM= go.uber.org/atomic v1.5.1/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= +go.uber.org/goleak v1.0.0 h1:qsup4IcBdlmsnGfqyLl4Ntn3C2XCCuKAE7DwHpScyUo= +go.uber.org/goleak v1.0.0/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= @@ -621,6 +638,7 @@ golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= +golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6 h1:QE6XYQK6naiK1EPAe1g/ILLxN5RBoH5xkJk3CqlMI/Y= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= @@ -633,6 +651,7 @@ golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHl golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= +golang.org/x/lint v0.0.0-20200130185559-910be7a94367 h1:0IiAsCRByjO2QjX7ZPkw5oU9x+n1YqRL802rjC0c3Aw= golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= @@ -640,6 +659,7 @@ golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKG golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.2.0 h1:KU7oHjnv3XNWfa5COkzUifxZmxp1TyI7ImMXqFxLwvQ= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -665,6 +685,7 @@ golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200301022130-244492dfa37a h1:GuSPYbZzB5/dcLNCwLQLsg3obCJtX9IJhpXkvY7kzk0= golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -740,13 +761,13 @@ golang.org/x/tools v0.0.0-20190425163242-31fd60d6bfdc/go.mod h1:RgjU9mgBXZiqYHBn golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190617190820-da514acc4774/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -760,13 +781,18 @@ golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapK golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200224181240-023911ca70b2 h1:L/G4KZvrQn7FWLN/LlulBtBzrLUhqjiGfTWWDmrh+IQ= golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200323144430-8dcfad9e016e h1:ssd5ulOvVWlh4kDSUF2SqzmMeWfjmwDXM+uGw/aQjRE= +golang.org/x/tools v0.0.0-20200323144430-8dcfad9e016e/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= +gonum.org/v1/gonum v0.6.1 h1:/LSrTrgZtpbXyAR6+0e152SROCkJJSh7goYWVmdPFGc= gonum.org/v1/gonum v0.6.1/go.mod h1:9mxDZsDKxgMAuccQkewq682L+0eCu4dCN2yonUJTCLU= +gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0 h1:OE9mWmgKkjJyEmDAAtGMPjXu+YNeGvK9VTSHY6+Qihc= gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= gonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b/go.mod h1:Wt8AAjI+ypCyYX3nZBvf6cAIx93T+c/OS2HFAYskSZc= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= diff --git a/test/templates.go b/test/templates.go index 4c5a035b..e94f176f 100644 --- a/test/templates.go +++ b/test/templates.go @@ -10,64 +10,64 @@ import ( // a new Vault instance and stores it in storage. // balance is an argument to the Vault constructor. // The Vault must have been deployed already. -func GenerateCreateTokenScript(fungibleAddr, flowAddr flow.Address) []byte { +func GenerateCreateTokenScript(fungibleAddr, tokenAddr flow.Address, tokenName, storageName string) []byte { template := ` - import FungibleToken from 0x%s - import FlowToken from 0x%s + import FungibleToken from 0x%[1]s + import %[3]s from 0x%[2]s transaction { prepare(acct: AuthAccount) { - let vault <- FlowToken.createEmptyVault() - acct.save(<-vault, to: /storage/flowTokenVault) + let vault <- %[3]s.createEmptyVault() + acct.save(<-vault, to: /storage/%[4]sVault) - acct.link<&FlowToken.Vault{FungibleToken.Receiver}>(/public/flowTokenReceiver, target: /storage/flowTokenVault) - acct.link<&FlowToken.Vault{FungibleToken.Balance}>(/public/flowTokenBalance, target: /storage/flowTokenVault) + acct.link<&%[3]s.Vault{FungibleToken.Receiver}>(/public/%[4]sReceiver, target: /storage/%[4]sVault) + acct.link<&%[3]s.Vault{FungibleToken.Balance}>(/public/%[4]sBalance, target: /storage/%[4]sVault) } } ` - return []byte(fmt.Sprintf(template, fungibleAddr, flowAddr)) + return []byte(fmt.Sprintf(template, fungibleAddr, tokenAddr, tokenName, storageName)) } // GenerateDestroyVaultScript creates a script that withdraws // tokens from a vault and destroys the tokens -func GenerateDestroyVaultScript(fungibleAddr, flowAddr flow.Address, withdrawAmount int) []byte { +func GenerateDestroyVaultScript(fungibleAddr, tokenAddr flow.Address, tokenName, storageName string, withdrawAmount int) []byte { template := ` - import FungibleToken from 0x%s - import FlowToken from 0x%s + import FungibleToken from 0x%[1]s + import %[3]s from 0x%[2]s transaction { prepare(acct: AuthAccount) { - let vault <- acct.load<@FlowToken.Vault>(from: /storage/flowTokenVault) + let vault <- acct.load<@%[3]s.Vault>(from: /storage/%[4]sVault) ?? panic("Couldn't load Vault from storage") - let withdrawVault <- vault.withdraw(amount: %d.0) + let withdrawVault <- vault.withdraw(amount: %[5]d.0) - acct.save(<-vault, to: /storage/flowTokenVault) + acct.save(<-vault, to: /storage/%[4]sVault) destroy withdrawVault } } ` - return []byte(fmt.Sprintf(template, fungibleAddr, flowAddr, withdrawAmount)) + return []byte(fmt.Sprintf(template, fungibleAddr, tokenAddr, tokenName, storageName, withdrawAmount)) } // GenerateTransferVaultScript creates a script that withdraws an tokens from an account // and deposits it to another account's vault -func GenerateTransferVaultScript(fungibleAddr, flowAddr flow.Address, receiverAddr flow.Address, amount int) []byte { +func GenerateTransferVaultScript(fungibleAddr, tokenAddr flow.Address, receiverAddr flow.Address, tokenName, storageName string, amount int) []byte { template := ` import FungibleToken from 0x%s - import FlowToken from 0x%s + import %s from 0x%s transaction { prepare(acct: AuthAccount) { let recipient = getAccount(0x%s) - let providerRef = acct.borrow<&FlowToken.Vault{FungibleToken.Provider}>(from: /storage/flowTokenVault) + let providerRef = acct.borrow<&%s.Vault{FungibleToken.Provider}>(from: /storage/%sVault) ?? panic("Could not borrow Provider reference to the Vault!") - let receiverRef = recipient.getCapability(/public/flowTokenReceiver)!.borrow<&FlowToken.Vault{FungibleToken.Receiver}>() + let receiverRef = recipient.getCapability(/public/%sReceiver)!.borrow<&%s.Vault{FungibleToken.Receiver}>() ?? panic("Could not borrow receiver reference to the recipient's Vault") let tokens <- providerRef.withdraw(amount: %d.0) @@ -77,121 +77,120 @@ func GenerateTransferVaultScript(fungibleAddr, flowAddr flow.Address, receiverAd } ` - return []byte(fmt.Sprintf(template, fungibleAddr, flowAddr, receiverAddr, amount)) + return []byte(fmt.Sprintf(template, fungibleAddr, tokenName, tokenAddr, receiverAddr, tokenName, storageName, storageName, tokenName, amount)) } // GenerateMintTokensScript creates a script that uses the admin resource // to mint new tokens and deposit them in a Vault -func GenerateMintTokensScript(fungibleAddr, flowAddr flow.Address, receiverAddr flow.Address, amount int) []byte { +func GenerateMintTokensScript(fungibleAddr, tokenAddr flow.Address, receiverAddr flow.Address, tokenName, storageName string, amount float64) []byte { template := ` - import FungibleToken from 0x%s - import FlowToken from 0x%s + import FungibleToken from 0x%[1]s + import %[3]s from 0x%[2]s transaction { + let tokenAdmin: &%[3]s.Administrator + let tokenReceiver: &%[3]s.Vault{FungibleToken.Receiver} - // Vault resource that holds the tokens that are being minted - var vault: @FungibleToken.Vault - prepare(signer: AuthAccount) { - - // Get a reference to the signer's MintAndBurn resource in storage - let mintAndBurn = signer.borrow<&FlowToken.MintAndBurn>(from: /storage/flowTokenMintAndBurn) - ?? panic("Couldn't borrow MintAndBurn reference from storage") - - // Mint 10 new tokens - self.vault <- mintAndBurn.mintTokens(amount: %d.0) + self.tokenAdmin = signer + .borrow<&%[3]s.Administrator>(from: /storage/%[4]sAdmin) + ?? panic("Signer is not the token admin") + + self.tokenReceiver = getAccount(0x%[5]s) + .getCapability(/public/%[4]sReceiver)! + .borrow<&%[3]s.Vault{FungibleToken.Receiver}>() + ?? panic("Unable to borrow receiver reference") } - + execute { - // Get the recipient's public account object - let recipient = getAccount(0x%s) - - // Get a reference to the recipient's Receiver - let receiver = recipient.getCapability(/public/flowTokenReceiver)! - .borrow<&FlowToken.Vault{FungibleToken.Receiver}>() - ?? panic("Couldn't borrow receiver reference to recipient's vault") - - // Deposit the newly minted token in the recipient's Receiver - receiver.deposit(from: <-self.vault) + let minter <- self.tokenAdmin.createNewMinter(allowedAmount: 100.0) + let mintedVault <- minter.mintTokens(amount: %[6]f) + + self.tokenReceiver.deposit(from: <-mintedVault) + + destroy minter } - } + } ` - return []byte(fmt.Sprintf(template, fungibleAddr, flowAddr, amount, receiverAddr)) + return []byte(fmt.Sprintf(template, fungibleAddr, tokenAddr, tokenName, storageName, receiverAddr, amount)) } // GenerateBurnTokensScript creates a script that uses the admin resource // to destroy tokens and deposit them in a Vault -func GenerateBurnTokensScript(fungibleAddr, flowAddr flow.Address, amount int) []byte { +func GenerateBurnTokensScript(fungibleAddr, tokenAddr flow.Address, tokenName, storageName string, amount int) []byte { template := ` - import FungibleToken from 0x%s - import FlowToken from 0x%s + import FungibleToken from 0x%[1]s + import %[3]s from 0x%[2]s transaction { // Vault resource that holds the tokens that are being burned let vault: @FungibleToken.Vault - let mintAndBurn: &FlowToken.MintAndBurn + let admin: &%[3]s.Administrator prepare(signer: AuthAccount) { - // Withdraw 10 tokens from the admin vault in storage - self.vault <- signer.borrow<&FlowToken.Vault>(from: /storage/flowTokenVault)! - .withdraw(amount: UFix64(%d)) + // Withdraw tokens from the admin vault in storage + self.vault <- signer.borrow<&%[3]s.Vault>(from: /storage/%[4]sVault)! + .withdraw(amount: UFix64(%[5]d)) - // Create a reference to the admin MintAndBurn resource in storage - self.mintAndBurn = signer.borrow<&FlowToken.MintAndBurn>(from: /storage/flowTokenMintAndBurn) - ?? panic("Could not borrow a reference to the Burn resource") + // Create a reference to the admin admin resource in storage + self.admin = signer.borrow<&%[3]s.Administrator>(from: /storage/%[4]sAdmin) + ?? panic("Could not borrow a reference to the admin resource") } execute { - // burn the withdrawn tokens - self.mintAndBurn.burnTokens(from: <-self.vault) + let burner <- self.admin.createNewBurner() + + burner.burnTokens(from: <-self.vault) + + destroy burner } } ` - return []byte(fmt.Sprintf(template, fungibleAddr, flowAddr, amount)) + return []byte(fmt.Sprintf(template, fungibleAddr, tokenAddr, tokenName, storageName, amount)) } // GenerateInspectVaultScript creates a script that retrieves a // Vault from the array in storage and makes assertions about // its balance. If these assertions fail, the script panics. -func GenerateInspectVaultScript(fungibleAddr, flowAddr, userAddr flow.Address, expectedBalance float64) []byte { +func GenerateInspectVaultScript(fungibleAddr, tokenAddr, userAddr flow.Address, tokenName, storageName string, expectedBalance float64) []byte { template := ` - import FungibleToken from 0x%s - import FlowToken from 0x%s + import FungibleToken from 0x%[1]s + import %[3]s from 0x%[2]s pub fun main() { - let acct = getAccount(0x%s) - let vaultRef = acct.getCapability(/public/flowTokenBalance)!.borrow<&FlowToken.Vault{FungibleToken.Balance}>() + let acct = getAccount(0x%[5]s) + let vaultRef = acct.getCapability(/public/%[4]sBalance)!.borrow<&%[3]s.Vault{FungibleToken.Balance}>() ?? panic("Could not borrow Balance reference to the Vault") assert( - vaultRef.balance == UFix64(%f), + vaultRef.balance == UFix64(%[6]f), message: "incorrect balance!" ) } ` - return []byte(fmt.Sprintf(template, fungibleAddr, flowAddr, userAddr, expectedBalance)) + return []byte(fmt.Sprintf(template, fungibleAddr, tokenAddr, tokenName, storageName, userAddr, expectedBalance)) } // GenerateInspectSupplyScript creates a script that reads // the total supply of tokens in existence // and makes assertions about the number -func GenerateInspectSupplyScript(fungibleAddr, flowAddr flow.Address, expectedSupply int) []byte { +func GenerateInspectSupplyScript(fungibleAddr, tokenAddr flow.Address, tokenName string, expectedSupply int) []byte { template := ` - import FungibleToken from 0x%s - import FlowToken from 0x%s + import FungibleToken from 0x%[1]s + import %[3]s from 0x%[2]s pub fun main() { assert( - FlowToken.totalSupply == UFix64(%d), + %[3]s.totalSupply == UFix64(%[4]d), message: "incorrect totalSupply!" ) } ` - return []byte(fmt.Sprintf(template, fungibleAddr, flowAddr, expectedSupply)) + return []byte(fmt.Sprintf(template, fungibleAddr, tokenAddr, tokenName, expectedSupply)) } diff --git a/test/test.go b/test/test.go index 403085b1..2004248d 100644 --- a/test/test.go +++ b/test/test.go @@ -56,7 +56,7 @@ func signAndSubmit( Submit(t, b, tx, shouldRevert) } -// submit submits a transaction and checks if it fails or not. +// Submit submits a transaction and checks if it fails or not. func Submit( t *testing.T, b *emulator.Blockchain, diff --git a/test/token_test.go b/test/token_test.go index 85ee83b3..40945df8 100644 --- a/test/token_test.go +++ b/test/token_test.go @@ -1,42 +1,29 @@ package test import ( - "encoding/hex" - "fmt" + "strings" "testing" + emulator "github.com/dapperlabs/flow-emulator" "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" "github.com/onflow/flow-go-sdk" "github.com/onflow/flow-go-sdk/crypto" "github.com/onflow/flow-go-sdk/test" -) -const ( - fungibleTokenContractFile = "../src/contracts/FungibleToken.cdc" - flowTokenContractFile = "../src/contracts/FlowToken.cdc" + "github.com/onflow/flow-ft/contracts" ) func TestTokenDeployment(t *testing.T) { b := newEmulator() - // Should be able to deploy a contract as a new account with no keys. - fungibleTokenCode := readFile(fungibleTokenContractFile) - fungibleAddr, err := b.CreateAccount(nil, fungibleTokenCode) - assert.NoError(t, err) - _, err = b.CommitBlock() - assert.NoError(t, err) + accountKeys := test.AccountKeyGenerator() - // Should be able to deploy a contract as a new account with no keys. - flowTokenCode := readFile(flowTokenContractFile) - flowAddr, err := b.CreateAccount(nil, flowTokenCode) - assert.NoError(t, err) - _, err = b.CommitBlock() - assert.NoError(t, err) + exampleTokenAccountKey, _ := accountKeys.NewWithSigner() + fungibleAddr, exampleTokenAddr := DeployTokenContracts(b, t, []*flow.AccountKey{exampleTokenAccountKey}) t.Run("Should have initialized Supply field correctly", func(t *testing.T) { - executeScriptAndCheck(t, b, GenerateInspectSupplyScript(fungibleAddr, flowAddr, 1000)) + executeScriptAndCheck(t, b, GenerateInspectSupplyScript(fungibleAddr, exampleTokenAddr, "ExampleToken", 1000)) }) } @@ -45,41 +32,30 @@ func TestCreateToken(t *testing.T) { accountKeys := test.AccountKeyGenerator() - // Should be able to deploy a contract as a new account with no keys. - fungibleTokenCode := readFile(fungibleTokenContractFile) - fungibleAddr, err := b.CreateAccount(nil, fungibleTokenCode) - assert.NoError(t, err) - _, err = b.CommitBlock() - assert.NoError(t, err) - - // Should be able to deploy a contract as a new account with no keys. - flowTokenCode := readFile(flowTokenContractFile) - flowAddr, err := b.CreateAccount(nil, flowTokenCode) - assert.NoError(t, err) - _, err = b.CommitBlock() - assert.NoError(t, err) + exampleTokenAccountKey, _ := accountKeys.NewWithSigner() + fungibleAddr, exampleTokenAddr := DeployTokenContracts(b, t, []*flow.AccountKey{exampleTokenAccountKey}) joshAccountKey, joshSigner := accountKeys.NewWithSigner() joshAddress, _ := b.CreateAccount([]*flow.AccountKey{joshAccountKey}, nil) t.Run("Should be able to create empty Vault that doesn't affect supply", func(t *testing.T) { tx := flow.NewTransaction(). - SetScript(GenerateCreateTokenScript(fungibleAddr, flowAddr)). + SetScript(GenerateCreateTokenScript(fungibleAddr, exampleTokenAddr, "ExampleToken", "exampleToken")). SetGasLimit(100). - SetProposalKey(b.RootKey().Address, b.RootKey().ID, b.RootKey().SequenceNumber). - SetPayer(b.RootKey().Address). + SetProposalKey(b.ServiceKey().Address, b.ServiceKey().ID, b.ServiceKey().SequenceNumber). + SetPayer(b.ServiceKey().Address). AddAuthorizer(joshAddress) signAndSubmit( t, b, tx, - []flow.Address{b.RootKey().Address, joshAddress}, - []crypto.Signer{b.RootKey().Signer(), joshSigner}, + []flow.Address{b.ServiceKey().Address, joshAddress}, + []crypto.Signer{b.ServiceKey().Signer(), joshSigner}, false, ) - executeScriptAndCheck(t, b, GenerateInspectVaultScript(fungibleAddr, flowAddr, joshAddress, 0)) + executeScriptAndCheck(t, b, GenerateInspectVaultScript(fungibleAddr, exampleTokenAddr, joshAddress, "ExampleToken", "exampleToken", 0)) - executeScriptAndCheck(t, b, GenerateInspectSupplyScript(fungibleAddr, flowAddr, 1000)) + executeScriptAndCheck(t, b, GenerateInspectSupplyScript(fungibleAddr, exampleTokenAddr, "ExampleToken", 1000)) }) } @@ -88,103 +64,91 @@ func TestExternalTransfers(t *testing.T) { accountKeys := test.AccountKeyGenerator() - // Should be able to deploy a contract as a new account with no keys. - fungibleTokenCode := readFile(fungibleTokenContractFile) - fungibleAddr, err := b.CreateAccount(nil, fungibleTokenCode) - assert.NoError(t, err) - _, err = b.CommitBlock() - assert.NoError(t, err) - - // Should be able to deploy a contract as a new account with no keys. - flowTokenCode := readFile(flowTokenContractFile) - flowAccountKey, flowSigner := accountKeys.NewWithSigner() - flowAddr, err := b.CreateAccount([]*flow.AccountKey{flowAccountKey}, flowTokenCode) - assert.NoError(t, err) - _, err = b.CommitBlock() - assert.NoError(t, err) + exampleTokenAccountKey, exampleTokenSigner := accountKeys.NewWithSigner() + fungibleAddr, exampleTokenAddr := DeployTokenContracts(b, t, []*flow.AccountKey{exampleTokenAccountKey}) joshAccountKey, joshSigner := accountKeys.NewWithSigner() joshAddress, _ := b.CreateAccount([]*flow.AccountKey{joshAccountKey}, nil) // then deploy the tokens to an account tx := flow.NewTransaction(). - SetScript(GenerateCreateTokenScript(fungibleAddr, flowAddr)). + SetScript(GenerateCreateTokenScript(fungibleAddr, exampleTokenAddr, "ExampleToken", "exampleToken")). SetGasLimit(100). - SetProposalKey(b.RootKey().Address, b.RootKey().ID, b.RootKey().SequenceNumber). - SetPayer(b.RootKey().Address). + SetProposalKey(b.ServiceKey().Address, b.ServiceKey().ID, b.ServiceKey().SequenceNumber). + SetPayer(b.ServiceKey().Address). AddAuthorizer(joshAddress) signAndSubmit( t, b, tx, - []flow.Address{b.RootKey().Address, joshAddress}, - []crypto.Signer{b.RootKey().Signer(), joshSigner}, + []flow.Address{b.ServiceKey().Address, joshAddress}, + []crypto.Signer{b.ServiceKey().Signer(), joshSigner}, false, ) t.Run("Shouldn't be able to deposit an empty Vault", func(t *testing.T) { tx := flow.NewTransaction(). - SetScript(GenerateTransferVaultScript(fungibleAddr, flowAddr, joshAddress, 0)). + SetScript(GenerateTransferVaultScript(fungibleAddr, exampleTokenAddr, joshAddress, "ExampleToken", "exampleToken", 0)). SetGasLimit(100). - SetProposalKey(b.RootKey().Address, b.RootKey().ID, b.RootKey().SequenceNumber). - SetPayer(b.RootKey().Address). - AddAuthorizer(flowAddr) + SetProposalKey(b.ServiceKey().Address, b.ServiceKey().ID, b.ServiceKey().SequenceNumber). + SetPayer(b.ServiceKey().Address). + AddAuthorizer(exampleTokenAddr) signAndSubmit( t, b, tx, - []flow.Address{b.RootKey().Address, flowAddr}, - []crypto.Signer{b.RootKey().Signer(), flowSigner}, + []flow.Address{b.ServiceKey().Address, exampleTokenAddr}, + []crypto.Signer{b.ServiceKey().Signer(), exampleTokenSigner}, true, ) // Assert that the vaults' balances are correct - executeScriptAndCheck(t, b, GenerateInspectVaultScript(fungibleAddr, flowAddr, flowAddr, 1000)) + executeScriptAndCheck(t, b, GenerateInspectVaultScript(fungibleAddr, exampleTokenAddr, exampleTokenAddr, "ExampleToken", "exampleToken", 1000)) - executeScriptAndCheck(t, b, GenerateInspectVaultScript(fungibleAddr, flowAddr, joshAddress, 0)) + executeScriptAndCheck(t, b, GenerateInspectVaultScript(fungibleAddr, exampleTokenAddr, joshAddress, "ExampleToken", "exampleToken", 0)) }) t.Run("Shouldn't be able to withdraw more than the balance of the Vault", func(t *testing.T) { tx := flow.NewTransaction(). - SetScript(GenerateTransferVaultScript(fungibleAddr, flowAddr, joshAddress, 30000)). + SetScript(GenerateTransferVaultScript(fungibleAddr, exampleTokenAddr, joshAddress, "ExampleToken", "exampleToken", 30000)). SetGasLimit(100). - SetProposalKey(b.RootKey().Address, b.RootKey().ID, b.RootKey().SequenceNumber). - SetPayer(b.RootKey().Address). - AddAuthorizer(flowAddr) + SetProposalKey(b.ServiceKey().Address, b.ServiceKey().ID, b.ServiceKey().SequenceNumber). + SetPayer(b.ServiceKey().Address). + AddAuthorizer(exampleTokenAddr) signAndSubmit( t, b, tx, - []flow.Address{b.RootKey().Address, flowAddr}, - []crypto.Signer{b.RootKey().Signer(), flowSigner}, + []flow.Address{b.ServiceKey().Address, exampleTokenAddr}, + []crypto.Signer{b.ServiceKey().Signer(), exampleTokenSigner}, true, ) // Assert that the vaults' balances are correct - executeScriptAndCheck(t, b, GenerateInspectVaultScript(fungibleAddr, flowAddr, flowAddr, 1000)) + executeScriptAndCheck(t, b, GenerateInspectVaultScript(fungibleAddr, exampleTokenAddr, exampleTokenAddr, "ExampleToken", "exampleToken", 1000)) - executeScriptAndCheck(t, b, GenerateInspectVaultScript(fungibleAddr, flowAddr, joshAddress, 0)) + executeScriptAndCheck(t, b, GenerateInspectVaultScript(fungibleAddr, exampleTokenAddr, joshAddress, "ExampleToken", "exampleToken", 0)) }) t.Run("Should be able to withdraw and deposit tokens from a vault", func(t *testing.T) { tx := flow.NewTransaction(). - SetScript(GenerateTransferVaultScript(fungibleAddr, flowAddr, joshAddress, 300)). + SetScript(GenerateTransferVaultScript(fungibleAddr, exampleTokenAddr, joshAddress, "ExampleToken", "exampleToken", 300)). SetGasLimit(100). - SetProposalKey(b.RootKey().Address, b.RootKey().ID, b.RootKey().SequenceNumber). - SetPayer(b.RootKey().Address). - AddAuthorizer(flowAddr) + SetProposalKey(b.ServiceKey().Address, b.ServiceKey().ID, b.ServiceKey().SequenceNumber). + SetPayer(b.ServiceKey().Address). + AddAuthorizer(exampleTokenAddr) signAndSubmit( t, b, tx, - []flow.Address{b.RootKey().Address, flowAddr}, - []crypto.Signer{b.RootKey().Signer(), flowSigner}, + []flow.Address{b.ServiceKey().Address, exampleTokenAddr}, + []crypto.Signer{b.ServiceKey().Signer(), exampleTokenSigner}, false, ) // Assert that the vaults' balances are correct - executeScriptAndCheck(t, b, GenerateInspectVaultScript(fungibleAddr, flowAddr, flowAddr, 700)) + executeScriptAndCheck(t, b, GenerateInspectVaultScript(fungibleAddr, exampleTokenAddr, exampleTokenAddr, "ExampleToken", "exampleToken", 700)) - executeScriptAndCheck(t, b, GenerateInspectVaultScript(fungibleAddr, flowAddr, joshAddress, 300)) + executeScriptAndCheck(t, b, GenerateInspectVaultScript(fungibleAddr, exampleTokenAddr, joshAddress, "ExampleToken", "exampleToken", 300)) - executeScriptAndCheck(t, b, GenerateInspectSupplyScript(fungibleAddr, flowAddr, 1000)) + executeScriptAndCheck(t, b, GenerateInspectSupplyScript(fungibleAddr, exampleTokenAddr, "ExampleToken", 1000)) }) } @@ -193,93 +157,81 @@ func TestVaultDestroy(t *testing.T) { accountKeys := test.AccountKeyGenerator() - // Should be able to deploy a contract as a new account with no keys. - fungibleTokenCode := readFile(fungibleTokenContractFile) - fungibleAddr, err := b.CreateAccount(nil, fungibleTokenCode) - assert.NoError(t, err) - _, err = b.CommitBlock() - assert.NoError(t, err) - - // Should be able to deploy a contract as a new account with no keys. - flowTokenCode := readFile(flowTokenContractFile) - flowAccountKey, flowSigner := accountKeys.NewWithSigner() - flowAddr, err := b.CreateAccount([]*flow.AccountKey{flowAccountKey}, flowTokenCode) - assert.NoError(t, err) - _, err = b.CommitBlock() - assert.NoError(t, err) + exampleTokenAccountKey, exampleTokenSigner := accountKeys.NewWithSigner() + fungibleAddr, exampleTokenAddr := DeployTokenContracts(b, t, []*flow.AccountKey{exampleTokenAccountKey}) joshAccountKey, joshSigner := accountKeys.NewWithSigner() joshAddress, _ := b.CreateAccount([]*flow.AccountKey{joshAccountKey}, nil) // then deploy the tokens to an account tx := flow.NewTransaction(). - SetScript(GenerateCreateTokenScript(fungibleAddr, flowAddr)). + SetScript(GenerateCreateTokenScript(fungibleAddr, exampleTokenAddr, "ExampleToken", "exampleToken")). SetGasLimit(100). - SetProposalKey(b.RootKey().Address, b.RootKey().ID, b.RootKey().SequenceNumber). - SetPayer(b.RootKey().Address). + SetProposalKey(b.ServiceKey().Address, b.ServiceKey().ID, b.ServiceKey().SequenceNumber). + SetPayer(b.ServiceKey().Address). AddAuthorizer(joshAddress) signAndSubmit( t, b, tx, - []flow.Address{b.RootKey().Address, joshAddress}, - []crypto.Signer{b.RootKey().Signer(), joshSigner}, + []flow.Address{b.ServiceKey().Address, joshAddress}, + []crypto.Signer{b.ServiceKey().Signer(), joshSigner}, false, ) tx = flow.NewTransaction(). - SetScript(GenerateTransferVaultScript(fungibleAddr, flowAddr, joshAddress, 300)). + SetScript(GenerateTransferVaultScript(fungibleAddr, exampleTokenAddr, joshAddress, "ExampleToken", "exampleToken", 300)). SetGasLimit(100). - SetProposalKey(b.RootKey().Address, b.RootKey().ID, b.RootKey().SequenceNumber). - SetPayer(b.RootKey().Address). - AddAuthorizer(flowAddr) + SetProposalKey(b.ServiceKey().Address, b.ServiceKey().ID, b.ServiceKey().SequenceNumber). + SetPayer(b.ServiceKey().Address). + AddAuthorizer(exampleTokenAddr) signAndSubmit( t, b, tx, - []flow.Address{b.RootKey().Address, flowAddr}, - []crypto.Signer{b.RootKey().Signer(), flowSigner}, + []flow.Address{b.ServiceKey().Address, exampleTokenAddr}, + []crypto.Signer{b.ServiceKey().Signer(), exampleTokenSigner}, false, ) t.Run("Should subtract tokens from supply when they are destroyed", func(t *testing.T) { tx := flow.NewTransaction(). - SetScript(GenerateDestroyVaultScript(fungibleAddr, flowAddr, 100)). + SetScript(GenerateDestroyVaultScript(fungibleAddr, exampleTokenAddr, "ExampleToken", "exampleToken", 100)). SetGasLimit(100). - SetProposalKey(b.RootKey().Address, b.RootKey().ID, b.RootKey().SequenceNumber). - SetPayer(b.RootKey().Address). - AddAuthorizer(flowAddr) + SetProposalKey(b.ServiceKey().Address, b.ServiceKey().ID, b.ServiceKey().SequenceNumber). + SetPayer(b.ServiceKey().Address). + AddAuthorizer(exampleTokenAddr) signAndSubmit( t, b, tx, - []flow.Address{b.RootKey().Address, flowAddr}, - []crypto.Signer{b.RootKey().Signer(), flowSigner}, + []flow.Address{b.ServiceKey().Address, exampleTokenAddr}, + []crypto.Signer{b.ServiceKey().Signer(), exampleTokenSigner}, false, ) // Assert that the vaults' balances are correct - executeScriptAndCheck(t, b, GenerateInspectVaultScript(fungibleAddr, flowAddr, flowAddr, 600)) + executeScriptAndCheck(t, b, GenerateInspectVaultScript(fungibleAddr, exampleTokenAddr, exampleTokenAddr, "ExampleToken", "exampleToken", 600)) - executeScriptAndCheck(t, b, GenerateInspectSupplyScript(fungibleAddr, flowAddr, 900)) + executeScriptAndCheck(t, b, GenerateInspectSupplyScript(fungibleAddr, exampleTokenAddr, "ExampleToken", 900)) }) t.Run("Should subtract tokens from supply when they are destroyed by a different account", func(t *testing.T) { tx := flow.NewTransaction(). - SetScript(GenerateDestroyVaultScript(fungibleAddr, flowAddr, 100)). + SetScript(GenerateDestroyVaultScript(fungibleAddr, exampleTokenAddr, "ExampleToken", "exampleToken", 100)). SetGasLimit(100). - SetProposalKey(b.RootKey().Address, b.RootKey().ID, b.RootKey().SequenceNumber). - SetPayer(b.RootKey().Address). + SetProposalKey(b.ServiceKey().Address, b.ServiceKey().ID, b.ServiceKey().SequenceNumber). + SetPayer(b.ServiceKey().Address). AddAuthorizer(joshAddress) signAndSubmit( t, b, tx, - []flow.Address{b.RootKey().Address, joshAddress}, - []crypto.Signer{b.RootKey().Signer(), joshSigner}, + []flow.Address{b.ServiceKey().Address, joshAddress}, + []crypto.Signer{b.ServiceKey().Signer(), joshSigner}, false, ) // Assert that the vaults' balances are correct - executeScriptAndCheck(t, b, GenerateInspectVaultScript(fungibleAddr, flowAddr, joshAddress, 200)) + executeScriptAndCheck(t, b, GenerateInspectVaultScript(fungibleAddr, exampleTokenAddr, joshAddress, "ExampleToken", "exampleToken", 200)) - executeScriptAndCheck(t, b, GenerateInspectSupplyScript(fungibleAddr, flowAddr, 800)) + executeScriptAndCheck(t, b, GenerateInspectSupplyScript(fungibleAddr, exampleTokenAddr, "ExampleToken", 800)) }) } @@ -289,231 +241,139 @@ func TestMintingAndBurning(t *testing.T) { accountKeys := test.AccountKeyGenerator() - // Should be able to deploy a contract as a new account with no keys. - fungibleTokenCode := readFile(fungibleTokenContractFile) - fungibleAddr, err := b.CreateAccount(nil, fungibleTokenCode) - assert.NoError(t, err) - _, err = b.CommitBlock() - assert.NoError(t, err) - - // Should be able to deploy a contract as a new account with no keys. - flowTokenCode := readFile(flowTokenContractFile) - flowAccountKey, flowSigner := accountKeys.NewWithSigner() - flowAddr, err := b.CreateAccount([]*flow.AccountKey{flowAccountKey}, flowTokenCode) - assert.NoError(t, err) - _, err = b.CommitBlock() - assert.NoError(t, err) + exampleTokenAccountKey, exampleTokenSigner := accountKeys.NewWithSigner() + fungibleAddr, exampleTokenAddr := DeployTokenContracts(b, t, []*flow.AccountKey{exampleTokenAccountKey}) joshAccountKey, joshSigner := accountKeys.NewWithSigner() joshAddress, _ := b.CreateAccount([]*flow.AccountKey{joshAccountKey}, nil) // then deploy the tokens to an account tx := flow.NewTransaction(). - SetScript(GenerateCreateTokenScript(fungibleAddr, flowAddr)). + SetScript(GenerateCreateTokenScript(fungibleAddr, exampleTokenAddr, "ExampleToken", "exampleToken")). SetGasLimit(100). - SetProposalKey(b.RootKey().Address, b.RootKey().ID, b.RootKey().SequenceNumber). - SetPayer(b.RootKey().Address). + SetProposalKey(b.ServiceKey().Address, b.ServiceKey().ID, b.ServiceKey().SequenceNumber). + SetPayer(b.ServiceKey().Address). AddAuthorizer(joshAddress) signAndSubmit( t, b, tx, - []flow.Address{b.RootKey().Address, joshAddress}, - []crypto.Signer{b.RootKey().Signer(), joshSigner}, + []flow.Address{b.ServiceKey().Address, joshAddress}, + []crypto.Signer{b.ServiceKey().Signer(), joshSigner}, false, ) t.Run("Shouldn't be able to mint zero tokens", func(t *testing.T) { tx := flow.NewTransaction(). - SetScript(GenerateMintTokensScript(fungibleAddr, flowAddr, joshAddress, 0)). + SetScript(GenerateMintTokensScript(fungibleAddr, exampleTokenAddr, joshAddress, "ExampleToken", "exampleToken", 0)). SetGasLimit(100). - SetProposalKey(b.RootKey().Address, b.RootKey().ID, b.RootKey().SequenceNumber). - SetPayer(b.RootKey().Address). - AddAuthorizer(flowAddr) + SetProposalKey(b.ServiceKey().Address, b.ServiceKey().ID, b.ServiceKey().SequenceNumber). + SetPayer(b.ServiceKey().Address). + AddAuthorizer(exampleTokenAddr) signAndSubmit( t, b, tx, - []flow.Address{b.RootKey().Address, flowAddr}, - []crypto.Signer{b.RootKey().Signer(), flowSigner}, + []flow.Address{b.ServiceKey().Address, exampleTokenAddr}, + []crypto.Signer{b.ServiceKey().Signer(), exampleTokenSigner}, true, ) // Assert that the vaults' balances are correct - executeScriptAndCheck(t, b, GenerateInspectVaultScript(fungibleAddr, flowAddr, flowAddr, 1000)) + executeScriptAndCheck(t, b, GenerateInspectVaultScript(fungibleAddr, exampleTokenAddr, exampleTokenAddr, "ExampleToken", "exampleToken", 1000)) // Assert that the vaults' balances are correct - executeScriptAndCheck(t, b, GenerateInspectVaultScript(fungibleAddr, flowAddr, joshAddress, 0)) + executeScriptAndCheck(t, b, GenerateInspectVaultScript(fungibleAddr, exampleTokenAddr, joshAddress, "ExampleToken", "exampleToken", 0)) - executeScriptAndCheck(t, b, GenerateInspectSupplyScript(fungibleAddr, flowAddr, 1000)) + executeScriptAndCheck(t, b, GenerateInspectSupplyScript(fungibleAddr, exampleTokenAddr, "ExampleToken", 1000)) }) t.Run("Shouldn't be able to mint more than the allowed amount", func(t *testing.T) { tx := flow.NewTransaction(). - SetScript(GenerateMintTokensScript(fungibleAddr, flowAddr, joshAddress, 101)). + SetScript(GenerateMintTokensScript(fungibleAddr, exampleTokenAddr, joshAddress, "ExampleToken", "exampleToken", 101)). SetGasLimit(100). - SetProposalKey(b.RootKey().Address, b.RootKey().ID, b.RootKey().SequenceNumber). - SetPayer(b.RootKey().Address). - AddAuthorizer(flowAddr) + SetProposalKey(b.ServiceKey().Address, b.ServiceKey().ID, b.ServiceKey().SequenceNumber). + SetPayer(b.ServiceKey().Address). + AddAuthorizer(exampleTokenAddr) signAndSubmit( t, b, tx, - []flow.Address{b.RootKey().Address, flowAddr}, - []crypto.Signer{b.RootKey().Signer(), flowSigner}, + []flow.Address{b.ServiceKey().Address, exampleTokenAddr}, + []crypto.Signer{b.ServiceKey().Signer(), exampleTokenSigner}, true, ) // Assert that the vaults' balances are correct - executeScriptAndCheck(t, b, GenerateInspectVaultScript(fungibleAddr, flowAddr, flowAddr, 1000)) + executeScriptAndCheck(t, b, GenerateInspectVaultScript(fungibleAddr, exampleTokenAddr, exampleTokenAddr, "ExampleToken", "exampleToken", 1000)) // Assert that the vaults' balances are correct - executeScriptAndCheck(t, b, GenerateInspectVaultScript(fungibleAddr, flowAddr, joshAddress, 0)) + executeScriptAndCheck(t, b, GenerateInspectVaultScript(fungibleAddr, exampleTokenAddr, joshAddress, "ExampleToken", "exampleToken", 0)) - executeScriptAndCheck(t, b, GenerateInspectSupplyScript(fungibleAddr, flowAddr, 1000)) + executeScriptAndCheck(t, b, GenerateInspectSupplyScript(fungibleAddr, exampleTokenAddr, "ExampleToken", 1000)) }) t.Run("Should mint tokens, deposit, and update balance and total supply", func(t *testing.T) { tx := flow.NewTransaction(). - SetScript(GenerateMintTokensScript(fungibleAddr, flowAddr, joshAddress, 50)). + SetScript(GenerateMintTokensScript(fungibleAddr, exampleTokenAddr, joshAddress, "ExampleToken", "exampleToken", 50)). SetGasLimit(100). - SetProposalKey(b.RootKey().Address, b.RootKey().ID, b.RootKey().SequenceNumber). - SetPayer(b.RootKey().Address). - AddAuthorizer(flowAddr) + SetProposalKey(b.ServiceKey().Address, b.ServiceKey().ID, b.ServiceKey().SequenceNumber). + SetPayer(b.ServiceKey().Address). + AddAuthorizer(exampleTokenAddr) signAndSubmit( t, b, tx, - []flow.Address{b.RootKey().Address, flowAddr}, - []crypto.Signer{b.RootKey().Signer(), flowSigner}, + []flow.Address{b.ServiceKey().Address, exampleTokenAddr}, + []crypto.Signer{b.ServiceKey().Signer(), exampleTokenSigner}, false, ) // Assert that the vaults' balances are correct - executeScriptAndCheck(t, b, GenerateInspectVaultScript(fungibleAddr, flowAddr, flowAddr, 1000)) + executeScriptAndCheck(t, b, GenerateInspectVaultScript(fungibleAddr, exampleTokenAddr, exampleTokenAddr, "ExampleToken", "exampleToken", 1000)) // Assert that the vaults' balances are correct - executeScriptAndCheck(t, b, GenerateInspectVaultScript(fungibleAddr, flowAddr, joshAddress, 50)) + executeScriptAndCheck(t, b, GenerateInspectVaultScript(fungibleAddr, exampleTokenAddr, joshAddress, "ExampleToken", "exampleToken", 50)) - executeScriptAndCheck(t, b, GenerateInspectSupplyScript(fungibleAddr, flowAddr, 1050)) + executeScriptAndCheck(t, b, GenerateInspectSupplyScript(fungibleAddr, exampleTokenAddr, "ExampleToken", 1050)) }) t.Run("Should burn tokens and update balance and total supply", func(t *testing.T) { tx := flow.NewTransaction(). - SetScript(GenerateBurnTokensScript(fungibleAddr, flowAddr, 50)). + SetScript(GenerateBurnTokensScript(fungibleAddr, exampleTokenAddr, "ExampleToken", "exampleToken", 50)). SetGasLimit(100). - SetProposalKey(b.RootKey().Address, b.RootKey().ID, b.RootKey().SequenceNumber). - SetPayer(b.RootKey().Address). - AddAuthorizer(flowAddr) + SetProposalKey(b.ServiceKey().Address, b.ServiceKey().ID, b.ServiceKey().SequenceNumber). + SetPayer(b.ServiceKey().Address). + AddAuthorizer(exampleTokenAddr) signAndSubmit( t, b, tx, - []flow.Address{b.RootKey().Address, flowAddr}, - []crypto.Signer{b.RootKey().Signer(), flowSigner}, + []flow.Address{b.ServiceKey().Address, exampleTokenAddr}, + []crypto.Signer{b.ServiceKey().Signer(), exampleTokenSigner}, false, ) // Assert that the vaults' balances are correct - executeScriptAndCheck(t, b, GenerateInspectVaultScript(fungibleAddr, flowAddr, flowAddr, 950)) + executeScriptAndCheck(t, b, GenerateInspectVaultScript(fungibleAddr, exampleTokenAddr, exampleTokenAddr, "ExampleToken", "exampleToken", 950)) - executeScriptAndCheck(t, b, GenerateInspectSupplyScript(fungibleAddr, flowAddr, 1000)) + executeScriptAndCheck(t, b, GenerateInspectSupplyScript(fungibleAddr, exampleTokenAddr, "ExampleToken", 1000)) }) } -func TestTokenAdministrator(t *testing.T) { - b := newEmulator() +func DeployTokenContracts(b *emulator.Blockchain, t *testing.T, key []*flow.AccountKey) (flow.Address, flow.Address) { // Should be able to deploy a contract as a new account with no keys. - fungibleTokenCode := readFile(fungibleTokenContractFile) - _, err := b.CreateAccount(nil, fungibleTokenCode) + fungibleTokenCode := contracts.FungibleToken() + fungibleAddr, err := b.CreateAccount(nil, fungibleTokenCode) assert.NoError(t, err) _, err = b.CommitBlock() assert.NoError(t, err) - // Should be able to deploy a contract as a new account with no keys. - flowTokenCode := readFile(flowTokenContractFile) - - setupScript := fmt.Sprintf(` - transaction { - prepare(signer: AuthAccount) { - let flowTokenAcct = AuthAccount(payer: signer) - - let admin = signer - flowTokenAcct.setCode("%s".decodeHex(), admin) - } - } - `, hex.EncodeToString(flowTokenCode)) - - setupTx := flow.NewTransaction(). - SetScript([]byte(setupScript)). - AddAuthorizer(b.RootKey().Address). - SetPayer(b.RootKey().Address). - SetProposalKey(b.RootKey().Address, b.RootKey().ID, b.RootKey().SequenceNumber) + exampleTokenCode := readFile("../src/contracts/ExampleToken.cdc") + codeWithFTAddr := strings.ReplaceAll(string(exampleTokenCode), "02", fungibleAddr.String()) - err = setupTx.SignEnvelope(b.RootKey().Address, b.RootKey().ID, b.RootKey().Signer()) - require.NoError(t, err) - - err = b.AddTransaction(*setupTx) - require.NoError(t, err) - - result, err := b.ExecuteNextTransaction() - require.NoError(t, err) - - if !assert.Nil(t, result.Error) { - t.Fatal(result.Error) - } + tokenAddr, err := b.CreateAccount(key, []byte(codeWithFTAddr)) + assert.NoError(t, err) _, err = b.CommitBlock() - require.NoError(t, err) - - mintScript := ` - import FungibleToken from 0x02 - import FlowToken from 0x06 - - transaction { - let tokenAdmin: &FlowToken.Administrator - let tokenReceiver: &FlowToken.Vault{FungibleToken.Receiver} - - prepare(signer: AuthAccount) { - self.tokenAdmin = signer - .borrow<&FlowToken.Administrator>(from: /storage/flowTokenAdmin) - ?? panic("Signer is not the token admin") - - self.tokenReceiver = signer - .getCapability(/public/flowTokenReceiver)! - .borrow<&FlowToken.Vault{FungibleToken.Receiver}>() - ?? panic("Unable to borrow receiver reference") - } - - execute { - let minter <- self.tokenAdmin.createNewMinter(allowedAmount: 100.0) - let mintedVault <- minter.mintTokens(amount: 100.0) - - self.tokenReceiver.deposit(from: <-mintedVault) - - log("Minted 100 tokens and deposited to admin account") - - destroy minter - } - } - ` - - mintTx := flow.NewTransaction(). - SetScript([]byte(mintScript)). - AddAuthorizer(b.RootKey().Address). - SetPayer(b.RootKey().Address). - SetProposalKey(b.RootKey().Address, b.RootKey().ID, b.RootKey().SequenceNumber) - - err = mintTx.SignEnvelope(b.RootKey().Address, b.RootKey().ID, b.RootKey().Signer()) - require.NoError(t, err) - - err = b.AddTransaction(*mintTx) - require.NoError(t, err) - - result, err = b.ExecuteNextTransaction() - require.NoError(t, err) - - if !assert.Nil(t, result.Error) { - t.Fatal(result.Error) - } + assert.NoError(t, err) - _, err = b.CommitBlock() - require.NoError(t, err) + return fungibleAddr, tokenAddr }