diff --git a/packages/lstolas/agents/lst_agent/aea-config.yaml b/packages/lstolas/agents/lst_agent/aea-config.yaml index 3f03d72..e806957 100644 --- a/packages/lstolas/agents/lst_agent/aea-config.yaml +++ b/packages/lstolas/agents/lst_agent/aea-config.yaml @@ -24,7 +24,7 @@ protocols: - open_aea/signing:1.0.0:bafybeig2d36zxy65vd7fwhs7scotuktydcarm74aprmrb5nioiymr3yixm skills: - eightballer/prometheus:0.1.0:bafybeicl5i7e467aowfarke4bbyixo2dggar276njmvyuwbsby5pxshhtu -- lstolas/lst_skill:0.1.0:bafybeidnr2ez26ahnpp224gyc24cis4oylxycpvklbfxjcygtpdnwkp42a +- lstolas/lst_skill:0.1.0:bafybeigpmounpcjgk2lppmtri56foqjwkr2xewnff6ssz3awqnecptgzdi customs: [] default_ledger: ethereum required_ledgers: diff --git a/packages/lstolas/agents/lst_agent_prod/aea-config.yaml b/packages/lstolas/agents/lst_agent_prod/aea-config.yaml index 5cbc892..a69402f 100644 --- a/packages/lstolas/agents/lst_agent_prod/aea-config.yaml +++ b/packages/lstolas/agents/lst_agent_prod/aea-config.yaml @@ -24,7 +24,7 @@ protocols: - open_aea/signing:1.0.0:bafybeig2d36zxy65vd7fwhs7scotuktydcarm74aprmrb5nioiymr3yixm skills: - eightballer/prometheus:0.1.0:bafybeicl5i7e467aowfarke4bbyixo2dggar276njmvyuwbsby5pxshhtu -- lstolas/lst_skill:0.1.0:bafybeidnr2ez26ahnpp224gyc24cis4oylxycpvklbfxjcygtpdnwkp42a +- lstolas/lst_skill:0.1.0:bafybeigpmounpcjgk2lppmtri56foqjwkr2xewnff6ssz3awqnecptgzdi customs: [] default_ledger: ethereum required_ledgers: @@ -99,7 +99,7 @@ models: args: l1_starting_block: 23648061 l2_starting_block: 42790245 - layer_1_rpc_endpoint: https://eth.drpc.org + layer_1_rpc_endpoint: https://0xrpc.io/eth layer_1_amb_home: '0x4C36d2919e407f0Cc2Ee3c993ccF8ac26d9CE64e' layer_1_olas_address: '0x0001A500A6B18995B03f44bb040A5fFc28E45CB0' layer_2_rpc_endpoint: https://gnosis.oat.farm diff --git a/packages/lstolas/skills/lst_skill/behaviours_classes/redeem_round.py b/packages/lstolas/skills/lst_skill/behaviours_classes/redeem_round.py index 2921154..9226d88 100644 --- a/packages/lstolas/skills/lst_skill/behaviours_classes/redeem_round.py +++ b/packages/lstolas/skills/lst_skill/behaviours_classes/redeem_round.py @@ -1,6 +1,7 @@ """Behaviour class for the state RedeemRound of the LstAbciApp.""" from enum import Enum +from textwrap import dedent from pydantic import BaseModel @@ -30,6 +31,7 @@ class PendingRequest(BaseModel): amount: int operation: str status: OperationStatus + block_number: int class RedeemRound(BaseState): @@ -79,11 +81,10 @@ def is_triggered(self) -> bool: self.strategy.layer_2_api, self.strategy.lst_staking_processor_l2_address, from_block=self.strategy.layer_2_starting_block - if self.last_completed_block is None - else self.last_completed_block, + if self.last_scanned_block is None + else self.last_scanned_block, ) ) - self.last_scanned_block = queued_requests.to_block if queued_requests.events: self.log.info(f"Found {len(queued_requests.events)} queued requests to be processed.") potential_events_to_process = [ @@ -93,19 +94,21 @@ def is_triggered(self) -> bool: amount=event.args.amount, operation="0x" + event.args.operation.hex(), status=OperationStatus(event.args.status), + block_number=event.blockNumber, ) for event in queued_requests.events ] + oldest_blocks: list[int] = [self.strategy.layer_2_api.api.eth.block_number] for event in potential_events_to_process: - if event.status is not OperationStatus.INSUFFICIENT_OLAS_BALANCE: - self.log.info( - f"Request with batch hash {event.batch_hash} has status {event.status} and will be skipped." - ) - continue self.send_notification_to_user( title="Redeem request detected", - msg=f"Detected a redeem request with batch hash {event.batch_hash}. Attempting to process it.", + msg=dedent(f""" + Detected a redeem request with batch hash {event.batch_hash}. Attempting to process it. + Chain ID: {self.strategy.layer_2_api.api.eth.chain_id} + Contract Address: {self.strategy.lst_staking_processor_l2_address} + Block Number: {event.block_number} + """), ) self.context.logger.info(f"Checking on event: {event}") @@ -122,21 +125,39 @@ def is_triggered(self) -> bool: .hex() # type: ignore ) # we now check if the request is still queued - is_still_queued = self.strategy.lst_staking_processor_l2_contract.queued_hashes( - self.strategy.layer_2_api, - self.strategy.lst_staking_processor_l2_address, - "0x" + queued_hash, - ).get("bool") - if is_still_queued: - self.events_to_process.append(event) + request_status = OperationStatus( + self.strategy.lst_staking_processor_l2_contract.queued_hashes( + self.strategy.layer_2_api, + self.strategy.lst_staking_processor_l2_address, + "0x" + queued_hash, + ).get("int") + ) + + if request_status != OperationStatus.NON_EXISTENT: self.log.info( - f"Request with batch hash {event.batch_hash} is state: {is_still_queued} and will be processed." + f"Request with batch hash {event.batch_hash} is still queued with status {request_status}." ) - else: - self.log.info( - f"Request with batch hash {event.batch_hash} is no longer queued and will be skipped." + + will_txn_be_sent = self.tx_settler.simulate( + contract_address=self.strategy.lst_staking_processor_l2_address, + function=self.strategy.lst_staking_processor_l2_contract.redeem, + ledger_api=self.strategy.layer_2_api, + batch_hash=event.batch_hash, + target=event.target, + amount=event.amount, + operation=event.operation, ) + + if will_txn_be_sent: + self.events_to_process.append(event) + self.log.info( + f"Request with batch hash {event.batch_hash} is state: {request_status} and will be sent." + ) + else: + oldest_blocks.append(event.block_number) + else: + self.log.info(f"Request with batch hash {event.batch_hash} is no ready yet checked next iteration.") + self.last_scanned_block = min(oldest_blocks) if self.events_to_process: return True - self.last_completed_block = self.last_scanned_block return False diff --git a/packages/lstolas/skills/lst_skill/models.py b/packages/lstolas/skills/lst_skill/models.py index 21351ec..6e4159c 100644 --- a/packages/lstolas/skills/lst_skill/models.py +++ b/packages/lstolas/skills/lst_skill/models.py @@ -300,9 +300,11 @@ def build_and_settle_transaction( chain_id_to_explorer = { 11155111: "https://sepolia.etherscan.io/tx/", 10200: "https://gnosis-chiado.blockscout.com/tx/", + 1: "https://etherscan.io/tx/", + 100: "https://gnosisscan.io/tx/", } - args = {k: esc_md2(v) for k, v in kwargs.items() if k != "attempts"} + args = {str(k): esc_md2(str(v)) for k, v in kwargs.items() if k != "attempts"} stringified_args = ", ".join(f"{k}={v}" for k, v in args.items()) url = chain_id_to_explorer.get(ledger_api.api.eth.chain_id, "") + tx_hash.hex() @@ -311,6 +313,7 @@ def build_and_settle_transaction( Contract: {html.escape(contract_address)}
Kwargs:
{html.escape(stringified_args)}
Transaction + Chain ID: {ledger_api.api.eth.chain_id!s} """) self.log.info(msg) self.send_notification_to_user(title="New txn executed!", msg=msg) @@ -325,3 +328,19 @@ def strategy(self) -> LstStrategy: def log(self): """Get the logger.""" return self.context.logger + + def simulate(self, contract_address: str, function: Callable, ledger_api: EthereumApi, **kwargs) -> bool: + """Simulate a transaction.""" + self.log.info(f"Simulating transaction for contract at address: {contract_address}") + txn = function( + ledger_api, + contract_address, + **kwargs, + ) + try: + txn.estimate_gas({"from": self.strategy.sender_address}) + self.log.info("Simulation successful, transaction would be sent.") + return True + except Exception as e: # pylint: disable=broad-except + self.log.exception(f"Simulation failed, transaction would NOT be sent. Error: {e}") + return False diff --git a/packages/lstolas/skills/lst_skill/skill.yaml b/packages/lstolas/skills/lst_skill/skill.yaml index a5e3ed4..95ef65e 100644 --- a/packages/lstolas/skills/lst_skill/skill.yaml +++ b/packages/lstolas/skills/lst_skill/skill.yaml @@ -18,14 +18,14 @@ fingerprint: behaviours_classes/claim_reward_tokens_round.py: bafybeia7d26votggvlw36wtp623unczgdmlwojqhkj4t62aeqdxrij6h64 behaviours_classes/error_rounds.py: bafybeihtghxlbb5k6s4egdibglto7h43xk3fz7vclhrizncq5vkwzlsqu4 behaviours_classes/finalize_bridged_tokens_round.py: bafybeifnxckqnez2apllpwlxj6rvrfat732xhorhqle3aut6wl2dr7ekxu - behaviours_classes/redeem_round.py: bafybeigcl5hk3mhgqzct7bg3c2bt6d2gwhoqaydpqp2whkxs262lytw7m4 + behaviours_classes/redeem_round.py: bafybeidn2dndogpohxjvlsxzyq5owgkb3tob2eqkzu2b6jcf6dncvgdobe behaviours_classes/starting_round.py: bafybeift5drjrtwcbssumcpfm2eczus6z6si4gppokvymhbqkfsajmhun4 behaviours_classes/trigger_l2_to_l1_bridge.py: bafybeiac6nikhnpyveenvtzdzwxqxe5ivtayxlz5enmpcfvtsmtnnpvbwm behaviours_classes/waiting_round.py: bafybeiekbnjih5txvpxi75itpjfv7nr65bf7kbgd2f4tdvanbjsewdp2ma dialogues.py: bafybeigbpewv7jsbyaybassv47sxk7bmvbl5pg25v2inr5gc6djch75rmi events_processing.py: bafybeihvdc6qwmzk6pizpuwhdjb7whtevt25uicjeghxzem2qtjko2biom handlers.py: bafybeigxyhzux4czjkaqntqmnjcfidchf2h6sitvxx6dknpwmoucbojqgq - models.py: bafybeihisehbnpxoyhthl63x3yaud4ouvlletxuck5op6gyz5fylmj72me + models.py: bafybeibzv5axz7g47km2hyt3tpzypglsqiyzmhb7ddzt2xe5rblqy4r3xe tests/test_check_work_behaviour.py: bafybeib45mbpf7ctr5aoyltwh34pljwpsh5zqentdqxerfkqx4tqhsg5h4 tests/test_conditional_behaviours.py: bafybeickfflcj6kw5k72w4a56xbzsiolv34vcfjkgr5o3wm4wluoztxqlm tests/test_fsm_behaviour.py: bafybeiellmhyw3fupa725t6yirtg3ct25vuttswvyfzwvr5k3l5x3zseby diff --git a/packages/packages.json b/packages/packages.json index 7fba43d..2514dab 100644 --- a/packages/packages.json +++ b/packages/packages.json @@ -11,9 +11,9 @@ "contract/eightballer/amb_gnosis_helper/0.1.0": "bafybeig37p3q4se2it75kt4zvqvrvzk4fqc7eyspspt3txooxxljkurkey", "contract/eightballer/erc_20/0.1.0": "bafybeig622mhgil3uq34d4l3r6moxisgvxwxtrosds2x7glx3kg5z4yqzq", "contract/lstolas/lst_staking_token_locked/0.1.0": "bafybeidw4povdmyzpszkzgnw6iv3w4gnbzboqq5dolxegjptcadv26lgyy", - "skill/lstolas/lst_skill/0.1.0": "bafybeidnr2ez26ahnpp224gyc24cis4oylxycpvklbfxjcygtpdnwkp42a", - "agent/lstolas/lst_agent/0.1.0": "bafybeiasu5mbpc6genaggcwzwekednfgut4cypu5kp6kje2utasgxrhfvu", - "agent/lstolas/lst_agent_prod/0.1.0": "bafybeifvc5iwrk4wgtagf4zgx2l54ydre2rg3i5tfywt2ltjohnicdpebu" + "skill/lstolas/lst_skill/0.1.0": "bafybeigpmounpcjgk2lppmtri56foqjwkr2xewnff6ssz3awqnecptgzdi", + "agent/lstolas/lst_agent/0.1.0": "bafybeigs56tnzbw66pnqgxbsju2s2opwlf5akdf3fageesbt6a65msyqwe", + "agent/lstolas/lst_agent_prod/0.1.0": "bafybeiekrzmcu2jgnw5p4yse4bokb6ihxjswhficxwox56mv7rphfqawxy" }, "third_party": { "protocol/open_aea/signing/1.0.0": "bafybeig2d36zxy65vd7fwhs7scotuktydcarm74aprmrb5nioiymr3yixm", diff --git a/poetry.lock b/poetry.lock index 099750a..803f23c 100644 --- a/poetry.lock +++ b/poetry.lock @@ -4281,14 +4281,14 @@ tests = ["hypothesis (>=3.27.0)", "pytest (>=3.2.1,!=3.3.0)"] [[package]] name = "pyright" -version = "1.1.405" +version = "1.1.407" description = "Command line wrapper for pyright" optional = false python-versions = ">=3.7" groups = ["dev"] files = [ - {file = "pyright-1.1.405-py3-none-any.whl", hash = "sha256:a2cb13700b5508ce8e5d4546034cb7ea4aedb60215c6c33f56cec7f53996035a"}, - {file = "pyright-1.1.405.tar.gz", hash = "sha256:5c2a30e1037af27eb463a1cc0b9f6d65fec48478ccf092c1ac28385a15c55763"}, + {file = "pyright-1.1.407-py3-none-any.whl", hash = "sha256:6dd419f54fcc13f03b52285796d65e639786373f433e243f8b94cf93a7444d21"}, + {file = "pyright-1.1.407.tar.gz", hash = "sha256:099674dba5c10489832d4a4b2d302636152a9a42d317986c38474c76fe562262"}, ] [package.dependencies]