Skip to content

Commit

Permalink
fix WFLOWHandler WFLOW withdrawal call
Browse files Browse the repository at this point in the history
  • Loading branch information
sisyphusSmiling committed Dec 3, 2024
1 parent 6ddfaaf commit 8c3241c
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 25 deletions.
17 changes: 6 additions & 11 deletions cadence/contracts/bridge/FlowEVMBridgeHandlers.cdc
Original file line number Diff line number Diff line change
Expand Up @@ -192,14 +192,6 @@ access(all) contract FlowEVMBridgeHandlers {
}
}

/**
TODO:
- Configure handler
-
- Update association between FLOW & WFLOW
- Remove any pre-conditions on FLOW in bridging functionality
*/

/// Facilitates moving Flow between Cadence and EVM as WFLOW. Since WFLOW is an artifact of the EVM ecosystem,
/// wrapping the native token as an ERC20, it does not have a place in Cadence's fungible token ecosystem.
/// Given the native interface on EVM.CadenceOwnedAccount and EVM.EVMAddress to move FLOW between Cadence and EVM,
Expand Down Expand Up @@ -338,7 +330,7 @@ access(all) contract FlowEVMBridgeHandlers {

// Unwrap the transferred WFLOW to FLOW, giving the bridge COA the necessary FLOW to withdraw from EVM
let unwrapResult = FlowEVMBridgeUtils.call(
signature: "withdraw(uint)",
signature: "withdraw(uint256)",
targetEVMAddress: wflowAddress,
args: [amount],
gasLimit: FlowEVMBridgeConfig.gasLimit,
Expand All @@ -351,7 +343,8 @@ access(all) contract FlowEVMBridgeHandlers {
// Cover underflow
assert(
postBalance > preBalance,
message: "Escrowed FLOW Balance did not increment after unwrapping WFLOW"
message: "Escrowed FLOW Balance did not increment after unwrapping WFLOW - pre: ".concat(preBalance.toString())
.concat(" post: ").concat(postBalance.toString())
)
// Confirm bridge COA's FLOW balance has incremented by the expected amount
assert(
Expand Down Expand Up @@ -382,7 +375,9 @@ access(all) contract FlowEVMBridgeHandlers {
return <-flowVault
}

/* --- Admin --- */
/* --- HandlerAdmin --- */
// Conforms to HandlerAdmin for enableBridging, but most of the methods are unnecessary given the strict
// association between FLOW and WFLOW
/// Sets the target type for the handler
access(FlowEVMBridgeHandlerInterfaces.Admin)
Expand Down
55 changes: 44 additions & 11 deletions cadence/tests/flow_evm_wflow_handler_tests.cdc
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import "FungibleToken"
import "NonFungibleToken"
import "FlowStorageFees"
import "EVM"
import "FlowEVMBridgeConfig"

import "test_helpers.cdc"

Expand Down Expand Up @@ -347,7 +348,7 @@ fun testOnboardWFLOWByEVMAddressFails() {
Test.expect(onboardingResult, Test.beFailed())
}

/* --- BRIDGING FUNGIBLE TOKENS - Test bridging both Cadence- & EVM-native fungible tokens --- */
/* --- BRIDGING FLOW to EVM as WFLOW and WFLOW from EVM as FLOW --- */

// Now enable TokenHandler to bridge in both directions
access(all)
Expand All @@ -361,6 +362,22 @@ fun testEnableWFLOWTokenHandlerSucceeds() {
// TODO: Validate event emission and values
}

// Validate that funds can be bridged from Cadence to EVM, resulting in balance increase in WFLOW as target
access(all)
fun testBridgeZeroFLOWTokenToEVMFails() {
// Attempt bridge 0 FLOW to EVM - should fail
bridgeTokensToEVM(
signer: alice,
vaultIdentifier: buildTypeIdentifier(
address: flowTokenAccountAddress,
contractName: "FlowToken",
resourceName: "Vault"
),
amount: 0.0,
beFailed: true
)
}

// Validate that funds can be bridged from Cadence to EVM, resulting in balance increase in WFLOW as target
access(all)
fun testBridgeFLOWTokenToEVMFirstSucceeds() {
Expand All @@ -372,6 +389,7 @@ fun testBridgeFLOWTokenToEVMFirstSucceeds() {
var cadenceBalance = getBalance(ownerAddr: alice.address, storagePathIdentifier: "flowTokenVault")
?? panic("Problem getting FlowToken balance")
Test.assert(cadenceBalance == flowFundingAmount - coaFundingAmount, message: "Invalid Cadence balance")
// Leave some FLOW as it's needed for storage, transaction, and bridge fees
let remainder = 1.0
let bridgeAmount = cadenceBalance - remainder

Expand Down Expand Up @@ -406,9 +424,23 @@ fun testBridgeFLOWTokenToEVMFirstSucceeds() {

// With all funds now in EVM, we can test bridging back to Cadence
access(all)
fun testBridgeWFLOWTokenFromEVMSecondSucceeds() {
fun testBridgeZeroWFLOWTokenFromEVMSecondFails() {
bridgeTokensFromEVM(
signer: alice,
vaultIdentifier: buildTypeIdentifier(
address: flowTokenAccountAddress,
contractName: "FlowToken",
resourceName: "Vault"
),
amount: UInt256(0),
beFailed: true
)
}

let wflowTotalSupplyBefore = getEVMTotalSupply(erc20AddressHex: wflowAddressHex)
// With all funds now in EVM, we can test bridging back to Cadence
access(all)
fun testBridgeWFLOWTokenFromEVMSecondSucceeds() {
// let wflowTotalSupplyBefore = getEVMTotalSupply(erc20AddressHex: wflowAddressHex)
let cadenceBalanceBefore = getBalance(ownerAddr: alice.address, storagePathIdentifier: "flowTokenVault")
?? panic("Problem getting FlowToken balance")
Expand All @@ -430,19 +462,20 @@ fun testBridgeWFLOWTokenFromEVMSecondSucceeds() {
// Confirm that Alice's balance has been bridged to Cadence
let cadenceBalanceAfter = getBalance(ownerAddr: alice.address, storagePathIdentifier: "flowTokenVault")
?? panic("Problem getting FlowToken balance")
Test.assertEqual(ufixEVMbalance, cadenceBalanceAfter)
let expectedBalanceAfter = cadenceBalanceBefore + ufixEVMbalance - FlowEVMBridgeConfig.baseFee
Test.assertEqual(expectedBalanceAfter, cadenceBalanceAfter)

// Confirm that the ERC20 balance was burned in the process of bridging
// Confirm that the WFLOW balance was transferred out in the process of bridging
let evmBalanceAfter = balanceOf(evmAddressHex: aliceCOAAddressHex, erc20AddressHex: wflowAddressHex)
Test.assertEqual(UInt256(0), evmBalanceAfter)

// // Validate that the ERC20 balance in circulation remained the same
// let erc20TotalSupplyAfter = getEVMTotalSupply(erc20AddressHex: wflowAddressHex)
// Test.assertEqual(wflowTotalSupplyBefore, erc20TotalSupplyAfter)
// Validate that the WFLOW supply in circulation reduced to 0
let wflowTotalSupplyAfter = getEVMTotalSupply(erc20AddressHex: wflowAddressHex)
Test.assertEqual(UInt256(0), wflowTotalSupplyAfter)

// // Validate that all ERC20 funds are now in escrow since all bridged to Cadence
// let escrowBalance = balanceOf(evmAddressHex: getBridgeCOAAddressHex(), erc20AddressHex: wflowAddressHex)
// Test.assertEqual(erc20TotalSupplyAfter, escrowBalance)
// Validate that all WFLOW funds are now in escrow since all bridged to Cadence
let escrowBalance = balanceOf(evmAddressHex: getBridgeCOAAddressHex(), erc20AddressHex: wflowAddressHex)
Test.assertEqual(wflowTotalSupplyAfter, escrowBalance)
}

// // Now test bridging with liquidity flow moving entirely from EVM to Cadence and back
Expand Down
11 changes: 8 additions & 3 deletions cadence/transactions/example-assets/evm-assets/unwrap_flow.cdc
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import "EVM"

import "FlowEVMBridgeUtils"

/// This transactions wraps FLOW tokens as WFLOW tokens, using the signing COA's EVM FLOW balance primarily. If the
/// This transactions wraps FLOW tokens as WFLOW tokens, using the signing COA's EVM FLOW balance primarily. If the
/// EVM balance is insufficient, the transaction will transfer FLOW from the Cadence balance to the EVM balance.
///
/// @param wflowContractHex: The EVM address of the WFLOW contract as a hex string
Expand All @@ -22,13 +22,18 @@ transaction(wflowContractHex: String, amount: UInt256) {
self.wflowAddress = EVM.addressFromString(wflowContractHex)
self.coa = signer.storage.borrow<auth(EVM.Call) &EVM.CadenceOwnedAccount>(from: /storage/evm)
?? panic("Could not borrow COA from provided gateway address")

self.preBalance = UInt(FlowEVMBridgeUtils.balanceOf(owner: self.coa.address(), evmContractAddress: self.wflowAddress))
assert(
self.preBalance >= UInt(amount),
message: "Amount exceeds current WFLOW balance of ".concat(self.preBalance.toString())
)
self.postBalance = 0
}

execute {
// Encode the withdraw function call
let calldata = EVM.encodeABIWithSignature("withdraw(uint)", [UInt(amount)])
let calldata = EVM.encodeABIWithSignature("withdraw(uint256)", [UInt(amount)])
// Define the value to send to the WFLOW contract - 0 to unwrap
let value = EVM.Balance(attoflow: 0)
// Call the WFLOW contract which should complete the unwrap
Expand All @@ -38,7 +43,7 @@ transaction(wflowContractHex: String, amount: UInt256) {
gasLimit: 15_000_000,
value: value
)
assert(result.status == EVM.Status.successful, message: "Failed to wrap FLOW as WFLOW")
assert(result.status == EVM.Status.successful, message: "Failed to unwrap FLOW as WFLOW")
self.postBalance = UInt(FlowEVMBridgeUtils.balanceOf(owner: self.coa.address(), evmContractAddress: self.wflowAddress))
}

Expand Down

0 comments on commit 8c3241c

Please sign in to comment.