Skip to content

Commit

Permalink
Merge branch 'main' into add-wflow-handler
Browse files Browse the repository at this point in the history
  • Loading branch information
sisyphusSmiling committed Sep 19, 2024
2 parents 53ce62f + af98c38 commit 0de2049
Show file tree
Hide file tree
Showing 7 changed files with 179 additions and 1 deletion.
2 changes: 2 additions & 0 deletions cadence/contracts/bridge/FlowEVMBridge.cdc
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,8 @@ contract FlowEVMBridge : IFlowEVMNFTBridge, IFlowEVMTokenBridge {
) {
pre {
!FlowEVMBridgeConfig.isPaused(): "Bridge operations are currently paused"
!FlowEVMBridgeConfig.isEVMAddressBlocked(address):
"This EVM contract is currently blocked from being onboarded"
}
/* Validate the EVM contract */
//
Expand Down
58 changes: 58 additions & 0 deletions cadence/contracts/bridge/FlowEVMBridgeConfig.cdc
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ contract FlowEVMBridgeConfig {
access(all) entitlement Gas
access(all) entitlement Fee
access(all) entitlement Pause
access(all) entitlement Blocklist

/*************
Fields
Expand Down Expand Up @@ -128,6 +129,13 @@ contract FlowEVMBridgeConfig {
return self.evmAddressHexToType[evmAddressHex]
}

/// Returns whether the given EVMAddress is currently blocked from onboarding to the bridge
///
access(all)
view fun isEVMAddressBlocked(_ evmAddress: EVM.EVMAddress): Bool {
return self.borrowBlocklist().isBlocked(evmAddress)
}

/****************************
Bridge Account Methods
****************************/
Expand Down Expand Up @@ -213,6 +221,26 @@ contract FlowEVMBridgeConfig {
return &self.typeToTokenHandlers[type]
}

/// Returns an entitled reference to the bridge EVMBlocklist
///
access(self)
view fun borrowBlocklist(): auth(Blocklist) &EVMBlocklist {
return self.account.storage.borrow<auth(Blocklist) &EVMBlocklist>(from: /storage/evmBlocklist)
?? panic("Missing or mis-typed Blocklist in storage")
}

/// Temporary method to initialize the EVMBlocklist resource as this resource was added after the contract was
/// deployed
///
access(all)
fun initBlocklist() {
let path = /storage/evmBlocklist
if self.account.storage.type(at: path) != nil{
return
}
self.account.storage.save(<-create EVMBlocklist(), to: path)
}

/*****************
Constructs
*****************/
Expand Down Expand Up @@ -245,6 +273,36 @@ contract FlowEVMBridgeConfig {
}
}

/// EVMBlocklist resource stores a mapping of EVM addresses that are blocked from onboarding to the bridge
///
access(all) resource EVMBlocklist {
/// Mapping of serialized EVM addresses to their blocked status
///
access(all) let blockList: {String: Bool}

init() {
self.blockList = {}
}

/// Returns whether the given EVM address is blocked from onboarding to the bridge
///
access(all) view fun isBlocked(_ evmAddress: EVM.EVMAddress): Bool {
return self.blockList[evmAddress.toString()] ?? false
}

/// Blocks the given EVM address from onboarding to the bridge
///
access(Blocklist) fun block(_ evmAddress: EVM.EVMAddress) {
self.blockList[evmAddress.toString()] = true
}

/// Removes the given EVM address from the blocklist
///
access(Blocklist) fun unblock(_ evmAddress: EVM.EVMAddress) {
self.blockList.remove(key: evmAddress.toString())
}
}

/*****************
Config Admin
*****************/
Expand Down
14 changes: 14 additions & 0 deletions cadence/scripts/bridge/is_evm_address_blocked.cdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import "EVM"

import "FlowEVMBridgeConfig"

/// Returns whether a EVM contract is blocked from onboarded to the FlowEVMBridge
///
/// @param evmAddressHex: The hex-encoded address of the EVM contract as a String
///
/// @return Whether the contract is blocked from onboarding to the FlowEVMBridge
///
access(all) fun main(evmAddressHex: String): Bool {
let address = EVM.addressFromString(evmAddressHex)
return FlowEVMBridgeConfig.isEVMAddressBlocked(address)
}
35 changes: 34 additions & 1 deletion cadence/tests/flow_evm_bridge_tests.cdc
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,13 @@ fun setup() {
arguments: []
)
Test.expect(err, Test.beNil())
// Initialize EVMBlocklist resource in account storage
let initBlocklistResult = executeTransaction(
"../transactions/bridge/admin/blocklist/init_blocklist.cdc",
[],
bridgeAccount
)
Test.expect(initBlocklistResult, Test.beSucceeded())

// Deploy registry
let registryDeploymentResult = executeTransaction(
Expand Down Expand Up @@ -954,11 +961,37 @@ access(all)
fun testOnboardERC721ByEVMAddressSucceeds() {
snapshot = getCurrentBlockHeight()

// Validate EVMBlocklist works by blocking the EVM address
let blockResult = executeTransaction(
"../transactions/bridge/admin/blocklist/block_evm_address.cdc",
[erc721AddressHex],
bridgeAccount
)
Test.expect(blockResult, Test.beSucceeded())

// onboarding should fail as the EVM address is blocked
var onboardingResult = executeTransaction(
"../transactions/bridge/onboarding/onboard_by_evm_address.cdc",
[erc721AddressHex],
alice
)
Test.expect(onboardingResult, Test.beFailed())

// Unblock the EVM address
let unblockResult = executeTransaction(
"../transactions/bridge/admin/blocklist/unblock_evm_address.cdc",
[erc721AddressHex],
bridgeAccount
)
Test.expect(unblockResult, Test.beSucceeded())

// And now onboarding should succeed
var requiresOnboarding = evmAddressRequiresOnboarding(erc721AddressHex)
?? panic("Problem getting onboarding requirement")
Test.assertEqual(true, requiresOnboarding)

var onboardingResult = executeTransaction(
onboardingResult = executeTransaction(
"../transactions/bridge/onboarding/onboard_by_evm_address.cdc",
[erc721AddressHex],
alice
Expand Down
29 changes: 29 additions & 0 deletions cadence/transactions/bridge/admin/blocklist/block_evm_address.cdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import "EVM"

import "FlowEVMBridgeConfig"

/// Blocks the given EVM contract address from onboarding.
///
/// @param evmContractHex: The EVM contract address to block from onboarding
///
transaction(evmContractHex: String) {

let evmBlocklist: auth(FlowEVMBridgeConfig.Blocklist) &FlowEVMBridgeConfig.EVMBlocklist
let evmAddress: EVM.EVMAddress

prepare(signer: auth(BorrowValue) &Account) {
FlowEVMBridgeConfig.initBlocklist()
self.evmBlocklist = signer.storage.borrow<auth(FlowEVMBridgeConfig.Blocklist) &FlowEVMBridgeConfig.EVMBlocklist>(
from: /storage/evmBlocklist
) ?? panic("Could not borrow FlowEVMBridgeConfig Admin reference")
self.evmAddress = EVM.addressFromString(evmContractHex)
}

execute {
self.evmBlocklist.block(self.evmAddress)
}

post {
FlowEVMBridgeConfig.isEVMAddressBlocked(self.evmAddress): "EVM address was not blocked"
}
}
14 changes: 14 additions & 0 deletions cadence/transactions/bridge/admin/blocklist/init_blocklist.cdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import "EVM"

import "FlowEVMBridgeConfig"

/// Initializes the EVMBlocklist in the bridge account if it does not yet exist at the expected path
///
transaction {

prepare(signer: &Account) {}

execute {
FlowEVMBridgeConfig.initBlocklist()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import "EVM"

import "FlowEVMBridgeConfig"

/// Unblocks the given EVM contract address from onboarding to the bridge.
///
/// @param evmContractHex: The EVM contract address to unblock
///
transaction(evmContractHex: String) {

let evmBlocklist: auth(FlowEVMBridgeConfig.Blocklist) &FlowEVMBridgeConfig.EVMBlocklist
let evmAddress: EVM.EVMAddress

prepare(signer: auth(BorrowValue) &Account) {
self.evmBlocklist = signer.storage.borrow<auth(FlowEVMBridgeConfig.Blocklist) &FlowEVMBridgeConfig.EVMBlocklist>(
from: /storage/evmBlocklist
) ?? panic("Could not borrow FlowEVMBridgeConfig EVMBlocklist reference")
self.evmAddress = EVM.addressFromString(evmContractHex)
}

execute {
self.evmBlocklist.unblock(self.evmAddress)
}

post {
!FlowEVMBridgeConfig.isEVMAddressBlocked(self.evmAddress): "EVM address was not unblocked"
}
}

0 comments on commit 0de2049

Please sign in to comment.