diff --git a/evm-bridging/README.md b/evm-bridging/README.md
index 081c89a..cea0bad 100644
--- a/evm-bridging/README.md
+++ b/evm-bridging/README.md
@@ -1,113 +1,99 @@
-#
NBA TopShot on FlowEVM [Initial Draft Version]
-
-**! This directory currently contains work in progress only !**
+# NBA TopShot on FlowEVM
## Introduction
-The `BridgedTopShotMoments` smart contract facilitates the creation of 1:1 ERC721 references for existing Cadence-native NBA Top Shot moments. By associating these references with the same metadata, it ensures seamless integration and interaction between Cadence and FlowEVM environments. This allows users to enjoy the benefits of both ecosystems while maintaining the integrity and uniqueness of their NBA Top Shot moments.
+The `BridgedTopShotMoments` smart contract enables NBA Top Shot moments to exist on FlowEVM as ERC721 tokens. Each ERC721 token is a 1:1 reference to a Cadence-native NBA Top Shot moment, maintaining the same metadata and uniqueness while allowing users to leverage both Flow and EVM ecosystems.
+
-## Getting Started
+## Prerequisites
-Install Foundry:
+1. Install Foundry:
```sh
curl -L https://foundry.paradigm.xyz | bash
foundryup
```
-Compile contracts and run tests:
+2. Install Flow CLI: [Instructions](https://developers.flow.com/tools/flow-cli/install)
+
+## Development
+
+1. Compile and test contracts:
+
```sh
forge test --force -vvv
```
-Install Flow CLI: [Instructions](https://developers.flow.com/tools/flow-cli/install)
-
-### Deploy & Verify Contracts
+2. Set up environment:
-Load environment variables after populating address and key details:
```sh
cp .env.example.testnet .env
+# Add your account details to .env and source it
source .env
```
-Run script to deploy and verify contracts (proxy and implementation):
+3. Deploy and verify contracts:
```sh
+# Deploy both proxy and implementation contracts
forge script --rpc-url $RPC_URL --private-key $DEPLOYER_PRIVATE_KEY --legacy script/Deploy.s.sol:DeployScript --broadcast --verify --verifier $VERIFIER_PROVIDER --verifier-url $VERIFIER_URL
-```
-
-If verification fails for one or both contracts, verify separately:
-```sh
+# If verification fails, verify individually
forge verify-contract --rpc-url $RPC_URL --verifier $VERIFIER_PROVIDER --verifier-url $VERIFIER_URL
```
-## Run Transactions
+## Usage
-### Direct EVM Calls
-
-Set NFT symbol (admin):
+### EVM Operations
```sh
-cast send $DEPLOYED_PROXY_CONTRACT_ADDRESS --rpc-url $RPC_URL --private-key $DEPLOYER_PRIVATE_KEY --legacy "setSymbol(string)"
-```
+# Approve operator for a NFT
+cast send $DEPLOYED_PROXY_CONTRACT_ADDRESS --rpc-url $RPC_URL --private-key --legacy "approve(address,uint256)"
-### EVM Calls From Cadence
+# Approve operator for all NFTs
+cast send $DEPLOYED_PROXY_CONTRACT_ADDRESS --rpc-url $RPC_URL --private-key --legacy "setApprovalForAll(address,bool)"
-Note: Populate arguments in json file before submitting the transactions.
+# Transfer NFT
+cast send $DEPLOYED_PROXY_CONTRACT_ADDRESS --rpc-url $RPC_URL --private-key --legacy "safeTransferFrom(address,address,uint256)"
-Bridge NFTs to EVM and wrap:
+# Query balance
+cast call $DEPLOYED_PROXY_CONTRACT_ADDRESS --rpc-url $RPC_URL "balanceOf(address)(uint256)" $DEPLOYER_ADDRESS
-```sh
-flow transactions send ./cadence/transactions/bridge_nfts_to_evm_and_wrap.cdc --args-json "$(cat ./cadence/transactions/bridge_nft_to_evm_and_wrap_args.json)" --network --signer --gas-limit 8000
-```
+# Query owner
+cast call $DEPLOYED_PROXY_CONTRACT_ADDRESS --rpc-url $RPC_URL "ownerOf(uint256)(address)"
-Wrap NFTs (NFTs already bridged to EVM):
+# Query token URI
+cast call $DEPLOYED_PROXY_CONTRACT_ADDRESS --rpc-url $RPC_URL "tokenURI(uint256)(string)"
-```sh
-flow transactions send ./cadence/transactions/wrap_nfts.cdc --args-json "$(cat ./cadence/transactions/wrap_nfts_args.json)" --network --signer
+# Set NFT symbol (admin only)
+cast send $DEPLOYED_PROXY_CONTRACT_ADDRESS --rpc-url $RPC_URL --private-key $DEPLOYER_PRIVATE_KEY --legacy "setSymbol(string)"
```
-Unwrap NFTs and Bridge NFTs from EVM:
-
-```sh
-flow transactions send ./cadence/transactions/unwrap_nfts_and_bridge_from_evm.cdc --args-json "$(cat ./cadence/transactions/unwrap_nfts_and_bridge_from_evm_args.json)" --network --signer --gas-limit 8000
-```
+### Cadence Operations
-Unwrap NFTs:
+> **Note**: Populate arguments in json file before submitting the transactions.
```sh
-flow transactions send ./cadence/transactions/unwrap_nfts.cdc --args-json "$(cat ./cadence/transactions/unwrap_nfts_args.json)" --network --signer
-```
-
-
-
-## Execute Queries
-
-### Direct EVM Calls
+# Bridge and wrap NFTs
+flow transactions send ./cadence/transactions/bridge_nfts_to_evm_and_wrap.cdc --args-json "$(cat ./cadence/transactions/bridge_nft_to_evm_and_wrap_args.json)" --network --signer --gas-limit 8000
-BalanceOf:
-```sh
-cast call $DEPLOYED_PROXY_CONTRACT_ADDRESS --rpc-url $RPC_URL "balanceOf(address)(uint256)" $DEPLOYER_ADDRESS
-```
+# Wrap already-bridged NFTs
+flow transactions send ./cadence/transactions/wrap_nfts.cdc --args-json "$(cat ./cadence/transactions/wrap_nfts_args.json)" --network --signer
-OwnerOf:
-```sh
-cast call $DEPLOYED_PROXY_CONTRACT_ADDRESS --rpc-url $RPC_URL "ownerOf(uint256)(address)"
-```
+# Unwrap and bridge back NFTs
+flow transactions send ./cadence/transactions/unwrap_nfts_and_bridge_from_evm.cdc --args-json "$(cat ./cadence/transactions/unwrap_nfts_and_bridge_from_evm_args.json)" --network --signer --gas-limit 8000
-### EVM Calls From Cadence
+# Unwrap NFTs
+flow transactions send ./cadence/transactions/unwrap_nfts.cdc --args-json "$(cat ./cadence/transactions/unwrap_nfts_args.json)" --network --signer
-```sh
+# Query ERC721 address
flow scripts execute ./evm-bridging/cadence/scripts/get_underlying_erc721_address.cdc --network testnet
```
-## Misc
-
-Fund testnet Flow EVM account:
+### Testnet Setup
-1. Use Flow Faucet: https://faucet.flow.com/fund-account
+1. Get testnet FLOW from [Flow Faucet](https://faucet.flow.com/fund-account)
2. Transfer FLOW to EVM address:
diff --git a/evm-bridging/test/BridgedTopShotMoments.t.sol b/evm-bridging/test/BridgedTopShotMoments.t.sol
index 241e395..a3ad9f6 100644
--- a/evm-bridging/test/BridgedTopShotMoments.t.sol
+++ b/evm-bridging/test/BridgedTopShotMoments.t.sol
@@ -12,6 +12,16 @@ import {Strings} from "openzeppelin-contracts/contracts/utils/Strings.sol";
import {CrossVMBridgeERC721FulfillmentUpgradeable} from "../src/lib/CrossVMBridgeERC721FulfillmentUpgradeable.sol";
import {CrossVMBridgeCallableUpgradeable} from "../src/lib/CrossVMBridgeCallableUpgradeable.sol";
+import {IERC721} from "@openzeppelin/contracts/interfaces/IERC721.sol";
+import {IERC721Metadata} from "@openzeppelin/contracts/interfaces/IERC721Metadata.sol";
+import {IERC721Enumerable} from "@openzeppelin/contracts/interfaces/IERC721Enumerable.sol";
+import {ICrossVMBridgeERC721Fulfillment} from "../src/interfaces/ICrossVMBridgeERC721Fulfillment.sol";
+import {ICrossVM} from "../src/interfaces/ICrossVM.sol";
+import {ICreatorToken, ILegacyCreatorToken} from "../src/interfaces/ICreatorToken.sol";
+import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol";
+import {IERC2981} from "@openzeppelin/contracts/interfaces/IERC2981.sol";
+import {IBridgePermissions} from "../src/interfaces/IBridgePermissions.sol";
+
// Add this minimal ERC721 implementation for testing
contract UnderlyingERC721 is ERC721, Ownable {
constructor(string memory name, string memory symbol) ERC721(name, symbol) Ownable(msg.sender) {}
@@ -86,6 +96,21 @@ contract BridgedTopShotMomentsTest is Test {
nftContract = BridgedTopShotMoments(proxyAddr);
}
+ /* Test interface implementations */
+
+ function test_SupportsInterface() public view {
+ assertEq(nftContract.supportsInterface(type(IERC165).interfaceId), true);
+ assertEq(nftContract.supportsInterface(type(IERC721).interfaceId), true);
+ assertEq(nftContract.supportsInterface(type(IERC721Metadata).interfaceId), true);
+ assertEq(nftContract.supportsInterface(type(IERC721Enumerable).interfaceId), true);
+ assertEq(nftContract.supportsInterface(type(ICrossVM).interfaceId), true);
+ assertEq(nftContract.supportsInterface(type(ICreatorToken).interfaceId), true);
+ assertEq(nftContract.supportsInterface(type(ILegacyCreatorToken).interfaceId), true);
+ assertEq(nftContract.supportsInterface(type(IERC2981).interfaceId), true);
+ assertEq(nftContract.supportsInterface(type(ICrossVMBridgeERC721Fulfillment).interfaceId), true);
+ assertEq(nftContract.supportsInterface(type(IBridgePermissions).interfaceId), true);
+ }
+
/* Test contract initialization */
function test_GetContractInfo() public view {
@@ -96,6 +121,10 @@ contract BridgedTopShotMomentsTest is Test {
assertEq(nftContract.getCadenceIdentifier(), cadenceNFTIdentifier);
assertEq(nftContract.contractURI(), contractURI);
assertEq(address(nftContract.underlying()), underlyingNftContractAddress);
+ assertEq(nftContract.vmBridgeAddress(), vmBridgeAddress);
+ assertEq(nftContract.getTransferValidator(), address(0));
+ assertEq(nftContract.royaltyAddress(), address(0));
+ assertEq(nftContract.royaltyBasisPoints(), 0);
}