Skip to content

Commit

Permalink
fix conformance errors & update setup commands
Browse files Browse the repository at this point in the history
  • Loading branch information
sisyphusSmiling committed Mar 19, 2024
1 parent 0e9fa73 commit d241bad
Show file tree
Hide file tree
Showing 8 changed files with 77 additions and 72 deletions.
9 changes: 3 additions & 6 deletions cadence/args/bridged-nft-code-chunks-args.json

Large diffs are not rendered by default.

31 changes: 17 additions & 14 deletions cadence/contracts/bridge/FlowEVMBridge.cdc
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,16 @@ contract FlowEVMBridge : IFlowEVMNFTBridge {
let tokenID = token.id
let evmID = CrossVMNFT.getEVMID(from: &token as &{NonFungibleToken.NFT}) ?? UInt256(token.id)

// Grab the URI from the NFT if available
var uri: String = ""
// Default to project-specified URI
if let metadata = token.resolveView(Type<CrossVMNFT.EVMBridgedMetadata>()) as! CrossVMNFT.EVMBridgedMetadata? {
uri = metadata.uri.uri()
} else {
// Otherwise, serialize the NFT using OpenSea Metadata strategy
uri = SerializeNFT.serializeNFTMetadataAsURI(&token as &{NonFungibleToken.NFT})
}

// Lock the NFT & calculate the storage used by the NFT
let storageUsed = FlowEVMBridgeNFTEscrow.lockNFT(<-token)
// Calculate the bridge fee on current rates
Expand All @@ -155,15 +165,6 @@ contract FlowEVMBridge : IFlowEVMNFTBridge {
let isFactoryDeployed = FlowEVMBridgeUtils.isEVMContractBridgeOwned(evmContractAddress: associatedAddress)
// Controlled by the bridge - mint or transfer based on existence
if isFactoryDeployed {
// Grab the URI from the NFT if available
var uri: String = ""
// Default to project-specified URI
if let metadata = token.resolveView(Type<CrossVMNFT.EVMBridgedMetadata>()) as! CrossVMNFT.EVMBridgedMetadata? {
uri = metadata.uri.uri()
} else {
// Otherwise, serialize the NFT using OpenSea Metadata strategy
uri = SerializeNFT.serializeNFTMetadataAsURI(&token as &{NonFungibleToken.NFT})
}

// Check if the ERC721 exists
let existsResponse = EVM.decodeABI(
Expand Down Expand Up @@ -277,6 +278,11 @@ contract FlowEVMBridge : IFlowEVMNFTBridge {
evmContractAddress: associatedAddress
)
assert(isEscrowed, message: "Transfer to bridge COA failed - cannot bridge NFT without bridge escrow")

// Derive the defining Cadence contract name & address & attempt to borrow it as IEVMBridgeNFTMinter
let contractName = FlowEVMBridgeUtils.getContractName(fromType: type)!
let contractAddress = FlowEVMBridgeUtils.getContractAddress(fromType: type)!
let nftContract = getAccount(contractAddress).contracts.borrow<&{IEVMBridgeNFTMinter}>(name: contractName)
// Get the token URI from the ERC721 contract
let uri = FlowEVMBridgeUtils.getTokenURI(evmContractAddress: associatedAddress, id: id)
// If the NFT is currently locked, unlock and return
Expand All @@ -285,18 +291,15 @@ contract FlowEVMBridge : IFlowEVMNFTBridge {

// If the NFT is bridge-defined, update the URI from the source ERC721 contract
if self.account.address == FlowEVMBridgeUtils.getContractAddress(fromType: type) {
nft.updateTokenURI(uri)
nftContract!.updateTokenURI(evmID: id, newURI: uri)
}

return <-nft
}
// Otherwise, we expect the NFT to be minted in Cadence
let contractAddress = FlowEVMBridgeUtils.getContractAddress(fromType: type)!
assert(self.account.address == contractAddress, message: "Unexpected error bridging NFT from EVM")

let contractName = FlowEVMBridgeUtils.getContractName(fromType: type)!
let nftContract = getAccount(contractAddress).contracts.borrow<&{IEVMBridgeNFTMinter}>(name: contractName)!
let nft <- nftContract.mintNFT(id: id, tokenURI: uri)
let nft <- nftContract!.mintNFT(id: id, tokenURI: uri)
return <-nft
}

Expand Down
7 changes: 7 additions & 0 deletions cadence/contracts/bridge/IEVMBridgeNFTMinter.cdc
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,11 @@ contract interface IEVMBridgeNFTMinter {
///
access(account)
fun mintNFT(id: UInt256, tokenURI: String): @{NonFungibleToken.NFT}

/// Allows the bridge to update the URI of bridged NFTs. This assumes that the EVM-defining project may contain
/// logic (onchain or offchain) which updates NFT metadata in the source ERC721 contract. On bridging, the URI can
/// then be updated in this contract to reflect the source ERC721 contract's metadata.
///
access(account)
fun updateTokenURI(evmID: UInt256, newURI: String)
}
21 changes: 7 additions & 14 deletions cadence/contracts/templates/emulator/EVMBridgedNFTTemplate.cdc
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ access(all) contract {{CONTRACT_NAME}} : ICrossVM, IEVMBridgeNFTMinter, NonFungi
return CrossVMNFT.EVMBridgedMetadata(
name: self.name,
symbol: self.symbol,
uri: CrossVMNFT.URI(self.tokenURI())
uri: CrossVMNFT.URI(baseURI: nil, value: self.tokenURI())
)
case Type<MetadataViews.Serial>():
return MetadataViews.Serial(
Expand Down Expand Up @@ -129,14 +129,6 @@ access(all) contract {{CONTRACT_NAME}} : ICrossVM, IEVMBridgeNFTMinter, NonFungi
access(all) view fun tokenURI(): String {
return {{CONTRACT_NAME}}.tokenURIs[self.evmID] ?? ""
}

/* --- Bridge only method --- */
//
/// Allows the bridge to update the URI against the source ERC721 contract on bridging back to Cadence
access(account)
fun updateURI(_ new: String) {
{{CONTRACT_NAME}}.updateTokenURI(id: self.evmID, newURI: new)
}
}

/// This resource holds associated NFTs, and serves queries about stored NFTs
Expand Down Expand Up @@ -328,7 +320,7 @@ access(all) contract {{CONTRACT_NAME}} : ICrossVM, IEVMBridgeNFTMinter, NonFungi
return CrossVMNFT.EVMBridgedMetadata(
name: self.name,
symbol: self.symbol,
uri: self.contractURI != nil ? CrossVMNFT.URI(self.contractURI!) : CrossVMNFT.URI("")
uri: self.contractURI != nil ? CrossVMNFT.URI(baseURI: nil, value: self.contractURI!) : CrossVMNFT.URI(baseURI: nil, value: "")
)
}
return nil
Expand All @@ -350,7 +342,6 @@ access(all) contract {{CONTRACT_NAME}} : ICrossVM, IEVMBridgeNFTMinter, NonFungi
name: self.name,
symbol: self.symbol,
evmID: id,
uri: tokenURI,
metadata: {
"Bridged Block": getCurrentBlock().height,
"Bridged Timestamp": getCurrentBlock().timestamp
Expand All @@ -363,11 +354,13 @@ access(all) contract {{CONTRACT_NAME}} : ICrossVM, IEVMBridgeNFTMinter, NonFungi
/// then be updated in this contract to reflect the source ERC721 contract's metadata.
///
access(account)
fun updateURI(id: UInt256, newURI: String) {
fun updateTokenURI(evmID: UInt256, newURI: String) {
pre {
self.tokenURIs[id] != nil: "No token with the given ERC721 ID exists"
self.tokenURIs[evmID] != nil: "No token with the given ERC721 ID exists"
}
if self.tokenURIs[evmID] != newURI {
self.tokenURIs[evmID] = newURI
}
self.tokenURIs[id] = newURI
}

init(name: String, symbol: String, evmContractAddress: EVM.EVMAddress, contractURI: String?) {
Expand Down
12 changes: 6 additions & 6 deletions flow.json
Original file line number Diff line number Diff line change
Expand Up @@ -149,22 +149,22 @@
"emulator": "f8d6e0586b0a20c7"
}
},
"Serialize": {
"source": "./cadence/contracts/utils/Serialize.cdc",
"SerializationInterfaces": {
"source": "./cadence/contracts/utils/SerializationInterfaces.cdc",
"aliases": {
"emulator": "f8d6e0586b0a20c7",
"testing": "0000000000000007"
}
},
"SerializeNFT": {
"source": "./cadence/contracts/utils/SerializeNFT.cdc",
"Serialize": {
"source": "./cadence/contracts/utils/Serialize.cdc",
"aliases": {
"emulator": "f8d6e0586b0a20c7",
"testing": "0000000000000007"
}
},
"SerializationInterfaces": {
"source": "./cadence/contracts/utils/SerializationInterfaces.cdc",
"SerializeNFT": {
"source": "./cadence/contracts/utils/SerializeNFT.cdc",
"aliases": {
"emulator": "f8d6e0586b0a20c7",
"testing": "0000000000000007"
Expand Down
20 changes: 10 additions & 10 deletions local/setup_emulator.1.sh
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
#!/bin/bash

flow-c1 transactions send ./cadence/transactions/evm/create_account.cdc 100.0
flow transactions send ./cadence/transactions/evm/create_account.cdc 100.0

flow-c1 accounts add-contract ./cadence/contracts/utils/ArrayUtils.cdc
flow-c1 accounts add-contract ./cadence/contracts/utils/StringUtils.cdc
flow-c1 accounts add-contract ./cadence/contracts/utils/ScopedFTProviders.cdc
flow accounts add-contract ./cadence/contracts/utils/ArrayUtils.cdc
flow accounts add-contract ./cadence/contracts/utils/StringUtils.cdc
flow accounts add-contract ./cadence/contracts/utils/ScopedFTProviders.cdc

flow-c1 accounts update-contract ./cadence/contracts/standards/EVM.cdc
flow accounts update-contract ./cadence/contracts/standards/EVM.cdc

# Create COA in emulator-account

# Deploy the Factory contract - NOTE THE `deployedContractAddress` IN THE EMITTED EVENT
flow-c1 transactions send ./cadence/transactions/evm/deploy.cdc \
flow transactions send ./cadence/transactions/evm/deploy.cdc \
--args-json "$(cat ./cadence/args/deploy-factory-args.json)"

# Deploy initial bridge contracts
flow-c1 accounts add-contract ./cadence/contracts/bridge/BridgePermissions.cdc
flow-c1 accounts add-contract ./cadence/contracts/bridge/ICrossVM.cdc
flow-c1 accounts add-contract ./cadence/contracts/bridge/CrossVMNFT.cdc
flow-c1 accounts add-contract ./cadence/contracts/bridge/FlowEVMBridgeConfig.cdc
flow accounts add-contract ./cadence/contracts/bridge/BridgePermissions.cdc
flow accounts add-contract ./cadence/contracts/bridge/ICrossVM.cdc
flow accounts add-contract ./cadence/contracts/bridge/CrossVMNFT.cdc
flow accounts add-contract ./cadence/contracts/bridge/FlowEVMBridgeConfig.cdc
47 changes: 26 additions & 21 deletions local/setup_emulator.2.sh
Original file line number Diff line number Diff line change
@@ -1,55 +1,60 @@
# Provided address is the address of the Factory contract deployed in the previous txn
flow-c1 accounts add-contract ./cadence/contracts/bridge/FlowEVMBridgeUtils.cdc \
flow accounts add-contract ./cadence/contracts/bridge/FlowEVMBridgeUtils.cdc \
<REPLACE WITH DEPLOYED FACTORY EVM ADDRESS>

flow-c1 accounts add-contract ./cadence/contracts/bridge/FlowEVMBridgeNFTEscrow.cdc
flow-c1 accounts add-contract ./cadence/contracts/bridge/FlowEVMBridgeTemplates.cdc
flow accounts add-contract ./cadence/contracts/bridge/FlowEVMBridgeNFTEscrow.cdc
flow accounts add-contract ./cadence/contracts/bridge/FlowEVMBridgeTemplates.cdc
# Add the templated contract code chunks for FlowEVMBridgedNFTTemplate.cdc contents
flow-c1 transactions send ./cadence/transactions/bridge/admin/upsert_contract_code_chunks.cdc \
flow transactions send ./cadence/transactions/bridge/admin/upsert_contract_code_chunks.cdc \
--args-json "$(cat ./cadence/args/bridged-nft-code-chunks-args.json)" --gas-limit 1600

flow-c1 accounts add-contract ./cadence/contracts/bridge/IEVMBridgeNFTMinter.cdc
flow accounts add-contract ./cadence/contracts/bridge/IEVMBridgeNFTMinter.cdc

# Deploy Serialization Utils
flow accounts add-contract ./cadence/contracts/utils/SerializationInterfaces.cdc
flow accounts add-contract ./cadence/contracts/utils/Serialize.cdc
flow accounts add-contract ./cadence/contracts/utils/SerializeNFT.cdc

# Deploy main bridge interface & contract
flow-c1 accounts add-contract ./cadence/contracts/bridge/IFlowEVMNFTBridge.cdc
flow-c1 accounts add-contract ./cadence/contracts/bridge/FlowEVMBridge.cdc
flow accounts add-contract ./cadence/contracts/bridge/IFlowEVMNFTBridge.cdc
flow accounts add-contract ./cadence/contracts/bridge/FlowEVMBridge.cdc

# Deploy the bridge router directing calls from COAs to the dedicated bridge
flow-c1 accounts add-contract ./cadence/contracts/bridge/EVMBridgeRouter.cdc 0xf8d6e0586b0a20c7 FlowEVMBridge
flow accounts add-contract ./cadence/contracts/bridge/EVMBridgeRouter.cdc 0xf8d6e0586b0a20c7 FlowEVMBridge

# Create `example-nft` account 179b6b1cb6755e31 with private key 96dfbadf086daa187100a24b1fd2b709b702954bbd030a394148e11bcbb799ef
flow-c1 accounts create --key "351e1310301a7374430f6077d7b1b679c9574f8e045234eac09568ceb15c4f5d937104b4c3180df1e416da20c9d58aac576ffc328a342198a5eae4a29a13c47a"
flow accounts create --key "351e1310301a7374430f6077d7b1b679c9574f8e045234eac09568ceb15c4f5d937104b4c3180df1e416da20c9d58aac576ffc328a342198a5eae4a29a13c47a"

# Create `user` account 0xf3fcd2c1a78f5eee with private key bce84aae316aec618888e5bdd24a3c8b8af46896c1ebe457e2f202a4a9c43075
flow-c1 accounts create --key "c695fa608bd40821552fae13bb710c917309690ed69c22866abad19d276c99296379358321d0123d7074c817dd646ae8f651734526179eaed9f33eba16601ff6"
flow accounts create --key "c695fa608bd40821552fae13bb710c917309690ed69c22866abad19d276c99296379358321d0123d7074c817dd646ae8f651734526179eaed9f33eba16601ff6"

# Create `erc721` account 0xe03daebed8ca0615 with private key bf602a4cdffb5610a008622f6601ba7059f8a6f533d7489457deb3d45875acb0
flow-c1 accounts create --key "9103fd9106a83a2ede667e2486848e13e5854ea512af9bbec9ad2aec155bd5b5c146b53a6c3fd619c591ae0cd730acb875e5b6e074047cf31d620b53c55a4fb4"
flow accounts create --key "9103fd9106a83a2ede667e2486848e13e5854ea512af9bbec9ad2aec155bd5b5c146b53a6c3fd619c591ae0cd730acb875e5b6e074047cf31d620b53c55a4fb4"

# Give the user some FLOW
flow-c1 transactions send ./cadence/transactions/flow-token/transfer_flow.cdc 0xf3fcd2c1a78f5eee 100.0
flow transactions send ./cadence/transactions/flow-token/transfer_flow.cdc 0xf3fcd2c1a78f5eee 100.0

# Give the erc721 some FLOW
flow-c1 transactions send ./cadence/transactions/flow-token/transfer_flow.cdc 0xe03daebed8ca0615 100.0
flow transactions send ./cadence/transactions/flow-token/transfer_flow.cdc 0xe03daebed8ca0615 100.0

# Create a COA for the user
flow-c1 transactions send ./cadence/transactions/evm/create_account.cdc 10.0 --signer user
flow transactions send ./cadence/transactions/evm/create_account.cdc 10.0 --signer user

# Create a COA for the erc721
flow-c1 transactions send ./cadence/transactions/evm/create_account.cdc 10.0 --signer erc721
flow transactions send ./cadence/transactions/evm/create_account.cdc 10.0 --signer erc721

# user transfers Flow to the COA
flow-c1 transactions send ./cadence/transactions/evm/deposit.cdc 10.0 --signer user
flow transactions send ./cadence/transactions/evm/deposit.cdc 10.0 --signer user

# erc721 transfers Flow to the COA
flow-c1 transactions send ./cadence/transactions/evm/deposit.cdc 10.0 --signer erc721
flow transactions send ./cadence/transactions/evm/deposit.cdc 10.0 --signer erc721

# Setup User with Example NFT collection - Will break flow.json config due to bug in CLI - break here and update flow.json manually
flow-c1 accounts add-contract ./cadence/contracts/example-assets/ExampleNFT.cdc --signer example-nft
flow accounts add-contract ./cadence/contracts/example-assets/ExampleNFT.cdc --signer example-nft

flow-c1 transactions send ./cadence/transactions/example-assets/setup_collection.cdc --signer user
flow-c1 transactions send ./cadence/transactions/example-assets/mint_nft.cdc f3fcd2c1a78f5eee example description thumbnail '[]' '[]' '[]' --signer example-nft
flow transactions send ./cadence/transactions/example-assets/setup_collection.cdc --signer user
flow transactions send ./cadence/transactions/example-assets/mint_nft.cdc f3fcd2c1a78f5eee example description thumbnail '[]' '[]' '[]' --signer example-nft

# Deploy ExampleERC721 contract with erc721's COA as owner - NOTE THE `deployedContractAddress` EMITTED IN THE RESULTING EVENT
flow-c1 transactions send ./cadence/transactions/evm/deploy.cdc \
flow transactions send ./cadence/transactions/evm/deploy.cdc \
--args-json "$(cat ./cadence/args/deploy-erc721-args.json)" --signer erc721
2 changes: 1 addition & 1 deletion local/setup_emulator.3.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Mint an ERC721 with ID 42 to the user's COA
flow-c1 transactions send ./cadence/transactions/example-assets/safe_mint_erc721.cdc \
flow transactions send ./cadence/transactions/example-assets/safe_mint_erc721.cdc \
<REPLACE WITH COA EVM ADDRESS OWNED BY USER> 42 "URI" <REPLACE WITH THE ERC721 ADDRESS DEPLOYED IN LAST STEP> 200000 \
--signer erc721

0 comments on commit d241bad

Please sign in to comment.