Skip to content

Commit

Permalink
update CrossVMMetadataViews & add to go lib
Browse files Browse the repository at this point in the history
  • Loading branch information
sisyphusSmiling committed Feb 6, 2025
1 parent 3c02d16 commit d11f5e0
Show file tree
Hide file tree
Showing 4 changed files with 124 additions and 22 deletions.
63 changes: 63 additions & 0 deletions contracts/CrossVMMetadataViews.cdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import "EVM"

/// This contract implements views originally proposed in FLIP-318 supporting NFT collections
/// with project-defined implementations across both Cadence & EVM.
///
access(all) contract CrossVMMetadataViews {

/// An enum denoting a VM. For now, there are only two VMs on Flow, but this enum could be
/// expanded in the event other VMs are supported on the network.
///
access(all) enum VM : UInt8 {
access(all) case Cadence
access(all) case EVM
}

/// View resolved at contract & resource level pointing to the associated EVM implementation.
/// NOTE: This view alone is not sufficient to validate an association across Cadence & EVM!
/// Both the Cadence Type/contract *and* the EVM contract should point to each other, with the
/// EVM pointer being facilitated by ICrossVM.sol contract interface methods. For more
/// information and context, see FLIP-318: https://github.com/onflow/flips/issues/318
///
access(all) struct EVMPointer {
/// The associated Cadence Type
access(all) let cadenceType: Type
/// The defining Cadence contract address
access(all) let cadenceContractAddress: Address
/// The associated EVM contract address
access(all) let evmContractAddress: EVM.EVMAddress
/// Whether the asset is Cadence- or EVM-native. Native here meaning the VM in which the
/// asset is distributed.
access(all) let nativeVM: VM

init(
cadenceType: Type,
cadenceContractAddress: Address,
evmContractAddress: EVM.EVMAddress,
nativeVM: VM
) {
self.cadenceType = cadenceType
self.cadenceContractAddress = cadenceContractAddress
self.evmContractAddress = evmContractAddress
self.nativeVM = nativeVM
}
}

/// View resolved at resource level denoting any metadata to be passed to the associated EVM
/// contract at the time of / bridging. This optional view would allow EVM side metadata to be
/// updated based on current Cadence state. If the / view is not supported, no bytes will be
/// passed into EVM when bridging.
///
access(all) struct EVMBytesMetadata {
/// Returns the bytes to be passed to the EVM contract on `fulfillToEVM` call, allowing the
/// EVM contract to update / the metadata associated with the NFT. The corresponding Solidity
/// `bytes` type allows the implementer greater / flexibility by enabling them to pass
/// arbitrary data between VMs.
access(all) let bytes: EVM.EVMBytes?

init(bytes: EVM.EVMBytes?) {
self.bytes = bytes
}
}

}
47 changes: 29 additions & 18 deletions lib/go/contracts/contracts.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,27 +14,30 @@ import (
)

var (
placeholderNonFungibleToken = regexp.MustCompile(`"NonFungibleToken"`)
nonFungibleTokenImport = "NonFungibleToken from "
placeholderMetadataViews = regexp.MustCompile(`"MetadataViews"`)
metadataViewsImport = "MetadataViews from "
placeholderFungibleToken = regexp.MustCompile(`"FungibleToken"`)
fungibleTokenImport = "FungibleToken from "
placeholderResolver = regexp.MustCompile(`"ViewResolver"`)
viewResolverImport = "ViewResolver from "
placeholderUniversalCollection = regexp.MustCompile(`"UniversalCollection"`)
universalCollectionImport = "UniversalCollection from "
placeholderNonFungibleToken = regexp.MustCompile(`"NonFungibleToken"`)
nonFungibleTokenImport = "NonFungibleToken from "
placeholderMetadataViews = regexp.MustCompile(`"MetadataViews"`)
metadataViewsImport = "MetadataViews from "
placeholderFungibleToken = regexp.MustCompile(`"FungibleToken"`)
fungibleTokenImport = "FungibleToken from "
placeholderResolver = regexp.MustCompile(`"ViewResolver"`)
viewResolverImport = "ViewResolver from "
placeholderUniversalCollection = regexp.MustCompile(`"UniversalCollection"`)
universalCollectionImport = "UniversalCollection from "
placeholderCrossVMMetadataViews = regexp.MustCompile(`"CrossVMMetadataViews"`)
crossVMMetadataViewsImport = "CrossVMMetadataViews from "
)

const (
filenameNonFungibleToken = "NonFungibleToken.cdc"
filenameExampleNFT = "ExampleNFT.cdc"
filenameMetadataViews = "MetadataViews.cdc"
filenameNFTMetadataViews = "NFTMetadataViews.cdc"
filenameViewResolver = "ViewResolver.cdc"
filenameUniversalCollection = "UniversalCollection.cdc"
filenameBasicNFT = "BasicNFT.cdc"
filenameFungibleToken = "utility/FungibleToken.cdc"
filenameNonFungibleToken = "NonFungibleToken.cdc"
filenameExampleNFT = "ExampleNFT.cdc"
filenameMetadataViews = "MetadataViews.cdc"
filenameCrossVMMetadataViews = "CrossVMMetadataViews.cdc"
filenameNFTMetadataViews = "NFTMetadataViews.cdc"
filenameViewResolver = "ViewResolver.cdc"
filenameUniversalCollection = "UniversalCollection.cdc"
filenameBasicNFT = "BasicNFT.cdc"
filenameFungibleToken = "utility/FungibleToken.cdc"
)

func withHexPrefix(address string) string {
Expand Down Expand Up @@ -84,6 +87,14 @@ func ViewResolver() []byte {
return []byte(code)
}

func CrossVMMetadataViews(evmAddress string) []byte {
code := assets.MustAssetString(filenameCrossVMMetadataViews)

code = placeholderFungibleToken.ReplaceAllString(code, fungibleTokenImport+withHexPrefix(evmAddress))

return []byte(code)
}

func UniversalCollection(nftAddress, resolverAddress, metadataAddress flow.Address) []byte {
code := assets.MustAssetString(filenameUniversalCollection)
code = placeholderMetadataViews.ReplaceAllString(code, metadataViewsImport+withHexPrefix(metadataAddress.String()))
Expand Down
5 changes: 5 additions & 0 deletions lib/go/contracts/contracts_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,8 @@ func TestMetadataViewsContract(t *testing.T) {
contract := contracts.MetadataViews(addrA, addrA, addrA)
assert.NotNil(t, contract)
}

func TestCrossVMMetadataViewsContract(t *testing.T) {
contract := contracts.CrossVMMetadataViews(addrA)
assert.NotNil(t, contract)
}
Loading

0 comments on commit d11f5e0

Please sign in to comment.