TransactionSEALED

^%◆■^▒▫▓█!□^◆!▫■░@◆█$@#◆%▫&^╲#◆▓&■▒╱░◆~@▪▒▒□╲■╱$▫*▓◆╳%╱╳~░╳■▫◇◇▪

Transaction ID

Timestamp

Feb 13, 2026, 03:29:01 AM UTC
2w ago

Block Height

142,042,305

Computation

0

Execution Error

Error Code: 1009

error caused by: 1 error occurred:

Raw Error

[Error Code: 1009] error caused by: 1 error occurred: * transaction verification failed: [Error Code: 1006] invalid proposal key: public key 6 on account f380b22ef386ac7e does not have a valid signature: [Error Code: 1009] invalid envelope key: public key 6 on account f380b22ef386ac7e does not have a valid signature: signature is not valid

Transaction Summary

Transaction

Script Arguments

0vaultIdentifierString
A.f1ab99c82dee3526.USDCFlow.Vault
1amountUInt256
100000
2recipientAddress

Cadence Script

1import MetadataViews from 0x1d7e57aa55817448
2import ViewResolver from 0x1d7e57aa55817448
3import NonFungibleToken from 0x1d7e57aa55817448
4
5import FungibleToken from 0xf233dcee88fe0abe
6import FlowToken from 0x1654653399040a61
7import FungibleTokenMetadataViews from 0xf233dcee88fe0abe
8
9import ScopedFTProviders from 0x1e4aa0b87d10b141
10
11import EVM from 0xe467b9dd11fa00df
12
13import FlowEVMBridgeUtils from 0x1e4aa0b87d10b141
14import FlowEVMBridge from 0x1e4aa0b87d10b141
15import FlowEVMBridgeConfig from 0x1e4aa0b87d10b141
16import StorageRent from 0x707adbad1428c624
17
18/// This transaction bridges fungible tokens from EVM to Cadence assuming it has already been onboarded to the
19/// FlowEVMBridge. The full amount to be transferred is sourced from EVM, so it's assumed the signer has sufficient
20/// balance of the ERC20 to bridging into Cadence. Also know that the recipient Flow account must have a Receiver
21/// capable of receiving the bridged tokens accessible via published Capability at the token's standard path.
22///
23/// NOTE: The ERC20 must have first been onboarded to the bridge. This can be checked via the method
24///     FlowEVMBridge.evmAddressRequiresOnboarding(address: self.evmContractAddress)
25///
26/// @param vaultIdentifier: The Cadence type identifier of the FungibleToken Vault to bridge
27///     - e.g. vault.getType().identifier
28/// @param amount: The amount of tokens to bridge from EVM and transfer to the recipient
29/// @param recipient: The Flow account address to receive the bridged tokens
30///
31transaction(vaultIdentifier: String, amount: UInt256, recipient: Address) {
32
33    let vaultType: Type
34    let receiver: &{FungibleToken.Vault}
35    let scopedProvider: @ScopedFTProviders.ScopedFTProvider
36    let coa: auth(EVM.Bridge) &EVM.CadenceOwnedAccount
37
38    prepare(signer: auth(BorrowValue, CopyValue, IssueStorageCapabilityController, PublishCapability, SaveValue, UnpublishCapability) &Account) {
39        /* --- Reference the signer's CadenceOwnedAccount --- */
40        //
41        // Borrow a reference to the signer's COA
42        self.coa = signer.storage.borrow<auth(EVM.Bridge) &EVM.CadenceOwnedAccount>(from: /storage/evm)
43            ?? panic("Could not borrow COA from provided gateway address")
44
45        /* --- Construct the Vault type --- */
46        //
47        // Construct the Vault type from the provided identifier
48        self.vaultType = CompositeType(vaultIdentifier)
49            ?? panic("Could not construct Vault type from identifier: ".concat(vaultIdentifier))
50        // Parse the Vault identifier into its components
51        let tokenContractAddress = FlowEVMBridgeUtils.getContractAddress(fromType: self.vaultType)
52            ?? panic("Could not get contract address from identifier: ".concat(vaultIdentifier))
53        let tokenContractName = FlowEVMBridgeUtils.getContractName(fromType: self.vaultType)
54            ?? panic("Could not get contract name from identifier: ".concat(vaultIdentifier))
55
56        /* --- Reference the signer's Vault --- */
57        //
58        // Borrow a reference to the FungibleToken Vault, configuring if necessary
59        let viewResolver = getAccount(tokenContractAddress).contracts.borrow<&{ViewResolver}>(name: tokenContractName)
60            ?? panic("Could not borrow ViewResolver from FungibleToken contract")
61        let vaultData = viewResolver.resolveContractView(
62                resourceType: self.vaultType,
63                viewType: Type<FungibleTokenMetadataViews.FTVaultData>()
64            ) as! FungibleTokenMetadataViews.FTVaultData? ?? panic("Could not resolve FTVaultData view")
65        // If the vault does not exist, create it and publish according to the contract's defined configuration
66        if signer.storage.borrow<&{FungibleToken.Vault}>(from: vaultData.storagePath) == nil {
67            signer.storage.save(<-vaultData.createEmptyVault(), to: vaultData.storagePath)
68
69            signer.capabilities.unpublish(vaultData.receiverPath)
70            signer.capabilities.unpublish(vaultData.metadataPath)
71
72            let receiverCap = signer.capabilities.storage.issue<&{FungibleToken.Vault}>(vaultData.storagePath)
73            let metadataCap = signer.capabilities.storage.issue<&{FungibleToken.Vault}>(vaultData.storagePath)
74
75            signer.capabilities.publish(receiverCap, at: vaultData.receiverPath)
76            signer.capabilities.publish(metadataCap, at: vaultData.metadataPath)
77        }
78        self.receiver = getAccount(recipient).capabilities.borrow<&{FungibleToken.Vault}>(vaultData.receiverPath)
79            ?? panic("Could not borrow Vault from recipient's account")
80
81        /* --- Configure a ScopedFTProvider --- */
82        //
83        // Calculate the bridge fee - bridging from EVM consumes no storage, so flat fee
84        let approxFee = FlowEVMBridgeUtils.calculateBridgeFee(bytes: 400_000)
85        // Issue and store bridge-dedicated Provider Capability in storage if necessary
86        if signer.storage.type(at: FlowEVMBridgeConfig.providerCapabilityStoragePath) == nil {
87            let providerCap = signer.capabilities.storage.issue<auth(FungibleToken.Withdraw) &{FungibleToken.Provider}>(
88                /storage/flowTokenVault
89            )
90            signer.storage.save(providerCap, to: FlowEVMBridgeConfig.providerCapabilityStoragePath)
91        }
92        // Copy the stored Provider capability and create a ScopedFTProvider
93        let providerCapCopy = signer.storage.copy<Capability<auth(FungibleToken.Withdraw) &{FungibleToken.Provider}>>(
94                from: FlowEVMBridgeConfig.providerCapabilityStoragePath
95            ) ?? panic("Invalid Provider Capability found in storage.")
96        let providerFilter = ScopedFTProviders.AllowanceFilter(approxFee)
97        self.scopedProvider <- ScopedFTProviders.createScopedFTProvider(
98                provider: providerCapCopy,
99                filters: [ providerFilter ],
100                expiration: getCurrentBlock().timestamp + 1.0
101            )
102    }
103
104    execute {
105        // Execute the bridge request
106        let vault: @{FungibleToken.Vault} <- self.coa.withdrawTokens(
107            type: self.vaultType,
108            amount: amount,
109            feeProvider: &self.scopedProvider as auth(FungibleToken.Withdraw) &{FungibleToken.Provider}
110        )
111        // Ensure the bridged vault is the correct type
112        assert(vault.getType() == self.vaultType, message: "Bridged vault type mismatch")
113        // Deposit the bridged token into the signer's vault
114        self.receiver.deposit(from: <-vault)
115        // Destroy the ScopedFTProvider
116        destroy self.scopedProvider
117        StorageRent.tryRefill(recipient)
118    }
119}