diff --git a/contracts/MultiSigFlowToken.cdc b/contracts/MultiSigFlowToken.cdc index cc6e9de..0f293f2 100644 --- a/contracts/MultiSigFlowToken.cdc +++ b/contracts/MultiSigFlowToken.cdc @@ -3,9 +3,6 @@ import OnChainMultiSig from 0x{{.OnChainMultiSig}} pub contract MultiSigFlowToken: FungibleToken { - // Total supply of Flow tokens in existence - pub var totalSupply: UFix64 - // Event that is emitted when the contract is created pub event TokensInitialized(initialSupply: UFix64) @@ -21,6 +18,9 @@ pub contract MultiSigFlowToken: FungibleToken { pub let VaultReceiverPubPath: PublicPath; pub let VaultPubSigner: PublicPath; + // Total supply of Flow tokens in existence + pub var totalSupply: UFix64 + // Vault // pub resource Vault: @@ -33,12 +33,10 @@ pub contract MultiSigFlowToken: FungibleToken { // holds the balance of a users tokens pub var balance: UFix64 - // initialize the balance at resource creation time - init(balance: UFix64) { - self.balance = balance; - self.multiSigManager <- OnChainMultiSig.createMultiSigManager(publicKeys: [], pubKeyAttrs: []) - } - + // Resource to keep track of partial sigatures and payloads, required for onchain multisig features. + // Limited to `access(self)` to avoid exposing all functions in `SignatureManager` interface to account owner(s) + access(self) let multiSigManager: @OnChainMultiSig.Manager; + pub fun withdraw(amount: UFix64): @FungibleToken.Vault { self.balance = self.balance - amount @@ -55,13 +53,9 @@ pub contract MultiSigFlowToken: FungibleToken { } // - // Below resource and interfaces are required for any resources wanting to use OnChainMultiSig + // Below are the interfaces are required for any resources wanting to use OnChainMultiSig // - // Resource to keep track of partial sigatures and payloads, required for onchain multisig features. - // Limited to `access(self)` to avoid exposing all functions in `SignatureManager` interface to account owner(s) - access(self) let multiSigManager: @OnChainMultiSig.Manager; - /// To submit a new paylaod, i.e. starting a new tx requiring, potentially requiring more signatures pub fun addNewPayload(payload: @OnChainMultiSig.PayloadDetails, publicKey: String, sig: [UInt8]) { self.multiSigManager.addNewPayload(resourceId: self.uuid, payload: <-payload, publicKey: publicKey, sig: sig); @@ -157,15 +151,21 @@ pub contract MultiSigFlowToken: FungibleToken { MultiSigFlowToken.totalSupply = MultiSigFlowToken.totalSupply - self.balance destroy self.multiSigManager } - } - pub fun createEmptyVault(): @Vault { - return <-create Vault(balance: 0.0) + // initialize the balance at resource creation time + init(balance: UFix64) { + self.balance = balance; + self.multiSigManager <- OnChainMultiSig.createMultiSigManager(publicKeys: [], pubKeyAttrs: []) + } + } pub resource Administrator { } + pub fun createEmptyVault(): @Vault { + return <-create Vault(balance: 0.0) + } init(adminAccount: AuthAccount) { self.totalSupply = 100000.0 diff --git a/contracts/OnChainMultiSig.cdc b/contracts/OnChainMultiSig.cdc index bf6207f..4b785bd 100644 --- a/contracts/OnChainMultiSig.cdc +++ b/contracts/OnChainMultiSig.cdc @@ -3,9 +3,82 @@ import FungibleToken from "./FungibleToken.cdc" pub contract OnChainMultiSig { + // + // ------- Events ------- + // pub event NewPayloadAdded(resourceId: UInt64, txIndex: UInt64); pub event NewPayloadSigAdded(resourceId: UInt64, txIndex: UInt64); + // + // ------- Interfaces ------- + // + + /// Public Signer + /// + /// These interfaces is intended for public usage, a resource that stores the @Manager should implement + /// + /// 1. addNewPayload: add new transaction payload to the signature store waiting for others to sign + /// 2. addPayloadSignature: add signature to store for existing paylaods by payload index + /// 3. executeTx: attempt to execute the transaction at a given index after required signatures have been added + /// 4. UUID: gets the uuid of this resource + /// 5. getTxIndex: gets the sequentially assigned current txIndex of multisig pending tx of this resource + /// 6. getSignerKeys: gets the list of public keys for the resource's multisig signers + /// 7. getSignerKeyAttr: gets the stored key attributes + /// Interfaces 1&2 use `OnChainMultiSig.Manager` resource for code implementation + /// Interface 3 needs to be implemented specifically for each resource + /// Interfaces 4-7 are useful information to interact with the multiSigManager + /// + /// For example, a `Vault` resource with onchain multisig capabilities should implement these interfaces, + /// see example in "./MultiSigFlowToken" + pub resource interface PublicSigner { + pub fun addNewPayload(payload: @PayloadDetails, publicKey: String, sig: [UInt8]); + pub fun addPayloadSignature (txIndex: UInt64, publicKey: String, sig: [UInt8]); + pub fun executeTx(txIndex: UInt64): @AnyResource?; + pub fun UUID(): UInt64; + pub fun getTxIndex(): UInt64; + pub fun getSignerKeys(): [String]; + pub fun getSignerKeyAttr(publicKey: String): PubKeyAttr?; + } + + /// Key Manager + /// + /// Optional interfaces for owner of the vault to add / remove keys in @Manager. + pub resource interface KeyManager { + pub fun addKeys( multiSigPubKeys: [String], multiSigKeyWeights: [UFix64]); + pub fun removeKeys( multiSigPubKeys: [String]); + } + + /// Signature Manager + /// + /// These interfaces are minimum required for implementors of `PublicSigner` to work + /// with the @Manager resource + pub resource interface SignatureManager { + pub fun getSignerKeys(): [String]; + pub fun getSignerKeyAttr(publicKey: String): PubKeyAttr?; + pub fun addNewPayload (resourceId: UInt64, payload: @PayloadDetails, publicKey: String, sig: [UInt8]); + pub fun addPayloadSignature (resourceId: UInt64, txIndex: UInt64, publicKey: String, sig: [UInt8]); + pub fun readyForExecution(txIndex: UInt64): @PayloadDetails?; + pub fun configureKeys (pks: [String], kws: [UFix64]); + pub fun removeKeys (pks: [String]); + } + + // + // ------- Struct ------- + // + + pub struct PubKeyAttr{ + pub let sigAlgo: UInt8; + pub let weight: UFix64 + + init(sa: UInt8, w: UFix64) { + self.sigAlgo = sa; + self.weight = w; + } + } + + // + // ------- Resources ------- + // /// PayloadDetails /// @@ -141,65 +214,6 @@ pub contract OnChainMultiSig { } } - pub struct PubKeyAttr{ - pub let sigAlgo: UInt8; - pub let weight: UFix64 - - init(sa: UInt8, w: UFix64) { - self.sigAlgo = sa; - self.weight = w; - } - } - - /// Public Signer - /// - /// These interfaces is intended for public usage, a resource that stores the @Manager should implement - /// - /// 1. addNewPayload: add new transaction payload to the signature store waiting for others to sign - /// 2. addPayloadSignature: add signature to store for existing paylaods by payload index - /// 3. executeTx: attempt to execute the transaction at a given index after required signatures have been added - /// 4. UUID: gets the uuid of this resource - /// 5. getTxIndex: gets the sequentially assigned current txIndex of multisig pending tx of this resource - /// 6. getSignerKeys: gets the list of public keys for the resource's multisig signers - /// 7. getSignerKeyAttr: gets the stored key attributes - /// Interfaces 1&2 use `OnChainMultiSig.Manager` resource for code implementation - /// Interface 3 needs to be implemented specifically for each resource - /// Interfaces 4-7 are useful information to interact with the multiSigManager - /// - /// For example, a `Vault` resource with onchain multisig capabilities should implement these interfaces, - /// see example in "./MultiSigFlowToken" - pub resource interface PublicSigner { - pub fun addNewPayload(payload: @PayloadDetails, publicKey: String, sig: [UInt8]); - pub fun addPayloadSignature (txIndex: UInt64, publicKey: String, sig: [UInt8]); - pub fun executeTx(txIndex: UInt64): @AnyResource?; - pub fun UUID(): UInt64; - pub fun getTxIndex(): UInt64; - pub fun getSignerKeys(): [String]; - pub fun getSignerKeyAttr(publicKey: String): PubKeyAttr?; - } - - /// Key Manager - /// - /// Optional interfaces for owner of the vault to add / remove keys in @Manager. - pub resource interface KeyManager { - pub fun addKeys( multiSigPubKeys: [String], multiSigKeyWeights: [UFix64]); - pub fun removeKeys( multiSigPubKeys: [String]); - } - - /// Signature Manager - /// - /// These interfaces are minimum required for implementors of `PublicSigner` to work - /// with the @Manager resource - pub resource interface SignatureManager { - pub fun getSignerKeys(): [String]; - pub fun getSignerKeyAttr(publicKey: String): PubKeyAttr?; - pub fun addNewPayload (resourceId: UInt64, payload: @PayloadDetails, publicKey: String, sig: [UInt8]); - pub fun addPayloadSignature (resourceId: UInt64, txIndex: UInt64, publicKey: String, sig: [UInt8]); - pub fun readyForExecution(txIndex: UInt64): @PayloadDetails?; - pub fun configureKeys (pks: [String], kws: [UFix64]); - pub fun removeKeys (pks: [String]); - } - /// Manager /// /// The main resource that stores, keys, payloads and signature before all signatures are collected / executed @@ -377,7 +391,11 @@ pub contract OnChainMultiSig { } } } - + + // + // ------- Functions -------- + // + pub fun createMultiSigManager(publicKeys: [String], pubKeyAttrs: [PubKeyAttr]): @Manager { return <- create Manager(publicKeys: publicKeys, pubKeyAttrs: pubKeyAttrs) }