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) + } } }