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

Contract updates for cadence 1.0 #21

Merged
merged 42 commits into from
Sep 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
cb471d5
copy standard contracts for cadence 1.0
austinkline Jan 10, 2024
3ae5b3d
add lost and found migration
austinkline Jan 11, 2024
3034d23
add example nft and token contracts
austinkline Jan 11, 2024
6a76f22
bump beta version
austinkline Jan 11, 2024
4b4376b
update stable cadence core contracts
austinkline Mar 8, 2024
ea2c71b
bump beta version
austinkline Mar 8, 2024
57af5b5
fix ExampleNFT
austinkline Mar 8, 2024
a589905
fix ExampleToken
austinkline Mar 8, 2024
f632b14
bump package version
austinkline Mar 11, 2024
32bbeca
sync flow-utils contracts
austinkline Mar 13, 2024
8087427
resync LostAndFound and all flow-utils
austinkline Mar 14, 2024
86c9200
bump version
austinkline Mar 14, 2024
ce91efb
duc migration
austinkline Mar 14, 2024
5673fba
handle flow utility token
austinkline Mar 14, 2024
47cb966
bump package
austinkline Mar 14, 2024
6933e83
update TokenForwarding contract
austinkline Mar 15, 2024
6ea7843
update LostAndFound
austinkline Mar 17, 2024
535aabe
sync ScopedFTProviders
austinkline Mar 19, 2024
f24759c
copy v1 of hybrid custody contracts
austinkline Apr 5, 2024
52b5540
bump package version
austinkline Apr 5, 2024
0661abc
hybrid custody contracts
austinkline Apr 14, 2024
b9e1a07
dapper offers + TopShot
austinkline Apr 14, 2024
70c111f
sync ScopedNFTProviders
austinkline Apr 17, 2024
3c13a4d
resync HC contracts
austinkline Apr 24, 2024
de02e4a
sync nft standard
austinkline May 4, 2024
d1377f6
sync flow-utils
austinkline May 4, 2024
5b49b21
sync FindViews and FLOAT
austinkline May 4, 2024
cb2b5a4
install crescendo in workflow
austinkline May 4, 2024
fc2eacb
sync MetadataViews, HybridCustody
austinkline May 4, 2024
5024346
correct factory contract name
austinkline May 5, 2024
b658e7f
sync lost and found
austinkline May 28, 2024
e3885e4
sync hybrid custody
austinkline May 28, 2024
d17b4f2
sync dapper offer dependencies
austinkline Aug 17, 2024
0c74f7a
flowty drops contracts (#22)
austinkline Aug 19, 2024
78a082a
Add CapabilityCache contract
austinkline Aug 24, 2024
a72a93f
add FungibleTokenSwitchboard contract
austinkline Aug 26, 2024
0249637
Add FungibleTokenRouter (#23)
austinkline Aug 27, 2024
5c82f73
bump version
austinkline Aug 27, 2024
f420532
sync router
austinkline Aug 28, 2024
be81034
version bump
austinkline Aug 28, 2024
90ba66f
sync Router
austinkline Aug 28, 2024
b459a38
sync drops contracts
austinkline Aug 28, 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
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,6 @@ jobs:
with:
node-version: '14'
- 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/master/install.sh)"
- name: Run tests
run: sh ./test.sh
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ Currently, the list includes:
| FTProviderFactory | 0x294e44e1ec6993c6 | 0xd8a7e05a7ac670c0 |
| FTReceiverFactory | 0x294e44e1ec6993c6 | 0xd8a7e05a7ac670c0 |
| NFTCollectionPublicFactory | 0x294e44e1ec6993c6 | 0xd8a7e05a7ac670c0 |
| NFTProviderAndCollectionPublicFactory | 0x294e44e1ec6993c6 | 0xd8a7e05a7ac670c0 |
| NFTProviderAndCollectionFactory | 0x294e44e1ec6993c6 | 0xd8a7e05a7ac670c0 |
| NFTProviderFactory | 0x294e44e1ec6993c6 | 0xd8a7e05a7ac670c0 |
| NFTCatalog | 0x49a7cda3a1eecc29 | 0x324c34e1c517e4db |
| NFTCatalogAdmin | 0x49a7cda3a1eecc29 | 0x324c34e1c517e4db |
Expand Down
44 changes: 44 additions & 0 deletions contracts/Burner.cdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/// Burner is a contract that can facilitate the destruction of any resource on flow.
///
/// Contributors
/// - Austin Kline - https://twitter.com/austin_flowty
/// - Deniz Edincik - https://twitter.com/bluesign
/// - Bastian Müller - https://twitter.com/turbolent
access(all) contract Burner {
/// When Crescendo (Cadence 1.0) is released, custom destructors will be removed from cadece.
/// Burnable is an interface meant to replace this lost feature, allowing anyone to add a callback
/// method to ensure they do not destroy something which is not meant to be,
/// or to add logic based on destruction such as tracking the supply of a FT Collection
///
/// NOTE: The only way to see benefit from this interface
/// is to always use the burn method in this contract. Anyone who owns a resource can always elect **not**
/// to destroy a resource this way
access(all) resource interface Burnable {
access(contract) fun burnCallback()
}

/// burn is a global method which will destroy any resource it is given.
/// If the provided resource implements the Burnable interface,
/// it will call the burnCallback method and then destroy afterwards.
access(all) fun burn(_ r: @AnyResource) {
if let s <- r as? @{Burnable} {
s.burnCallback()
destroy s
} else if let arr <- r as? @[AnyResource] {
while arr.length > 0 {
let item <- arr.removeFirst()
self.burn(<-item)
}
destroy arr
} else if let dict <- r as? @{HashableStruct: AnyResource} {
let keys = dict.keys
while keys.length > 0 {
let item <- dict.remove(key: keys.removeFirst())!
self.burn(<-item)
}
destroy dict
} else {
destroy r
}
}
}
76 changes: 37 additions & 39 deletions contracts/FlowStorageFees.cdc
Original file line number Diff line number Diff line change
Expand Up @@ -17,29 +17,29 @@
import "FungibleToken"
import "FlowToken"

pub contract FlowStorageFees {
access(all) contract FlowStorageFees {

// Emitted when the amount of storage capacity an account has per reserved Flow token changes
pub event StorageMegaBytesPerReservedFLOWChanged(_ storageMegaBytesPerReservedFLOW: UFix64)
access(all) event StorageMegaBytesPerReservedFLOWChanged(_ storageMegaBytesPerReservedFLOW: UFix64)

// Emitted when the minimum amount of Flow tokens that an account needs to have reserved for storage capacity changes.
pub event MinimumStorageReservationChanged(_ minimumStorageReservation: UFix64)
access(all) event MinimumStorageReservationChanged(_ minimumStorageReservation: UFix64)

// Defines how much storage capacity every account has per reserved Flow token.
// definition is written per unit of flow instead of the inverse,
// so there is no loss of precision calculating storage from flow,
// but there is loss of precision when calculating flow per storage.
pub var storageMegaBytesPerReservedFLOW: UFix64
access(all) var storageMegaBytesPerReservedFLOW: UFix64

// Defines the minimum amount of Flow tokens that every account needs to have reserved for storage capacity.
// If an account has less then this amount reserved by the end of any transaction it participated in, the transaction will fail.
pub var minimumStorageReservation: UFix64
access(all) var minimumStorageReservation: UFix64

// An administrator resource that can change the parameters of the FlowStorageFees smart contract.
pub resource Administrator {
access(all) resource Administrator {

// Changes the amount of storage capacity an account has per accounts' reserved storage FLOW.
pub fun setStorageMegaBytesPerReservedFLOW(_ storageMegaBytesPerReservedFLOW: UFix64) {
access(all) fun setStorageMegaBytesPerReservedFLOW(_ storageMegaBytesPerReservedFLOW: UFix64) {
if FlowStorageFees.storageMegaBytesPerReservedFLOW == storageMegaBytesPerReservedFLOW {
return
}
Expand All @@ -48,7 +48,7 @@ pub contract FlowStorageFees {
}

// Changes the minimum amount of FLOW an account has to have reserved.
pub fun setMinimumStorageReservation(_ minimumStorageReservation: UFix64) {
access(all) fun setMinimumStorageReservation(_ minimumStorageReservation: UFix64) {
if FlowStorageFees.minimumStorageReservation == minimumStorageReservation {
return
}
Expand All @@ -63,19 +63,19 @@ pub contract FlowStorageFees {
///
/// Returns megabytes
/// If the account has no default balance it is counted as a balance of 0.0 FLOW
pub fun calculateAccountCapacity(_ accountAddress: Address): UFix64 {
access(all) fun calculateAccountCapacity(_ accountAddress: Address): UFix64 {
var balance = 0.0
if let balanceRef = getAccount(accountAddress)
.getCapability<&FlowToken.Vault{FungibleToken.Balance}>(/public/flowTokenBalance)!
.borrow() {
balance = balanceRef.balance
let acct = getAccount(accountAddress)

if let balanceRef = acct.capabilities.borrow<&FlowToken.Vault>(/public/flowTokenBalance) {
balance = balanceRef.balance
}

return self.accountBalanceToAccountStorageCapacity(balance)
}

/// calculateAccountsCapacity returns the storage capacity of a batch of accounts
pub fun calculateAccountsCapacity(_ accountAddresses: [Address]): [UFix64] {
access(all) fun calculateAccountsCapacity(_ accountAddresses: [Address]): [UFix64] {
let capacities: [UFix64] = []
for accountAddress in accountAddresses {
let capacity = self.calculateAccountCapacity(accountAddress)
Expand All @@ -88,19 +88,19 @@ pub contract FlowStorageFees {
// This is used to check if a transaction will fail because of any account being over the storage capacity
// The payer is an exception as its storage capacity is derived from its balance minus the maximum possible transaction fees
// (transaction fees if the execution effort is at the execution efort limit, a.k.a.: computation limit, a.k.a.: gas limit)
pub fun getAccountsCapacityForTransactionStorageCheck(accountAddresses: [Address], payer: Address, maxTxFees: UFix64): [UFix64] {
access(all) fun getAccountsCapacityForTransactionStorageCheck(accountAddresses: [Address], payer: Address, maxTxFees: UFix64): [UFix64] {
let capacities: [UFix64] = []
for accountAddress in accountAddresses {
var balance = 0.0
if let balanceRef = getAccount(accountAddress)
.getCapability<&FlowToken.Vault{FungibleToken.Balance}>(/public/flowTokenBalance)!
.borrow() {
if accountAddress == payer {
// if the account is the payer, deduct the maximum possible transaction fees from the balance
balance = balanceRef.balance.saturatingSubtract(maxTxFees)
} else {
balance = balanceRef.balance
}
let acct = getAccount(accountAddress)

if let balanceRef = acct.capabilities.borrow<&FlowToken.Vault>(/public/flowTokenBalance) {
if accountAddress == payer {
// if the account is the payer, deduct the maximum possible transaction fees from the balance
balance = balanceRef.balance.saturatingSubtract(maxTxFees)
} else {
balance = balanceRef.balance
}
}

capacities.append(self.accountBalanceToAccountStorageCapacity(balance))
Expand All @@ -110,7 +110,7 @@ pub contract FlowStorageFees {

// accountBalanceToAccountStorageCapacity returns the storage capacity
// an account would have with given the flow balance of the account.
pub fun accountBalanceToAccountStorageCapacity(_ balance: UFix64): UFix64 {
access(all) view fun accountBalanceToAccountStorageCapacity(_ balance: UFix64): UFix64 {
// get address token balance
if balance < self.minimumStorageReservation {
// if < then minimum return 0
Expand All @@ -123,25 +123,25 @@ pub contract FlowStorageFees {

// Amount in Flow tokens
// Returns megabytes
pub fun flowToStorageCapacity(_ amount: UFix64): UFix64 {
access(all) view fun flowToStorageCapacity(_ amount: UFix64): UFix64 {
return amount.saturatingMultiply(FlowStorageFees.storageMegaBytesPerReservedFLOW)
}

// Amount in megabytes
// Returns Flow tokens
pub fun storageCapacityToFlow(_ amount: UFix64): UFix64 {
if FlowStorageFees.storageMegaBytesPerReservedFLOW == 0.0 as UFix64 {
return 0.0 as UFix64
access(all) view fun storageCapacityToFlow(_ amount: UFix64): UFix64 {
if FlowStorageFees.storageMegaBytesPerReservedFLOW == 0.0 {
return 0.0
}
// possible loss of precision
// putting the result back into `flowToStorageCapacity` might not yield the same result
return amount / FlowStorageFees.storageMegaBytesPerReservedFLOW
}

// converts storage used from UInt64 Bytes to UFix64 Megabytes.
pub fun convertUInt64StorageBytesToUFix64Megabytes(_ storage: UInt64): UFix64 {
access(all) view fun convertUInt64StorageBytesToUFix64Megabytes(_ storage: UInt64): UFix64 {
// safe convert UInt64 to UFix64 (without overflow)
let f = UFix64(storage % 100000000 as UInt64) * 0.00000001 as UFix64 + UFix64(storage / 100000000 as UInt64)
let f = UFix64(storage % 100000000) * 0.00000001 + UFix64(storage / 100000000)
// decimal point correction. Megabytes to bytes have a conversion of 10^-6 while UFix64 minimum value is 10^-8
let storageMb = f.saturatingMultiply(100.0)
return storageMb
Expand All @@ -151,13 +151,12 @@ pub contract FlowStorageFees {
///
/// The available balance of an account is its default token balance minus what is reserved for storage.
/// If the account has no default balance it is counted as a balance of 0.0 FLOW
pub fun defaultTokenAvailableBalance(_ accountAddress: Address): UFix64 {
access(all) fun defaultTokenAvailableBalance(_ accountAddress: Address): UFix64 {
//get balance of account
let acct = getAccount(accountAddress)
var balance = 0.0
if let balanceRef = acct
.getCapability(/public/flowTokenBalance)
.borrow<&FlowToken.Vault{FungibleToken.Balance}>() {

if let balanceRef = acct.capabilities.borrow<&FlowToken.Vault>(/public/flowTokenBalance) {
balance = balanceRef.balance
}

Expand All @@ -171,9 +170,9 @@ pub contract FlowStorageFees {
///
/// The reserved balance of an account is its storage used multiplied by the storage cost per flow token.
/// The reserved balance is at least the minimum storage reservation.
pub fun defaultTokenReservedBalance(_ accountAddress: Address): UFix64 {
access(all) view fun defaultTokenReservedBalance(_ accountAddress: Address): UFix64 {
let acct = getAccount(accountAddress)
var reserved = self.storageCapacityToFlow(self.convertUInt64StorageBytesToUFix64Megabytes(acct.storageUsed))
var reserved = self.storageCapacityToFlow(self.convertUInt64StorageBytesToUFix64Megabytes(acct.storage.used))
// at least self.minimumStorageReservation should be reserved
if reserved < self.minimumStorageReservation {
reserved = self.minimumStorageReservation
Expand All @@ -187,7 +186,6 @@ pub contract FlowStorageFees {
self.minimumStorageReservation = 0.0 // or 0 kb of minimum storage reservation

let admin <- create Administrator()
self.account.save(<-admin, to: /storage/storageFeesAdmin)
self.account.storage.save(<-admin, to: /storage/storageFeesAdmin)
}
}

Loading
Loading