Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Crescendo #164

Merged
merged 34 commits into from
May 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
82d8da8
- Update all HybridCustody contract dependencies
austinkline Mar 23, 2024
acaa263
address all contract errors/warnings
austinkline Apr 1, 2024
dd03073
split entitlements up
austinkline Apr 1, 2024
ec07d6d
remove placeholder entitlement
austinkline Apr 1, 2024
2bff3f3
move public capability retrieval to the CapabilityFactory
austinkline Apr 1, 2024
58b081f
fix CapabilityDelegator tests
austinkline Apr 1, 2024
42746d4
fix CapabilityFactory tests
austinkline Apr 1, 2024
1301040
fix HybridCustody tests
austinkline Apr 3, 2024
1731fe6
configure tests with flow-c1
austinkline Apr 3, 2024
317016a
add exclusions to code coverage
austinkline Apr 3, 2024
ed12538
add Burnable Interface
austinkline Apr 3, 2024
b075ab0
fix access level for burn callback
austinkline Apr 3, 2024
96fbbbf
add missing tests, make a new _borrowAccount method for internal use …
austinkline Apr 3, 2024
53ff595
add tests for burn callback
austinkline Apr 3, 2024
2d12790
add test for public capabilities
austinkline Apr 3, 2024
0336192
add comments to burnCallback methods
austinkline Apr 3, 2024
da10712
remove all variables and references to private paths
austinkline Apr 12, 2024
419deea
update entitlements
austinkline Apr 12, 2024
ce76340
more entitlements changes
austinkline Apr 12, 2024
3e923b5
add {Collection} and {Vault} factories
austinkline Apr 17, 2024
83b7571
add missing contract in config
austinkline Apr 17, 2024
0c8ef75
remove incorrect entitlement usage
austinkline Apr 22, 2024
547abbe
remove built-in entitlements
austinkline Apr 24, 2024
2b22935
correct entitlements for NFT.Withdraw because migrations also need th…
austinkline Apr 24, 2024
0c0243b
update Burner testnet alias
sisyphusSmiling Apr 24, 2024
1346ae1
sync new nft standard and public capability retrieval changes
austinkline May 4, 2024
6b46b3b
add temporary local migration report
sisyphusSmiling May 7, 2024
8ae4eee
remove all conjunctions from function acess modifiers
austinkline May 7, 2024
2671d5d
update local migration report
sisyphusSmiling May 7, 2024
b646f85
fix FTVaultFactory
austinkline May 7, 2024
051c49c
fix migration types for child account factory and delegator
austinkline May 8, 2024
7562ab1
fix tests
austinkline May 8, 2024
0b41ec7
update ChildAccount.delegator field to CapabilityDelegator.Delegator
sisyphusSmiling May 8, 2024
756be5f
remove temp report directory
sisyphusSmiling May 8, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions .github/workflows/integration-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,9 @@ jobs:
with:
go-version: 1.18
- name: Install Flow CLI
run: bash -ci "$(curl -fsSL https://raw.githubusercontent.com/onflow/flow-cli/master/install.sh)" -- v1.5.0
run: bash -ci "$(curl -fsSL https://raw.githubusercontent.com/onflow/flow-cli/feature/stable-cadence/install.sh)"
- name: Run tests
run: sh ./test.sh
- name: Normalize coverage report filepaths
run : sh ./normalize_coverage_report.sh
- name: Upload coverage reports to Codecov
uses: codecov/codecov-action@v3
env:
Expand Down
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ coverage.lcov
.idea
*.pkey
*.private
*.pem
*.pem
node_modules/
10 changes: 5 additions & 5 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
[submodule "modules/flow-nft"]
path = modules/flow-nft
url = https://github.com/Flowtyio/flow-nft.git
[submodule "flow-ft"]
path = flow-ft
url = https://github.com/Flowtyio/flow-ft.git
url = https://github.com/onflow/flow-nft.git
[submodule "modules/flow-utils"]
path = modules/flow-utils
url = https://github.com/Flowtyio/flow-utils.git
url = https://github.com/green-goo-dao/flow-utils.git
[submodule "modules/flow-ft"]
path = modules/flow-ft
url = https://github.com/onflow/flow-ft.git
11 changes: 11 additions & 0 deletions codecov.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
ignore:
- "contracts/standard/ExampleNFT.cdc"
- "contracts/standard/ExampleNFT2.cdc"
- "contracts/standard/ExampleToken.cdc"
- "contracts/factories/FTBalanceFactory.cdc"
- "contracts/factories/FTProviderFactory.cdc"
- "contracts/factories/FTReceiverFactory.cdc"
- "contracts/factories/NFTCollectionPublicFactory.cdc"
- "contracts/factories/NFTProviderFactory.cdc"
- "contracts/factories/FTVaultFactory.cdc"
- "contracts/factories/NFTCollectionFactory.cdc"
54 changes: 28 additions & 26 deletions contracts/CapabilityDelegator.cdc
Original file line number Diff line number Diff line change
Expand Up @@ -7,56 +7,59 @@
/// private `Delegator` can only be borrowed from the child account when you have access to the full `ChildAccount`
/// resource.
///
pub contract CapabilityDelegator {
access(all) contract CapabilityDelegator {

/* --- Canonical Paths --- */
//
pub let StoragePath: StoragePath
pub let PrivatePath: PrivatePath
pub let PublicPath: PublicPath
access(all) let StoragePath: StoragePath
access(all) let PublicPath: PublicPath

access(all) entitlement Get
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel like this entitlement needs a slightly more descriptive name, but I'm not 100% sure of my opinion

access(all) entitlement Add
access(all) entitlement Delete

/* --- Events --- */
//
pub event DelegatorCreated(id: UInt64)
pub event DelegatorUpdated(id: UInt64, capabilityType: Type, isPublic: Bool, active: Bool)
access(all) event DelegatorCreated(id: UInt64)
access(all) event DelegatorUpdated(id: UInt64, capabilityType: Type, isPublic: Bool, active: Bool)

/// Private interface for Capability retrieval
///
pub resource interface GetterPrivate {
austinkline marked this conversation as resolved.
Show resolved Hide resolved
pub fun getPrivateCapability(_ type: Type): Capability? {
access(all) resource interface GetterPrivate {
access(Get) view fun getPrivateCapability(_ type: Type): Capability? {
post {
result == nil || type.isSubtype(of: result.getType()): "incorrect returned capability type"
}
}
pub fun findFirstPrivateType(_ type: Type): Type?
pub fun getAllPrivate(): [Capability]
access(all) view fun findFirstPrivateType(_ type: Type): Type?
austinkline marked this conversation as resolved.
Show resolved Hide resolved
access(Get) fun getAllPrivate(): [Capability]
}

/// Exposes public Capability retrieval
///
pub resource interface GetterPublic {
pub fun getPublicCapability(_ type: Type): Capability? {
access(all) resource interface GetterPublic {
access(all) view fun getPublicCapability(_ type: Type): Capability? {
post {
result == nil || type.isSubtype(of: result.getType()): "incorrect returned capability type "
result == nil || type.isSubtype(of: result.getType()): "incorrect returned capability type"
}
}

pub fun findFirstPublicType(_ type: Type): Type?
pub fun getAllPublic(): [Capability]
access(all) view fun findFirstPublicType(_ type: Type): Type?
access(all) view fun getAllPublic(): [Capability]
}

/// This Delegator is used to store Capabilities, partitioned by public and private access with corresponding
/// GetterPublic and GetterPrivate conformances.AccountCapabilityController
///
pub resource Delegator: GetterPublic, GetterPrivate {
access(all) resource Delegator: GetterPublic, GetterPrivate {
access(self) let privateCapabilities: {Type: Capability}
access(self) let publicCapabilities: {Type: Capability}

// ------ Begin Getter methods
//
/// Returns the public Capability of the given Type if it exists
///
pub fun getPublicCapability(_ type: Type): Capability? {
access(all) view fun getPublicCapability(_ type: Type): Capability? {
return self.publicCapabilities[type]
}

Expand All @@ -66,23 +69,23 @@ pub contract CapabilityDelegator {
/// @param type: Type of the Capability to retrieve
/// @return Capability of the given Type if it exists, nil otherwise
///
pub fun getPrivateCapability(_ type: Type): Capability? {
access(Get) view fun getPrivateCapability(_ type: Type): Capability? {
return self.privateCapabilities[type]
}

/// Returns all public Capabilities
///
/// @return List of all public Capabilities
///
pub fun getAllPublic(): [Capability] {
access(all) view fun getAllPublic(): [Capability] {
return self.publicCapabilities.values
}

/// Returns all private Capabilities
///
/// @return List of all private Capabilities
///
pub fun getAllPrivate(): [Capability] {
access(Get) fun getAllPrivate(): [Capability] {
return self.privateCapabilities.values
}

Expand All @@ -91,7 +94,7 @@ pub contract CapabilityDelegator {
/// @param type: Type to check for subtypes
/// @return First public Type that is a subtype of the given Type, nil otherwise
///
pub fun findFirstPublicType(_ type: Type): Type? {
access(all) view fun findFirstPublicType(_ type: Type): Type? {
for t in self.publicCapabilities.keys {
if t.isSubtype(of: type) {
return t
Expand All @@ -106,7 +109,7 @@ pub contract CapabilityDelegator {
/// @param type: Type to check for subtypes
/// @return First private Type that is a subtype of the given Type, nil otherwise
///
pub fun findFirstPrivateType(_ type: Type): Type? {
access(all) view fun findFirstPrivateType(_ type: Type): Type? {
for t in self.privateCapabilities.keys {
if t.isSubtype(of: type) {
return t
Expand All @@ -122,7 +125,7 @@ pub contract CapabilityDelegator {
/// @param cap: Capability to add
/// @param isPublic: Whether the Capability should be public or private
///
pub fun addCapability(cap: Capability, isPublic: Bool) {
access(Add) fun addCapability(cap: Capability, isPublic: Bool) {
pre {
cap.check<&AnyResource>(): "Invalid Capability provided"
}
Expand All @@ -138,7 +141,7 @@ pub contract CapabilityDelegator {
///
/// @param cap: Capability to remove
///
pub fun removeCapability(cap: Capability) {
access(Delete) fun removeCapability(cap: Capability) {
if let removedPublic = self.publicCapabilities.remove(key: cap.getType()) {
emit DelegatorUpdated(id: self.uuid, capabilityType: cap.getType(), isPublic: true, active: false)
}
Expand All @@ -158,7 +161,7 @@ pub contract CapabilityDelegator {
///
/// @return Newly created Delegator
///
pub fun createDelegator(): @Delegator {
access(all) fun createDelegator(): @Delegator {
let delegator <- create Delegator()
emit DelegatorCreated(id: delegator.uuid)
return <- delegator
Expand All @@ -167,7 +170,6 @@ pub contract CapabilityDelegator {
init() {
let identifier = "CapabilityDelegator_".concat(self.account.address.toString())
self.StoragePath = StoragePath(identifier: identifier)!
self.PrivatePath = PrivatePath(identifier: identifier)!
self.PublicPath = PublicPath(identifier: identifier)!
}
}
Expand Down
38 changes: 20 additions & 18 deletions contracts/CapabilityFactory.cdc
Original file line number Diff line number Diff line change
Expand Up @@ -13,45 +13,48 @@
/// Capabilities is critical to the use case of Hybrid Custody. It's advised to use Factories sparingly and only for
/// cases where Capabilities must be castable by the caller.
///
pub contract CapabilityFactory {
access(all) contract CapabilityFactory {

pub let StoragePath: StoragePath
pub let PrivatePath: PrivatePath
pub let PublicPath: PublicPath
access(all) let StoragePath: StoragePath
access(all) let PublicPath: PublicPath

access(all) entitlement Add
access(all) entitlement Delete

austinkline marked this conversation as resolved.
Show resolved Hide resolved
/// Factory structures a common interface for Capability retrieval from a given account at a specified path
///
pub struct interface Factory {
pub fun getCapability(acct: &AuthAccount, path: CapabilityPath): Capability
access(all) struct interface Factory {
access(all) view fun getCapability(acct: auth(Capabilities) &Account, controllerID: UInt64): Capability?
access(all) view fun getPublicCapability(acct: &Account, path: PublicPath): Capability?
}

/// Getter defines an interface for retrieval of a Factory if contained within the implementing resource
///
pub resource interface Getter {
pub fun getSupportedTypes(): [Type]
pub fun getFactory(_ t: Type): {CapabilityFactory.Factory}?
access(all) resource interface Getter {
access(all) view fun getSupportedTypes(): [Type]
access(all) view fun getFactory(_ t: Type): {CapabilityFactory.Factory}?
}

/// Manager is a resource that contains Factories and implements the Getter interface for retrieval of contained
/// Factories
///
pub resource Manager: Getter {
access(all) resource Manager: Getter {
/// Mapping of Factories indexed on Type of Capability they retrieve
pub let factories: {Type: {CapabilityFactory.Factory}}
access(all) let factories: {Type: {CapabilityFactory.Factory}}

/// Retrieves a list of Types supported by contained Factories
///
/// @return List of Types supported by the Manager
///
pub fun getSupportedTypes(): [Type] {
access(all) view fun getSupportedTypes(): [Type] {
return self.factories.keys
}

/// Retrieves a Factory from the Manager, returning it or nil if it doesn't exist
///
/// @param t: Type the Factory is indexed on
///
pub fun getFactory(_ t: Type): {CapabilityFactory.Factory}? {
access(all) view fun getFactory(_ t: Type): {CapabilityFactory.Factory}? {
return self.factories[t]
}

Expand All @@ -60,7 +63,7 @@ pub contract CapabilityFactory {
/// @param t: Type of Capability the Factory retrieves
/// @param f: Factory to add
///
pub fun addFactory(_ t: Type, _ f: {CapabilityFactory.Factory}) {
access(Add) fun addFactory(_ t: Type, _ f: {CapabilityFactory.Factory}) {
pre {
!self.factories.containsKey(t): "Factory of given type already exists"
}
Expand All @@ -72,15 +75,15 @@ pub contract CapabilityFactory {
/// @param t: Type of Capability the Factory retrieves
/// @param f: Factory to replace existing Factory
///
pub fun updateFactory(_ t: Type, _ f: {CapabilityFactory.Factory}) {
access(Add) fun updateFactory(_ t: Type, _ f: {CapabilityFactory.Factory}) {
self.factories[t] = f
}

/// Removes a Factory from the Manager, returning it or nil if it didn't exist
///
/// @param t: Type the Factory is indexed on
///
pub fun removeFactory(_ t: Type): {CapabilityFactory.Factory}? {
access(Delete) fun removeFactory(_ t: Type): {CapabilityFactory.Factory}? {
return self.factories.remove(key: t)
}

Expand All @@ -92,14 +95,13 @@ pub contract CapabilityFactory {
/// Creates a Manager resource
///
/// @return Manager resource
pub fun createFactoryManager(): @Manager {
access(all) fun createFactoryManager(): @Manager {
return <- create Manager()
}

init() {
let identifier = "CapabilityFactory_".concat(self.account.address.toString())
self.StoragePath = StoragePath(identifier: identifier)!
self.PrivatePath = PrivatePath(identifier: identifier)!
self.PublicPath = PublicPath(identifier: identifier)!
}
}
Loading
Loading