-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #76 from onflow/standup-script
Bridge standup script + Flow Port & Migrationnet prep
- Loading branch information
Showing
18 changed files
with
4,629 additions
and
93 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -25,4 +25,7 @@ coverage.lcov | |
*.pem | ||
|
||
# Local configs | ||
local.flow.json | ||
local.flow.json | ||
|
||
# Local | ||
.DS_Store |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
65 changes: 65 additions & 0 deletions
65
cadence/args/bridged-token-code-chunks-args-crescendo.json
Large diffs are not rendered by default.
Oops, something went wrong.
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import "EVM" | ||
|
||
import "EVMUtils" | ||
import "FlowEVMBridgeConfig" | ||
|
||
/// Returns the Cadence Type associated with the given EVM address (as its hex String) | ||
/// | ||
/// @param evmAddressHex: The hex-encoded address of the EVM contract as a String | ||
/// | ||
/// @return The Cadence Type associated with the EVM address or nil if the address is not onboarded. `nil` may also be | ||
/// returned if the address is not a valid EVM address. | ||
/// | ||
access(all) | ||
fun main(addressHex: String): Type? { | ||
let address = EVMUtils.getEVMAddressFromHexString(address: addressHex) | ||
return address != nil ? FlowEVMBridgeConfig.getTypeAssociated(with: address!) : nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
53 changes: 53 additions & 0 deletions
53
cadence/transactions/example-assets/evm-assets/safe_transfer_from_erc721.cdc
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
import "EVM" | ||
|
||
import "EVMUtils" | ||
import "FlowEVMBridgeUtils" | ||
|
||
/// Executes an NFT transfer to the defined recipient address against the specified ERC721 contract. | ||
/// | ||
transaction(evmContractAddressHex: String, recipientAddressHex: String, id: UInt256) { | ||
|
||
let evmContractAddress: EVM.EVMAddress | ||
let recipientAddress: EVM.EVMAddress | ||
let coa: auth(EVM.Call) &EVM.CadenceOwnedAccount | ||
var senderOwnerCheck: Bool | ||
var recipientOwnerCheck: Bool | ||
|
||
prepare(signer: auth(BorrowValue) &Account) { | ||
self.evmContractAddress = EVMUtils.getEVMAddressFromHexString(address: evmContractAddressHex) ?? panic("Invalid contract address") | ||
self.recipientAddress = EVMUtils.getEVMAddressFromHexString(address: recipientAddressHex) ?? panic("Invalid recipient address") | ||
|
||
self.coa = signer.storage.borrow<auth(EVM.Call) &EVM.CadenceOwnedAccount>(from: /storage/evm) | ||
?? panic("Could not borrow CadenceOwnedAccount reference") | ||
|
||
self.senderOwnerCheck = FlowEVMBridgeUtils.isOwnerOrApproved( | ||
ofNFT: id, | ||
owner: self.coa.address(), | ||
evmContractAddress: self.evmContractAddress | ||
) | ||
self.recipientOwnerCheck = false | ||
} | ||
|
||
execute { | ||
let calldata = EVM.encodeABIWithSignature( | ||
"safeTransferFrom(address,address,uint256)", | ||
[self.coa.address(), self.recipientAddress, id] | ||
) | ||
let callResult = self.coa.call( | ||
to: self.evmContractAddress, | ||
data: calldata, | ||
gasLimit: 15_000_000, | ||
value: EVM.Balance(attoflow: 0) | ||
) | ||
assert(callResult.status == EVM.Status.successful, message: "Call to ERC721 contract failed") | ||
self.recipientOwnerCheck = FlowEVMBridgeUtils.isOwnerOrApproved( | ||
ofNFT: id, | ||
owner: self.recipientAddress, | ||
evmContractAddress: self.evmContractAddress | ||
) | ||
} | ||
|
||
post { | ||
self.recipientOwnerCheck: "Recipient did not receive the token" | ||
} | ||
} |
42 changes: 42 additions & 0 deletions
42
cadence/transactions/example-assets/evm-assets/transfer_erc20.cdc
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
import "EVM" | ||
|
||
import "EVMUtils" | ||
import "FlowEVMBridgeUtils" | ||
|
||
/// Executes a token transfer to the defined recipient address against the specified ERC20 contract. | ||
/// | ||
transaction(evmContractAddressHex: String, recipientAddressHex: String, amount: UInt256) { | ||
|
||
let evmContractAddress: EVM.EVMAddress | ||
let recipientAddress: EVM.EVMAddress | ||
let coa: auth(EVM.Call) &EVM.CadenceOwnedAccount | ||
let preBalance: UInt256 | ||
var postBalance: UInt256 | ||
|
||
prepare(signer: auth(BorrowValue) &Account) { | ||
self.evmContractAddress = EVMUtils.getEVMAddressFromHexString(address: evmContractAddressHex) ?? panic("Invalid contract address") | ||
self.recipientAddress = EVMUtils.getEVMAddressFromHexString(address: recipientAddressHex) ?? panic("Invalid recipient address") | ||
|
||
self.coa = signer.storage.borrow<auth(EVM.Call) &EVM.CadenceOwnedAccount>(from: /storage/evm) | ||
?? panic("Could not borrow CadenceOwnedAccount reference") | ||
|
||
self.preBalance = FlowEVMBridgeUtils.balanceOf(owner: self.coa.address(), evmContractAddress: self.evmContractAddress) | ||
self.postBalance = 0 | ||
} | ||
|
||
execute { | ||
let calldata = EVM.encodeABIWithSignature("transfer(address,uint256)", [self.recipientAddress, amount]) | ||
let callResult = self.coa.call( | ||
to: self.evmContractAddress, | ||
data: calldata, | ||
gasLimit: 15_000_000, | ||
value: EVM.Balance(attoflow: 0) | ||
) | ||
assert(callResult.status == EVM.Status.successful, message: "Call to ERC20 contract failed") | ||
self.postBalance = FlowEVMBridgeUtils.balanceOf(owner: self.coa.address(), evmContractAddress: self.evmContractAddress) | ||
} | ||
|
||
post { | ||
self.postBalance == self.preBalance - amount: "Transfer failed" | ||
} | ||
} |
106 changes: 106 additions & 0 deletions
106
cadence/transactions/flow-token/dynamic_vm_transfer.cdc
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
import "FungibleToken" | ||
import "FlowToken" | ||
|
||
import "EVM" | ||
|
||
import "EVMUtils" | ||
|
||
// Transfers $FLOW from the signer's account to the recipient's address, determining the target VM based on the format | ||
// of the recipient's hex address. Note that the sender's funds are sourced by default from the target VM, pulling any | ||
// difference from the alternate VM if available. e.g. Transfers to Flow addresses will first attempt to withdraw from | ||
// the signer's Flow vault, pulling any remaining funds from the signer's EVM account if available. Transfers to EVM | ||
// addresses will first attempt to withdraw from the signer's EVM account, pulling any remaining funds from the signer's | ||
// Flow vault if available. If the signer's balance across both VMs is insufficient, the transaction will revert. | ||
/// | ||
/// @param addressString: The recipient's address in hex format - this should be either an EVM address or a Flow address | ||
/// @param amount: The amount of $FLOW to transfer as a UFix64 value | ||
/// | ||
transaction(addressString: String, amount: UFix64) { | ||
|
||
let sentVault: @FlowToken.Vault | ||
let evmRecipient: EVM.EVMAddress? | ||
var receiver: &{FungibleToken.Receiver}? | ||
|
||
prepare(signer: auth(BorrowValue, SaveValue) &Account) { | ||
// Reference signer's COA if one exists | ||
let coa = signer.storage.borrow<auth(EVM.Withdraw) &EVM.CadenceOwnedAccount>(from: /storage/evm) | ||
|
||
// Reference signer's FlowToken Vault | ||
let sourceVault = signer.storage.borrow<auth(FungibleToken.Withdraw) &FlowToken.Vault>(from: /storage/flowTokenVault) | ||
?? panic("Could not borrow signer's FlowToken.Vault") | ||
let cadenceBalance = sourceVault.balance | ||
|
||
// Define optional recipients for both VMs | ||
self.receiver = nil | ||
let cadenceRecipient = Address.fromString(addressString) | ||
self.evmRecipient = cadenceRecipient == nil ? EVMUtils.getEVMAddressFromHexString(address: addressString) : nil | ||
// Validate exactly one target address is assigned | ||
if cadenceRecipient != nil && self.evmRecipient != nil { | ||
panic("Malformed recipient address - assignable as both Cadence and EVM addresses") | ||
} else if cadenceRecipient == nil && self.evmRecipient == nil { | ||
panic("Malformed recipient address - not assignable as either Cadence or EVM address") | ||
} | ||
|
||
// Create empty FLOW vault to capture funds | ||
self.sentVault <- FlowToken.createEmptyVault(vaultType: Type<@FlowToken.Vault>()) | ||
/// If the target VM is Flow, does the Vault have sufficient balance to cover? | ||
if cadenceRecipient != nil { | ||
// Assign the Receiver of the $FLOW transfer | ||
self.receiver = getAccount(cadenceRecipient!).capabilities.borrow<&{FungibleToken.Receiver}>( | ||
/public/flowTokenReceiver | ||
) ?? panic("Could not borrow reference to recipient's FungibleToken.Receiver") | ||
|
||
// Withdraw from the signer's Cadence Vault and deposit to sentVault | ||
var withdrawAmount = amount < cadenceBalance ? amount : cadenceBalance | ||
self.sentVault.deposit(from: <-sourceVault.withdraw(amount: withdrawAmount)) | ||
|
||
// If the cadence balance didn't cover the amount, check the signer's EVM balance | ||
if amount > self.sentVault.balance { | ||
let difference = amount - cadenceBalance | ||
// Revert if the signer doesn't have an EVM account or EVM balance is insufficient | ||
if coa == nil || difference < coa!.balance().inFLOW() { | ||
panic("Insufficient balance across Flow and EVM accounts") | ||
} | ||
|
||
// Withdraw from the signer's EVM account and deposit to sentVault | ||
let withdrawFromEVM = EVM.Balance(attoflow: 0) | ||
withdrawFromEVM.setFLOW(flow: difference) | ||
self.sentVault.deposit(from: <-coa!.withdraw(balance: withdrawFromEVM)) | ||
} | ||
} else if self.evmRecipient != nil { | ||
// Check signer's balance can cover the amount | ||
if coa != nil { | ||
// Determine the amount to withdraw from the signer's EVM account | ||
let balance = coa!.balance() | ||
let withdrawAmount = amount < balance.inFLOW() ? amount : balance.inFLOW() | ||
balance.setFLOW(flow: withdrawAmount) | ||
|
||
// Withdraw funds from EVM to the sentVault | ||
self.sentVault.deposit(from: <-coa!.withdraw(balance: balance)) | ||
} | ||
if amount > self.sentVault.balance { | ||
// Insufficient amount withdrawn from EVM, check signer's Flow balance | ||
let difference = amount - self.sentVault.balance | ||
if difference > cadenceBalance { | ||
panic("Insufficient balance across Flow and EVM accounts") | ||
} | ||
// Withdraw from the signer's Cadence Vault and deposit to sentVault | ||
self.sentVault.deposit(from: <-sourceVault.withdraw(amount: difference)) | ||
} | ||
} | ||
} | ||
|
||
pre { | ||
self.sentVault.balance == amount: "Attempting to send an incorrect amount of $FLOW" | ||
} | ||
|
||
execute { | ||
// Complete Cadence transfer if the FungibleToken Receiver is assigned | ||
if self.receiver != nil { | ||
self.receiver!.deposit(from: <-self.sentVault) | ||
} else { | ||
// Otherwise, complete EVM transfer | ||
self.evmRecipient!.deposit(from: <-self.sentVault) | ||
} | ||
} | ||
} |
Oops, something went wrong.