diff --git a/cadence/scripts/evm/call.cdc b/cadence/scripts/evm/call.cdc index 39658ad2..49969abe 100644 --- a/cadence/scripts/evm/call.cdc +++ b/cadence/scripts/evm/call.cdc @@ -36,5 +36,9 @@ access(all) fun main( value: EVM.Balance(attoflow: 0) ) - return EVM.decodeABI(types: getTypeArray(typeIdentifiers), data: evmResult.data) + if typeIdentifiers.length == 0 { + return [] + } else { + return EVM.decodeABI(types: getTypeArray(typeIdentifiers), data: evmResult.data) + } } diff --git a/cadence/scripts/evm/get_evm_address_string.cdc b/cadence/scripts/evm/get_evm_address_string.cdc index a4f5a239..45f4a28b 100644 --- a/cadence/scripts/evm/get_evm_address_string.cdc +++ b/cadence/scripts/evm/get_evm_address_string.cdc @@ -3,13 +3,9 @@ import "EVM" /// Returns the hex encoded address of the COA in the given Flow address /// access(all) fun main(flowAddress: Address): String? { - if let address: EVM.EVMAddress = getAuthAccount(flowAddress) - .storage.borrow<&EVM.CadenceOwnedAccount>(from: /storage/evm)?.address() { - let bytes: [UInt8] = [] - for byte in address.bytes { - bytes.append(byte) - } - return String.encodeHex(bytes) - } - return nil + return getAuthAccount(flowAddress) + .storage.borrow<&EVM.CadenceOwnedAccount>(from: /storage/evm) + ?.address() + ?.toString() + ?? nil } diff --git a/cadence/scripts/evm/get_evm_address_string_from_bytes.cdc b/cadence/scripts/evm/get_evm_address_string_from_bytes.cdc index e531d935..93a752b5 100644 --- a/cadence/scripts/evm/get_evm_address_string_from_bytes.cdc +++ b/cadence/scripts/evm/get_evm_address_string_from_bytes.cdc @@ -5,7 +5,5 @@ import "EVM" access(all) fun main(bytes: [UInt8]): String? { let constBytes = bytes.toConstantSized<[UInt8; 20]>() ?? panic("Problem converting provided EVMAddress compatible byte array - check byte array contains 20 bytes") - return EVM.EVMAddress( - bytes: constBytes - ) + return EVM.EVMAddress(bytes: constBytes).toString() } diff --git a/cadence/transactions/evm/create_account.cdc b/cadence/transactions/evm/create_account.cdc index 57d31241..e670783b 100644 --- a/cadence/transactions/evm/create_account.cdc +++ b/cadence/transactions/evm/create_account.cdc @@ -1,31 +1,62 @@ -import "EVM" +import "Burner" import "FungibleToken" import "FlowToken" +import "EVM" /// Creates a COA and saves it in the signer's Flow account & passing the given value of Flow into FlowEVM /// transaction(amount: UFix64) { - let sentVault: @FlowToken.Vault - let auth: auth(IssueStorageCapabilityController, IssueStorageCapabilityController, PublishCapability, SaveValue, UnpublishCapability) &Account + let fundingVault: @FlowToken.Vault? + let coa: &EVM.CadenceOwnedAccount + + prepare(signer: auth(BorrowValue, SaveValue, IssueStorageCapabilityController, PublishCapability) &Account) { + /* --- Configure COA --- */ + // + // Ensure there is not yet a CadenceOwnedAccount in the standard path + let coaPath = /storage/evm + if signer.storage.type(at: coaPath) != nil { + panic( + "Object already exists in signer's account at path=".concat(coaPath.toString()) + .concat(". Make sure the signing account does not already have a CadenceOwnedAccount.") + ) + } + // COA not found in standard path, create and publish a public **unentitled** capability + signer.storage.save(<-EVM.createCadenceOwnedAccount(), to: coaPath) + let coaCapability = signer.capabilities.storage.issue<&EVM.CadenceOwnedAccount>(coaPath) + signer.capabilities.publish(coaCapability, at: /public/evm) - prepare(signer: auth(BorrowValue, IssueStorageCapabilityController, PublishCapability, SaveValue, UnpublishCapability) &Account) { - let vaultRef = signer.storage.borrow( - from: /storage/flowTokenVault - ) ?? panic("Could not borrow reference to the owner's Vault!") + // Borrow the CadenceOwnedAccount reference + self.coa = signer.storage.borrow<&EVM.CadenceOwnedAccount>( + from: coaPath + ) ?? panic( + "Could not find CadenceOwnedAccount (COA) in signer's account at path=".concat(coaPath.toString()) + .concat(". Make sure the signing account has initialized a COA at the expected path.") + ) - self.sentVault <- vaultRef.withdraw(amount: amount) as! @FlowToken.Vault - self.auth = signer + /* --- Assign fundingVault --- */ + // + if amount > 0.0 { + // Reference the signer's FLOW vault & withdraw the funding amount + let vault = signer.storage.borrow(from: /storage/flowTokenVault) + ?? panic("Could not borrow a reference to the signer's FLOW vault from path=/storage/flowTokenVault") + self.fundingVault <- vault.withdraw(amount: amount) as! @FlowToken.Vault + } else { + // No funding requested, so no need to withdraw from the vault + self.fundingVault <- nil + } } - execute { - let coa <- EVM.createCadenceOwnedAccount() - coa.deposit(from: <-self.sentVault) + pre { + self.fundingVault == nil || self.fundingVault?.balance ?? 0.0 == amount: + "Mismatched funding vault acquired given requested amount=".concat(amount.toString()) + } - let storagePath = StoragePath(identifier: "evm")! - let publicPath = PublicPath(identifier: "evm")! - self.auth.storage.save<@EVM.CadenceOwnedAccount>(<-coa, to: storagePath) - let addressableCap = self.auth.capabilities.storage.issue<&EVM.CadenceOwnedAccount>(storagePath) - self.auth.capabilities.unpublish(publicPath) - self.auth.capabilities.publish(addressableCap, at: publicPath) + execute { + // Fund if necessary + if self.fundingVault != nil || self.fundingVault?.balance ?? 0.0 > 0.0 { + self.coa.deposit(from: <-self.fundingVault!) + } else { + Burner.burn(<-self.fundingVault) + } } } diff --git a/cadence/transactions/evm/destroy_coa.cdc b/cadence/transactions/evm/destroy_coa.cdc index 2a8e8dab..d802e1bb 100644 --- a/cadence/transactions/evm/destroy_coa.cdc +++ b/cadence/transactions/evm/destroy_coa.cdc @@ -1,9 +1,21 @@ +import "Burner" import "EVM" -/// !!! CAUTION: Destroys the COA in the signer's account !!! +/// !!! CAUTION: Destroys the COA in the signer's account !!! /// transaction { - prepare(signer: auth(LoadValue) &Account) { - destroy signer.storage.load<@EVM.CadenceOwnedAccount>(from: /storage/evm)! + prepare(signer: auth(LoadValue, StorageCapabilities, UnpublishCapability) &Account) { + // Unpublish the COA capability + signer.capabilities.unpublish(/public/evm) + + // Delete all COA capabilities + signer.capabilities.storage.forEachController(forPath: /storage/evm, fun (controller: &StorageCapabilityController): Bool { + controller.delete() + return true + }) + + // Destroy the COA + let coa <- signer.storage.load<@EVM.CadenceOwnedAccount>(from: /storage/evm)! + Burner.burn(<-coa) } } diff --git a/cadence/transactions/evm/withdraw.cdc b/cadence/transactions/evm/withdraw.cdc index 7142cdde..e5d68c09 100644 --- a/cadence/transactions/evm/withdraw.cdc +++ b/cadence/transactions/evm/withdraw.cdc @@ -28,6 +28,6 @@ transaction(amount: UFix64) { } post { - self.vault.balance == self.preBalance + amount: "Problem transfering Flow between environments!" + self.vault.balance == self.preBalance + amount: "Problem transferring Flow between environments!" } } diff --git a/flow.json b/flow.json index 65384829..c7de7c9c 100644 --- a/flow.json +++ b/flow.json @@ -260,7 +260,7 @@ }, "EVM": { "source": "mainnet://e467b9dd11fa00df.EVM", - "hash": "1b1f3fe59d964b8afde33d3150ab89f257373aa253ae412c8b02fb176dd03698", + "hash": "5c69921fa06088b477e2758e122636b39d3d3eb5316807c206c5680d9ac74c7e", "aliases": { "emulator": "f8d6e0586b0a20c7", "mainnet": "e467b9dd11fa00df", @@ -287,7 +287,7 @@ }, "FungibleToken": { "source": "mainnet://f233dcee88fe0abe.FungibleToken", - "hash": "1410889b47fef8b02f6867eef3d67a75288a56a651b67a7e815ce273ad301cff", + "hash": "050328d01c6cde307fbe14960632666848d9b7ea4fef03ca8c0bbfb0f2884068", "aliases": { "emulator": "ee82856bf20e2aa6", "mainnet": "f233dcee88fe0abe", @@ -296,7 +296,7 @@ }, "FungibleTokenMetadataViews": { "source": "mainnet://f233dcee88fe0abe.FungibleTokenMetadataViews", - "hash": "294ada6a3df68757fcac4d794f62307c2ea4fe49c93f67e3771d3c6d8377dd47", + "hash": "dff704a6e3da83997ed48bcd244aaa3eac0733156759a37c76a58ab08863016a", "aliases": { "emulator": "ee82856bf20e2aa6", "mainnet": "f233dcee88fe0abe", @@ -305,7 +305,7 @@ }, "MetadataViews": { "source": "mainnet://1d7e57aa55817448.MetadataViews", - "hash": "be26ea7959d7cbc06ac69fe00926b812c4da67984ea2d1bde1029141ae091378", + "hash": "10a239cc26e825077de6c8b424409ae173e78e8391df62750b6ba19ffd048f51", "aliases": { "emulator": "f8d6e0586b0a20c7", "mainnet": "1d7e57aa55817448", @@ -314,7 +314,7 @@ }, "NonFungibleToken": { "source": "mainnet://1d7e57aa55817448.NonFungibleToken", - "hash": "49a58b950afdaf0728fdb7d4eb47cf4f2ec3077d655f274b7fdeb504c742f528", + "hash": "b63f10e00d1a814492822652dac7c0574428a200e4c26cb3c832c4829e2778f0", "aliases": { "emulator": "f8d6e0586b0a20c7", "mainnet": "1d7e57aa55817448",