Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 32 additions & 56 deletions cadence/contracts/bridge/FlowEVMBridge.cdc

Large diffs are not rendered by default.

26 changes: 12 additions & 14 deletions cadence/contracts/bridge/FlowEVMBridgeAccessor.cdc
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ contract FlowEVMBridgeAccessor {
): @{NonFungibleToken.NFT} {
// Define a callback function, enabling the bridge to act on the ephemeral COA reference in scope
var executed = false
fun callback(target: EVM.EVMAddress): EVM.Result {
fun callback(target: EVM.EVMAddress): EVM.ResultDecoded {
pre {
!executed: "Callback can only be executed once"
FlowEVMBridge.getAssociatedEVMAddress(with: type) ?? FlowEVMBridgeConfig.getLegacyEVMAddressAssociated(with: type) != nil:
Expand All @@ -69,14 +69,13 @@ contract FlowEVMBridgeAccessor {
message: "Target EVM contract \(target.toString()) is not association with NFT Type \(type.identifier) - COA `safeTransferFrom` callback rejected")

executed = true
return caller.call(
return caller.callWithSigAndArgs(
to: target,
data: EVM.encodeABIWithSignature(
"safeTransferFrom(address,address,uint256)",
[caller.address(), FlowEVMBridge.getBridgeCOAEVMAddress(), id]
),
signature: "safeTransferFrom(address,address,uint256)",
args: [caller.address(), FlowEVMBridge.getBridgeCOAEVMAddress(), id],
gasLimit: FlowEVMBridgeConfig.gasLimit,
value: EVM.Balance(attoflow: 0)
value: 0,
resultTypes: nil
)
}
// Execute the bridge request
Expand Down Expand Up @@ -129,22 +128,21 @@ contract FlowEVMBridgeAccessor {
let roundedAmount = FlowEVMBridgeUtils.castERC20AmountToCadencePrecision(amount, erc20Address: associatedEVMAddress)
// Define a callback function, enabling the bridge to act on the ephemeral COA reference in scope
var executed = false
fun callback(): EVM.Result {
fun callback(): EVM.ResultDecoded {
pre {
!executed: "Callback can only be executed once"
}
post {
executed: "Callback must be executed"
}
executed = true
return caller.call(
return caller.callWithSigAndArgs(
to: associatedEVMAddress,
data: EVM.encodeABIWithSignature(
"transfer(address,uint256)",
[FlowEVMBridge.getBridgeCOAEVMAddress(), roundedAmount]
),
signature: "transfer(address,uint256)",
args: [FlowEVMBridge.getBridgeCOAEVMAddress(), roundedAmount],
gasLimit: FlowEVMBridgeConfig.gasLimit,
value: EVM.Balance(attoflow: 0)
value: 0,
resultTypes: nil
)
}
// Execute the bridge request
Expand Down
57 changes: 21 additions & 36 deletions cadence/contracts/bridge/FlowEVMBridgeHandlers.cdc
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ access(all) contract FlowEVMBridgeHandlers {
let amount = tokens.balance
let uintAmount = FlowEVMBridgeUtils.convertCadenceAmountToERC20Amount(amount, erc20Address: evmAddress)

assert(uintAmount > UInt256(0), message: "Amount to bridge must be greater than 0")
assert(uintAmount > 0, message: "Amount to bridge must be greater than 0")

Burner.burn(<-tokens)

Expand All @@ -127,7 +127,7 @@ access(all) contract FlowEVMBridgeHandlers {
owner: EVM.EVMAddress,
type: Type,
amount: UInt256,
protectedTransferCall: fun (): EVM.Result
protectedTransferCall: fun (): EVM.ResultDecoded
): @{FungibleToken.Vault} {
let evmAddress = self.getTargetEVMAddress()!

Expand All @@ -147,7 +147,7 @@ access(all) contract FlowEVMBridgeHandlers {

// After state confirmation, mint the tokens and return
let minter = self.borrowMinter()
?? panic("Cannot bridge - Minter not set in ".concat(self.getType().identifier))
?? panic("Cannot bridge - Minter not set in \(self.getType().identifier)")
let minted <- minter.mint(amount: ufixAmount)
return <-minted
}
Expand All @@ -170,7 +170,7 @@ access(all) contract FlowEVMBridgeHandlers {
access(FlowEVMBridgeHandlerInterfaces.Admin)
fun setMinter(_ minter: @{FlowEVMBridgeHandlerInterfaces.TokenMinter}) {
pre {
self.minter == nil: "Minter has already been set in ".concat(self.getType().identifier)
self.minter == nil: "Minter has already been set in \(self.getType().identifier)"
}
self.minter <-! minter
}
Expand All @@ -179,7 +179,7 @@ access(all) contract FlowEVMBridgeHandlers {
access(FlowEVMBridgeHandlerInterfaces.Admin)
fun enableBridging() {
pre {
self.minter != nil: "Cannot enable ".concat(self.getType().identifier).concat(" without a minter")
self.minter != nil: "Cannot enable \(self.getType().identifier) without a minter"
}
self.enabled = true
}
Expand Down Expand Up @@ -262,12 +262,13 @@ access(all) contract FlowEVMBridgeHandlers {
let preBalance = FlowEVMBridgeUtils.balanceOf(owner: coa.address(), evmContractAddress: wflowAddress)

// Wrap the deposited FLOW as WFLOW, giving the bridge COA the necessary WFLOW to transfer
let wrapResult = FlowEVMBridgeUtils.call(
let wrapResult = FlowEVMBridgeUtils.callWithSigAndArgs(
signature: "deposit()",
targetEVMAddress: wflowAddress,
args: [],
gasLimit: FlowEVMBridgeConfig.gasLimit,
value: balance
value: balance,
resultTypes: nil
)
assert(wrapResult.status == EVM.Status.successful, message: "Failed to wrap FLOW as WFLOW")

Expand All @@ -276,16 +277,12 @@ access(all) contract FlowEVMBridgeHandlers {
// Cover underflow
assert(
postBalance > preBalance,
message: "Escrowed WFLOW balance did not increment after wrapping FLOW - pre: "
.concat(preBalance.toString()).concat(" | post: ").concat(postBalance.toString())
message: "Escrowed WFLOW balance did not increment after wrapping FLOW - pre: \(preBalance.toString()) | post: \(postBalance.toString())"
)
// Confirm bridge COA's WFLOW balance has incremented by the expected amount
assert(
postBalance - preBalance == uintAmount,
message: "Escrowed WFLOW balance after wrapping does not match requested amount - expected: "
.concat((preBalance + uintAmount).toString())
.concat(" | actual: ")
.concat((postBalance - preBalance).toString())
message: "Escrowed WFLOW balance after wrapping does not match requested amount - expected: \(preBalance + uintAmount).toString()) | actual: \(postBalance - preBalance).toString())"
)

// Transfer WFLOW to recipient
Expand All @@ -307,7 +304,7 @@ access(all) contract FlowEVMBridgeHandlers {
owner: EVM.EVMAddress,
type: Type,
amount: UInt256,
protectedTransferCall: fun (): EVM.Result
protectedTransferCall: fun (): EVM.ResultDecoded
): @{FungibleToken.Vault} {
let wflowAddress = self.getTargetEVMAddress()!

Expand All @@ -318,8 +315,7 @@ access(all) contract FlowEVMBridgeHandlers {
)
assert(
ufixAmount > 0.0,
message: "Requested UInt256 amount ".concat(amount.toString()).concat(" converted to 0.0 ")
.concat(" - try bridging a larger amount to avoid UFix64 precision loss during conversion")
message: "Requested UInt256 amount \(amount.toString()) converted to 0.0 - try bridging a larger amount to avoid UFix64 precision loss during conversion"
)

// Transfers WFLOW to bridge COA as escrow
Expand All @@ -335,12 +331,13 @@ access(all) contract FlowEVMBridgeHandlers {
let preBalance = coa.balance().attoflow

// Unwrap the transferred WFLOW to FLOW, giving the bridge COA the necessary FLOW to withdraw from EVM
let unwrapResult = FlowEVMBridgeUtils.call(
let unwrapResult = FlowEVMBridgeUtils.callWithSigAndArgs(
signature: "withdraw(uint256)",
targetEVMAddress: wflowAddress,
args: [amount],
gasLimit: FlowEVMBridgeConfig.gasLimit,
value: 0.0
value: 0.0,
resultTypes: nil
)
assert(unwrapResult.status == EVM.Status.successful, message: "Failed to unwrap WFLOW as FLOW")

Expand All @@ -349,34 +346,24 @@ access(all) contract FlowEVMBridgeHandlers {
// Cover underflow
assert(
postBalance > preBalance,
message: "Escrowed FLOW Balance did not increment after unwrapping WFLOW - pre: ".concat(preBalance.toString())
.concat(" | post: ").concat(postBalance.toString())
message: "Escrowed FLOW Balance did not increment after unwrapping WFLOW - pre: \(preBalance.toString()) | post: \(postBalance.toString())"
)
// Confirm bridge COA's FLOW balance has incremented by the expected amount
assert(
UInt256(postBalance - preBalance) == amount,
message: "Escrowed WFLOW balance after unwrapping does not match requested amount - expected: "
.concat((UInt256(preBalance) + amount).toString())
.concat(" | actual: ")
.concat((postBalance - preBalance).toString())
message: "Escrowed WFLOW balance after unwrapping does not match requested amount - expected: \(UInt256(preBalance) + amount).toString()) | actual: \(postBalance - preBalance).toString())"
)

// Withdraw escrowed FLOW from bridge COA
let withdrawBalance = EVM.Balance(attoflow: UInt(amount))
assert(
UInt256(withdrawBalance.attoflow) == amount,
message: "Requested balance failed to convert to attoflow - expected: "
.concat(amount.toString())
.concat(" | actual: ")
.concat(withdrawBalance.attoflow.toString())
message: "Requested balance failed to convert to attoflow - expected: \(amount.toString()) | actual: \(withdrawBalance.attoflow.toString())"
)
let flowVault <- coa.withdraw(balance: withdrawBalance)
assert(
flowVault.balance == ufixAmount,
message: "Resulting FLOW Vault balance does not match requested amount - expected: "
.concat(ufixAmount.toString())
.concat(" | actual: ")
.concat(flowVault.balance.toString())
message: "Resulting FLOW Vault balance does not match requested amount - expected: \(ufixAmount.toString()) | actual: \(flowVault.balance.toString())"
)
return <-flowVault
}
Expand All @@ -388,15 +375,13 @@ access(all) contract FlowEVMBridgeHandlers {
/// Sets the target type for the handler
access(FlowEVMBridgeHandlerInterfaces.Admin)
fun setTargetType(_ type: Type) {
panic("WFLOWTokenHandler has targetType set to "
.concat(self.targetType.identifier).concat(" at initialization"))
panic("WFLOWTokenHandler has targetType set to \(self.targetType.identifier) at initialization")
}

/// Sets the target EVM address for the handler
access(FlowEVMBridgeHandlerInterfaces.Admin)
fun setTargetEVMAddress(_ address: EVM.EVMAddress) {
panic("WFLOWTokenHandler has EVMAddress set to "
.concat(self.targetEVMAddress.toString()).concat(" at initialization"))
panic("WFLOWTokenHandler has EVMAddress set to \(self.targetEVMAddress.toString()) at initialization")
}

/// Sets the target type for the handler
Expand Down
Loading
Loading