Skip to content
Draft
Show file tree
Hide file tree
Changes from 2 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
1 change: 1 addition & 0 deletions core/constraints/abstract.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ class ConstraintApp(Enum):
ENS = "ENS"
EAS = "EAS"
GITCOIN_PASSPORT = "gitcoin_passport"
ARBITRUM = "arbitrum"

@classmethod
def choices(cls):
Expand Down
44 changes: 44 additions & 0 deletions core/constraints/arbitrum.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
from core.constraints.abstract import (
ConstraintApp,
ConstraintParam,
ConstraintVerification,
)
from core.thirdpartyapp.arbitrum import ArbitrumUtils


class HasBridgedToken(ConstraintVerification):
_param_keys = [
ConstraintParam.ADDRESS,
ConstraintParam.MINIMUM,
ConstraintParam.CHAIN,
]
app_name = ConstraintApp.ARBITRUM.value

def __init__(self, user_profile) -> None:
super().__init__(user_profile)

def is_observed(self, *args, **kwargs) -> bool:
minimum_amount = float(self.param_values[ConstraintParam.MINIMUM.name])
chain = self.param_values[ConstraintParam.CHAIN.name]
token_address = self.param_values[ConstraintParam.ADDRESS.name]

arb_utils = ArbitrumUtils()
user_wallets = self.user_addresses

for wallet in user_wallets:
bridging_results = arb_utils.check_bridge_transactions(
wallet, token_address, minimum_amount
)

if chain == "ethereum_to_arbitrum":
return bridging_results["Ethereum to Arbitrum"]
elif chain == "arbitrum_to_ethereum":
return bridging_results["Arbitrum to Ethereum"]
elif chain == "arbitrum_to_nova":
return bridging_results["Arbitrum to Nova"]
elif chain == "nova_to_arbitrum":
return bridging_results["Nova to Arbitrum"]
elif chain == "any":
return any(bridging_results.values())
else:
raise ValueError(f"Invalid chain parameter: {chain}")
1 change: 1 addition & 0 deletions core/thirdpartyapp/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from .arbitrum import ArbitrumUtils
from .EAS import EASUtils
from .ens import ENSUtil # noqa: F401
from .farcaster import FarcasterUtil # noqa: F401
Expand Down
102 changes: 102 additions & 0 deletions core/thirdpartyapp/arbitrum.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
from web3 import Web3


class ArbitrumUtils:
def __init__(self):
# Initialize Web3 instances
self.eth_w3 = Web3.HTTPProvider(
"https://mainnet.infura.io/v3/YOUR_INFURA_PROJECT_ID"
)
self.arb_w3 = Web3.HTTPProvider("https://arb1.arbitrum.io/rpc")
self.nova_w3 = Web3.HTTPProvider("https://nova.arbitrum.io/rpc")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please check Web3Util in core.utils


# Bridge contract addresses
self.eth_arb_bridge = "0x8315177aB297bA92A06054cE80a67Ed4DBd7ed3a"
self.arb_eth_bridge = "0x0000000000000000000000000000000000000064"
self.arb_nova_bridge = "0x0000000000000000000000000000000000000064"
self.nova_arb_bridge = "0x0000000000000000000000000000000000000064"

# ABI for the bridge contracts
self.bridge_abi = [
{
"anonymous": False,
"inputs": [
{"indexed": True, "name": "l1Token", "type": "address"},
{"indexed": True, "name": "from", "type": "address"},
{"indexed": True, "name": "to", "type": "address"},
{"indexed": False, "name": "amount", "type": "uint256"},
],
"name": "ERC20DepositInitiated",
"type": "event",
},
{
"anonymous": False,
"inputs": [
{"indexed": True, "name": "l1Token", "type": "address"},
{"indexed": True, "name": "from", "type": "address"},
{"indexed": True, "name": "to", "type": "address"},
{"indexed": False, "name": "amount", "type": "uint256"},
],
"name": "WithdrawalInitiated",
"type": "event",
},
]

def check_bridge_transactions(self, wallet_address, token_address, amount):
# Create contract instances
eth_arb_contract = self.eth_w3.eth.contract(
address=self.eth_arb_bridge, abi=self.bridge_abi
)
arb_eth_contract = self.arb_w3.eth.contract(
address=self.arb_eth_bridge, abi=self.bridge_abi
)
arb_nova_contract = self.arb_w3.eth.contract(
address=self.arb_nova_bridge, abi=self.bridge_abi
)
nova_arb_contract = self.nova_w3.eth.contract(
address=self.nova_arb_bridge, abi=self.bridge_abi
)

results = {}

# Check Ethereum to Arbitrum
eth_arb_filter = eth_arb_contract.events.ERC20DepositInitiated.createFilter(
fromBlock=0,
argument_filters={"from": wallet_address, "l1Token": token_address},
)
eth_arb_events = eth_arb_filter.get_all_entries()
results["Ethereum to Arbitrum"] = any(
event["args"]["amount"] >= amount for event in eth_arb_events
)

# Check Arbitrum to Ethereum
arb_eth_filter = arb_eth_contract.events.WithdrawalInitiated.createFilter(
fromBlock=0,
argument_filters={"from": wallet_address, "l1Token": token_address},
)
arb_eth_events = arb_eth_filter.get_all_entries()
results["Arbitrum to Ethereum"] = any(
event["args"]["amount"] >= amount for event in arb_eth_events
)

# Check Arbitrum to Nova
arb_nova_filter = arb_nova_contract.events.WithdrawalInitiated.createFilter(
fromBlock=0,
argument_filters={"from": wallet_address, "l1Token": token_address},
)
arb_nova_events = arb_nova_filter.get_all_entries()
results["Arbitrum to Nova"] = any(
event["args"]["amount"] >= amount for event in arb_nova_events
)

# Check Nova to Arbitrum
nova_arb_filter = nova_arb_contract.events.WithdrawalInitiated.createFilter(
fromBlock=0,
argument_filters={"from": wallet_address, "l1Token": token_address},
)
nova_arb_events = nova_arb_filter.get_all_entries()
results["Nova to Arbitrum"] = any(
event["args"]["amount"] >= amount for event in nova_arb_events
)

return results