From 8fc6e0417bd00b032a8fef890d3d1dd90b8882b9 Mon Sep 17 00:00:00 2001 From: danishtroon Date: Wed, 23 Feb 2022 11:28:42 +0000 Subject: [PATCH 1/5] integrate the usdc-token with socialtoken --- .env | 6 + flow1.json | 99 +++ tasks/deploy/USDC.go | 255 ++++++++ tasks/deploy/util.go | 605 ++++++++++++++++++ tasks/deploy_usdc_social/main.go | 270 ++++++++ transactions/deploy_contract_with_auth.cdc | 138 ++++ transactions/deploy_social_token.cdc | 17 + .../transfer_flow_tokens_emulator.cdc | 44 ++ transactions/upgrade_contract.cdc | 18 + 9 files changed, 1452 insertions(+) create mode 100644 .env create mode 100644 flow1.json create mode 100644 tasks/deploy/USDC.go create mode 100644 tasks/deploy/util.go create mode 100644 tasks/deploy_usdc_social/main.go create mode 100644 transactions/deploy_contract_with_auth.cdc create mode 100644 transactions/deploy_social_token.cdc create mode 100644 transactions/transfer_flow_tokens_emulator.cdc create mode 100644 transactions/upgrade_contract.cdc diff --git a/.env b/.env new file mode 100644 index 0000000..ed1499e --- /dev/null +++ b/.env @@ -0,0 +1,6 @@ +# Emulator +# -------- +NETWORK=emulator +RPC_ADDRESS=localhost:3569 +OWNER_ADDRESS=f8d6e0586b0a20c7 +FUNGIBLE_TOKEN_ADDRESS=ee82856bf20e2aa6 \ No newline at end of file diff --git a/flow1.json b/flow1.json new file mode 100644 index 0000000..abdfd45 --- /dev/null +++ b/flow1.json @@ -0,0 +1,99 @@ +{ + + "emulators": { + "default": { + "port": 3569, + "serviceAccount": "emulator-account" + } + }, + "contracts": { + "Debug": "./contracts/Debug.cdc", + "SocialToken": { + "source": "./contracts/SocialToken.cdc", + "aliases": { + "emulator": "0x0ae53cb6e3f42a79", + "testnet": "0x7e60df042a9c0868" + } + }, + "FungibleToken": { + "source": "./contracts/FungibleToken.cdc", + "aliases": { + "emulator": "0xee82856bf20e2aa6", + "testnet": "0x9a0766d93b6608b7" + } + }, + "FUSD": { + "source": "./contracts/FUSD.cdc", + "aliases": { + "emulator": "0x0ae53cb6e3f42a79", + "testnet": "0x7e60df042a9c0868" + } + }, + "Controller": { + "source": "./contracts/Controller.cdc", + "aliases": { + "emulator": "0x0ae53cb6e3f42a79", + "testnet": "0x7e60df042a9c0868" + } + }, + "FiatTokenInterface": { + "source": "./contracts/FiatTokenInterface.cdc", + "aliases": { + "emulator": "0x0ae53cb6e3f42a79", + "testnet": "0x7e60df042a9c0868" + } + }, + "OnChainMultiSig": { + "source": "./contracts/OnChainMultiSig.cdc", + "aliases": { + "emulator": "0x0ae53cb6e3f42a79", + "testnet": "0x7e60df042a9c0868" + } + } + }, + "networks": { + "emulator": "127.0.0.1:3569", + "mainnet": "access.mainnet.nodes.onflow.org:9000", + "testnet": "access.devnet.nodes.onflow.org:9000" + }, + "accounts": { + "emulator-account": { + "address": "f8d6e0586b0a20c7", + "key": "dc0097a6b58533e56af78c955e7b0c0f386b5f44f22b75c390beab7fcb1af13f" + }, + "emulator-first": { + "address": "01cf0e2f2f715450", + "key": "d5457a187e9642a8e49d4032b3b4f85c92da7202c79681d9302c6e444e7033a8" + }, + "emulator-second": { + "address": "179b6b1cb6755e31", + "key": "d5457a187e9642a8e49d4032b3b4f85c92da7202c79681d9302c6e444e7033a8" + }, + "emulator-3": { + "address": "f3fcd2c1a78f5eee", + "key": "d5457a187e9642a8e49d4032b3b4f85c92da7202c79681d9302c6e444e7033a8" + }, + "emulator-4": { + "address": "e03daebed8ca0615", + "key": "d5457a187e9642a8e49d4032b3b4f85c92da7202c79681d9302c6e444e7033a8" + }, + "emulator-5": { + "address": "045a1763c93006ca", + "key": "d5457a187e9642a8e49d4032b3b4f85c92da7202c79681d9302c6e444e7033a8" + } + }, + "deployments": { + "emulator": { + "emulator-account": [ + "FungibleToken", + "FUSD", + "Controller", + "FiatTokenInterface", + "OnChainMultiSig", + "SocialToken" + ], + "emulator-first": [], + "emulator-second": [] + } + } +} \ No newline at end of file diff --git a/tasks/deploy/USDC.go b/tasks/deploy/USDC.go new file mode 100644 index 0000000..78a22b2 --- /dev/null +++ b/tasks/deploy/USDC.go @@ -0,0 +1,255 @@ +package main + +import ( + "fmt" + "log" + "bytes" + "io/ioutil" + "os" + "time" + + "text/template" + "encoding/hex" + + + "github.com/onflow/cadence" + + "github.com/bjartek/go-with-the-flow/v2/gwtf" + + "github.com/onflow/flow-go-sdk" +) + +// func CallUSDCMain(){ + +// _, err := DeployFiatTokenContract(g, "owner", "USDC", "0.1.0") +// fmt.Println("err: ", err) +// if err != nil { +// log.Fatal("Cannot deploy contract") +// } +// } + +func main() { + // This relative path to flow.json is different in tests as it is the main package + // jsonPath := ".././flow.json" + + // var flowJSON []string = []string{jsonPath} + // g := gwtf.NewGoWithTheFlow(flowJSON, os.Getenv("NETWORK"), false, 3) + g := gwtf.NewGoWithTheFlowInMemoryEmulator() + + _, err := DeployFiatTokenContract(g, "owner", "USDC", "0.1.0") + fmt.Println("err: ", err) + if err != nil { + log.Fatal("Cannot deploy contract") + } +} + +// Useful multisig accounts +// These are named by the weights +// i.e. Account500_1 has a weight of 500.0 +const Acct1000 = "w-1000" +const Acct500_1 = "w-500-1" +const Acct500_2 = "w-500-2" +const Acct250_1 = "w-250-1" +const Acct250_2 = "w-250-2" +const Config = ".././flow.json" + +var FlowJSON []string = []string{Config} + +type Addresses struct { + FungibleToken string + FiatTokenInterface string + FiatToken string + OnChainMultiSig string +} + +type TestEvent struct { + Name string + Fields map[string]string +} + +var addresses Addresses + +func ParseCadenceTemplate(templatePath string) []byte { + fb, err := ioutil.ReadFile(templatePath) + if err != nil { + panic(err) + } + + tmpl, err := template.New("Template").Parse(string(fb)) + if err != nil { + panic(err) + } + + // Addresss for emulator are + // addresses = Addresses{"ee82856bf20e2aa6", "01cf0e2f2f715450", "01cf0e2f2f715450", "01cf0e2f2f715450", "01cf0e2f2f715450"} + addresses = Addresses{os.Getenv("FUNGIBLE_TOKEN_ADDRESS"), os.Getenv("OWNER_ADDRESS"), os.Getenv("OWNER_ADDRESS"), os.Getenv("OWNER_ADDRESS")} + + buf := &bytes.Buffer{} + err = tmpl.Execute(buf, addresses) + if err != nil { + panic(err) + } + + return buf.Bytes() +} + + +func GetMultiSigKeys(g *gwtf.GoWithTheFlow) (MultiSigPubKeys []cadence.Value, MultiSigKeyWeights []cadence.Value, MultiSigAlgos []cadence.Value) { + pk1000 := g.Account(Acct1000).Key().ToConfig().PrivateKey.PublicKey().String() + pk500_1 := g.Account(Acct500_1).Key().ToConfig().PrivateKey.PublicKey().String() + pk500_2 := g.Account(Acct500_2).Key().ToConfig().PrivateKey.PublicKey().String() + pk250_1 := g.Account(Acct250_1).Key().ToConfig().PrivateKey.PublicKey().String() + pk250_2 := g.Account(Acct250_2).Key().ToConfig().PrivateKey.PublicKey().String() + + w1000, _ := cadence.NewUFix64("1000.0") + w500, _ := cadence.NewUFix64("500.0") + w250, _ := cadence.NewUFix64("250.0") + + MultiSigPubKeys = []cadence.Value{ + cadence.String(pk1000[2:]), + cadence.String(pk500_1[2:]), + cadence.String(pk500_2[2:]), + cadence.String(pk250_1[2:]), + cadence.String(pk250_2[2:]), + } + + MultiSigAlgos = []cadence.Value{ + cadence.NewUInt8(1), + cadence.NewUInt8(1), + cadence.NewUInt8(1), + cadence.NewUInt8(1), + cadence.NewUInt8(1), + } + MultiSigKeyWeights = []cadence.Value{w1000, w500, w500, w250, w250} + return +} + +func ParseTestEvents(events []flow.Event) (formatedEvents []*gwtf.FormatedEvent) { + for _, e := range events { + formatedEvents = append(formatedEvents, gwtf.ParseEvent(e, uint64(0), time.Now(), nil)) + } + return +} + + +func DeployFiatTokenContract( + g *gwtf.GoWithTheFlow, + ownerAcct string, tokenName string, version string) (events []*gwtf.FormatedEvent, err error) { + + contractCode := ParseCadenceTemplate("././contracts/FiatToken.cdc") + + + txFilename := "deploy_contract_with_auth" + fmt.Println("parse template", txFilename) + //code := ParseCadenceTemplate(txFilename) + encodedStr := hex.EncodeToString(contractCode) + + if g.Network == "emulator" { + g.CreateAccounts("emulator-account") + } + fmt.Println("Accounts created") + multiSigPubKeys, multiSigKeyWeights, multiSigAlgos := GetMultiSigKeys(g) + fmt.Println("keys created") + e, err := g.TransactionFromFile(txFilename). + SignProposeAndPayAs(ownerAcct). + StringArgument("FiatToken"). + StringArgument(encodedStr). + // Vault + Argument(cadence.Path{Domain: "storage", Identifier: "USDCVault-2"}). + Argument(cadence.Path{Domain: "public", Identifier: "USDCVaultBalance-2"}). + Argument(cadence.Path{Domain: "public", Identifier: "USDCVaultUUID-2"}). + Argument(cadence.Path{Domain: "public", Identifier: "USDCVaultReceiver-2"}). + + // Blocklist executor + Argument(cadence.Path{Domain: "storage", Identifier: "USDCBlocklistExe-2"}). + // Blocklister + Argument(cadence.Path{Domain: "storage", Identifier: "USDCBlocklister-2"}). + Argument(cadence.Path{Domain: "public", Identifier: "USDCBlocklisterCapReceiver-2"}). + Argument(cadence.Path{Domain: "public", Identifier: "USDCBlocklisterUUID-2"}). + Argument(cadence.Path{Domain: "public", Identifier: "USDCBlocklisterPublicSigner-2"}). + // Pause executor + Argument(cadence.Path{Domain: "storage", Identifier: "USDCPauseExe-2"}). + // Pauser + Argument(cadence.Path{Domain: "storage", Identifier: "USDCPauser-2"}). + Argument(cadence.Path{Domain: "public", Identifier: "USDCPauserCapReceiver-2"}). + Argument(cadence.Path{Domain: "public", Identifier: "USDCPauserUUID-2"}). + Argument(cadence.Path{Domain: "public", Identifier: "USDCPauserPublicSigner-2"}). + // Admin executor + Argument(cadence.Path{Domain: "storage", Identifier: "USDCAdminExe-2"}). + //Admin + Argument(cadence.Path{Domain: "storage", Identifier: "USDCAdmin-2"}). + Argument(cadence.Path{Domain: "public", Identifier: "USDCAdminCapReceiver-2"}). + Argument(cadence.Path{Domain: "public", Identifier: "USDCAdminUUID-2"}). + Argument(cadence.Path{Domain: "public", Identifier: "USDCAdminPublicSigner-2"}). + // Owner executor + Argument(cadence.Path{Domain: "storage", Identifier: "USDCOwnerExe-2"}). + // Owner + Argument(cadence.Path{Domain: "storage", Identifier: "USDCOwner-2"}). + Argument(cadence.Path{Domain: "public", Identifier: "USDCOwnerCapReceiver-2"}). + Argument(cadence.Path{Domain: "public", Identifier: "USDCOwnerUUID-2"}). + Argument(cadence.Path{Domain: "public", Identifier: "USDCOwnerPubSigner-2"}). + // Master Minter Executor + Argument(cadence.Path{Domain: "storage", Identifier: "USDCMasterMinterExe-2"}). + // Master Minter + Argument(cadence.Path{Domain: "storage", Identifier: "USDCMasterMinter-2"}). + Argument(cadence.Path{Domain: "public", Identifier: "USDCMasterMinterCapReceiver-2"}). + Argument(cadence.Path{Domain: "public", Identifier: "USDCMasterMinterPublicSigner-2"}). + Argument(cadence.Path{Domain: "public", Identifier: "USDCMasterMinterUUID-2"}). + // Minter Controller + Argument(cadence.Path{Domain: "storage", Identifier: "USDCMinterController-2"}). + Argument(cadence.Path{Domain: "public", Identifier: "USDCMinterControllerUUID-2"}). + Argument(cadence.Path{Domain: "public", Identifier: "USDCMinterControllerPublicSigner-2"}). + // Minter + Argument(cadence.Path{Domain: "storage", Identifier: "USDCMinter-2"}). + Argument(cadence.Path{Domain: "public", Identifier: "USDCMinterUUID-2"}). + // Initial resource capabilities + Argument(cadence.Path{Domain: "private", Identifier: "USDCAdminCap-2"}). + Argument(cadence.Path{Domain: "private", Identifier: "USDCOwnerCap-2"}). + Argument(cadence.Path{Domain: "private", Identifier: "USDCMasterMinterCap-2"}). + Argument(cadence.Path{Domain: "private", Identifier: "USDCPauserCap-2"}). + Argument(cadence.Path{Domain: "private", Identifier: "USDCBlocklisterCap-2"}). + StringArgument(tokenName). + StringArgument(version). + UFix64Argument("1000000000.00000000"). + BooleanArgument(false). + Argument(cadence.NewArray(multiSigPubKeys)). + Argument(cadence.NewArray(multiSigKeyWeights)). + Argument(cadence.NewArray(multiSigAlgos)). + Argument(cadence.NewArray(multiSigPubKeys)). + Argument(cadence.NewArray(multiSigKeyWeights)). + Argument(cadence.NewArray(multiSigAlgos)). + Argument(cadence.NewArray(multiSigPubKeys)). + Argument(cadence.NewArray(multiSigKeyWeights)). + Argument(cadence.NewArray(multiSigAlgos)). + Argument(cadence.NewArray(multiSigPubKeys)). + Argument(cadence.NewArray(multiSigKeyWeights)). + Argument(cadence.NewArray(multiSigAlgos)). + Argument(cadence.NewArray(multiSigPubKeys)). + Argument(cadence.NewArray(multiSigKeyWeights)). + Argument(cadence.NewArray(multiSigAlgos)). + RunE() + gwtf.PrintEvents(e, map[string][]string{}) + events = ParseTestEvents(e) + + return +} + +func UpgradeFiatTokenContract( + g *gwtf.GoWithTheFlow, + ownerAcct string, version string) (events []*gwtf.FormatedEvent, err error) { + contractCode := ParseCadenceTemplate("../../../contracts/FiatToken.cdc") + txFilename := "../../../transactions/upgrade_contract.cdc" + //code := ParseCadenceTemplate(txFilename) + encodedStr := hex.EncodeToString(contractCode) + + e, err := g.TransactionFromFile(txFilename). + SignProposeAndPayAs(ownerAcct). + StringArgument("FiatToken"). + StringArgument(encodedStr). + StringArgument(version). + RunE() + gwtf.PrintEvents(e, map[string][]string{}) + events = ParseTestEvents(e) + + return +} diff --git a/tasks/deploy/util.go b/tasks/deploy/util.go new file mode 100644 index 0000000..8ce2d0b --- /dev/null +++ b/tasks/deploy/util.go @@ -0,0 +1,605 @@ +package util + +import ( + "bytes" + "encoding/hex" + "errors" + "io/ioutil" + "os" + "testing" + "time" + + "text/template" + + "github.com/bjartek/go-with-the-flow/v2/gwtf" + "github.com/onflow/cadence" + "github.com/onflow/flow-go-sdk" + "github.com/onflow/flow-go-sdk/crypto" + "github.com/stretchr/testify/assert" +) + +// Useful multisig accounts +// These are named by the weights +// i.e. Account500_1 has a weight of 500.0 +const Acct1000 = "w-1000" +const Acct500_1 = "w-500-1" +const Acct500_2 = "w-500-2" +const Acct250_1 = "w-250-1" +const Acct250_2 = "w-250-2" +const Config = "../.././flow.json" + +var FlowJSON []string = []string{Config} + +type Addresses struct { + FungibleToken string + FiatTokenInterface string + FiatToken string + OnChainMultiSig string +} + +type TestEvent struct { + Name string + Fields map[string]string +} + +var addresses Addresses + +func ParseCadenceTemplate(templatePath string) []byte { + fb, err := ioutil.ReadFile(templatePath) + if err != nil { + panic(err) + } + + tmpl, err := template.New("Template").Parse(string(fb)) + if err != nil { + panic(err) + } + + // Addresss for emulator are + // addresses = Addresses{"ee82856bf20e2aa6", "01cf0e2f2f715450", "01cf0e2f2f715450", "01cf0e2f2f715450", "01cf0e2f2f715450"} + addresses = Addresses{os.Getenv("FUNGIBLE_TOKEN_ADDRESS"), os.Getenv("OWNER_ADDRESS"), os.Getenv("OWNER_ADDRESS"), os.Getenv("OWNER_ADDRESS")} + + buf := &bytes.Buffer{} + err = tmpl.Execute(buf, addresses) + if err != nil { + panic(err) + } + + return buf.Bytes() +} + +func ParseTestEvents(events []flow.Event) (formatedEvents []*gwtf.FormatedEvent) { + for _, e := range events { + formatedEvents = append(formatedEvents, gwtf.ParseEvent(e, uint64(0), time.Now(), nil)) + } + return +} + +func NewExpectedEvent(contract string, name string) TestEvent { + return TestEvent{ + Name: "A." + addresses.FiatToken + "." + contract + "." + name, + Fields: map[string]string{}, + } +} + +func (te TestEvent) AddField(fieldName string, fieldValue string) TestEvent { + te.Fields[fieldName] = fieldValue + return te +} + +func (te TestEvent) AssertHasKey(t *testing.T, event *gwtf.FormatedEvent, key string) { + assert.Equal(t, event.Name, te.Name) + _, exist := event.Fields[key] + assert.Equal(t, true, exist) +} + +func (te TestEvent) AssertEqual(t *testing.T, event *gwtf.FormatedEvent) { + assert.Equal(t, event.Name, te.Name) + assert.Equal(t, len(te.Fields), len(event.Fields)) + for k := range te.Fields { + assert.Equal(t, te.Fields[k], event.Fields[k]) + } +} + +// Gets the address in the format of a hex string from an account name +func GetAccountAddr(g *gwtf.GoWithTheFlow, name string) string { + address := g.Account(name).Address().String() + zeroPrefix := "0" + if string(address[0]) == zeroPrefix { + address = address[1:] + } + return "0x" + address +} + +func ReadCadenceCode(ContractPath string) []byte { + b, err := ioutil.ReadFile(ContractPath) + if err != nil { + panic(err) + } + return b +} + +func GetTotalSupply(g *gwtf.GoWithTheFlow) (result cadence.UFix64, err error) { + filename := "../../../scripts/contract/get_total_supply.cdc" + script := ParseCadenceTemplate(filename) + r, err := g.ScriptFromFile(filename, script).RunReturns() + result = r.(cadence.UFix64) + return +} + +func GetName(g *gwtf.GoWithTheFlow) (result string, err error) { + filename := "../../../scripts/contract/get_name.cdc" + script := ParseCadenceTemplate(filename) + r, err := g.ScriptFromFile(filename, script).RunReturns() + result = r.ToGoValue().(string) + return +} + +func GetVersion(g *gwtf.GoWithTheFlow) (result string, err error) { + filename := "../../../scripts/contract/get_version.cdc" + script := ParseCadenceTemplate(filename) + r, err := g.ScriptFromFile(filename, script).RunReturns() + result = r.ToGoValue().(string) + return +} + +func GetBalance(g *gwtf.GoWithTheFlow, account string) (result cadence.UFix64, err error) { + filename := "../../../scripts/vault/get_balance.cdc" + script := ParseCadenceTemplate(filename) + value, err := g.ScriptFromFile(filename, script).AccountArgument(account).RunReturns() + if err != nil { + return + } + result = value.(cadence.UFix64) + return +} + +func GetUUID(g *gwtf.GoWithTheFlow, account string, resourceName string) (r uint64, err error) { + filename := "../../../scripts/contract/get_resource_uuid.cdc" + script := ParseCadenceTemplate(filename) + value, err := g.ScriptFromFile(filename, script).AccountArgument(account).StringArgument(resourceName).RunReturns() + if err != nil { + return + } + r, ok := value.ToGoValue().(uint64) + if !ok { + err = errors.New("returned not uint64") + } + return +} + +func ConvertCadenceByteArray(a cadence.Value) (b []uint8) { + // type assertion of interface + i := a.ToGoValue().([]interface{}) + + for _, e := range i { + // type assertion of uint8 + b = append(b, e.(uint8)) + } + return + +} + +func ConvertCadenceStringArray(a cadence.Value) (b []string) { + // type assertion of interface + i := a.ToGoValue().([]interface{}) + + for _, e := range i { + b = append(b, e.(string)) + } + return +} + +// Multisig utility functions and type + +// Arguement for Multisig functions `Multisig_SignAndSubmit` +// This allows for generic functions to type cast the arguments into +// correct cadence types. +// i.e. for a cadence.UFix64, Arg {V: "12.00", T: "UFix64"} +type Arg struct { + V interface{} + T string +} + +// Signing payload offline +func SignPayloadOffline(g *gwtf.GoWithTheFlow, message []byte, signingAcct string) (sig string, err error) { + s := g.Account(signingAcct).Key().ToConfig() + signer := crypto.NewInMemorySigner(s.PrivateKey, s.HashAlgo) + message = append(flow.UserDomainTag[:], message...) + sigbytes, err := signer.Sign(message) + if err != nil { + return + } + + sig = hex.EncodeToString(sigbytes) + return +} + +func GetSignableDataFromScript( + g *gwtf.GoWithTheFlow, + txIndex uint64, + method string, + args ...cadence.Value, +) (signable []byte, err error) { + filename := "../../../scripts/calc_signable_data.cdc" + script := ParseCadenceTemplate(filename) + + ctxIndex, err := g.ScriptFromFile(filename, script).Argument(cadence.NewOptional(cadence.UInt64(txIndex))).RunReturns() + if err != nil { + return + } + signable = append(signable, ConvertCadenceByteArray(ctxIndex)...) + cMethod, err := g.ScriptFromFile(filename, script).Argument(cadence.NewOptional(cadence.String(method))).RunReturns() + if err != nil { + return + } + signable = append(signable, ConvertCadenceByteArray(cMethod)...) + + for _, arg := range args { + var b cadence.Value + b, err = g.ScriptFromFile(filename, script).Argument(cadence.NewOptional(arg)).RunReturns() + if err != nil { + return nil, err + } + signable = append(signable, ConvertCadenceByteArray(b)...) + } + return +} + +func ConvertToCadenceValue(g *gwtf.GoWithTheFlow, args ...Arg) (a []cadence.Value, err error) { + for _, arg := range args { + var b cadence.Value + switch arg.T { + case "String": + b = cadence.String(arg.V.(string)) + case "UFix64": + b, err = cadence.NewUFix64(arg.V.(string)) + case "UInt8": + b = cadence.NewUInt8(arg.V.(uint8)) + case "UInt64": + b = cadence.UInt64(arg.V.(uint64)) + case "Address": + b = cadence.BytesToAddress(g.Account(arg.V.(string)).Address().Bytes()) + default: + err = errors.New("Type not supported") + } + a = append(a, b) + } + return +} + +func MultiSig_Sign( + g *gwtf.GoWithTheFlow, + txIndex uint64, + signerAcct string, + resourceAcct string, + resourceName string, + method string, + args ...Arg, +) (sig string, err error) { + + cadenceArgs, err := ConvertToCadenceValue(g, args...) + if err != nil { + return + } + + signable, err := GetSignableDataFromScript(g, txIndex, method, cadenceArgs...) + if err != nil { + return + } + + sig, err = SignPayloadOffline(g, signable, signerAcct) + return +} + +func MultiSig_SignAndSubmit( + g *gwtf.GoWithTheFlow, + newPayload bool, + txIndex uint64, + signerAcct string, + resourceAcct string, + resourceName string, + method string, + args ...Arg, +) (events []*gwtf.FormatedEvent, err error) { + + cadenceArgs, err := ConvertToCadenceValue(g, args...) + if err != nil { + return nil, err + } + + signable, err := GetSignableDataFromScript(g, txIndex, method, cadenceArgs...) + if err != nil { + return + } + + sig, err := SignPayloadOffline(g, signable, signerAcct) + if err != nil { + return + } + if newPayload { + return multiSig_NewPayload(g, sig, txIndex, method, cadenceArgs, signerAcct, resourceAcct, resourceName) + } else { + return multiSig_AddPayloadSignature(g, sig, txIndex, signerAcct, resourceAcct, resourceName) + } +} + +func multiSig_NewPayload( + g *gwtf.GoWithTheFlow, + sig string, + txIndex uint64, + method string, + args []cadence.Value, + signerAcct string, + resourceAcct string, + resourceName string, +) (events []*gwtf.FormatedEvent, err error) { + txFilename := "../../../transactions/onChainMultiSig/add_new_payload.cdc" + txScript := ParseCadenceTemplate(txFilename) + + path, err := GetPubSignerPath(g, resourceAcct, resourceName) + if err != nil { + return + } + signerPubKey := g.Account(signerAcct).Key().ToConfig().PrivateKey.PublicKey().String() + e, err := g.TransactionFromFile(txFilename, txScript). + SignProposeAndPayAs(signerAcct). + StringArgument(sig). + UInt64Argument(txIndex). + StringArgument(method). + Argument(cadence.NewArray(args)). + StringArgument(signerPubKey[2:]). + AccountArgument(resourceAcct). + Argument(path). + RunE() + events = ParseTestEvents(e) + return +} + +func MultiSig_SignAndSubmitNewPayload( + g *gwtf.GoWithTheFlow, + txIndex uint64, + signerAcct string, + resourceAcct string, + resourceName string, + method string, + args ...Arg, +) (events []*gwtf.FormatedEvent, err error) { + + cadenceArgs, err := ConvertToCadenceValue(g, args...) + if err != nil { + return nil, err + } + + signable, err := GetSignableDataFromScript(g, txIndex, method, cadenceArgs...) + if err != nil { + return + } + + sig, err := SignPayloadOffline(g, signable, signerAcct) + if err != nil { + return + } + + txFilename := "../../../transactions/onChainMultiSig/add_new_payload.cdc" + txScript := ParseCadenceTemplate(txFilename) + + path, err := GetPubSignerPath(g, resourceAcct, resourceName) + if err != nil { + return + } + signerPubKey := g.Account(signerAcct).Key().ToConfig().PrivateKey.PublicKey().String() + e, err := g.TransactionFromFile(txFilename, txScript). + SignProposeAndPayAs(signerAcct). + StringArgument(sig). + UInt64Argument(txIndex). + StringArgument(method). + Argument(cadence.NewArray(cadenceArgs)). + StringArgument(signerPubKey[2:]). + AccountArgument(resourceAcct). + Argument(path). + RunE() + events = ParseTestEvents(e) + return +} +func multiSig_AddPayloadSignature( + g *gwtf.GoWithTheFlow, + sig string, + txIndex uint64, + signerAcct string, + resourceAcct string, + resourceName string, +) (events []*gwtf.FormatedEvent, err error) { + txFilename := "../../../transactions/onChainMultiSig/add_payload_signature.cdc" + txScript := ParseCadenceTemplate(txFilename) + + path, err := GetPubSignerPath(g, resourceAcct, resourceName) + if err != nil { + return + } + signerPubKey := g.Account(signerAcct).Key().ToConfig().PrivateKey.PublicKey().String() + e, err := g.TransactionFromFile(txFilename, txScript). + SignProposeAndPayAs(signerAcct). + StringArgument(sig). + UInt64Argument(txIndex). + StringArgument(signerPubKey[2:]). + AccountArgument(resourceAcct). + Argument(path). + RunE() + events = ParseTestEvents(e) + return +} + +func MultiSig_ExecuteTx( + g *gwtf.GoWithTheFlow, + index uint64, + payerAcct string, + resourceAcct string, + resourceName string, +) (events []*gwtf.FormatedEvent, err error) { + txFilename := "../../../transactions/onChainMultiSig/executeTx.cdc" + txScript := ParseCadenceTemplate(txFilename) + + path, err := GetPubSignerPath(g, resourceAcct, resourceName) + if err != nil { + return + } + + e, err := g.TransactionFromFile(txFilename, txScript). + SignProposeAndPayAs(payerAcct). + UInt64Argument(index). + AccountArgument(resourceAcct). + Argument(path). + RunE() + events = ParseTestEvents(e) + return +} + +func MultiSig_SubmitMultiAndExecute( + g *gwtf.GoWithTheFlow, + sigs []string, + txIndex uint64, + signerAccts []string, + resourceAcct string, + resourceName string, + payerAcct string, + method string, + args ...Arg, +) (events []*gwtf.FormatedEvent, err error) { + txFilename := "../../../transactions/onChainMultiSig/add_and_execute.cdc" + txScript := ParseCadenceTemplate(txFilename) + + cadenceArgs, err := ConvertToCadenceValue(g, args...) + if err != nil { + return nil, err + } + + path, err := GetPubSignerPath(g, resourceAcct, resourceName) + if err != nil { + return + } + + var signerPubKeys []cadence.Value + var signatures []cadence.Value + var pk string + + for i := 0; i < len(sigs); i++ { + pk = g.Account(signerAccts[i]).Key().ToConfig().PrivateKey.PublicKey().String() + signerPubKeys = append(signerPubKeys, cadence.NewString(pk[2:])) + signatures = append(signatures, cadence.NewString(sigs[i])) + } + + sigs_array := cadence.NewArray(signatures) + pubkey_array := cadence.NewArray(signerPubKeys) + e, err := g.TransactionFromFile(txFilename, txScript). + SignProposeAndPayAs(payerAcct). + Argument(sigs_array). + UInt64Argument(txIndex). + StringArgument(method). + Argument(cadence.NewArray(cadenceArgs)). + Argument(pubkey_array). + AccountArgument(resourceAcct). + Argument(path). + RunE() + events = ParseTestEvents(e) + return +} + +func GetStoreKeys(g *gwtf.GoWithTheFlow, resourceAcct string, resourceName string) (result []string, err error) { + filename := "../../../scripts/onChainMultiSig/get_store_keys.cdc" + script := ParseCadenceTemplate(filename) + path, err := GetPubSignerPath(g, resourceAcct, resourceName) + if err != nil { + return + } + value, err := g.ScriptFromFile(filename, script).AccountArgument(resourceAcct).Argument(path).RunReturns() + if err != nil { + return + } + result = ConvertCadenceStringArray(value) + return +} + +func GetKeyWeight(g *gwtf.GoWithTheFlow, signerAcct string, resourceAcct string, resourceName string) (result cadence.UFix64, err error) { + filename := "../../../scripts/onChainMultiSig/get_key_weight.cdc" + script := ParseCadenceTemplate(filename) + signerPubKey := g.Account(signerAcct).Key().ToConfig().PrivateKey.PublicKey().String()[2:] + path, err := GetPubSignerPath(g, resourceAcct, resourceName) + if err != nil { + return + } + value, err := g.ScriptFromFile(filename, script). + AccountArgument(resourceAcct). + StringArgument(signerPubKey). + Argument(path). + RunReturns() + if err != nil { + return + } + result = value.(cadence.UFix64) + return +} + +func GetTxIndex(g *gwtf.GoWithTheFlow, resourceAcct string, resourceName string) (result uint64, err error) { + filename := "../../../scripts/onChainMultiSig/get_tx_index.cdc" + script := ParseCadenceTemplate(filename) + path, err := GetPubSignerPath(g, resourceAcct, resourceName) + if err != nil { + return + } + value, err := g.ScriptFromFile(filename, script).AccountArgument(resourceAcct).Argument(path).RunReturns() + if err != nil { + return + } + result = value.ToGoValue().(uint64) + return +} + +func GetPubSignerPath(g *gwtf.GoWithTheFlow, resourceAcct string, resourceName string) (result cadence.Value, err error) { + filename := "../../../scripts/onChainMultiSig/get_pubsigner_path.cdc" + script := ParseCadenceTemplate(filename) + result, err = g.ScriptFromFile(filename, script).StringArgument(resourceName).RunReturns() + return +} + +func ContainsKey(g *gwtf.GoWithTheFlow, resourceAcct string, resourceName string, key string) (result bool, err error) { + keys, err := GetStoreKeys(g, resourceAcct, resourceName) + result = false + for _, k := range keys { + if k == key { + result = true + return + } + } + return +} + +func GetMultiSigKeys(g *gwtf.GoWithTheFlow) (MultiSigPubKeys []cadence.Value, MultiSigKeyWeights []cadence.Value, MultiSigAlgos []cadence.Value) { + pk1000 := g.Account(Acct1000).Key().ToConfig().PrivateKey.PublicKey().String() + pk500_1 := g.Account(Acct500_1).Key().ToConfig().PrivateKey.PublicKey().String() + pk500_2 := g.Account(Acct500_2).Key().ToConfig().PrivateKey.PublicKey().String() + pk250_1 := g.Account(Acct250_1).Key().ToConfig().PrivateKey.PublicKey().String() + pk250_2 := g.Account(Acct250_2).Key().ToConfig().PrivateKey.PublicKey().String() + + w1000, _ := cadence.NewUFix64("1000.0") + w500, _ := cadence.NewUFix64("500.0") + w250, _ := cadence.NewUFix64("250.0") + + MultiSigPubKeys = []cadence.Value{ + cadence.String(pk1000[2:]), + cadence.String(pk500_1[2:]), + cadence.String(pk500_2[2:]), + cadence.String(pk250_1[2:]), + cadence.String(pk250_2[2:]), + } + + MultiSigAlgos = []cadence.Value{ + cadence.NewUInt8(1), + cadence.NewUInt8(1), + cadence.NewUInt8(1), + cadence.NewUInt8(1), + cadence.NewUInt8(1), + } + MultiSigKeyWeights = []cadence.Value{w1000, w500, w500, w250, w250} + return +} diff --git a/tasks/deploy_usdc_social/main.go b/tasks/deploy_usdc_social/main.go new file mode 100644 index 0000000..be43913 --- /dev/null +++ b/tasks/deploy_usdc_social/main.go @@ -0,0 +1,270 @@ +package main + +import ( + "fmt" + "log" + "bytes" + "io/ioutil" + "os" + "time" + + "text/template" + "encoding/hex" + + + "github.com/onflow/cadence" + + "github.com/bjartek/go-with-the-flow/v2/gwtf" + + "github.com/onflow/flow-go-sdk" +) + + +func main() { + + g := gwtf.NewGoWithTheFlowInMemoryEmulator() + + _, err := DeployFiatTokenContract(g, "account", "USDC", "0.1.0") + fmt.Println("err: ", err) + if err != nil { + log.Fatal("Cannot deploy contract") + } + x, err := DeploySocialTokenContract(g, "testaccount", "SocialToken") + if err != nil { + log.Fatal("Cannot deploy socialToken contract", err) + }else{ + fmt.Println("socialToken deployed successfully", x) + } +} + +// Useful multisig accounts +// These are named by the weights +// i.e. Account500_1 has a weight of 500.0 +const Acct1000 = "w-1000" +const Acct500_1 = "w-500-1" +const Acct500_2 = "w-500-2" +const Acct250_1 = "w-250-1" +const Acct250_2 = "w-250-2" +const Config = ".././flow.json" + +var FlowJSON []string = []string{Config} + +type Addresses struct { + FungibleToken string + FiatTokenInterface string + FiatToken string + OnChainMultiSig string +} + +type TestEvent struct { + Name string + Fields map[string]string +} + +var addresses Addresses + +func ParseCadenceTemplate(templatePath string) []byte { + fb, err := ioutil.ReadFile(templatePath) + if err != nil { + panic(err) + } + + tmpl, err := template.New("Template").Parse(string(fb)) + if err != nil { + panic(err) + } + + // Addresss for emulator are + // addresses = Addresses{"ee82856bf20e2aa6", "01cf0e2f2f715450", "01cf0e2f2f715450", "01cf0e2f2f715450", "01cf0e2f2f715450"} + addresses = Addresses{os.Getenv("FUNGIBLE_TOKEN_ADDRESS"), os.Getenv("OWNER_ADDRESS"), os.Getenv("OWNER_ADDRESS"), os.Getenv("OWNER_ADDRESS")} + + buf := &bytes.Buffer{} + err = tmpl.Execute(buf, addresses) + if err != nil { + panic(err) + } + + return buf.Bytes() +} + + +func GetMultiSigKeys(g *gwtf.GoWithTheFlow) (MultiSigPubKeys []cadence.Value, MultiSigKeyWeights []cadence.Value, MultiSigAlgos []cadence.Value) { + pk1000 := g.Account(Acct1000).Key().ToConfig().PrivateKey.PublicKey().String() + pk500_1 := g.Account(Acct500_1).Key().ToConfig().PrivateKey.PublicKey().String() + pk500_2 := g.Account(Acct500_2).Key().ToConfig().PrivateKey.PublicKey().String() + pk250_1 := g.Account(Acct250_1).Key().ToConfig().PrivateKey.PublicKey().String() + pk250_2 := g.Account(Acct250_2).Key().ToConfig().PrivateKey.PublicKey().String() + + w1000, _ := cadence.NewUFix64("1000.0") + w500, _ := cadence.NewUFix64("500.0") + w250, _ := cadence.NewUFix64("250.0") + + MultiSigPubKeys = []cadence.Value{ + cadence.String(pk1000[2:]), + cadence.String(pk500_1[2:]), + cadence.String(pk500_2[2:]), + cadence.String(pk250_1[2:]), + cadence.String(pk250_2[2:]), + } + + MultiSigAlgos = []cadence.Value{ + cadence.NewUInt8(1), + cadence.NewUInt8(1), + cadence.NewUInt8(1), + cadence.NewUInt8(1), + cadence.NewUInt8(1), + } + MultiSigKeyWeights = []cadence.Value{w1000, w500, w500, w250, w250} + return +} + +func ParseTestEvents(events []flow.Event) (formatedEvents []*gwtf.FormatedEvent) { + for _, e := range events { + formatedEvents = append(formatedEvents, gwtf.ParseEvent(e, uint64(0), time.Now(), nil)) + } + return +} + +func DeploySocialTokenContract(g *gwtf.GoWithTheFlow, ownerAcct string,tokenName string) (events []*gwtf.FormatedEvent, err error){ + + contractCode := ParseCadenceTemplate("././contracts/SocialToken.cdc") + fmt.Println("hello we are in social token") + + txFilename := "deploy_social_token" + + fmt.Println("parse socialToken template", txFilename) + //code := ParseCadenceTemplate(txFilename) + encodedStr := hex.EncodeToString(contractCode) + fmt.Println("template encoded") + + e, err := g.TransactionFromFile(txFilename). + SignProposeAndPayAs(ownerAcct). + StringArgument("SocialToken"). + StringArgument(encodedStr). + RunE() + gwtf.PrintEvents(e, map[string][]string{}) + events = ParseTestEvents(e) + + return +} +func DeployFiatTokenContract( + g *gwtf.GoWithTheFlow, + ownerAcct string, tokenName string, version string) (events []*gwtf.FormatedEvent, err error) { + + contractCode := ParseCadenceTemplate("././contracts/FiatToken.cdc") + + + txFilename := "deploy_contract_with_auth" + fmt.Println("parse template", txFilename) + //code := ParseCadenceTemplate(txFilename) + encodedStr := hex.EncodeToString(contractCode) + + if g.Network == "emulator" { + g.CreateAccounts("emulator-account") + } + fmt.Println("Accounts created") + multiSigPubKeys, multiSigKeyWeights, multiSigAlgos := GetMultiSigKeys(g) + fmt.Println("keys created") + e, err := g.TransactionFromFile(txFilename). + SignProposeAndPayAs(ownerAcct). + StringArgument("FiatToken"). + StringArgument(encodedStr). + // Vault + Argument(cadence.Path{Domain: "storage", Identifier: "USDCVault-2"}). + Argument(cadence.Path{Domain: "public", Identifier: "USDCVaultBalance-2"}). + Argument(cadence.Path{Domain: "public", Identifier: "USDCVaultUUID-2"}). + Argument(cadence.Path{Domain: "public", Identifier: "USDCVaultReceiver-2"}). + + // Blocklist executor + Argument(cadence.Path{Domain: "storage", Identifier: "USDCBlocklistExe-2"}). + // Blocklister + Argument(cadence.Path{Domain: "storage", Identifier: "USDCBlocklister-2"}). + Argument(cadence.Path{Domain: "public", Identifier: "USDCBlocklisterCapReceiver-2"}). + Argument(cadence.Path{Domain: "public", Identifier: "USDCBlocklisterUUID-2"}). + Argument(cadence.Path{Domain: "public", Identifier: "USDCBlocklisterPublicSigner-2"}). + // Pause executor + Argument(cadence.Path{Domain: "storage", Identifier: "USDCPauseExe-2"}). + // Pauser + Argument(cadence.Path{Domain: "storage", Identifier: "USDCPauser-2"}). + Argument(cadence.Path{Domain: "public", Identifier: "USDCPauserCapReceiver-2"}). + Argument(cadence.Path{Domain: "public", Identifier: "USDCPauserUUID-2"}). + Argument(cadence.Path{Domain: "public", Identifier: "USDCPauserPublicSigner-2"}). + // Admin executor + Argument(cadence.Path{Domain: "storage", Identifier: "USDCAdminExe-2"}). + //Admin + Argument(cadence.Path{Domain: "storage", Identifier: "USDCAdmin-2"}). + Argument(cadence.Path{Domain: "public", Identifier: "USDCAdminCapReceiver-2"}). + Argument(cadence.Path{Domain: "public", Identifier: "USDCAdminUUID-2"}). + Argument(cadence.Path{Domain: "public", Identifier: "USDCAdminPublicSigner-2"}). + // Owner executor + Argument(cadence.Path{Domain: "storage", Identifier: "USDCOwnerExe-2"}). + // Owner + Argument(cadence.Path{Domain: "storage", Identifier: "USDCOwner-2"}). + Argument(cadence.Path{Domain: "public", Identifier: "USDCOwnerCapReceiver-2"}). + Argument(cadence.Path{Domain: "public", Identifier: "USDCOwnerUUID-2"}). + Argument(cadence.Path{Domain: "public", Identifier: "USDCOwnerPubSigner-2"}). + // Master Minter Executor + Argument(cadence.Path{Domain: "storage", Identifier: "USDCMasterMinterExe-2"}). + // Master Minter + Argument(cadence.Path{Domain: "storage", Identifier: "USDCMasterMinter-2"}). + Argument(cadence.Path{Domain: "public", Identifier: "USDCMasterMinterCapReceiver-2"}). + Argument(cadence.Path{Domain: "public", Identifier: "USDCMasterMinterPublicSigner-2"}). + Argument(cadence.Path{Domain: "public", Identifier: "USDCMasterMinterUUID-2"}). + // Minter Controller + Argument(cadence.Path{Domain: "storage", Identifier: "USDCMinterController-2"}). + Argument(cadence.Path{Domain: "public", Identifier: "USDCMinterControllerUUID-2"}). + Argument(cadence.Path{Domain: "public", Identifier: "USDCMinterControllerPublicSigner-2"}). + // Minter + Argument(cadence.Path{Domain: "storage", Identifier: "USDCMinter-2"}). + Argument(cadence.Path{Domain: "public", Identifier: "USDCMinterUUID-2"}). + // Initial resource capabilities + Argument(cadence.Path{Domain: "private", Identifier: "USDCAdminCap-2"}). + Argument(cadence.Path{Domain: "private", Identifier: "USDCOwnerCap-2"}). + Argument(cadence.Path{Domain: "private", Identifier: "USDCMasterMinterCap-2"}). + Argument(cadence.Path{Domain: "private", Identifier: "USDCPauserCap-2"}). + Argument(cadence.Path{Domain: "private", Identifier: "USDCBlocklisterCap-2"}). + StringArgument(tokenName). + StringArgument(version). + UFix64Argument("1000000000.00000000"). + BooleanArgument(false). + Argument(cadence.NewArray(multiSigPubKeys)). + Argument(cadence.NewArray(multiSigKeyWeights)). + Argument(cadence.NewArray(multiSigAlgos)). + Argument(cadence.NewArray(multiSigPubKeys)). + Argument(cadence.NewArray(multiSigKeyWeights)). + Argument(cadence.NewArray(multiSigAlgos)). + Argument(cadence.NewArray(multiSigPubKeys)). + Argument(cadence.NewArray(multiSigKeyWeights)). + Argument(cadence.NewArray(multiSigAlgos)). + Argument(cadence.NewArray(multiSigPubKeys)). + Argument(cadence.NewArray(multiSigKeyWeights)). + Argument(cadence.NewArray(multiSigAlgos)). + Argument(cadence.NewArray(multiSigPubKeys)). + Argument(cadence.NewArray(multiSigKeyWeights)). + Argument(cadence.NewArray(multiSigAlgos)). + RunE() + gwtf.PrintEvents(e, map[string][]string{}) + events = ParseTestEvents(e) + + return +} + +func UpgradeFiatTokenContract( + g *gwtf.GoWithTheFlow, + ownerAcct string, version string) (events []*gwtf.FormatedEvent, err error) { + contractCode := ParseCadenceTemplate("././contracts/FiatToken.cdc") + txFilename := "upgrade_contract.cdc" + //code := ParseCadenceTemplate(txFilename) + encodedStr := hex.EncodeToString(contractCode) + + e, err := g.TransactionFromFile(txFilename). + SignProposeAndPayAs(ownerAcct). + StringArgument("FiatToken"). + StringArgument(encodedStr). + StringArgument(version). + RunE() + gwtf.PrintEvents(e, map[string][]string{}) + events = ParseTestEvents(e) + + return +} diff --git a/transactions/deploy_contract_with_auth.cdc b/transactions/deploy_contract_with_auth.cdc new file mode 100644 index 0000000..0360d20 --- /dev/null +++ b/transactions/deploy_contract_with_auth.cdc @@ -0,0 +1,138 @@ +// This transactions deploys the FiatToken contract +// +// Owner (AuthAccount) of this script is the owner of the contract +// +transaction( + contractName: String, + code: String, + VaultStoragePath: StoragePath, + VaultBalancePubPath: PublicPath, + VaultUUIDPubPath: PublicPath, + VaultReceiverPubPath: PublicPath, + BlocklistExecutorStoragePath: StoragePath, + BlocklisterStoragePath: StoragePath, + BlocklisterCapReceiverPubPath: PublicPath, + BlocklisterUUIDPubPath: PublicPath, + BlocklisterPubSigner: PublicPath, + PauseExecutorStoragePath: StoragePath, + PauserStoragePath: StoragePath, + PauserCapReceiverPubPath: PublicPath, + PauserUUIDPubPath: PublicPath, + PauserPubSigner: PublicPath, + AdminExecutorStoragePath: StoragePath, + AdminStoragePath: StoragePath, + AdminCapReceiverPubPath: PublicPath, + AdminUUIDPubPath: PublicPath, + AdminPubSigner: PublicPath, + OwnerExecutorStoragePath: StoragePath, + OwnerStoragePath: StoragePath, + OwnerCapReceiverPubPath: PublicPath, + OwnerUUIDPubPath: PublicPath, + OwnerPubSigner: PublicPath, + MasterMinterExecutorStoragePath: StoragePath, + MasterMinterStoragePath: StoragePath, + MasterMinterCapReceiverPubPath: PublicPath, + MasterMinterPubSigner: PublicPath, + MasterMinterUUIDPubPath: PublicPath, + MinterControllerStoragePath: StoragePath, + MinterControllerUUIDPubPath: PublicPath, + MinterControllerPubSigner: PublicPath, + MinterStoragePath: StoragePath, + MinterUUIDPubPath: PublicPath, + initialAdminCapabilityPrivPath: PrivatePath, + initialOwnerCapabilityPrivPath: PrivatePath, + initialMasterMinterCapabilityPrivPath: PrivatePath, + initialPauserCapabilityPrivPath: PrivatePath, + initialBlocklisterCapabilityPrivPath: PrivatePath, + tokenName: String, + version: String, + initTotalSupply: UFix64, + initPaused: Bool, + adminAccountPubKeys: [String], + adminAccountKeyWeights: [UFix64], + adminAccountKeyAlgos: [UInt8], + ownerAccountPubKeys: [String], + ownerAccountKeyWeights: [UFix64], + ownerAccountKeyAlgos: [UInt8], + masterMinterAccountPubKeys: [String], + masterMinterAccountKeyWeights: [UFix64], + masterMinterAccountKeyAlgos: [UInt8], + blocklisterAccountPubKeys: [String], + blocklisterAccountKeyWeights: [UFix64], + blocklisterAccountKeyAlgos: [UInt8], + pauserAccountPubKeys: [String], + pauserAccountKeyWeights: [UFix64], + pauserAccountKeyAlgos: [UInt8], +) { + prepare(contractAccount: AuthAccount) { + let existingContract = contractAccount.contracts.get(name: contractName) + + if (existingContract == nil) { + contractAccount.contracts.add( + name: contractName, + code: code.decodeHex(), + contractAccount, + VaultStoragePath: VaultStoragePath, + VaultBalancePubPath: VaultBalancePubPath, + VaultUUIDPubPath: VaultUUIDPubPath, + VaultReceiverPubPath: VaultReceiverPubPath, + BlocklistExecutorStoragePath: BlocklistExecutorStoragePath, + BlocklisterStoragePath: BlocklisterStoragePath, + BlocklisterCapReceiverPubPath: BlocklisterCapReceiverPubPath, + BlocklisterUUIDPubPath: BlocklisterUUIDPubPath, + BlocklisterPubSigner: BlocklisterPubSigner, + PauseExecutorStoragePath: PauseExecutorStoragePath, + PauserStoragePath: PauserStoragePath, + PauserCapReceiverPubPath: PauserCapReceiverPubPath, + PauserUUIDPubPath: PauserUUIDPubPath, + PauserPubSigner: PauserPubSigner, + AdminExecutorStoragePath: AdminExecutorStoragePath, + AdminStoragePath: AdminStoragePath, + AdminCapReceiverPubPath: AdminCapReceiverPubPath, + AdminUUIDPubPath: AdminUUIDPubPath, + AdminPubSigner: AdminPubSigner, + OwnerExecutorStoragePath: OwnerExecutorStoragePath, + OwnerStoragePath: OwnerStoragePath, + OwnerCapReceiverPubPath: OwnerCapReceiverPubPath, + OwnerUUIDPubPath: OwnerUUIDPubPath, + OwnerPubSigner: OwnerPubSigner, + MasterMinterExecutorStoragePath: MasterMinterExecutorStoragePath, + MasterMinterStoragePath: MasterMinterStoragePath, + MasterMinterCapReceiverPubPath: MasterMinterCapReceiverPubPath, + MasterMinterPubSigner: MasterMinterPubSigner, + MasterMinterUUIDPubPath: MasterMinterUUIDPubPath, + MinterControllerStoragePath: MinterControllerStoragePath, + MinterControllerUUIDPubPath: MinterControllerUUIDPubPath, + MinterControllerPubSigner: MinterControllerPubSigner, + MinterStoragePath: MinterStoragePath, + MinterUUIDPubPath: MinterUUIDPubPath, + initialAdminCapabilityPrivPath: initialAdminCapabilityPrivPath, + initialOwnerCapabilityPrivPath: initialOwnerCapabilityPrivPath, + initialMasterMinterCapabilityPrivPath: initialMasterMinterCapabilityPrivPath, + initialPauserCapabilityPrivPath: initialPauserCapabilityPrivPath, + initialBlocklisterCapabilityPrivPath: initialBlocklisterCapabilityPrivPath, + tokenName: tokenName, + version: version, + initTotalSupply: initTotalSupply, + initPaused: initPaused, + adminAccountPubKeys: adminAccountPubKeys, + adminAccountKeyWeights: adminAccountKeyWeights, + adminAccountKeyAlgos: adminAccountKeyAlgos, + ownerAccountPubKeys: ownerAccountPubKeys, + ownerAccountKeyWeights: ownerAccountKeyWeights, + ownerAccountKeyAlgos: ownerAccountKeyAlgos, + masterMinterAccountPubKeys: masterMinterAccountPubKeys, + masterMinterAccountKeyWeights: masterMinterAccountKeyWeights, + masterMinterAccountKeyAlgos: masterMinterAccountKeyAlgos, + blocklisterAccountPubKeys: blocklisterAccountPubKeys, + blocklisterAccountKeyWeights: blocklisterAccountKeyWeights, + blocklisterAccountKeyAlgos: blocklisterAccountKeyAlgos, + pauserAccountPubKeys: pauserAccountPubKeys, + pauserAccountKeyWeights: pauserAccountKeyWeights, + pauserAccountKeyAlgos: pauserAccountKeyAlgos, + ) + } else { + contractAccount.contracts.update__experimental(name: contractName, code: code.decodeHex()) + } + } +} diff --git a/transactions/deploy_social_token.cdc b/transactions/deploy_social_token.cdc new file mode 100644 index 0000000..6c533aa --- /dev/null +++ b/transactions/deploy_social_token.cdc @@ -0,0 +1,17 @@ +transaction( + contractName: String, + code: String, +) { + prepare(contractAccount: AuthAccount) { + let existingContract = contractAccount.contracts.get(name: contractName) + + if (existingContract == nil) { + contractAccount.contracts.add( + name: contractName, + code: code.decodeHex() + ) + } else { + contractAccount.contracts.update__experimental(name: contractName, code: code.decodeHex()) + } + } +} diff --git a/transactions/transfer_flow_tokens_emulator.cdc b/transactions/transfer_flow_tokens_emulator.cdc new file mode 100644 index 0000000..ba17ac2 --- /dev/null +++ b/transactions/transfer_flow_tokens_emulator.cdc @@ -0,0 +1,44 @@ +// This transaction is a template for a transaction that +// could be used by anyone to send tokens to another account +// that has been set up to receive tokens. +// +// The withdraw amount and the account from getAccount +// would be the parameters to the transaction + +// Here we use hard-coded testnet addresses for the emulator +// This is required because the newly created account requires +// balance for the deployment of the FiatToken contract. + +import FungibleToken from 0xee82856bf20e2aa6 +import FlowToken from 0x0ae53cb6e3f42a79 + +transaction(amount: UFix64, to: Address) { + + // The Vault resource that holds the tokens that are being transferred + let sentVault: @FungibleToken.Vault + + prepare(signer: AuthAccount) { + + // Get a reference to the signer's stored vault + let vaultRef = signer.borrow<&FlowToken.Vault>(from: /storage/flowTokenVault) + ?? panic("Could not borrow reference to the owner's Vault!") + + // Withdraw tokens from the signer's stored vault + self.sentVault <- vaultRef.withdraw(amount: amount) + } + + execute { + log("transferring") + log(to) + + // Get a reference to the recipient's Receiver + let receiverRef = getAccount(to) + .getCapability(/public/flowTokenReceiver) + .borrow<&{FungibleToken.Receiver}>() + ?? panic("Could not borrow receiver reference to the recipient's Vault") + + // Deposit the withdrawn tokens in the recipient's receiver + receiverRef.deposit(from: <-self.sentVault) + } +} + diff --git a/transactions/upgrade_contract.cdc b/transactions/upgrade_contract.cdc new file mode 100644 index 0000000..d90fac8 --- /dev/null +++ b/transactions/upgrade_contract.cdc @@ -0,0 +1,18 @@ +import FiatToken from 0x{{.FiatToken}} +// This transactions upgrades the FiatToken contract with a resource +// +// Admin (AuthAccount) of this script is the owner of the contract +// +transaction( + contractName: String, + code: String, + version: String +) { + prepare(admin: AuthAccount) { + // get a reference to the account's Admin + let a = admin.borrow<&FiatToken.Admin>(from: FiatToken.AdminStoragePath) + ?? panic ("no admin resource avaialble"); + + a.upgradeContract(name: contractName, code: code.decodeHex(), version: version); + } +} From cd9d4ed3109a91c93e5d0ec3c4681bf68036c6e2 Mon Sep 17 00:00:00 2001 From: danishtroon Date: Wed, 23 Feb 2022 11:47:32 +0000 Subject: [PATCH 2/5] udpate the changes --- Makefile | 9 ++ contracts/FiatToken.cdc | 2 +- contracts/SocialToken.cdc | 98 ++++++++++------- flow.json | 226 ++++++++++++++++++++++++++++---------- 4 files changed, 234 insertions(+), 101 deletions(-) diff --git a/Makefile b/Makefile index a057730..400a5ca 100644 --- a/Makefile +++ b/Makefile @@ -87,3 +87,12 @@ mint-2000-burn-1300-tokens: .PHONY: mint-5000-burn-3500-tokens mint-5000-burn-3500-tokens: go run ./tasks/mint_5000_burn_3500_tokens/main.go + +.PHONY: mint-5000-burn-3500-tokens +deploy-USDC: + go run ./tasks/deploy/USDC.go + +.PHONY: deploy-USDC +deploy-USDC-socialToken: + go run ./tasks/deploy_usdc_social/main.go +.PHONY: deploy-USDC-socialToken \ No newline at end of file diff --git a/contracts/FiatToken.cdc b/contracts/FiatToken.cdc index 5696b09..33b5457 100644 --- a/contracts/FiatToken.cdc +++ b/contracts/FiatToken.cdc @@ -1,5 +1,5 @@ import Crypto -import FungibleToken from 0xf8d6e0586b0a20c7 +import FungibleToken from 0xee82856bf20e2aa6 import OnChainMultiSig from 0xf8d6e0586b0a20c7 pub contract FiatToken: FungibleToken { diff --git a/contracts/SocialToken.cdc b/contracts/SocialToken.cdc index 75973a9..63fdd9e 100644 --- a/contracts/SocialToken.cdc +++ b/contracts/SocialToken.cdc @@ -1,6 +1,6 @@ import FungibleToken from 0xee82856bf20e2aa6 import Controller from 0xf8d6e0586b0a20c7 -import FUSD from 0xf8d6e0586b0a20c7 +import FiatToken from 0xf8d6e0586b0a20c7 pub contract SocialToken: FungibleToken { @@ -18,8 +18,8 @@ pub contract SocialToken: FungibleToken { // a variable that store admin capability to utilize methods of controller contract access(contract) let adminRef : Capability<&{Controller.SocialTokenResourcePublic}> - // a variable which will store the structure of FUSDPool - pub var collateralPool: FUSDPool + // a variable which will store the structure of USDCPool + pub var collateralPool: USDCPool pub resource interface SocialTokenPublic { pub fun getTokenId(): String @@ -126,37 +126,41 @@ pub contract SocialToken: FungibleToken { return <- create Burner() } - // A structure that contains all the data related to the FUSDPool - pub struct FUSDPool { + // A structure that contains all the data related to the USDCPool + pub struct USDCPool { pub let receiver: Capability<&{FungibleToken.Receiver}> pub let provider: Capability<&{FungibleToken.Provider}> pub let balance : Capability<&{FungibleToken.Balance}> + pub let resourceId : Capability<&FiatToken.Vault{FiatToken.ResourceId}> init( _receiver: Capability<&{FungibleToken.Receiver}>, _provider: Capability<&{FungibleToken.Provider}>, - _balance : Capability<&{FungibleToken.Balance}> + _balance : Capability<&{FungibleToken.Balance}>, + _resourceId : Capability<&FiatToken.Vault{FiatToken.ResourceId}> + ) { self.receiver = _receiver self.provider = _provider self.balance = _balance + self.resourceId = _resourceId } } // method to distribute fee of a token when a token minted, distribute to admin and artist - access(contract) fun distributeFee(_ tokenId : String, _ fusdPayment: @FungibleToken.Vault): @FungibleToken.Vault { - let amount = fusdPayment.balance + access(contract) fun distributeFee(_ tokenId : String, _ usdcPayment: @FungibleToken.Vault): @FungibleToken.Vault { + let amount = usdcPayment.balance let tokenDetails = Controller.getTokenDetails(tokenId) for address in tokenDetails.feeSplitterDetail.keys { let feeStructer = tokenDetails.feeSplitterDetail[address] let tempAmmount = amount * feeStructer!.percentage - let tempraryVault <- fusdPayment.withdraw(amount:tempAmmount) + let tempraryVault <- usdcPayment.withdraw(amount:tempAmmount) let account = getAccount(address) - let depositSigner= account.getCapability<&FUSD.Vault{FungibleToken.Receiver}>(/public/fusdReceiver) + let depositSigner= account.getCapability<&FiatToken.Vault{FungibleToken.Receiver}>(FiatToken.VaultReceiverPubPath) .borrow() ??panic("could not borrow reference to the receiver") depositSigner.deposit(from:<- tempraryVault) } - return <- fusdPayment + return <- usdcPayment } pub fun getMintPrice(_ tokenId: String, _ amount: UFix64): UFix64 { pre { @@ -194,7 +198,7 @@ pub contract SocialToken: FungibleToken { } pub resource interface MinterPublic { - pub fun mintTokens(_ tokenId: String, _ amount: UFix64, fusdPayment: @FungibleToken.Vault, receiverVault: Capability<&AnyResource{FungibleToken.Receiver}>): @SocialToken.Vault + pub fun mintTokens(_ tokenId: String, _ amount: UFix64, usdcPayment: @FungibleToken.Vault, receiverVault: Capability<&AnyResource{FungibleToken.Receiver}>): @SocialToken.Vault } pub resource Minter: MinterPublic { @@ -203,7 +207,7 @@ pub contract SocialToken: FungibleToken { // Parameters: // tokenId: The ID of the token that will be minted // amount: amount to pay for the tokens - // fusdPayment: will take the fusd balance + // usdcPayment: will take the usdc balance // receiverVault: will return the remaining balance to the user // Pre-Conditions: // tokenId must not be null @@ -212,26 +216,26 @@ pub contract SocialToken: FungibleToken { // // Returns: The SocialToken Vault // - pub fun mintTokens(_ tokenId: String, _ amount: UFix64, fusdPayment: @FungibleToken.Vault, receiverVault: Capability<&AnyResource{FungibleToken.Receiver}>): @SocialToken.Vault { + pub fun mintTokens(_ tokenId: String, _ amount: UFix64, usdcPayment: @FungibleToken.Vault, receiverVault: Capability<&AnyResource{FungibleToken.Receiver}>): @SocialToken.Vault { pre { amount > 0.0: "Amount minted must be greater than zero" - fusdPayment.balance > 0.0: "Balance should be greater than zero" + usdcPayment.balance > 0.0: "Balance should be greater than zero" Controller.getTokenDetails(tokenId).tokenId !=nil: "toke not registered" amount + Controller.getTokenDetails(tokenId).issuedSupply <= Controller.getTokenDetails(tokenId).maxSupply : "Max supply reached" SocialToken.adminRef.borrow() !=nil: "social token does not have controller capability" } - var remainingFUSD = 0.0 + var remainingUSDC = 0.0 var remainingSocialToken = 0.0 let mintPrice = SocialToken.getMintPrice(tokenId, amount) let mintedTokenPrice = SocialToken.getMintPrice(tokenId, 1.0) - assert(fusdPayment.balance >= mintPrice, message: "You don't have sufficient balance to mint tokens") - var totalPayment = fusdPayment.balance + assert(usdcPayment.balance >= mintPrice, message: "You don't have sufficient balance to mint tokens") + var totalPayment = usdcPayment.balance assert(totalPayment>=mintPrice, message: "No payment yet") let extraAmount = totalPayment-mintPrice if(extraAmount > 0.0) { //Create Vault of extra amount and deposit back to user totalPayment=totalPayment-extraAmount - let remainingAmountVault <- fusdPayment.withdraw(amount: extraAmount) + let remainingAmountVault <- usdcPayment.withdraw(amount: extraAmount) let remainingVault = receiverVault.borrow()! remainingVault.deposit(from: <- remainingAmountVault) } @@ -239,7 +243,7 @@ pub contract SocialToken: FungibleToken { tempraryVar.setTokenId(tokenId) let tokenDetails = Controller.getTokenDetails(tokenId) SocialToken.adminRef.borrow()!.incrementIssuedSupply(tokenId, amount) - let remainingAmount <- SocialToken.distributeFee(tokenId, <- fusdPayment) + let remainingAmount <- SocialToken.distributeFee(tokenId, <- usdcPayment) SocialToken.totalSupply = SocialToken.totalSupply + amount SocialToken.adminRef.borrow()!.incrementReserve(tokenId, remainingAmount.balance) @@ -287,28 +291,44 @@ pub contract SocialToken: FungibleToken { self.adminRef = adminPrivateCap - let vault <-FUSD.createEmptyVault() - self.account.save(<-vault, to:/storage/fusdVault) - - self.account.link<&FUSD.Vault{FungibleToken.Receiver}>( - /public/fusdReceiver, - target: /storage/fusdVault + let vault <-FiatToken.createEmptyVault() + // self.account.save(<-vault, to:FiatToken.VaultStoragePath) + self.account.save(<-vault, to: FiatToken.VaultStoragePath) + + // Create a public capability to the Vault that only exposes + // the deposit function through the Receiver interface + self.account.link<&FiatToken.Vault{FungibleToken.Receiver}>( + FiatToken.VaultReceiverPubPath, + target: FiatToken.VaultStoragePath ) - - self.account.link<&FUSD.Vault{FungibleToken.Balance}>( - /public/fusdBalance, - target: /storage/fusdVault + + // Create a public capability to the Vault that only exposes + // the UUID() function through the VaultUUID interface + self.account.link<&FiatToken.Vault{FiatToken.ResourceId}>( + FiatToken.VaultUUIDPubPath, + target: FiatToken.VaultStoragePath ) - - self.account.link<&FUSD.Vault{FungibleToken.Provider}>( - /private/fusdProvider, - target: /storage/fusdVault + + // Create a public capability to the Vault that only exposes + // the balance field through the Balance interface + self.account.link<&FiatToken.Vault{FungibleToken.Balance}>( + FiatToken.VaultBalancePubPath, + target: FiatToken.VaultStoragePath ) - - self.collateralPool = FUSDPool( - _receiver: self.account.getCapability<&FUSD.Vault{FungibleToken.Receiver}>(/public/fusdReceiver), - _provider: self.account.getCapability<&FUSD.Vault{FungibleToken.Provider}>(/private/fusdProvider), - _balance : self.account.getCapability<&FUSD.Vault{FungibleToken.Balance}>(/public/fusdBalance) + + // Create a private capability to the Vault that only exposes + // the balance field through the Balance interface + self.account.link<&FiatToken.Vault{FungibleToken.Provider}>( + /private/usdcProvider, + target: FiatToken.VaultStoragePath + ) + + + self.collateralPool = USDCPool( + _receiver: self.account.getCapability<&FiatToken.Vault{FungibleToken.Receiver}>(FiatToken.VaultReceiverPubPath), + _provider: self.account.getCapability<&FiatToken.Vault{FungibleToken.Provider}>(/private/usdcProvider), + _balance : self.account.getCapability<&FiatToken.Vault{FungibleToken.Balance}>(FiatToken.VaultBalancePubPath), + _resourceId : self.account.getCapability<&FiatToken.Vault{FiatToken.ResourceId}>(FiatToken.VaultUUIDPubPath) ) emit TokensInitialized(initialSupply:self.totalSupply) } diff --git a/flow.json b/flow.json index 7b905dd..5897ff3 100644 --- a/flow.json +++ b/flow.json @@ -1,83 +1,187 @@ { - - "emulators": { - "default": { - "port": 3569, - "serviceAccount": "emulator-account" - } - }, - "contracts": { - "Debug": "./contracts/Debug.cdc", - "SocialToken": { + "emulators": { + "default": { + "port": 3569, + "serviceAccount": "emulator-account" + } + }, + "deployments": { + "emulator": { + "emulator-owner": ["Controller","FiatTokenInterface", "OnChainMultiSig"], + "emulator-allowance": [], + "emulator-blocklister": [], + "emulator-minter": [], + "emulator-minterController1": [], + "emulator-minterController2": [], + "emulator-non-allowance" : [], + "emulator-non-blocklister":[], + "emulator-non-minter": [], + "emulator-non-multisig-account": [], + "emulator-non-pauser": [], + "emulator-non-vaulted-account": [], + "emulator-pauser": [], + "emulator-vaulted-account": [], + "emulator-w-1000": [], + "emulator-w-500-1": [], + "emulator-w-500-2": [], + "emulator-w-250-1": [], + "emulator-w-250-2": [] + } + }, + "contracts": { + "FungibleToken": { + "source": "./contracts/FungibleToken.cdc", + "aliases": { + "emulator": "0xee82856bf20e2aa6", + "testnet": "0x9a0766d93b6608b7", + "mainnet": "0xf233dcee88fe0abe" + } + }, + "SocialToken": { "source": "./contracts/SocialToken.cdc", "aliases": { - "emulator": "0x0ae53cb6e3f42a79", + "emulator": "0xf8d6e0586b0a20c7", "testnet": "0x7e60df042a9c0868" } }, - "FungibleToken": { - "source": "./contracts/FungibleToken.cdc", + "FUSD": { + "source": "./contracts/FUSD.cdc", "aliases": { - "emulator": "0xee82856bf20e2aa6", - "testnet": "0x9a0766d93b6608b7" + "emulator": "0xf8d6e0586b0a20c7", + "testnet": "0x7e60df042a9c0868" } }, - "FUSD": { - "source": "./contracts/FUSD.cdc", + "Controller": { + "source": "./contracts/Controller.cdc", "aliases": { - "emulator": "0x0ae53cb6e3f42a79", + "emulator": "0xf8d6e0586b0a20c7", "testnet": "0x7e60df042a9c0868" } }, - "Controller": { - "source": "./contracts/Controller.cdc", + "FiatTokenInterface": { + "source": "./contracts/FiatTokenInterface.cdc", "aliases": { - "emulator": "0x0ae53cb6e3f42a79", + "emulator": "0xf8d6e0586b0a20c7", + "testnet": "0x7e60df042a9c0868" + } + }, + "OnChainMultiSig": { + "source": "./contracts/OnChainMultiSig.cdc", + "aliases": { + "emulator": "0xf8d6e0586b0a20c7", "testnet": "0x7e60df042a9c0868" } } + }, + "networks": { + "emulator": "127.0.0.1:3569", + "mainnet": "access.mainnet.nodes.onflow.org:9000", + "testnet": "access.devnet.nodes.onflow.org:9000" + }, + "accounts": { + "emulator-account": { + "address": "f8d6e0586b0a20c7", + "key" : "758abfd76ad82071cbeeb309f251eeefbe9bb8442557de745769a6ff0a912636" + }, + "emulator-owner": { + "address": "f8d6e0586b0a20c7", + "key" : "758abfd76ad82071cbeeb309f251eeefbe9bb8442557de745769a6ff0a912636" + }, + "emulator-testaccount": { + "address": "01cf0e2f2f715450", + "key" : "9c687961e7a1abe1e445830e7ec118ffd1e2a0449cf705f5476b3f100e94dc29" }, - "networks": { - "emulator": "127.0.0.1:3569", - "mainnet": "access.mainnet.nodes.onflow.org:9000", - "testnet": "access.devnet.nodes.onflow.org:9000" - }, - "accounts": { - "emulator-account": { - "address": "f8d6e0586b0a20c7", - "key": "dc0097a6b58533e56af78c955e7b0c0f386b5f44f22b75c390beab7fcb1af13f" - }, - "emulator-first": { + "emulator-allowance" : { + "address": "179b6b1cb6755e31", + "key" : "9c687961e7a1abe1e445830e7ec118ffd1e2a0449cf705f5476b3f100e94dc29" + }, + "emulator-blocklister" : { + "address": "f3fcd2c1a78f5eee", + "key" : "9c687961e7a1abe1e445830e7ec118ffd1e2a0449cf705f5476b3f100e94dc29" + }, + "emulator-minter" : { + "address": "e03daebed8ca0615", + "key" : "9c687961e7a1abe1e445830e7ec118ffd1e2a0449cf705f5476b3f100e94dc29" + }, + "emulator-minterController1" : { + "address": "045a1763c93006ca", + "key" : "9c687961e7a1abe1e445830e7ec118ffd1e2a0449cf705f5476b3f100e94dc29" + }, + "emulator-minterController2" : { + "address": "120e725050340cab", + "key" : "9c687961e7a1abe1e445830e7ec118ffd1e2a0449cf705f5476b3f100e94dc29" + }, + "emulator-non-allowance" : { + "address": "f669cb8d41ce0c74", + "key" : "9c687961e7a1abe1e445830e7ec118ffd1e2a0449cf705f5476b3f100e94dc29" + }, + "emulator-non-blocklister" : { + "address": "192440c99cb17282", + "key" : "9c687961e7a1abe1e445830e7ec118ffd1e2a0449cf705f5476b3f100e94dc29" + }, + "emulator-non-minter" : { + "address": "fd43f9148d4b725d", + "key" : "9c687961e7a1abe1e445830e7ec118ffd1e2a0449cf705f5476b3f100e94dc29" + }, + "emulator-non-multisig-account" : { + "address": "eb179c27144f783c", + "key" : "9c687961e7a1abe1e445830e7ec118ffd1e2a0449cf705f5476b3f100e94dc29" + }, + "emulator-non-pauser" : { + "address": "f7025fa05b578e3", + "key" : "9c687961e7a1abe1e445830e7ec118ffd1e2a0449cf705f5476b3f100e94dc29" + }, + "emulator-non-vaulted-account" : { + "address": "e2f72218abeec2b9", + "key" : "9c687961e7a1abe1e445830e7ec118ffd1e2a0449cf705f5476b3f100e94dc29" + }, + "emulator-pauser" : { + "address": "6909bc5ba14c266", + "key" : "9c687961e7a1abe1e445830e7ec118ffd1e2a0449cf705f5476b3f100e94dc29" + }, + "emulator-vaulted-account" : { + "address": "10c4fef62310c807", + "key" : "c7b5941fa9dc429f752057ef1f5b4d393470256f20ad0853d4343dde84a70946" + }, + "emulator-w-1000" : { + "address": "f4a3472b32eac8d8", + "key" : "3548f83a45e04050033112b81722f29c6d853fd00eb79a08101025900ca4c543" + }, + "emulator-w-250-1" : { + "address": "1beecc6fef95b62e", + "key" : "8da7a03dbcdd9d84d4e5e9875744accf7810d41fc60dd2522e5fa3f1441eff1d" + }, + "emulator-w-250-2" : { + "address": "ff8975b2fe6fb6f1", + "key" : "2e20dc54149cd114e265ef09b6dd09e222ce1979257b359fb6db53b64f260c6e" + }, + "emulator-w-500-1" : { + "address": "e9dd1081676bbc90", + "key" : "9c687961e7a1abe1e445830e7ec118ffd1e2a0449cf705f5476b3f100e94dc29" + }, + "emulator-w-500-2" : { + "address": "dbaa95c7691bc4f", + "key" : "bf242a7c12e299d90e4621d99501d1e27ccdc4d511cdf1f0fbba37a47e83bd24" + }, + "emulator-first": { "address": "01cf0e2f2f715450", "key": "d5457a187e9642a8e49d4032b3b4f85c92da7202c79681d9302c6e444e7033a8" - }, - "emulator-second": { - "address": "179b6b1cb6755e31", - "key": "d5457a187e9642a8e49d4032b3b4f85c92da7202c79681d9302c6e444e7033a8" - }, - "emulator-3": { - "address": "f3fcd2c1a78f5eee", - "key": "d5457a187e9642a8e49d4032b3b4f85c92da7202c79681d9302c6e444e7033a8" - }, - "emulator-4": { - "address": "e03daebed8ca0615", - "key": "d5457a187e9642a8e49d4032b3b4f85c92da7202c79681d9302c6e444e7033a8" - }, - "emulator-5": { - "address": "045a1763c93006ca", - "key": "d5457a187e9642a8e49d4032b3b4f85c92da7202c79681d9302c6e444e7033a8" - } }, - "deployments": { - "emulator": { - "emulator-account": [ - "FungibleToken", - "FUSD", - "Controller", - "SocialToken" - ], - "emulator-first": [], - "emulator-second": [] - } + "emulator-second": { + "address": "179b6b1cb6755e31", + "key": "d5457a187e9642a8e49d4032b3b4f85c92da7202c79681d9302c6e444e7033a8" + }, + "emulator-3": { + "address": "f3fcd2c1a78f5eee", + "key": "d5457a187e9642a8e49d4032b3b4f85c92da7202c79681d9302c6e444e7033a8" + }, + "emulator-4": { + "address": "e03daebed8ca0615", + "key": "d5457a187e9642a8e49d4032b3b4f85c92da7202c79681d9302c6e444e7033a8" + }, + "emulator-5": { + "address": "045a1763c93006ca", + "key": "d5457a187e9642a8e49d4032b3b4f85c92da7202c79681d9302c6e444e7033a8" } -} \ No newline at end of file + } +} From ac2b912d4dd1e942f280abd674d4b9870cdcce41 Mon Sep 17 00:00:00 2001 From: danishtroon Date: Thu, 24 Feb 2022 14:28:32 +0000 Subject: [PATCH 3/5] add the new testcase with full flow with usdc-token --- Makefile | 6 +- contracts/SocialToken.cdc | 2 +- flow.json | 132 ++++--- scripts/get_resource.cdc | 39 ++ scripts/get_social_balance.cdc | 2 +- scripts/get_social_burn_quote.cdc | 2 +- scripts/get_social_mint_quote.cdc | 2 +- scripts/get_usdc_balance.cdc | 19 + tasks/mint_burnt_and_usdc/main.go | 386 +++++++++++++++++++ transactions/burn_social_token.cdc | 8 +- transactions/configure_allowance.cdc | 13 + transactions/configure_minter_allowance.cdc | 13 + transactions/configure_minter_controller.cdc | 15 + transactions/create_new_minter.cdc | 43 +++ transactions/create_new_minterController.cdc | 47 +++ transactions/create_usdc_vault.cdc | 53 +++ transactions/mint_Social_token_usdc.cdc | 43 +++ transactions/mint_usdc.cdc | 26 ++ transactions/setup_social_vault.cdc | 2 +- 19 files changed, 780 insertions(+), 73 deletions(-) create mode 100644 scripts/get_resource.cdc create mode 100644 scripts/get_usdc_balance.cdc create mode 100644 tasks/mint_burnt_and_usdc/main.go create mode 100644 transactions/configure_allowance.cdc create mode 100644 transactions/configure_minter_allowance.cdc create mode 100644 transactions/configure_minter_controller.cdc create mode 100644 transactions/create_new_minter.cdc create mode 100644 transactions/create_new_minterController.cdc create mode 100644 transactions/create_usdc_vault.cdc create mode 100644 transactions/mint_Social_token_usdc.cdc create mode 100644 transactions/mint_usdc.cdc diff --git a/Makefile b/Makefile index 400a5ca..c84e8e6 100644 --- a/Makefile +++ b/Makefile @@ -95,4 +95,8 @@ deploy-USDC: .PHONY: deploy-USDC deploy-USDC-socialToken: go run ./tasks/deploy_usdc_social/main.go -.PHONY: deploy-USDC-socialToken \ No newline at end of file + +.PHONY: deploy-USDC-socialToken +mint-burn-with-USDC-socialToken: + go run ./tasks/mint_burnt_and_usdc/main.go +.PHONY: mint-burn-with-USDC-socialToken \ No newline at end of file diff --git a/contracts/SocialToken.cdc b/contracts/SocialToken.cdc index 63fdd9e..47848fe 100644 --- a/contracts/SocialToken.cdc +++ b/contracts/SocialToken.cdc @@ -286,7 +286,7 @@ pub contract SocialToken: FungibleToken { init() { self.totalSupply = 0.0 - var adminPrivateCap = self.account.getCapability + var adminPrivateCap = self.account.getCapability <&{Controller.SocialTokenResourcePublic}>(/private/SocialTokenResourcePrivatePath) self.adminRef = adminPrivateCap diff --git a/flow.json b/flow.json index 5897ff3..63b2217 100644 --- a/flow.json +++ b/flow.json @@ -88,100 +88,104 @@ "key" : "758abfd76ad82071cbeeb309f251eeefbe9bb8442557de745769a6ff0a912636" }, "emulator-testaccount": { - "address": "01cf0e2f2f715450", - "key" : "9c687961e7a1abe1e445830e7ec118ffd1e2a0449cf705f5476b3f100e94dc29" + "address": "01cf0e2f2f715450", + "key" : "9c687961e7a1abe1e445830e7ec118ffd1e2a0449cf705f5476b3f100e94dc29" }, - "emulator-allowance" : { + "emulator-user": { + "address": "01cf0e2f2f715450", + "key" : "9c687961e7a1abe1e445830e7ec118ffd1e2a0449cf705f5476b3f100e94dc29" + }, + "emulator-first": { + "address": "0f7025fa05b578e3", + "key" : "9c687961e7a1abe1e445830e7ec118ffd1e2a0449cf705f5476b3f100e94dc29" + }, + "emulator-second": { + "address": "1e7bd52309d4e4b4", + "key" : "758abfd76ad82071cbeeb309f251eeefbe9bb8442557de745769a6ff0a912636" + }, + "emulator-third": { + "address": "fa1c6cfe182ee46b", + "key" : "758abfd76ad82071cbeeb309f251eeefbe9bb8442557de745769a6ff0a912636" + }, + "emulator-fourth": { + "address": "ec4809cd812aee0a", + "key" : "758abfd76ad82071cbeeb309f251eeefbe9bb8442557de745769a6ff0a912636" + }, + "emulator-fifth": { + "address": "082fb01090d0eed5", + "key" : "9c687961e7a1abe1e445830e7ec118ffd1e2a0449cf705f5476b3f100e94dc29" + }, + "emulator-allowance" : { "address": "179b6b1cb6755e31", "key" : "9c687961e7a1abe1e445830e7ec118ffd1e2a0449cf705f5476b3f100e94dc29" }, - "emulator-blocklister" : { + "emulator-blocklister" : { "address": "f3fcd2c1a78f5eee", "key" : "9c687961e7a1abe1e445830e7ec118ffd1e2a0449cf705f5476b3f100e94dc29" }, - "emulator-minter" : { + "emulator-minter" : { "address": "e03daebed8ca0615", "key" : "9c687961e7a1abe1e445830e7ec118ffd1e2a0449cf705f5476b3f100e94dc29" }, - "emulator-minterController1" : { + "emulator-minterController1" : { "address": "045a1763c93006ca", "key" : "9c687961e7a1abe1e445830e7ec118ffd1e2a0449cf705f5476b3f100e94dc29" }, - "emulator-minterController2" : { + "emulator-minterController2" : { "address": "120e725050340cab", "key" : "9c687961e7a1abe1e445830e7ec118ffd1e2a0449cf705f5476b3f100e94dc29" }, - "emulator-non-allowance" : { + "emulator-non-allowance" : { "address": "f669cb8d41ce0c74", - "key" : "9c687961e7a1abe1e445830e7ec118ffd1e2a0449cf705f5476b3f100e94dc29" + "key" : "9c687961e7a1abe1e445830e7ec118ffd1e2a0449cf705f5476b3f100e94dc29" }, - "emulator-non-blocklister" : { + "emulator-non-blocklister" : { "address": "192440c99cb17282", "key" : "9c687961e7a1abe1e445830e7ec118ffd1e2a0449cf705f5476b3f100e94dc29" - }, - "emulator-non-minter" : { + }, + "emulator-non-minter" : { "address": "fd43f9148d4b725d", - "key" : "9c687961e7a1abe1e445830e7ec118ffd1e2a0449cf705f5476b3f100e94dc29" - }, - "emulator-non-multisig-account" : { + "key" : "9c687961e7a1abe1e445830e7ec118ffd1e2a0449cf705f5476b3f100e94dc29" + }, + "emulator-non-multisig-account" : { "address": "eb179c27144f783c", - "key" : "9c687961e7a1abe1e445830e7ec118ffd1e2a0449cf705f5476b3f100e94dc29" - }, - "emulator-non-pauser" : { + "key" : "9c687961e7a1abe1e445830e7ec118ffd1e2a0449cf705f5476b3f100e94dc29" + }, + "emulator-non-pauser" : { "address": "f7025fa05b578e3", - "key" : "9c687961e7a1abe1e445830e7ec118ffd1e2a0449cf705f5476b3f100e94dc29" - }, - "emulator-non-vaulted-account" : { + "key" : "9c687961e7a1abe1e445830e7ec118ffd1e2a0449cf705f5476b3f100e94dc29" + }, + "emulator-non-vaulted-account" : { "address": "e2f72218abeec2b9", - "key" : "9c687961e7a1abe1e445830e7ec118ffd1e2a0449cf705f5476b3f100e94dc29" - }, - "emulator-pauser" : { + "key" : "9c687961e7a1abe1e445830e7ec118ffd1e2a0449cf705f5476b3f100e94dc29" + }, + "emulator-pauser" : { "address": "6909bc5ba14c266", - "key" : "9c687961e7a1abe1e445830e7ec118ffd1e2a0449cf705f5476b3f100e94dc29" - }, - "emulator-vaulted-account" : { + "key" : "9c687961e7a1abe1e445830e7ec118ffd1e2a0449cf705f5476b3f100e94dc29" + }, + "emulator-vaulted-account" : { "address": "10c4fef62310c807", - "key" : "c7b5941fa9dc429f752057ef1f5b4d393470256f20ad0853d4343dde84a70946" - }, - "emulator-w-1000" : { + "key" : "c7b5941fa9dc429f752057ef1f5b4d393470256f20ad0853d4343dde84a70946" + }, + "emulator-w-1000" : { "address": "f4a3472b32eac8d8", - "key" : "3548f83a45e04050033112b81722f29c6d853fd00eb79a08101025900ca4c543" - }, - "emulator-w-250-1" : { + "key" : "3548f83a45e04050033112b81722f29c6d853fd00eb79a08101025900ca4c543" + }, + "emulator-w-250-1" : { "address": "1beecc6fef95b62e", - "key" : "8da7a03dbcdd9d84d4e5e9875744accf7810d41fc60dd2522e5fa3f1441eff1d" - }, - "emulator-w-250-2" : { + "key" : "8da7a03dbcdd9d84d4e5e9875744accf7810d41fc60dd2522e5fa3f1441eff1d" + }, + "emulator-w-250-2" : { "address": "ff8975b2fe6fb6f1", - "key" : "2e20dc54149cd114e265ef09b6dd09e222ce1979257b359fb6db53b64f260c6e" - }, - "emulator-w-500-1" : { + "key" : "2e20dc54149cd114e265ef09b6dd09e222ce1979257b359fb6db53b64f260c6e" + }, + "emulator-w-500-1" : { "address": "e9dd1081676bbc90", - "key" : "9c687961e7a1abe1e445830e7ec118ffd1e2a0449cf705f5476b3f100e94dc29" - }, - "emulator-w-500-2" : { + "key" : "9c687961e7a1abe1e445830e7ec118ffd1e2a0449cf705f5476b3f100e94dc29" + }, + "emulator-w-500-2" : { "address": "dbaa95c7691bc4f", - "key" : "bf242a7c12e299d90e4621d99501d1e27ccdc4d511cdf1f0fbba37a47e83bd24" - }, - "emulator-first": { - "address": "01cf0e2f2f715450", - "key": "d5457a187e9642a8e49d4032b3b4f85c92da7202c79681d9302c6e444e7033a8" - }, - "emulator-second": { - "address": "179b6b1cb6755e31", - "key": "d5457a187e9642a8e49d4032b3b4f85c92da7202c79681d9302c6e444e7033a8" - }, - "emulator-3": { - "address": "f3fcd2c1a78f5eee", - "key": "d5457a187e9642a8e49d4032b3b4f85c92da7202c79681d9302c6e444e7033a8" - }, - "emulator-4": { - "address": "e03daebed8ca0615", - "key": "d5457a187e9642a8e49d4032b3b4f85c92da7202c79681d9302c6e444e7033a8" - }, - "emulator-5": { - "address": "045a1763c93006ca", - "key": "d5457a187e9642a8e49d4032b3b4f85c92da7202c79681d9302c6e444e7033a8" - } + "key" : "bf242a7c12e299d90e4621d99501d1e27ccdc4d511cdf1f0fbba37a47e83bd24" + } } } diff --git a/scripts/get_resource.cdc b/scripts/get_resource.cdc new file mode 100644 index 0000000..e3306fb --- /dev/null +++ b/scripts/get_resource.cdc @@ -0,0 +1,39 @@ +// This script uses the resources PubSigner Public path to use the UUID function for uuid +// +// Alternatively, if the resource owner do not want to link PubSigner path, they can simply +// link the ResourceId interfaces and this script should then use the UUIDPubPath, i.e. VaultUUIDPubPath + +import FiatToken from 0xf8d6e0586b0a20c7 +import OnChainMultiSig from 0xf8d6e0586b0a20c7 + +pub fun main(resourceAddr: Address, resourceName: String): UInt64 { + let resourceAcct = getAccount(resourceAddr) + var resourcePubPath: PublicPath = FiatToken.VaultUUIDPubPath + + switch resourceName { + case "Vault": + resourcePubPath = FiatToken.VaultUUIDPubPath + case "Minter": + resourcePubPath = FiatToken.MinterUUIDPubPath + case "MinterController": + resourcePubPath = FiatToken.MinterControllerUUIDPubPath + case "MasterMinter": + resourcePubPath = FiatToken.MasterMinterUUIDPubPath + case "Pauser": + resourcePubPath = FiatToken.PauserUUIDPubPath + case "Blocklister": + resourcePubPath = FiatToken.BlocklisterUUIDPubPath + case "Admin": + resourcePubPath = FiatToken.AdminUUIDPubPath + case "Owner": + resourcePubPath = FiatToken.OwnerUUIDPubPath + default: + panic ("Resource not supported") + } + + let ref = resourceAcct.getCapability(resourcePubPath) + .borrow<&{FiatToken.ResourceId}>() + ?? panic("Could not borrow Get UUID reference to the Resource") + + return ref.UUID() +} \ No newline at end of file diff --git a/scripts/get_social_balance.cdc b/scripts/get_social_balance.cdc index 2a9aa5a..1995df5 100644 --- a/scripts/get_social_balance.cdc +++ b/scripts/get_social_balance.cdc @@ -1,5 +1,5 @@ import FungibleToken from 0xee82856bf20e2aa6 -import SocialToken from 0xf8d6e0586b0a20c7 +import SocialToken from 0x1cf0e2f2f715450 import Controller from 0xf8d6e0586b0a20c7 pub fun main(address:Address,tokenId: String): UFix64 { diff --git a/scripts/get_social_burn_quote.cdc b/scripts/get_social_burn_quote.cdc index ddc7874..65fc5c3 100644 --- a/scripts/get_social_burn_quote.cdc +++ b/scripts/get_social_burn_quote.cdc @@ -1,6 +1,6 @@ // This script reads the mintQuote field of Admin's Minter Resource -import SocialToken from 0xf8d6e0586b0a20c7 +import SocialToken from 0x1cf0e2f2f715450 pub fun main(amount: UFix64, tokenId: String):UFix64{ diff --git a/scripts/get_social_mint_quote.cdc b/scripts/get_social_mint_quote.cdc index 593d080..11b0603 100644 --- a/scripts/get_social_mint_quote.cdc +++ b/scripts/get_social_mint_quote.cdc @@ -1,6 +1,6 @@ // This script reads the mintQuote field of Admin's Minter Resource -import SocialToken from 0xf8d6e0586b0a20c7 +import SocialToken from 0x1cf0e2f2f715450 pub fun main(amount: UFix64, tokenId: String):UFix64{ diff --git a/scripts/get_usdc_balance.cdc b/scripts/get_usdc_balance.cdc new file mode 100644 index 0000000..c39c3f8 --- /dev/null +++ b/scripts/get_usdc_balance.cdc @@ -0,0 +1,19 @@ +// This script returns the balance of an account's FUSD vault. +// +// Parameters: +// - address: The address of the account holding the FUSD vault. +// +// This script will fail if they account does not have an FUSD vault. +// To check if an account has a vault or initialize a new vault, +// use check_fusd_vault_setup.cdc and setup_fusd_vault.cdc respectively. +import FungibleToken from 0xee82856bf20e2aa6 +import FiatToken from 0xf8d6e0586b0a20c7 +pub fun main(address: Address): UFix64 { + let account = getAccount(address) + + let vaultRef = account.getCapability(FiatToken.VaultBalancePubPath) + .borrow<&FiatToken.Vault{FungibleToken.Balance}>() + ?? panic("Could not borrow Balance reference to the Vault") + + return vaultRef.balance +} \ No newline at end of file diff --git a/tasks/mint_burnt_and_usdc/main.go b/tasks/mint_burnt_and_usdc/main.go new file mode 100644 index 0000000..1f55c0a --- /dev/null +++ b/tasks/mint_burnt_and_usdc/main.go @@ -0,0 +1,386 @@ +package main + +import ( + "fmt" + "log" + "bytes" + "io/ioutil" + "os" + "time" + + "text/template" + "encoding/hex" + + "github.com/onflow/cadence" + + "github.com/bjartek/go-with-the-flow/v2/gwtf" + + "github.com/onflow/flow-go-sdk" +) + +func main() { + + //This method starts an in memory flow emulator + // - it then looks at all the contracts in the deployment block for emulator and deploys them + // - then it looks at all the accounts that does not have contracts in them and create those accounts. These can be used as stakeholders in your "storyline" below. + // - when referencing accounts in the "storyline" below note that the default option is to prepened the network to the account name, This is done so that it is easy to run a storyline against emulator, tesnet and mainnet. This can be disabled with the `DoNotPrependNetworkToAccountNames` method on the g object below. + + + g := gwtf.NewGoWithTheFlowInMemoryEmulator() + + _, err := DeployFiatTokenContract(g, "account", "USDC", "0.1.0") + fmt.Println("err: ", err) + if err != nil { + log.Fatal("Cannot deploy contract") + } + x, err := DeploySocialTokenContract(g, "testaccount", "SocialToken") + if err != nil { + log.Fatal("Cannot deploy socialToken contract", err) + }else{ + fmt.Println("socialToken deployed successfully", x) + } + multiSigPubKeys, multiSigKeyWeights, multiSigAlgos := GetMultiSigKeys(g) + + + //Setup FUSD Vaults for all accounts + log.Printf(" ------") + g.TransactionFromFile("create_usdc_vault").SignProposeAndPayAs("first").RunPrintEventsFull() + log.Printf(" ---") + + g.TransactionFromFile("create_usdc_vault").SignProposeAndPayAs("account").RunPrintEventsFull() // Artist Vault + + g.TransactionFromFile("create_usdc_vault").SignProposeAndPayAs("blocklister").RunPrintEventsFull() // Artist Vault + + //create new minter + g.TransactionFromFile("create_new_minter").SignProposeAndPayAs("minter").AccountArgument("minter").Argument(cadence.NewArray(multiSigPubKeys)).Argument(cadence.NewArray(multiSigKeyWeights)).Argument(cadence.NewArray(multiSigAlgos)).RunPrintEventsFull() + + //create new minter controller + g.TransactionFromFile("create_new_minterController").SignProposeAndPayAs("minterController1").AccountArgument("minterController1").Argument(cadence.NewArray(multiSigPubKeys)).Argument(cadence.NewArray(multiSigKeyWeights)).Argument(cadence.NewArray(multiSigAlgos)).RunPrintEventsFull() + + //get minter resourceid + minterResource := g.ScriptFromFile("get_resource").AccountArgument("minter").StringArgument("Minter").RunFailOnError() + //fmt.Printf("t1: %T\n", minterResource) + fmt.Println("minterResource", minterResource) + //get minter controller resourceid + minterConrollerResource := g.ScriptFromFile("get_resource").AccountArgument("minterController1").StringArgument("MinterController").RunFailOnError() + //fmt.Printf("t1: %T\n", minterConrollerResource) + fmt.Println("minterResource", minterConrollerResource) + minter := uint64(114) + minterController := uint64(115) + //configure minter controller to manage the minter + g.TransactionFromFile("configure_minter_controller").SignProposeAndPayAs("account").UInt64Argument(minter).UInt64Argument(minterController).RunPrintEventsFull() + + //configure allowance + g.TransactionFromFile("configure_allowance").SignProposeAndPayAs("minterController1").UFix64Argument("2500000000.00").RunPrintEventsFull() + + // first Account Mints and deposits in one transaction + //g.TransactionFromFile("mint_usdc").SignProposeAndPayAs("minter").UFix64Argument("2500000000.00").AccountArgument("blocklister").RunPrintEventsFull() + + g.TransactionFromFile("mint_usdc").SignProposeAndPayAs("minter").UFix64Argument("2500000000.00").AccountArgument("first").RunPrintEventsFull() + //-------------------------------------------------// + //--------- Register Account -----------// + //-------------------------------------------------// + + //Register Token for a new account + g.TransactionFromFile("register_token").SignProposeAndPayAs("account").StringArgument("TestSymbol").UFix64Argument("10000000.00").AccountArgument("blocklister").RunPrintEventsFull() + + //--------------------------------------------------// + //-- SETUP Admin and Add Capability of Controller --// + //--------------------------------------------------// + g.TransactionFromFile("setup_admin_account").SignProposeAndPayAs("testaccount").RunPrintEventsFull() + + g.TransactionFromFile("add_admin_account").SignProposeAndPayAs("account").AccountArgument("testaccount").RunPrintEventsFull() + + //--------------------------------------------------// + //--------- SETUP AND MINT SOCIAL TOKEN ------------// + //--------------------------------------------------// + + //Setup SocialToken Vaults for both accounts + g.TransactionFromFile("setup_social_vault").SignProposeAndPayAs("first").StringArgument("TestSymbol_0xf3fcd2c1a78f5eee").RunPrintEventsFull() + g.TransactionFromFile("setup_social_vault").SignProposeAndPayAs("blocklister").StringArgument("TestSymbol_0xf3fcd2c1a78f5eee").RunPrintEventsFull() + //flow.TransactionFromFile("social_token/setup_social_vault").SignProposeAndPayAs("account").RunPrintEventsFull() + + mintQuote := g.ScriptFromFile("get_social_mint_quote").UFix64Argument("10000000.00").StringArgument("TestSymbol_0xf3fcd2c1a78f5eee").RunFailOnError() + log.Printf(" ------ Social Mint Quote ----- %s", mintQuote) + + //Log balance + usdcfirstAccountBalance := g.ScriptFromFile("get_usdc_balance").AccountArgument("first").RunFailOnError() + log.Printf("USDC balance of account 'first account' %s", usdcfirstAccountBalance) + + // mint social Tokens + g.TransactionFromFile("mint_Social_token_usdc").SignProposeAndPayAs("first").StringArgument("TestSymbol_0xf3fcd2c1a78f5eee").UFix64Argument("10000000.00").UFix64Argument(mintQuote.String()).RunPrintEventsFull() + + log.Printf(" ------ Social Mint Quote ----- %s", mintQuote) + //Admin Account deposits minter into first account + // flow.TransactionFromFile("social_token/deposit_social_minter").SignProposeAndPayAs("account").AccountArgument("first").RunPrintEventsFull() + TokenDetails := g.ScriptFromFile("get_social_details").StringArgument("TestSymbol_0xf3fcd2c1a78f5eee").RunFailOnError() + log.Printf(" ------ Social Token Details ----- %s", TokenDetails) + + // Get the balance of all accounts + ArtistAccountBalance := g.ScriptFromFile("get_issued_supply").StringArgument("TestSymbol_0xf3fcd2c1a78f5eee").RunFailOnError() + log.Printf(" ------ get Issued Supply ----- %s", ArtistAccountBalance) + + BurnPrice := g.ScriptFromFile("get_social_burn_quote").UFix64Argument("10000000.00").StringArgument("TestSymbol_0xf3fcd2c1a78f5eee").RunFailOnError() + log.Printf(" ------ first Burn Price ----- %s", BurnPrice) + + firstSocialBalance := g.ScriptFromFile("get_social_balance").AccountArgument("first").StringArgument("TestSymbol_0xf3fcd2c1a78f5eee").RunFailOnError() + log.Printf(" ------ first Social Token Balance ----- %s", firstSocialBalance) + + //reserve before burning social tokens + reserve := g.ScriptFromFile("get_reserve").StringArgument("TestSymbol_0xf3fcd2c1a78f5eee").RunFailOnError() + log.Printf(" ------ reserve before buring social tokens----- %s", reserve) + + // burn social Tokens + g.TransactionFromFile("burn_social_token").SignProposeAndPayAs("first").StringArgument("TestSymbol_0xf3fcd2c1a78f5eee").UFix64Argument("10000000.00000000").RunPrintEventsFull() + + //reserve before burning social tokens + reserve = g.ScriptFromFile("get_reserve").StringArgument("TestSymbol_0xf3fcd2c1a78f5eee").RunFailOnError() + log.Printf(" ------ reserve after buring social tokens----- %s", reserve) + + // Get the balance of all accounts + ArtistAccountBalanceUSDC := g.ScriptFromFile("get_usdc_balance").AccountArgument("blocklister").RunFailOnError() + log.Printf(" ------ first USDC Balance after burning ----- %s", ArtistAccountBalanceUSDC) + + ArtistAccountBalance = g.ScriptFromFile("get_social_balance").AccountArgument("blocklister").StringArgument("TestSymbol_0xf3fcd2c1a78f5eee").RunFailOnError() + log.Printf(" ------ first Social Balance after burning ----- %s", ArtistAccountBalance) + + //Log balance + fusdfirstAccountBalance := g.ScriptFromFile("get_usdc_balance").AccountArgument("first").RunFailOnError() + log.Printf("FUSD balance of account 'artist account' %s", fusdfirstAccountBalance) + + AdminBalance := g.ScriptFromFile("get_usdc_balance").AccountArgument("account").RunFailOnError() + log.Printf("Admin balance of account %s", AdminBalance) + +} + +// Useful multisig accounts +// These are named by the weights +// i.e. Account500_1 has a weight of 500.0 +const Acct1000 = "w-1000" +const Acct500_1 = "w-500-1" +const Acct500_2 = "w-500-2" +const Acct250_1 = "w-250-1" +const Acct250_2 = "w-250-2" +const Config = ".././flow.json" + +var FlowJSON []string = []string{Config} + +type Addresses struct { + FungibleToken string + FiatTokenInterface string + FiatToken string + OnChainMultiSig string +} + +type TestEvent struct { + Name string + Fields map[string]string +} + +var addresses Addresses + +func ParseCadenceTemplate(templatePath string) []byte { + fb, err := ioutil.ReadFile(templatePath) + if err != nil { + panic(err) + } + + tmpl, err := template.New("Template").Parse(string(fb)) + if err != nil { + panic(err) + } + + // Addresss for emulator are + // addresses = Addresses{"ee82856bf20e2aa6", "01cf0e2f2f715450", "01cf0e2f2f715450", "01cf0e2f2f715450", "01cf0e2f2f715450"} + addresses = Addresses{os.Getenv("FUNGIBLE_TOKEN_ADDRESS"), os.Getenv("OWNER_ADDRESS"), os.Getenv("OWNER_ADDRESS"), os.Getenv("OWNER_ADDRESS")} + + buf := &bytes.Buffer{} + err = tmpl.Execute(buf, addresses) + if err != nil { + panic(err) + } + + return buf.Bytes() +} + + +func GetMultiSigKeys(g *gwtf.GoWithTheFlow) (MultiSigPubKeys []cadence.Value, MultiSigKeyWeights []cadence.Value, MultiSigAlgos []cadence.Value) { + pk1000 := g.Account(Acct1000).Key().ToConfig().PrivateKey.PublicKey().String() + pk500_1 := g.Account(Acct500_1).Key().ToConfig().PrivateKey.PublicKey().String() + pk500_2 := g.Account(Acct500_2).Key().ToConfig().PrivateKey.PublicKey().String() + pk250_1 := g.Account(Acct250_1).Key().ToConfig().PrivateKey.PublicKey().String() + pk250_2 := g.Account(Acct250_2).Key().ToConfig().PrivateKey.PublicKey().String() + + w1000, _ := cadence.NewUFix64("1000.0") + w500, _ := cadence.NewUFix64("500.0") + w250, _ := cadence.NewUFix64("250.0") + + MultiSigPubKeys = []cadence.Value{ + cadence.String(pk1000[2:]), + cadence.String(pk500_1[2:]), + cadence.String(pk500_2[2:]), + cadence.String(pk250_1[2:]), + cadence.String(pk250_2[2:]), + } + + MultiSigAlgos = []cadence.Value{ + cadence.NewUInt8(1), + cadence.NewUInt8(1), + cadence.NewUInt8(1), + cadence.NewUInt8(1), + cadence.NewUInt8(1), + } + MultiSigKeyWeights = []cadence.Value{w1000, w500, w500, w250, w250} + return +} + +func ParseTestEvents(events []flow.Event) (formatedEvents []*gwtf.FormatedEvent) { + for _, e := range events { + formatedEvents = append(formatedEvents, gwtf.ParseEvent(e, uint64(0), time.Now(), nil)) + } + return +} + +func DeploySocialTokenContract(g *gwtf.GoWithTheFlow, ownerAcct string,tokenName string) (events []*gwtf.FormatedEvent, err error){ + + contractCode := ParseCadenceTemplate("././contracts/SocialToken.cdc") + fmt.Println("hello we are in social token") + + txFilename := "deploy_social_token" + + fmt.Println("parse socialToken template", txFilename) + //code := ParseCadenceTemplate(txFilename) + encodedStr := hex.EncodeToString(contractCode) + fmt.Println("template encoded") + + e, err := g.TransactionFromFile(txFilename). + SignProposeAndPayAs(ownerAcct). + StringArgument("SocialToken"). + StringArgument(encodedStr). + RunE() + gwtf.PrintEvents(e, map[string][]string{}) + events = ParseTestEvents(e) + + return +} +func DeployFiatTokenContract( + g *gwtf.GoWithTheFlow, + ownerAcct string, tokenName string, version string) (events []*gwtf.FormatedEvent, err error) { + + contractCode := ParseCadenceTemplate("././contracts/FiatToken.cdc") + + + txFilename := "deploy_contract_with_auth" + fmt.Println("parse template", txFilename) + //code := ParseCadenceTemplate(txFilename) + encodedStr := hex.EncodeToString(contractCode) + + if g.Network == "emulator" { + g.CreateAccounts("emulator-account") + } + fmt.Println("Accounts created") + multiSigPubKeys, multiSigKeyWeights, multiSigAlgos := GetMultiSigKeys(g) + fmt.Println("keys created") + e, err := g.TransactionFromFile(txFilename). + SignProposeAndPayAs(ownerAcct). + StringArgument("FiatToken"). + StringArgument(encodedStr). + // Vault + Argument(cadence.Path{Domain: "storage", Identifier: "USDCVault-2"}). + Argument(cadence.Path{Domain: "public", Identifier: "USDCVaultBalance-2"}). + Argument(cadence.Path{Domain: "public", Identifier: "USDCVaultUUID-2"}). + Argument(cadence.Path{Domain: "public", Identifier: "USDCVaultReceiver-2"}). + + // Blocklist executor + Argument(cadence.Path{Domain: "storage", Identifier: "USDCBlocklistExe-2"}). + // Blocklister + Argument(cadence.Path{Domain: "storage", Identifier: "USDCBlocklister-2"}). + Argument(cadence.Path{Domain: "public", Identifier: "USDCBlocklisterCapReceiver-2"}). + Argument(cadence.Path{Domain: "public", Identifier: "USDCBlocklisterUUID-2"}). + Argument(cadence.Path{Domain: "public", Identifier: "USDCBlocklisterPublicSigner-2"}). + // Pause executor + Argument(cadence.Path{Domain: "storage", Identifier: "USDCPauseExe-2"}). + // Pafirst + Argument(cadence.Path{Domain: "storage", Identifier: "USDCPafirst-2"}). + Argument(cadence.Path{Domain: "public", Identifier: "USDCPafirstCapReceiver-2"}). + Argument(cadence.Path{Domain: "public", Identifier: "USDCPafirstUUID-2"}). + Argument(cadence.Path{Domain: "public", Identifier: "USDCPafirstPublicSigner-2"}). + // Admin executor + Argument(cadence.Path{Domain: "storage", Identifier: "USDCAdminExe-2"}). + //Admin + Argument(cadence.Path{Domain: "storage", Identifier: "USDCAdmin-2"}). + Argument(cadence.Path{Domain: "public", Identifier: "USDCAdminCapReceiver-2"}). + Argument(cadence.Path{Domain: "public", Identifier: "USDCAdminUUID-2"}). + Argument(cadence.Path{Domain: "public", Identifier: "USDCAdminPublicSigner-2"}). + // Owner executor + Argument(cadence.Path{Domain: "storage", Identifier: "USDCOwnerExe-2"}). + // Owner + Argument(cadence.Path{Domain: "storage", Identifier: "USDCOwner-2"}). + Argument(cadence.Path{Domain: "public", Identifier: "USDCOwnerCapReceiver-2"}). + Argument(cadence.Path{Domain: "public", Identifier: "USDCOwnerUUID-2"}). + Argument(cadence.Path{Domain: "public", Identifier: "USDCOwnerPubSigner-2"}). + // Master Minter Executor + Argument(cadence.Path{Domain: "storage", Identifier: "USDCMasterMinterExe-2"}). + // Master Minter + Argument(cadence.Path{Domain: "storage", Identifier: "USDCMasterMinter-2"}). + Argument(cadence.Path{Domain: "public", Identifier: "USDCMasterMinterCapReceiver-2"}). + Argument(cadence.Path{Domain: "public", Identifier: "USDCMasterMinterPublicSigner-2"}). + Argument(cadence.Path{Domain: "public", Identifier: "USDCMasterMinterUUID-2"}). + // Minter Controller + Argument(cadence.Path{Domain: "storage", Identifier: "USDCMinterController-2"}). + Argument(cadence.Path{Domain: "public", Identifier: "USDCMinterControllerUUID-2"}). + Argument(cadence.Path{Domain: "public", Identifier: "USDCMinterControllerPublicSigner-2"}). + // Minter + Argument(cadence.Path{Domain: "storage", Identifier: "USDCMinter-2"}). + Argument(cadence.Path{Domain: "public", Identifier: "USDCMinterUUID-2"}). + // Initial resource capabilities + Argument(cadence.Path{Domain: "private", Identifier: "USDCAdminCap-2"}). + Argument(cadence.Path{Domain: "private", Identifier: "USDCOwnerCap-2"}). + Argument(cadence.Path{Domain: "private", Identifier: "USDCMasterMinterCap-2"}). + Argument(cadence.Path{Domain: "private", Identifier: "USDCPafirstCap-2"}). + Argument(cadence.Path{Domain: "private", Identifier: "USDCBlocklisterCap-2"}). + StringArgument(tokenName). + StringArgument(version). + UFix64Argument("1000000000.00000000"). + BooleanArgument(false). + Argument(cadence.NewArray(multiSigPubKeys)). + Argument(cadence.NewArray(multiSigKeyWeights)). + Argument(cadence.NewArray(multiSigAlgos)). + Argument(cadence.NewArray(multiSigPubKeys)). + Argument(cadence.NewArray(multiSigKeyWeights)). + Argument(cadence.NewArray(multiSigAlgos)). + Argument(cadence.NewArray(multiSigPubKeys)). + Argument(cadence.NewArray(multiSigKeyWeights)). + Argument(cadence.NewArray(multiSigAlgos)). + Argument(cadence.NewArray(multiSigPubKeys)). + Argument(cadence.NewArray(multiSigKeyWeights)). + Argument(cadence.NewArray(multiSigAlgos)). + Argument(cadence.NewArray(multiSigPubKeys)). + Argument(cadence.NewArray(multiSigKeyWeights)). + Argument(cadence.NewArray(multiSigAlgos)). + RunE() + gwtf.PrintEvents(e, map[string][]string{}) + events = ParseTestEvents(e) + + return +} + +func UpgradeFiatTokenContract( + g *gwtf.GoWithTheFlow, + ownerAcct string, version string) (events []*gwtf.FormatedEvent, err error) { + contractCode := ParseCadenceTemplate("././contracts/FiatToken.cdc") + txFilename := "upgrade_contract.cdc" + //code := ParseCadenceTemplate(txFilename) + encodedStr := hex.EncodeToString(contractCode) + + e, err := g.TransactionFromFile(txFilename). + SignProposeAndPayAs(ownerAcct). + StringArgument("FiatToken"). + StringArgument(encodedStr). + StringArgument(version). + RunE() + gwtf.PrintEvents(e, map[string][]string{}) + events = ParseTestEvents(e) + + return +} diff --git a/transactions/burn_social_token.cdc b/transactions/burn_social_token.cdc index 6f44521..c8ef746 100644 --- a/transactions/burn_social_token.cdc +++ b/transactions/burn_social_token.cdc @@ -1,6 +1,7 @@ import FungibleToken from 0xee82856bf20e2aa6 -import SocialToken from 0xf8d6e0586b0a20c7 +import SocialToken from 0x01cf0e2f2f715450 import Controller from 0xf8d6e0586b0a20c7 +import FiatToken from 0xf8d6e0586b0a20c7 transaction (tokenId: String, amountArtistToken: UFix64){ @@ -29,9 +30,10 @@ transaction (tokenId: String, amountArtistToken: UFix64){ ?? panic("Could not borrow receiver reference to the recipient's Vault 2") let burnedTokens <- burner.burnTokens(from: <- self.sentVault) let userReceiver = getAccount(self.accountAddress) - .getCapability(/public/fusdReceiver) - .borrow<&{FungibleToken.Receiver}>() + .getCapability(FiatToken.VaultReceiverPubPath) + .borrow<&FiatToken.Vault{FungibleToken.Receiver}>() ?? panic("Unable to borrow receiver reference") + userReceiver.deposit(from: <-burnedTokens) } } diff --git a/transactions/configure_allowance.cdc b/transactions/configure_allowance.cdc new file mode 100644 index 0000000..e521a65 --- /dev/null +++ b/transactions/configure_allowance.cdc @@ -0,0 +1,13 @@ +// MinterController uses this to configure minter allowance +// It succeeds of MinterController has assigned Minter from MasterMinter + +import FiatToken from 0xf8d6e0586b0a20c7 + +transaction (amount: UFix64) { + prepare(minterController: AuthAccount) { + let mc = minterController.borrow<&FiatToken.MinterController>(from: FiatToken.MinterControllerStoragePath) + ?? panic ("no minter controller resource avaialble"); + + mc.configureMinterAllowance(allowance: amount); + } +} \ No newline at end of file diff --git a/transactions/configure_minter_allowance.cdc b/transactions/configure_minter_allowance.cdc new file mode 100644 index 0000000..e521a65 --- /dev/null +++ b/transactions/configure_minter_allowance.cdc @@ -0,0 +1,13 @@ +// MinterController uses this to configure minter allowance +// It succeeds of MinterController has assigned Minter from MasterMinter + +import FiatToken from 0xf8d6e0586b0a20c7 + +transaction (amount: UFix64) { + prepare(minterController: AuthAccount) { + let mc = minterController.borrow<&FiatToken.MinterController>(from: FiatToken.MinterControllerStoragePath) + ?? panic ("no minter controller resource avaialble"); + + mc.configureMinterAllowance(allowance: amount); + } +} \ No newline at end of file diff --git a/transactions/configure_minter_controller.cdc b/transactions/configure_minter_controller.cdc new file mode 100644 index 0000000..6888398 --- /dev/null +++ b/transactions/configure_minter_controller.cdc @@ -0,0 +1,15 @@ +// Masterminter uses this to configure which Minter the MinterController manages + +import FiatToken from 0xf8d6e0586b0a20c7 + +transaction (minter: UInt64, minterController: UInt64) { + prepare(masterMinter: AuthAccount) { + let mm = masterMinter.borrow<&FiatToken.MasterMinterExecutor>(from: FiatToken.MasterMinterExecutorStoragePath) + ?? panic ("no masterminter resource avaialble"); + + mm.configureMinterController(minter: minter, minterController: minterController); + } + post { + FiatToken.getManagedMinter(resourceId: minterController) == minter : "minterController not configured" + } +} \ No newline at end of file diff --git a/transactions/create_new_minter.cdc b/transactions/create_new_minter.cdc new file mode 100644 index 0000000..8e0f751 --- /dev/null +++ b/transactions/create_new_minter.cdc @@ -0,0 +1,43 @@ +// This script creates a new Minter resource. +// If no onchain-multisig is required, empty publicKeys and pubKeyWeights array can be used. +// If account already has a Minter, it will remove it and create a new one. +// +// Minter are granted allowance by the UUID. +// If a new one is created, the UUID will be different and will not have the same allowance. + +import FungibleToken from 0xee82856bf20e2aa6 +import FiatToken from 0xf8d6e0586b0a20c7 +import OnChainMultiSig from 0xf8d6e0586b0a20c7 + +transaction(minterAddr: Address, publicKeys: [String], pubKeyWeights: [UFix64], multiSigAlgos: [UInt8]) { + prepare (minter: AuthAccount) { + + // Check and return if they already have a minter resource + //assert(minter.borrow<&FiatToken.Minter>(from: FiatToken.MinterStoragePath) != nil, message: "account already has minter resource") + // DANGER: Remove existing minter if present + if minter.borrow<&FiatToken.Minter>(from: FiatToken.MinterStoragePath) != nil { + minter.unlink(FiatToken.MinterUUIDPubPath) + let m <- minter.load<@FiatToken.Minter>(from: FiatToken.MinterStoragePath) + destroy m + } + + var i = 0; + let pka: [OnChainMultiSig.PubKeyAttr] = [] + while i < pubKeyWeights.length { + let a = OnChainMultiSig.PubKeyAttr(sa: multiSigAlgos[i], w: pubKeyWeights[i]) + pka.append(a) + i = i + 1; + } + + minter.save(<- FiatToken.createNewMinter(), to: FiatToken.MinterStoragePath); + + minter.link<&FiatToken.Minter{FiatToken.ResourceId}>(FiatToken.MinterUUIDPubPath, target: FiatToken.MinterStoragePath) + ?? panic("Could not link minter uuid"); + + } + + post { + getAccount(minterAddr).getCapability<&{FiatToken.ResourceId}>(FiatToken.MinterUUIDPubPath).check() : + "MinterUUID link not set" + } +} \ No newline at end of file diff --git a/transactions/create_new_minterController.cdc b/transactions/create_new_minterController.cdc new file mode 100644 index 0000000..bef570e --- /dev/null +++ b/transactions/create_new_minterController.cdc @@ -0,0 +1,47 @@ +// This script creates a new MinterController resource. +// If no onchain-multisig is required, empty publicKeys and pubKeyWeights array can be used. +// If account already has a MinterController, it will remove it and create a new one. +// +// MinterController are assigned Minter by the UUID. +// If a new one is created, the UUID will be different and will not have the same Minter to control. + +import FiatToken from 0xf8d6e0586b0a20c7 +import OnChainMultiSig from 0xf8d6e0586b0a20c7 + +transaction(minterControllerAddr: Address, publicKeys: [String], pubKeyWeights: [UFix64], multiSigAlgos: [UInt8]) { + + prepare (minterController: AuthAccount) { + + // Check and return if they already have a minter controller resource + if minterController.borrow<&FiatToken.MinterController>(from: FiatToken.MinterControllerStoragePath) != nil { + minterController.unlink(FiatToken.MinterControllerUUIDPubPath) + minterController.unlink(FiatToken.MinterControllerPubSigner) + let m <- minterController.load<@FiatToken.MinterController>(from: FiatToken.MinterControllerStoragePath) + destroy m + } + + var i = 0; + let pka: [OnChainMultiSig.PubKeyAttr] = [] + while i < pubKeyWeights.length { + let a = OnChainMultiSig.PubKeyAttr(sa: multiSigAlgos[i], w: pubKeyWeights[i]) + pka.append(a) + i = i + 1; + } + + minterController.save(<- FiatToken.createNewMinterController(publicKeys: publicKeys, pubKeyAttrs: pka), to: FiatToken.MinterControllerStoragePath); + + minterController.link<&FiatToken.MinterController{FiatToken.ResourceId}>(FiatToken.MinterControllerUUIDPubPath, target: FiatToken.MinterControllerStoragePath) + ?? panic("Could not link minter controller uuid"); + + minterController.link<&FiatToken.MinterController{OnChainMultiSig.PublicSigner}>(FiatToken.MinterControllerPubSigner, target: FiatToken.MinterControllerStoragePath) + ?? panic("Could not link minter controller public signer"); + } + + post { + getAccount(minterControllerAddr).getCapability<&{FiatToken.ResourceId}>(FiatToken.MinterControllerUUIDPubPath).check() : + "MinterControllerUUID link not set" + + getAccount(minterControllerAddr).getCapability<&{OnChainMultiSig.PublicSigner}>(FiatToken.MinterControllerPubSigner).check() : + "MinterControllerPubSigner link not set" + } +} \ No newline at end of file diff --git a/transactions/create_usdc_vault.cdc b/transactions/create_usdc_vault.cdc new file mode 100644 index 0000000..a6f882c --- /dev/null +++ b/transactions/create_usdc_vault.cdc @@ -0,0 +1,53 @@ +// This script is used to add a Vault resource to their account so that they can use FiatToken +// +// If the Vault already exist for the account, the script will return immediately without error +// +// If not onchain-multisig is required, pubkeys and key weights can be empty +// Vault resource must follow the FuntibleToken interface where initialiser only takes the balance +// As a result, the Vault owner is required to directly add public keys to the OnChainMultiSig.Manager +// via the `addKeys` method in the OnchainMultiSig.KeyManager interface. +// +// Therefore if multisig is required for the vault, the account itself should have the same key weight +// distribution as it does for the Vault. +import FungibleToken from 0xee82856bf20e2aa6 +import FiatToken from 0xf8d6e0586b0a20c7 +import OnChainMultiSig from 0xf8d6e0586b0a20c7 + +transaction() { + + prepare(signer: AuthAccount) { + + // Return early if the account already stores a FiatToken Vault + if signer.borrow<&FiatToken.Vault>(from: FiatToken.VaultStoragePath) != nil { + return + } + + // Create a new ExampleToken Vault and put it in storage + signer.save( + <-FiatToken.createEmptyVault(), + to: FiatToken.VaultStoragePath + ) + + // Create a public capability to the Vault that only exposes + // the deposit function through the Receiver interface + signer.link<&FiatToken.Vault{FungibleToken.Receiver}>( + FiatToken.VaultReceiverPubPath, + target: FiatToken.VaultStoragePath + ) + + // Create a public capability to the Vault that only exposes + // the UUID() function through the VaultUUID interface + signer.link<&FiatToken.Vault{FiatToken.ResourceId}>( + FiatToken.VaultUUIDPubPath, + target: FiatToken.VaultStoragePath + ) + + // Create a public capability to the Vault that only exposes + // the balance field through the Balance interface + signer.link<&FiatToken.Vault{FungibleToken.Balance}>( + FiatToken.VaultBalancePubPath, + target: FiatToken.VaultStoragePath + ) + + } +} \ No newline at end of file diff --git a/transactions/mint_Social_token_usdc.cdc b/transactions/mint_Social_token_usdc.cdc new file mode 100644 index 0000000..504a5d6 --- /dev/null +++ b/transactions/mint_Social_token_usdc.cdc @@ -0,0 +1,43 @@ +import SocialToken from 0x01cf0e2f2f715450 +import FungibleToken from 0xee82856bf20e2aa6 +import FiatToken from 0xf8d6e0586b0a20c7 +import Controller from 0xf8d6e0586b0a20c7 + +transaction(tokenId: String, amountArtistToken: UFix64, amountUsdToken: UFix64) { + + // The Vault resource that holds the tokens that are being transferred + let sentVault: @FungibleToken.Vault + + let trxAddress : Address + let usdcReceiver: Capability<&AnyResource{FungibleToken.Receiver}> + + + prepare(acct: AuthAccount) { + + self.trxAddress = acct.address + + let vaultRef = acct.borrow<&FiatToken.Vault>(from: FiatToken.VaultStoragePath) + ?? panic("Could not borrow reference to the owner's Vault!") + + self.sentVault <- vaultRef.withdraw(amount: amountUsdToken) + self.usdcReceiver = getAccount(acct.address) + .getCapability<&{FungibleToken.Receiver}>(FiatToken.VaultReceiverPubPath) + } + + execute { + + let tokenDetails = Controller.getTokenDetails(tokenId) + let minter = getAccount(self.trxAddress) + .getCapability(tokenDetails.socialMinterPublicPath) + .borrow<&{SocialToken.MinterPublic}>() + ?? panic("Could not borrow receiver reference to the S recipient's Vault") + let mintedTokens <- minter.mintTokens(tokenDetails.tokenId, amountArtistToken, usdcPayment: <- self.sentVault, receiverVault: self.usdcReceiver) + + let receiverRef = getAccount(self.trxAddress) + .getCapability(tokenDetails.tokenResourcePublicPath) + .borrow<&SocialToken.Vault{FungibleToken.Receiver}>() + ?? panic("Could not borrow receiver reference to the S recipient's Vault 2") + + receiverRef.deposit(from: <-mintedTokens) + } +} \ No newline at end of file diff --git a/transactions/mint_usdc.cdc b/transactions/mint_usdc.cdc new file mode 100644 index 0000000..4cd3f53 --- /dev/null +++ b/transactions/mint_usdc.cdc @@ -0,0 +1,26 @@ + + +// This script mints token on FiatToken contract and deposits the minted amount to the receiver's Vault +// It will fail if minter does not have enough allowance, is blocklisted or contract is paused + +import FungibleToken from 0xee82856bf20e2aa6 +import FiatToken from 0xf8d6e0586b0a20c7 + +transaction (amount: UFix64, receiver: Address) { + let mintedVault: @FungibleToken.Vault; + + prepare(minter: AuthAccount) { + let m = minter.borrow<&FiatToken.Minter>(from: FiatToken.MinterStoragePath) + ?? panic ("no minter resource avaialble"); + self.mintedVault <- m.mint(amount: amount) + } + + execute { + let recvAcct = getAccount(receiver); + let receiverRef = recvAcct.getCapability(FiatToken.VaultReceiverPubPath) + .borrow<&{FungibleToken.Receiver}>() + ?? panic("Could not borrow receiver reference to the recipient's Vault") + + receiverRef.deposit(from: <-self.mintedVault) + } +} \ No newline at end of file diff --git a/transactions/setup_social_vault.cdc b/transactions/setup_social_vault.cdc index 60f5fbb..700332f 100644 --- a/transactions/setup_social_vault.cdc +++ b/transactions/setup_social_vault.cdc @@ -1,4 +1,4 @@ -import SocialToken from 0xf8d6e0586b0a20c7 +import SocialToken from 0x01cf0e2f2f715450 import FungibleToken from 0xee82856bf20e2aa6 import Controller from 0xf8d6e0586b0a20c7 From 7a7787276ffff4b3d1bcaf58e7e9f012ddbdc6f5 Mon Sep 17 00:00:00 2001 From: danishtroon Date: Thu, 24 Feb 2022 15:07:43 +0000 Subject: [PATCH 4/5] added the fee spliter detail functionality --- contracts/Controller.cdc | 15 +++++++++++---- tasks/mint_burnt_and_usdc/main.go | 2 ++ transactions/register_token.cdc | 6 +----- transactions/setfeeSpliterDetail.cdc | 16 ++++++++++++++++ 4 files changed, 30 insertions(+), 9 deletions(-) create mode 100644 transactions/setfeeSpliterDetail.cdc diff --git a/contracts/Controller.cdc b/contracts/Controller.cdc index dc9aae7..2314104 100644 --- a/contracts/Controller.cdc +++ b/contracts/Controller.cdc @@ -17,7 +17,9 @@ pub contract Controller { pub event registerToken(_ tokenId: String, _ symbol: String, _ maxSupply: UFix64, _ artist: Address) // Emitted when a Percentage of social token is updated pub event updatePercentage(_ percentage: UFix64) - + // Emitted when fee for social token is updated + pub event updateFeeSpliterDetail(_ tokenId: String) + // Paths pub let AdminStoragePath: StoragePath pub var SocialTokenResourceStoragePath: StoragePath @@ -105,10 +107,11 @@ pub struct TokenStructure { } pub resource interface SpecialCapability { - pub fun registerToken( _ symbol: String, _ maxSupply: UFix64, _ feeSplitterDetail: {Address: FeeStructure}, _ artist: Address, + pub fun registerToken( _ symbol: String, _ maxSupply: UFix64, _ artist: Address, _ tokenStoragePath: StoragePath, _ tokenPublicPath: PublicPath, _ socialMinterStoragePath: StoragePath, _ socialMinterPublicPath: PublicPath, _ socialBurnerStoragePath: StoragePath, _ socialBurnerPublicPath: PublicPath) + pub fun updateFeeSpliterDetail( _ tokenId: String, _ feeSplitterDetail: {Address: FeeStructure}) } pub resource interface UserSpecialCapability { @@ -123,7 +126,7 @@ pub struct TokenStructure { } pub resource Admin: SpecialCapability { - pub fun registerToken( _ symbol: String, _ maxSupply: UFix64, _ feeSplitterDetail: {Address:FeeStructure}, _ artist: Address, + pub fun registerToken( _ symbol: String, _ maxSupply: UFix64, _ artist: Address, _ tokenStoragePath: StoragePath, _ tokenPublicPath: PublicPath, _ socialMinterStoragePath: StoragePath, _ socialMinterPublicPath: PublicPath, _ socialBurnerStoragePath: StoragePath, _ socialBurnerPublicPath: PublicPath) { @@ -140,9 +143,13 @@ pub struct TokenStructure { tokenStoragePath, tokenPublicPath, socialMinterStoragePath, socialMinterPublicPath, socialBurnerStoragePath, socialBurnerPublicPath) - Controller.allSocialTokens[tokenId]!.setFeeSpliterDetail(feeSplitterDetail) emit registerToken(tokenId, symbol, maxSupply, artistAddress) } + + pub fun updateFeeSpliterDetail( _ tokenId: String, _ feeSplitterDetail: {Address: FeeStructure}) { + Controller.allSocialTokens[tokenId]!.setFeeSpliterDetail(feeSplitterDetail) + emit updateFeeSpliterDetail(tokenId) + } } pub resource SocialTokenResource : SocialTokenResourcePublic , UserSpecialCapability { diff --git a/tasks/mint_burnt_and_usdc/main.go b/tasks/mint_burnt_and_usdc/main.go index 1f55c0a..c6f1a2d 100644 --- a/tasks/mint_burnt_and_usdc/main.go +++ b/tasks/mint_burnt_and_usdc/main.go @@ -84,6 +84,8 @@ func main() { //Register Token for a new account g.TransactionFromFile("register_token").SignProposeAndPayAs("account").StringArgument("TestSymbol").UFix64Argument("10000000.00").AccountArgument("blocklister").RunPrintEventsFull() + //add setfeeSpliterDetail for given Token + g.TransactionFromFile("setfeeSpliterDetail").SignProposeAndPayAs("account").StringArgument("TestSymbol_0xf3fcd2c1a78f5eee").AccountArgument("blocklister").RunPrintEventsFull() //--------------------------------------------------// //-- SETUP Admin and Add Capability of Controller --// //--------------------------------------------------// diff --git a/transactions/register_token.cdc b/transactions/register_token.cdc index 5377873..42ab4eb 100644 --- a/transactions/register_token.cdc +++ b/transactions/register_token.cdc @@ -5,10 +5,6 @@ transaction (symbol: String, maxSupply: UFix64, artistAddress: Address){ let adminResource = acct.borrow<&Controller.Admin>(from:Controller.AdminStoragePath) ??panic("could not borrow a reference to the admin") - let feeSplitterDetail: {Address:Controller.FeeStructure} = { - acct.address: Controller.FeeStructure(0.05), - artistAddress: Controller.FeeStructure(0.15) - } let tokenStoragePath = /storage/TestSymbol_0x05 let tokenPublicPath = /public/TestSymbol_0x05 @@ -16,7 +12,7 @@ transaction (symbol: String, maxSupply: UFix64, artistAddress: Address){ let socialMinterPublicPath = /public/TestSymbol_0x5Minter let socialBurnerStoragePath = /storage/TestSymbol_0x5Burner let socialBurnerPublicPath = /public/TestSymbol_0x5Burner - adminResource.registerToken(symbol, maxSupply, feeSplitterDetail, artistAddress, + adminResource.registerToken(symbol, maxSupply, artistAddress, tokenStoragePath, tokenPublicPath, socialMinterStoragePath, socialMinterPublicPath, socialBurnerStoragePath, socialBurnerPublicPath diff --git a/transactions/setfeeSpliterDetail.cdc b/transactions/setfeeSpliterDetail.cdc new file mode 100644 index 0000000..f455a21 --- /dev/null +++ b/transactions/setfeeSpliterDetail.cdc @@ -0,0 +1,16 @@ +import Controller from 0xf8d6e0586b0a20c7 + +transaction (tokenId: String, artistAddress: Address){ + prepare(acct: AuthAccount) { + let adminResource = acct.borrow<&Controller.Admin>(from:Controller.AdminStoragePath) + ??panic("could not borrow a reference to the admin") + + let feeSplitterDetail: {Address:Controller.FeeStructure} = { + acct.address: Controller.FeeStructure(0.05), + artistAddress: Controller.FeeStructure(0.15) + } + + + adminResource.updateFeeSpliterDetail(tokenId, feeSplitterDetail) + } +} \ No newline at end of file From 0fcb74cdc82348ba0dcb806ea042a3c1c28c4dce Mon Sep 17 00:00:00 2001 From: danishtroon Date: Fri, 25 Feb 2022 08:16:30 +0000 Subject: [PATCH 5/5] udpate the changes --- contracts/Controller.cdc | 12 +-- contracts/SocialToken.cdc | 2 +- flow1.json | 99 ------------------- tasks/mint_burnt_and_usdc/main.go | 4 +- ...terDetail.cdc => setfeeSplitterDetail.cdc} | 2 +- 5 files changed, 10 insertions(+), 109 deletions(-) delete mode 100644 flow1.json rename transactions/{setfeeSpliterDetail.cdc => setfeeSplitterDetail.cdc} (87%) diff --git a/contracts/Controller.cdc b/contracts/Controller.cdc index 2314104..f2fa5cb 100644 --- a/contracts/Controller.cdc +++ b/contracts/Controller.cdc @@ -18,7 +18,7 @@ pub contract Controller { // Emitted when a Percentage of social token is updated pub event updatePercentage(_ percentage: UFix64) // Emitted when fee for social token is updated - pub event updateFeeSpliterDetail(_ tokenId: String) + pub event updateFeeSplitterDetail(_ tokenId: String) // Paths pub let AdminStoragePath: StoragePath @@ -99,7 +99,7 @@ pub struct TokenStructure { } - pub fun setFeeSpliterDetail(_ feeSplitterDetail: {Address: FeeStructure}) { + pub fun setFeeSplitterDetail(_ feeSplitterDetail: {Address: FeeStructure}) { pre { } self.feeSplitterDetail = feeSplitterDetail @@ -111,7 +111,7 @@ pub struct TokenStructure { _ tokenStoragePath: StoragePath, _ tokenPublicPath: PublicPath, _ socialMinterStoragePath: StoragePath, _ socialMinterPublicPath: PublicPath, _ socialBurnerStoragePath: StoragePath, _ socialBurnerPublicPath: PublicPath) - pub fun updateFeeSpliterDetail( _ tokenId: String, _ feeSplitterDetail: {Address: FeeStructure}) + pub fun updateFeeSplitterDetail( _ tokenId: String, _ feeSplitterDetail: {Address: FeeStructure}) } pub resource interface UserSpecialCapability { @@ -146,9 +146,9 @@ pub struct TokenStructure { emit registerToken(tokenId, symbol, maxSupply, artistAddress) } - pub fun updateFeeSpliterDetail( _ tokenId: String, _ feeSplitterDetail: {Address: FeeStructure}) { - Controller.allSocialTokens[tokenId]!.setFeeSpliterDetail(feeSplitterDetail) - emit updateFeeSpliterDetail(tokenId) + pub fun updateFeeSplitterDetail( _ tokenId: String, _ feeSplitterDetail: {Address: FeeStructure}) { + Controller.allSocialTokens[tokenId]!.setFeeSplitterDetail(feeSplitterDetail) + emit updateFeeSplitterDetail(tokenId) } } diff --git a/contracts/SocialToken.cdc b/contracts/SocialToken.cdc index 47848fe..63fdd9e 100644 --- a/contracts/SocialToken.cdc +++ b/contracts/SocialToken.cdc @@ -286,7 +286,7 @@ pub contract SocialToken: FungibleToken { init() { self.totalSupply = 0.0 - var adminPrivateCap = self.account.getCapability + var adminPrivateCap = self.account.getCapability <&{Controller.SocialTokenResourcePublic}>(/private/SocialTokenResourcePrivatePath) self.adminRef = adminPrivateCap diff --git a/flow1.json b/flow1.json deleted file mode 100644 index abdfd45..0000000 --- a/flow1.json +++ /dev/null @@ -1,99 +0,0 @@ -{ - - "emulators": { - "default": { - "port": 3569, - "serviceAccount": "emulator-account" - } - }, - "contracts": { - "Debug": "./contracts/Debug.cdc", - "SocialToken": { - "source": "./contracts/SocialToken.cdc", - "aliases": { - "emulator": "0x0ae53cb6e3f42a79", - "testnet": "0x7e60df042a9c0868" - } - }, - "FungibleToken": { - "source": "./contracts/FungibleToken.cdc", - "aliases": { - "emulator": "0xee82856bf20e2aa6", - "testnet": "0x9a0766d93b6608b7" - } - }, - "FUSD": { - "source": "./contracts/FUSD.cdc", - "aliases": { - "emulator": "0x0ae53cb6e3f42a79", - "testnet": "0x7e60df042a9c0868" - } - }, - "Controller": { - "source": "./contracts/Controller.cdc", - "aliases": { - "emulator": "0x0ae53cb6e3f42a79", - "testnet": "0x7e60df042a9c0868" - } - }, - "FiatTokenInterface": { - "source": "./contracts/FiatTokenInterface.cdc", - "aliases": { - "emulator": "0x0ae53cb6e3f42a79", - "testnet": "0x7e60df042a9c0868" - } - }, - "OnChainMultiSig": { - "source": "./contracts/OnChainMultiSig.cdc", - "aliases": { - "emulator": "0x0ae53cb6e3f42a79", - "testnet": "0x7e60df042a9c0868" - } - } - }, - "networks": { - "emulator": "127.0.0.1:3569", - "mainnet": "access.mainnet.nodes.onflow.org:9000", - "testnet": "access.devnet.nodes.onflow.org:9000" - }, - "accounts": { - "emulator-account": { - "address": "f8d6e0586b0a20c7", - "key": "dc0097a6b58533e56af78c955e7b0c0f386b5f44f22b75c390beab7fcb1af13f" - }, - "emulator-first": { - "address": "01cf0e2f2f715450", - "key": "d5457a187e9642a8e49d4032b3b4f85c92da7202c79681d9302c6e444e7033a8" - }, - "emulator-second": { - "address": "179b6b1cb6755e31", - "key": "d5457a187e9642a8e49d4032b3b4f85c92da7202c79681d9302c6e444e7033a8" - }, - "emulator-3": { - "address": "f3fcd2c1a78f5eee", - "key": "d5457a187e9642a8e49d4032b3b4f85c92da7202c79681d9302c6e444e7033a8" - }, - "emulator-4": { - "address": "e03daebed8ca0615", - "key": "d5457a187e9642a8e49d4032b3b4f85c92da7202c79681d9302c6e444e7033a8" - }, - "emulator-5": { - "address": "045a1763c93006ca", - "key": "d5457a187e9642a8e49d4032b3b4f85c92da7202c79681d9302c6e444e7033a8" - } - }, - "deployments": { - "emulator": { - "emulator-account": [ - "FungibleToken", - "FUSD", - "Controller", - "FiatTokenInterface", - "OnChainMultiSig", - "SocialToken" - ], - "emulator-first": [], - "emulator-second": [] - } - } -} \ No newline at end of file diff --git a/tasks/mint_burnt_and_usdc/main.go b/tasks/mint_burnt_and_usdc/main.go index c6f1a2d..ef36905 100644 --- a/tasks/mint_burnt_and_usdc/main.go +++ b/tasks/mint_burnt_and_usdc/main.go @@ -84,8 +84,8 @@ func main() { //Register Token for a new account g.TransactionFromFile("register_token").SignProposeAndPayAs("account").StringArgument("TestSymbol").UFix64Argument("10000000.00").AccountArgument("blocklister").RunPrintEventsFull() - //add setfeeSpliterDetail for given Token - g.TransactionFromFile("setfeeSpliterDetail").SignProposeAndPayAs("account").StringArgument("TestSymbol_0xf3fcd2c1a78f5eee").AccountArgument("blocklister").RunPrintEventsFull() + //add setfeeSplitterDetail for given Token + g.TransactionFromFile("setfeeSplitterDetail").SignProposeAndPayAs("account").StringArgument("TestSymbol_0xf3fcd2c1a78f5eee").AccountArgument("blocklister").RunPrintEventsFull() //--------------------------------------------------// //-- SETUP Admin and Add Capability of Controller --// //--------------------------------------------------// diff --git a/transactions/setfeeSpliterDetail.cdc b/transactions/setfeeSplitterDetail.cdc similarity index 87% rename from transactions/setfeeSpliterDetail.cdc rename to transactions/setfeeSplitterDetail.cdc index f455a21..1eee9f2 100644 --- a/transactions/setfeeSpliterDetail.cdc +++ b/transactions/setfeeSplitterDetail.cdc @@ -11,6 +11,6 @@ transaction (tokenId: String, artistAddress: Address){ } - adminResource.updateFeeSpliterDetail(tokenId, feeSplitterDetail) + adminResource.updateFeeSplitterDetail(tokenId, feeSplitterDetail) } } \ No newline at end of file