From 6657bb229e68b5b1019519c1dbada7df9793bd91 Mon Sep 17 00:00:00 2001 From: claravanstaden Date: Wed, 7 Jan 2026 14:28:13 +0200 Subject: [PATCH 01/17] beefy client wrapper --- .../scripts/DeployBeefyClientWrapper.sol | 83 +++ contracts/src/BeefyClientWrapper.sol | 335 +++++++++ contracts/src/BeefyClientWrapperProxy.sol | 51 ++ contracts/src/interfaces/IBeefyClient.sol | 63 ++ contracts/test/BeefyClientWrapper.t.sol | 648 ++++++++++++++++++ 5 files changed, 1180 insertions(+) create mode 100644 contracts/scripts/DeployBeefyClientWrapper.sol create mode 100644 contracts/src/BeefyClientWrapper.sol create mode 100644 contracts/src/BeefyClientWrapperProxy.sol create mode 100644 contracts/src/interfaces/IBeefyClient.sol create mode 100644 contracts/test/BeefyClientWrapper.t.sol diff --git a/contracts/scripts/DeployBeefyClientWrapper.sol b/contracts/scripts/DeployBeefyClientWrapper.sol new file mode 100644 index 000000000..53a277e49 --- /dev/null +++ b/contracts/scripts/DeployBeefyClientWrapper.sol @@ -0,0 +1,83 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2023 Snowfork +pragma solidity 0.8.28; + +import {Script} from "forge-std/Script.sol"; +import {console} from "forge-std/console.sol"; +import {BeefyClientWrapper} from "../src/BeefyClientWrapper.sol"; +import {BeefyClientWrapperProxy} from "../src/BeefyClientWrapperProxy.sol"; + +contract DeployBeefyClientWrapper is Script { + struct Config { + address beefyClient; + address owner; + uint256 maxGasPrice; + uint256 gracePeriodBlocks; + uint256 minBlockIncrement; + } + + function readConfig() internal returns (Config memory config) { + config = Config({ + beefyClient: vm.envAddress("BEEFY_CLIENT_ADDRESS"), + owner: vm.envAddress("REFUND_PROXY_OWNER"), + maxGasPrice: vm.envOr("MAX_GAS_PRICE", uint256(100 gwei)), + gracePeriodBlocks: vm.envOr("GRACE_PERIOD_BLOCKS", uint256(10)), + minBlockIncrement: vm.envOr("MIN_BLOCK_INCREMENT", uint256(100)) + }); + } + + function run() public { + vm.startBroadcast(); + + Config memory config = readConfig(); + + BeefyClientWrapper implementation = new BeefyClientWrapper(); + + bytes memory initParams = abi.encode( + config.beefyClient, + config.owner, + config.maxGasPrice, + config.gracePeriodBlocks, + config.minBlockIncrement + ); + + BeefyClientWrapperProxy proxy = + new BeefyClientWrapperProxy(address(implementation), initParams); + + console.log("Implementation:", address(implementation)); + console.log("Proxy:", address(proxy)); + + vm.stopBroadcast(); + } + + function runWithRelayers(address[] calldata relayers) public { + vm.startBroadcast(); + + Config memory config = readConfig(); + + BeefyClientWrapper implementation = new BeefyClientWrapper(); + + bytes memory initParams = abi.encode( + config.beefyClient, + config.owner, + config.maxGasPrice, + config.gracePeriodBlocks, + config.minBlockIncrement + ); + + BeefyClientWrapperProxy proxy = + new BeefyClientWrapperProxy(address(implementation), initParams); + + BeefyClientWrapper refund = BeefyClientWrapper(payable(address(proxy))); + + for (uint256 i = 0; i < relayers.length; i++) { + refund.addRelayer(relayers[i]); + } + + console.log("Implementation:", address(implementation)); + console.log("Proxy:", address(proxy)); + console.log("Relayers added:", relayers.length); + + vm.stopBroadcast(); + } +} diff --git a/contracts/src/BeefyClientWrapper.sol b/contracts/src/BeefyClientWrapper.sol new file mode 100644 index 000000000..b1e1696fb --- /dev/null +++ b/contracts/src/BeefyClientWrapper.sol @@ -0,0 +1,335 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2023 Snowfork +pragma solidity 0.8.28; + +import {IBeefyClient} from "./interfaces/IBeefyClient.sol"; +import {IInitializable} from "./interfaces/IInitializable.sol"; +import {IUpgradable} from "./interfaces/IUpgradable.sol"; +import {ERC1967} from "./utils/ERC1967.sol"; + +/** + * @title BeefyClientWrapper + * @dev Forwards BeefyClient submissions and refunds gas costs to whitelisted relayers. + * Implements soft round-robin scheduling to prevent competition. + */ +contract BeefyClientWrapper is IInitializable, IUpgradable { + event RelayerAdded(address indexed relayer); + event RelayerRemoved(address indexed relayer); + event SubmissionRefunded(address indexed relayer, uint256 amount, uint256 gasUsed); + event TurnAdvanced(uint256 indexed newTurnIndex, address indexed nextRelayer); + event FundsDeposited(address indexed depositor, uint256 amount); + event FundsWithdrawn(address indexed recipient, uint256 amount); + event ConfigUpdated(string parameter, uint256 value); + + error Unauthorized(); + error NotARelayer(); + error NotYourTurn(); + error InsufficientBlockIncrement(); + error RelayerAlreadyExists(); + error RelayerNotFound(); + error NoRelayers(); + error InvalidAddress(); + error InvalidTicket(); + error NotTicketOwner(); + error TransferFailed(); + error AlreadyInitialized(); + error TicketAlreadyActive(); + + address public owner; + IBeefyClient public beefyClient; + uint256 public maxGasPrice; + address[] public relayers; + mapping(address => bool) public isRelayer; + mapping(address => uint256) private relayerIndex; + uint256 public currentTurnIndex; + uint256 public lastSubmissionBlock; + uint256 public gracePeriodBlocks; + uint256 public minBlockIncrement; + mapping(bytes32 => address) public ticketOwner; + mapping(address => bytes32) public activeTicket; + bool private initialized; + + function initialize(bytes calldata data) external override { + if (initialized) { + revert AlreadyInitialized(); + } + initialized = true; + + ( + address _beefyClient, + address _owner, + uint256 _maxGasPrice, + uint256 _gracePeriodBlocks, + uint256 _minBlockIncrement + ) = abi.decode(data, (address, address, uint256, uint256, uint256)); + + if (_beefyClient == address(0) || _owner == address(0)) { + revert InvalidAddress(); + } + + beefyClient = IBeefyClient(_beefyClient); + owner = _owner; + maxGasPrice = _maxGasPrice; + gracePeriodBlocks = _gracePeriodBlocks; + minBlockIncrement = _minBlockIncrement; + } + + /* Beefy Client Proxy Functions */ + + function submitInitial( + IBeefyClient.Commitment calldata commitment, + uint256[] calldata bitfield, + IBeefyClient.ValidatorProof calldata proof + ) external { + _checkEligibleRelayer(); + if (activeTicket[msg.sender] != bytes32(0)) { + revert TicketAlreadyActive(); + } + uint256 startGas = gasleft(); + + uint64 latestBlock = beefyClient.latestBeefyBlock(); + if (commitment.blockNumber < latestBlock + minBlockIncrement) { + revert InsufficientBlockIncrement(); + } + + beefyClient.submitInitial(commitment, bitfield, proof); + + bytes32 commitmentHash = keccak256(abi.encode(commitment)); + ticketOwner[commitmentHash] = msg.sender; + activeTicket[msg.sender] = commitmentHash; + + _refundGas(startGas); + } + + function commitPrevRandao(bytes32 commitmentHash) external { + uint256 startGas = gasleft(); + + if (ticketOwner[commitmentHash] != msg.sender) { + revert NotTicketOwner(); + } + + beefyClient.commitPrevRandao(commitmentHash); + + _refundGas(startGas); + } + + function submitFinal( + IBeefyClient.Commitment calldata commitment, + uint256[] calldata bitfield, + IBeefyClient.ValidatorProof[] calldata proofs, + IBeefyClient.MMRLeaf calldata leaf, + bytes32[] calldata leafProof, + uint256 leafProofOrder + ) external { + uint256 startGas = gasleft(); + + bytes32 commitmentHash = keccak256(abi.encode(commitment)); + if (ticketOwner[commitmentHash] != msg.sender) { + revert NotTicketOwner(); + } + + beefyClient.submitFinal(commitment, bitfield, proofs, leaf, leafProof, leafProofOrder); + + delete ticketOwner[commitmentHash]; + delete activeTicket[msg.sender]; + _advanceTurn(); + _refundGas(startGas); + } + + function createFinalBitfield(bytes32 commitmentHash, uint256[] calldata bitfield) + external + view + returns (uint256[] memory) + { + return beefyClient.createFinalBitfield(commitmentHash, bitfield); + } + + function latestBeefyBlock() external view returns (uint64) { + return beefyClient.latestBeefyBlock(); + } + + function clearTicket() external { + bytes32 commitmentHash = activeTicket[msg.sender]; + if (commitmentHash == bytes32(0)) { + revert InvalidTicket(); + } + + delete ticketOwner[commitmentHash]; + delete activeTicket[msg.sender]; + } + + /* Internal Functions */ + + function _checkOwner() internal view { + if (msg.sender != owner) { + revert Unauthorized(); + } + } + + function _checkEligibleRelayer() internal view { + if (!isRelayer[msg.sender]) { + revert NotARelayer(); + } + + if (relayers.length > 0) { + address assignedRelayer = relayers[currentTurnIndex % relayers.length]; + bool isAssignedRelayer = (msg.sender == assignedRelayer); + bool gracePeriodActive = block.number > lastSubmissionBlock + gracePeriodBlocks; + + if (!isAssignedRelayer && !gracePeriodActive) { + revert NotYourTurn(); + } + } + } + + function _refundGas(uint256 startGas) internal { + uint256 gasUsed = startGas - gasleft() + 21000; + uint256 effectiveGasPrice = tx.gasprice < maxGasPrice ? tx.gasprice : maxGasPrice; + uint256 refundAmount = gasUsed * effectiveGasPrice; + + if (address(this).balance >= refundAmount) { + (bool success,) = payable(msg.sender).call{value: refundAmount}(""); + if (success) { + emit SubmissionRefunded(msg.sender, refundAmount, gasUsed); + } + } + } + + function _advanceTurn() internal { + currentTurnIndex++; + lastSubmissionBlock = block.number; + + if (relayers.length > 0) { + address nextRelayer = relayers[currentTurnIndex % relayers.length]; + emit TurnAdvanced(currentTurnIndex, nextRelayer); + } + } + + /* Admin Functions */ + + function addRelayer(address relayer) external { + _checkOwner(); + if (relayer == address(0)) { + revert InvalidAddress(); + } + if (isRelayer[relayer]) { + revert RelayerAlreadyExists(); + } + + relayerIndex[relayer] = relayers.length; + relayers.push(relayer); + isRelayer[relayer] = true; + + emit RelayerAdded(relayer); + } + + function removeRelayer(address relayer) external { + _checkOwner(); + if (!isRelayer[relayer]) { + revert RelayerNotFound(); + } + + uint256 indexToRemove = relayerIndex[relayer]; + uint256 lastIndex = relayers.length - 1; + + if (indexToRemove != lastIndex) { + address lastRelayer = relayers[lastIndex]; + relayers[indexToRemove] = lastRelayer; + relayerIndex[lastRelayer] = indexToRemove; + } + + relayers.pop(); + delete isRelayer[relayer]; + delete relayerIndex[relayer]; + + emit RelayerRemoved(relayer); + } + + function setMaxGasPrice(uint256 _maxGasPrice) external { + _checkOwner(); + maxGasPrice = _maxGasPrice; + emit ConfigUpdated("maxGasPrice", _maxGasPrice); + } + + function setGracePeriod(uint256 _gracePeriodBlocks) external { + _checkOwner(); + gracePeriodBlocks = _gracePeriodBlocks; + emit ConfigUpdated("gracePeriodBlocks", _gracePeriodBlocks); + } + + function setMinBlockIncrement(uint256 _minBlockIncrement) external { + _checkOwner(); + minBlockIncrement = _minBlockIncrement; + emit ConfigUpdated("minBlockIncrement", _minBlockIncrement); + } + + function withdrawFunds(address payable recipient, uint256 amount) external { + _checkOwner(); + if (recipient == address(0)) { + revert InvalidAddress(); + } + + (bool success,) = recipient.call{value: amount}(""); + if (!success) { + revert TransferFailed(); + } + + emit FundsWithdrawn(recipient, amount); + } + + function transferOwnership(address newOwner) external { + _checkOwner(); + if (newOwner == address(0)) { + revert InvalidAddress(); + } + owner = newOwner; + } + + /* Upgrade Functions */ + + function upgradeTo(address newImplementation, bytes32 expectedCodeHash) external { + _checkOwner(); + if (newImplementation.code.length == 0) { + revert InvalidContract(); + } + if (newImplementation.codehash != expectedCodeHash) { + revert InvalidCodeHash(); + } + + ERC1967.store(newImplementation); + emit Upgraded(newImplementation); + } + + function implementation() external view override returns (address) { + return ERC1967.load(); + } + + /* View Functions */ + + function getCurrentTurnRelayer() external view returns (address) { + if (relayers.length == 0) { + return address(0); + } + return relayers[currentTurnIndex % relayers.length]; + } + + function isGracePeriodActive() external view returns (bool) { + return block.number > lastSubmissionBlock + gracePeriodBlocks; + } + + function getRelayers() external view returns (address[] memory) { + return relayers; + } + + function getRelayerCount() external view returns (uint256) { + return relayers.length; + } + + function getBalance() external view returns (uint256) { + return address(this).balance; + } + + receive() external payable { + emit FundsDeposited(msg.sender, msg.value); + } +} diff --git a/contracts/src/BeefyClientWrapperProxy.sol b/contracts/src/BeefyClientWrapperProxy.sol new file mode 100644 index 000000000..b6be6ac3e --- /dev/null +++ b/contracts/src/BeefyClientWrapperProxy.sol @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2023 Snowfork +pragma solidity 0.8.28; + +import {ERC1967} from "./utils/ERC1967.sol"; +import {Call} from "./utils/Call.sol"; +import {IInitializable} from "./interfaces/IInitializable.sol"; + +contract BeefyClientWrapperProxy is IInitializable { + error Unauthorized(); + + constructor(address implementation, bytes memory params) { + // Store the address of the implementation contract + ERC1967.store(implementation); + // Initialize storage by calling the implementation's `initialize(bytes)` function + // using `delegatecall`. + (bool success, bytes memory returndata) = + implementation.delegatecall(abi.encodeCall(IInitializable.initialize, params)); + Call.verifyResult(success, returndata); + } + + // Prevent fallback() from calling `IInitializable.initialize(bytes)` on the implementation + // contract + function initialize(bytes calldata) external pure { + revert Unauthorized(); + } + + fallback() external payable { + address implementation = ERC1967.load(); + assembly { + calldatacopy(0, 0, calldatasize()) + let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0) + returndatacopy(0, 0, returndatasize()) + switch result + case 0 { revert(0, returndatasize()) } + default { return(0, returndatasize()) } + } + } + + // Accept ETH deposits to fund relayer refunds + receive() external payable { + address implementation = ERC1967.load(); + assembly { + let result := delegatecall(gas(), implementation, 0, 0, 0, 0) + returndatacopy(0, 0, returndatasize()) + switch result + case 0 { revert(0, returndatasize()) } + default { return(0, returndatasize()) } + } + } +} diff --git a/contracts/src/interfaces/IBeefyClient.sol b/contracts/src/interfaces/IBeefyClient.sol new file mode 100644 index 000000000..b71e4e966 --- /dev/null +++ b/contracts/src/interfaces/IBeefyClient.sol @@ -0,0 +1,63 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2023 Snowfork +pragma solidity 0.8.28; + +interface IBeefyClient { + /* Types */ + + struct PayloadItem { + bytes2 payloadID; + bytes data; + } + + struct Commitment { + uint32 blockNumber; + uint64 validatorSetID; + PayloadItem[] payload; + } + + struct ValidatorProof { + uint8 v; + bytes32 r; + bytes32 s; + uint256 index; + address account; + bytes32[] proof; + } + + struct MMRLeaf { + uint8 version; + uint32 parentNumber; + bytes32 parentHash; + uint64 nextAuthoritySetID; + uint32 nextAuthoritySetLen; + bytes32 nextAuthoritySetRoot; + bytes32 parachainHeadsRoot; + } + + function latestBeefyBlock() external view returns (uint64); + + function latestMMRRoot() external view returns (bytes32); + + function submitInitial( + Commitment calldata commitment, + uint256[] calldata bitfield, + ValidatorProof calldata proof + ) external; + + function commitPrevRandao(bytes32 commitmentHash) external; + + function submitFinal( + Commitment calldata commitment, + uint256[] calldata bitfield, + ValidatorProof[] calldata proofs, + MMRLeaf calldata leaf, + bytes32[] calldata leafProof, + uint256 leafProofOrder + ) external; + + function createFinalBitfield(bytes32 commitmentHash, uint256[] calldata bitfield) + external + view + returns (uint256[] memory); +} diff --git a/contracts/test/BeefyClientWrapper.t.sol b/contracts/test/BeefyClientWrapper.t.sol new file mode 100644 index 000000000..1125b1184 --- /dev/null +++ b/contracts/test/BeefyClientWrapper.t.sol @@ -0,0 +1,648 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity 0.8.28; + +import {Test} from "forge-std/Test.sol"; +import {console} from "forge-std/console.sol"; + +import {BeefyClientWrapper} from "../src/BeefyClientWrapper.sol"; +import {BeefyClientWrapperProxy} from "../src/BeefyClientWrapperProxy.sol"; +import {IBeefyClient} from "../src/interfaces/IBeefyClient.sol"; +import {IUpgradable} from "../src/interfaces/IUpgradable.sol"; + +/** + * @title MockBeefyClient + * @dev A simplified mock of BeefyClient for testing the refund proxy + */ +contract MockBeefyClient { + uint64 public latestBeefyBlock; + bytes32 public latestMMRRoot; + + // Track submissions for verification + uint256 public submitInitialCount; + uint256 public commitPrevRandaoCount; + uint256 public submitFinalCount; + + mapping(bytes32 => bool) public ticketExists; + + constructor(uint64 _initialBeefyBlock) { + latestBeefyBlock = _initialBeefyBlock; + } + + function submitInitial( + IBeefyClient.Commitment calldata commitment, + uint256[] calldata, + IBeefyClient.ValidatorProof calldata + ) external { + // Just track that it was called and create a ticket + submitInitialCount++; + bytes32 commitmentHash = keccak256(abi.encode(commitment)); + ticketExists[commitmentHash] = true; + } + + function commitPrevRandao(bytes32 commitmentHash) external { + require(ticketExists[commitmentHash], "No ticket"); + commitPrevRandaoCount++; + } + + function submitFinal( + IBeefyClient.Commitment calldata commitment, + uint256[] calldata, + IBeefyClient.ValidatorProof[] calldata, + IBeefyClient.MMRLeaf calldata, + bytes32[] calldata, + uint256 + ) external { + bytes32 commitmentHash = keccak256(abi.encode(commitment)); + require(ticketExists[commitmentHash], "No ticket"); + submitFinalCount++; + delete ticketExists[commitmentHash]; + + // Update latest beefy block + latestBeefyBlock = commitment.blockNumber; + } + + function createFinalBitfield(bytes32, uint256[] calldata bitfield) + external + pure + returns (uint256[] memory) + { + return bitfield; + } + + function setLatestBeefyBlock(uint64 _block) external { + latestBeefyBlock = _block; + } +} + +contract BeefyClientWrapperTest is Test { + BeefyClientWrapper implementation; + BeefyClientWrapperProxy proxy; + BeefyClientWrapper wrapper; + MockBeefyClient mockBeefyClient; + + address owner = address(0x1); + address relayer1 = address(0x2); + address relayer2 = address(0x3); + address relayer3 = address(0x4); + address nonRelayer = address(0x5); + + uint256 constant MAX_GAS_PRICE = 100 gwei; + uint256 constant GRACE_PERIOD_BLOCKS = 10; + uint256 constant MIN_BLOCK_INCREMENT = 100; + uint256 constant INITIAL_BEEFY_BLOCK = 1000; + + function setUp() public { + // Deploy mock BeefyClient + mockBeefyClient = new MockBeefyClient(uint64(INITIAL_BEEFY_BLOCK)); + + // Deploy implementation + implementation = new BeefyClientWrapper(); + + // Encode initialization parameters + bytes memory initParams = abi.encode( + address(mockBeefyClient), + owner, + MAX_GAS_PRICE, + GRACE_PERIOD_BLOCKS, + MIN_BLOCK_INCREMENT + ); + + // Deploy proxy + proxy = new BeefyClientWrapperProxy(address(implementation), initParams); + + // Get interface to proxy + wrapper = BeefyClientWrapper(payable(address(proxy))); + + // Fund the proxy with ETH for refunds + vm.deal(address(proxy), 100 ether); + + // Add relayers + vm.startPrank(owner); + wrapper.addRelayer(relayer1); + wrapper.addRelayer(relayer2); + wrapper.addRelayer(relayer3); + vm.stopPrank(); + } + + /* Helper Functions */ + + function createCommitment(uint32 blockNumber) internal pure returns (IBeefyClient.Commitment memory) { + IBeefyClient.PayloadItem[] memory payload = new IBeefyClient.PayloadItem[](1); + payload[0] = IBeefyClient.PayloadItem(bytes2("mh"), abi.encodePacked(bytes32(0))); + return IBeefyClient.Commitment(blockNumber, 1, payload); + } + + function createValidatorProof() internal pure returns (IBeefyClient.ValidatorProof memory) { + bytes32[] memory proof = new bytes32[](0); + return IBeefyClient.ValidatorProof(27, bytes32(0), bytes32(0), 0, address(0), proof); + } + + function createValidatorProofs(uint256 count) internal pure returns (IBeefyClient.ValidatorProof[] memory) { + IBeefyClient.ValidatorProof[] memory proofs = new IBeefyClient.ValidatorProof[](count); + for (uint256 i = 0; i < count; i++) { + bytes32[] memory proof = new bytes32[](0); + proofs[i] = IBeefyClient.ValidatorProof(27, bytes32(0), bytes32(0), i, address(0), proof); + } + return proofs; + } + + function createMMRLeaf() internal pure returns (IBeefyClient.MMRLeaf memory) { + return IBeefyClient.MMRLeaf(1, 0, bytes32(0), 1, 100, bytes32(0), bytes32(0)); + } + + /* Initialization Tests */ + + function test_initialization() public { + assertEq(wrapper.owner(), owner); + assertEq(address(wrapper.beefyClient()), address(mockBeefyClient)); + assertEq(wrapper.maxGasPrice(), MAX_GAS_PRICE); + assertEq(wrapper.gracePeriodBlocks(), GRACE_PERIOD_BLOCKS); + assertEq(wrapper.minBlockIncrement(), MIN_BLOCK_INCREMENT); + } + + function test_cannotReinitialize() public { + bytes memory initParams = abi.encode( + address(mockBeefyClient), + owner, + MAX_GAS_PRICE, + GRACE_PERIOD_BLOCKS, + MIN_BLOCK_INCREMENT + ); + + // The proxy blocks initialize() calls with Unauthorized() error + // This prevents reinitialization attempts through the proxy + vm.expectRevert(BeefyClientWrapperProxy.Unauthorized.selector); + wrapper.initialize(initParams); + } + + /* Relayer Management Tests */ + + function test_addRelayer() public { + address newRelayer = address(0x100); + + vm.prank(owner); + wrapper.addRelayer(newRelayer); + + assertTrue(wrapper.isRelayer(newRelayer)); + assertEq(wrapper.getRelayerCount(), 4); + } + + function test_addRelayer_onlyOwner() public { + vm.prank(nonRelayer); + vm.expectRevert(BeefyClientWrapper.Unauthorized.selector); + wrapper.addRelayer(address(0x100)); + } + + function test_addRelayer_alreadyExists() public { + vm.prank(owner); + vm.expectRevert(BeefyClientWrapper.RelayerAlreadyExists.selector); + wrapper.addRelayer(relayer1); + } + + function test_removeRelayer() public { + vm.prank(owner); + wrapper.removeRelayer(relayer2); + + assertFalse(wrapper.isRelayer(relayer2)); + assertEq(wrapper.getRelayerCount(), 2); + } + + function test_removeRelayer_notFound() public { + vm.prank(owner); + vm.expectRevert(BeefyClientWrapper.RelayerNotFound.selector); + wrapper.removeRelayer(nonRelayer); + } + + /* Round-Robin Tests */ + + function test_getCurrentTurnRelayer() public { + address currentRelayer = wrapper.getCurrentTurnRelayer(); + assertEq(currentRelayer, relayer1); // First relayer at index 0 + } + + function test_onlyAssignedRelayerCanSubmit() public { + uint32 newBlockNumber = uint32(INITIAL_BEEFY_BLOCK + MIN_BLOCK_INCREMENT + 1); + IBeefyClient.Commitment memory commitment = createCommitment(newBlockNumber); + uint256[] memory bitfield = new uint256[](1); + IBeefyClient.ValidatorProof memory proof = createValidatorProof(); + + // relayer2 is not the assigned relayer (relayer1 is) + vm.prank(relayer2); + vm.expectRevert(BeefyClientWrapper.NotYourTurn.selector); + wrapper.submitInitial(commitment, bitfield, proof); + } + + function test_gracePeriodAllowsAnyRelayer() public { + // Advance past grace period + vm.roll(block.number + GRACE_PERIOD_BLOCKS + 1); + + uint32 newBlockNumber = uint32(INITIAL_BEEFY_BLOCK + MIN_BLOCK_INCREMENT + 1); + IBeefyClient.Commitment memory commitment = createCommitment(newBlockNumber); + uint256[] memory bitfield = new uint256[](1); + IBeefyClient.ValidatorProof memory proof = createValidatorProof(); + + // relayer2 can submit during grace period + vm.prank(relayer2); + wrapper.submitInitial(commitment, bitfield, proof); + + assertEq(mockBeefyClient.submitInitialCount(), 1); + } + + function test_isGracePeriodActive() public { + assertFalse(wrapper.isGracePeriodActive()); + + vm.roll(block.number + GRACE_PERIOD_BLOCKS + 1); + assertTrue(wrapper.isGracePeriodActive()); + } + + /* Submission Flow Tests */ + + function test_fullSubmissionFlow() public { + uint32 newBlockNumber = uint32(INITIAL_BEEFY_BLOCK + MIN_BLOCK_INCREMENT + 1); + IBeefyClient.Commitment memory commitment = createCommitment(newBlockNumber); + uint256[] memory bitfield = new uint256[](1); + IBeefyClient.ValidatorProof memory proof = createValidatorProof(); + IBeefyClient.ValidatorProof[] memory proofs = createValidatorProofs(1); + IBeefyClient.MMRLeaf memory leaf = createMMRLeaf(); + bytes32[] memory leafProof = new bytes32[](0); + + // Step 1: submitInitial + vm.prank(relayer1); + wrapper.submitInitial(commitment, bitfield, proof); + assertEq(mockBeefyClient.submitInitialCount(), 1); + + // Step 2: commitPrevRandao + bytes32 commitmentHash = keccak256(abi.encode(commitment)); + vm.prank(relayer1); + wrapper.commitPrevRandao(commitmentHash); + assertEq(mockBeefyClient.commitPrevRandaoCount(), 1); + + // Step 3: submitFinal + vm.prank(relayer1); + wrapper.submitFinal(commitment, bitfield, proofs, leaf, leafProof, 0); + assertEq(mockBeefyClient.submitFinalCount(), 1); + + // Verify turn advanced + assertEq(wrapper.currentTurnIndex(), 1); + assertEq(wrapper.getCurrentTurnRelayer(), relayer2); + } + + function test_onlyTicketOwnerCanCommitPrevRandao() public { + uint32 newBlockNumber = uint32(INITIAL_BEEFY_BLOCK + MIN_BLOCK_INCREMENT + 1); + IBeefyClient.Commitment memory commitment = createCommitment(newBlockNumber); + uint256[] memory bitfield = new uint256[](1); + IBeefyClient.ValidatorProof memory proof = createValidatorProof(); + + // relayer1 submits initial + vm.prank(relayer1); + wrapper.submitInitial(commitment, bitfield, proof); + + // relayer2 tries to commit (should fail) + bytes32 commitmentHash = keccak256(abi.encode(commitment)); + vm.prank(relayer2); + vm.expectRevert(BeefyClientWrapper.NotTicketOwner.selector); + wrapper.commitPrevRandao(commitmentHash); + } + + function test_onlyTicketOwnerCanSubmitFinal() public { + uint32 newBlockNumber = uint32(INITIAL_BEEFY_BLOCK + MIN_BLOCK_INCREMENT + 1); + IBeefyClient.Commitment memory commitment = createCommitment(newBlockNumber); + uint256[] memory bitfield = new uint256[](1); + IBeefyClient.ValidatorProof memory proof = createValidatorProof(); + IBeefyClient.ValidatorProof[] memory proofs = createValidatorProofs(1); + IBeefyClient.MMRLeaf memory leaf = createMMRLeaf(); + bytes32[] memory leafProof = new bytes32[](0); + + // relayer1 submits initial and commits + vm.startPrank(relayer1); + wrapper.submitInitial(commitment, bitfield, proof); + bytes32 commitmentHash = keccak256(abi.encode(commitment)); + wrapper.commitPrevRandao(commitmentHash); + vm.stopPrank(); + + // relayer2 tries to submit final (should fail) + vm.prank(relayer2); + vm.expectRevert(BeefyClientWrapper.NotTicketOwner.selector); + wrapper.submitFinal(commitment, bitfield, proofs, leaf, leafProof, 0); + } + + /* Anti-Spam Tests */ + + function test_minBlockIncrementEnforced() public { + // Try to submit with insufficient block increment + uint32 newBlockNumber = uint32(INITIAL_BEEFY_BLOCK + MIN_BLOCK_INCREMENT - 1); + IBeefyClient.Commitment memory commitment = createCommitment(newBlockNumber); + uint256[] memory bitfield = new uint256[](1); + IBeefyClient.ValidatorProof memory proof = createValidatorProof(); + + vm.prank(relayer1); + vm.expectRevert(BeefyClientWrapper.InsufficientBlockIncrement.selector); + wrapper.submitInitial(commitment, bitfield, proof); + } + + function test_validBlockIncrementSucceeds() public { + uint32 newBlockNumber = uint32(INITIAL_BEEFY_BLOCK + MIN_BLOCK_INCREMENT); + IBeefyClient.Commitment memory commitment = createCommitment(newBlockNumber); + uint256[] memory bitfield = new uint256[](1); + IBeefyClient.ValidatorProof memory proof = createValidatorProof(); + + vm.prank(relayer1); + wrapper.submitInitial(commitment, bitfield, proof); + + assertEq(mockBeefyClient.submitInitialCount(), 1); + } + + /* Refund Tests */ + + function test_refundsSentOnSubmission() public { + uint32 newBlockNumber = uint32(INITIAL_BEEFY_BLOCK + MIN_BLOCK_INCREMENT + 1); + IBeefyClient.Commitment memory commitment = createCommitment(newBlockNumber); + uint256[] memory bitfield = new uint256[](1); + IBeefyClient.ValidatorProof memory proof = createValidatorProof(); + + uint256 relayerBalanceBefore = relayer1.balance; + + vm.prank(relayer1); + vm.txGasPrice(50 gwei); + wrapper.submitInitial(commitment, bitfield, proof); + + // Relayer should have received a refund + assertGt(relayer1.balance, relayerBalanceBefore); + } + + function test_refundCappedAtMaxGasPrice() public { + uint32 newBlockNumber = uint32(INITIAL_BEEFY_BLOCK + MIN_BLOCK_INCREMENT + 1); + IBeefyClient.Commitment memory commitment = createCommitment(newBlockNumber); + uint256[] memory bitfield = new uint256[](1); + IBeefyClient.ValidatorProof memory proof = createValidatorProof(); + + uint256 relayerBalanceBefore = relayer1.balance; + uint256 proxyBalanceBefore = address(proxy).balance; + + // Use gas price higher than max + vm.prank(relayer1); + vm.txGasPrice(200 gwei); // Higher than MAX_GAS_PRICE (100 gwei) + wrapper.submitInitial(commitment, bitfield, proof); + + uint256 refundAmount = relayer1.balance - relayerBalanceBefore; + uint256 proxySpent = proxyBalanceBefore - address(proxy).balance; + + // Refund should be based on maxGasPrice, not actual tx.gasprice + assertEq(refundAmount, proxySpent); + } + + function test_noRefundWhenInsufficientBalance() public { + // Drain wrapper balance + vm.prank(owner); + wrapper.withdrawFunds(payable(owner), address(proxy).balance); + + uint32 newBlockNumber = uint32(INITIAL_BEEFY_BLOCK + MIN_BLOCK_INCREMENT + 1); + IBeefyClient.Commitment memory commitment = createCommitment(newBlockNumber); + uint256[] memory bitfield = new uint256[](1); + IBeefyClient.ValidatorProof memory proof = createValidatorProof(); + + uint256 relayerBalanceBefore = relayer1.balance; + + // Submission should still succeed, just no refund + vm.prank(relayer1); + wrapper.submitInitial(commitment, bitfield, proof); + + assertEq(relayer1.balance, relayerBalanceBefore); // No refund + assertEq(mockBeefyClient.submitInitialCount(), 1); // But submission succeeded + } + + /* Admin Function Tests */ + + function test_setMaxGasPrice() public { + vm.prank(owner); + wrapper.setMaxGasPrice(200 gwei); + + assertEq(wrapper.maxGasPrice(), 200 gwei); + } + + function test_setGracePeriod() public { + vm.prank(owner); + wrapper.setGracePeriod(20); + + assertEq(wrapper.gracePeriodBlocks(), 20); + } + + function test_setMinBlockIncrement() public { + vm.prank(owner); + wrapper.setMinBlockIncrement(200); + + assertEq(wrapper.minBlockIncrement(), 200); + } + + function test_withdrawFunds() public { + uint256 ownerBalanceBefore = owner.balance; + uint256 withdrawAmount = 10 ether; + + vm.prank(owner); + wrapper.withdrawFunds(payable(owner), withdrawAmount); + + assertEq(owner.balance, ownerBalanceBefore + withdrawAmount); + } + + function test_transferOwnership() public { + address newOwner = address(0x999); + + vm.prank(owner); + wrapper.transferOwnership(newOwner); + + assertEq(wrapper.owner(), newOwner); + } + + function test_adminFunctions_onlyOwner() public { + vm.startPrank(nonRelayer); + + vm.expectRevert(BeefyClientWrapper.Unauthorized.selector); + wrapper.setMaxGasPrice(1); + + vm.expectRevert(BeefyClientWrapper.Unauthorized.selector); + wrapper.setGracePeriod(1); + + vm.expectRevert(BeefyClientWrapper.Unauthorized.selector); + wrapper.setMinBlockIncrement(1); + + vm.expectRevert(BeefyClientWrapper.Unauthorized.selector); + wrapper.withdrawFunds(payable(nonRelayer), 1); + + vm.expectRevert(BeefyClientWrapper.Unauthorized.selector); + wrapper.transferOwnership(nonRelayer); + + vm.stopPrank(); + } + + /* Deposit Tests */ + + function test_acceptsDeposits() public { + uint256 balanceBefore = address(proxy).balance; + + vm.deal(address(this), 1 ether); + (bool success,) = address(proxy).call{value: 1 ether}(""); + + assertTrue(success); + assertEq(address(proxy).balance, balanceBefore + 1 ether); + } + + /* Non-Relayer Tests */ + + function test_nonRelayerCannotSubmit() public { + uint32 newBlockNumber = uint32(INITIAL_BEEFY_BLOCK + MIN_BLOCK_INCREMENT + 1); + IBeefyClient.Commitment memory commitment = createCommitment(newBlockNumber); + uint256[] memory bitfield = new uint256[](1); + IBeefyClient.ValidatorProof memory proof = createValidatorProof(); + + vm.prank(nonRelayer); + vm.expectRevert(BeefyClientWrapper.NotARelayer.selector); + wrapper.submitInitial(commitment, bitfield, proof); + } + + /* View Function Tests */ + + function test_getRelayers() public { + address[] memory allRelayers = wrapper.getRelayers(); + assertEq(allRelayers.length, 3); + assertEq(allRelayers[0], relayer1); + assertEq(allRelayers[1], relayer2); + assertEq(allRelayers[2], relayer3); + } + + function test_getBalance() public { + assertEq(wrapper.getBalance(), 100 ether); + } + + /* Upgrade Tests */ + + function test_implementation() public { + assertEq(wrapper.implementation(), address(implementation)); + } + + function test_upgradeTo() public { + BeefyClientWrapper newImpl = new BeefyClientWrapper(); + + vm.prank(owner); + wrapper.upgradeTo(address(newImpl), address(newImpl).codehash); + + assertEq(wrapper.implementation(), address(newImpl)); + } + + function test_upgradeTo_invalidContract() public { + vm.prank(owner); + vm.expectRevert(IUpgradable.InvalidContract.selector); + wrapper.upgradeTo(address(0x123), bytes32(0)); + } + + function test_upgradeTo_invalidCodeHash() public { + BeefyClientWrapper newImpl = new BeefyClientWrapper(); + + vm.prank(owner); + vm.expectRevert(IUpgradable.InvalidCodeHash.selector); + wrapper.upgradeTo(address(newImpl), bytes32(uint256(0x123))); + } + + /* One Ticket Per Relayer Tests */ + + function test_cannotSubmitSecondTicketWhileActive() public { + uint32 newBlockNumber = uint32(INITIAL_BEEFY_BLOCK + MIN_BLOCK_INCREMENT + 1); + IBeefyClient.Commitment memory commitment1 = createCommitment(newBlockNumber); + uint256[] memory bitfield = new uint256[](1); + IBeefyClient.ValidatorProof memory proof = createValidatorProof(); + + // relayer1 submits first ticket + vm.prank(relayer1); + wrapper.submitInitial(commitment1, bitfield, proof); + + // Update mock to allow another submission + mockBeefyClient.setLatestBeefyBlock(uint64(newBlockNumber)); + + // relayer1 tries to submit second ticket (should fail) + uint32 newBlockNumber2 = uint32(newBlockNumber + MIN_BLOCK_INCREMENT + 1); + IBeefyClient.Commitment memory commitment2 = createCommitment(newBlockNumber2); + + vm.prank(relayer1); + vm.expectRevert(BeefyClientWrapper.TicketAlreadyActive.selector); + wrapper.submitInitial(commitment2, bitfield, proof); + } + + function test_clearTicketAllowsNewSubmission() public { + uint32 newBlockNumber = uint32(INITIAL_BEEFY_BLOCK + MIN_BLOCK_INCREMENT + 1); + IBeefyClient.Commitment memory commitment1 = createCommitment(newBlockNumber); + uint256[] memory bitfield = new uint256[](1); + IBeefyClient.ValidatorProof memory proof = createValidatorProof(); + + // relayer1 submits first ticket + vm.prank(relayer1); + wrapper.submitInitial(commitment1, bitfield, proof); + + // relayer1 clears their ticket + vm.prank(relayer1); + wrapper.clearTicket(); + + // Now relayer1 can submit again + uint32 newBlockNumber2 = uint32(newBlockNumber + 1); + IBeefyClient.Commitment memory commitment2 = createCommitment(newBlockNumber2); + + vm.prank(relayer1); + wrapper.submitInitial(commitment2, bitfield, proof); + + assertEq(mockBeefyClient.submitInitialCount(), 2); + } + + function test_clearTicketRevertsIfNoActiveTicket() public { + vm.prank(relayer1); + vm.expectRevert(BeefyClientWrapper.InvalidTicket.selector); + wrapper.clearTicket(); + } + + function test_submitFinalClearsActiveTicket() public { + uint32 newBlockNumber = uint32(INITIAL_BEEFY_BLOCK + MIN_BLOCK_INCREMENT + 1); + IBeefyClient.Commitment memory commitment = createCommitment(newBlockNumber); + uint256[] memory bitfield = new uint256[](1); + IBeefyClient.ValidatorProof memory proof = createValidatorProof(); + IBeefyClient.ValidatorProof[] memory proofs = createValidatorProofs(1); + IBeefyClient.MMRLeaf memory leaf = createMMRLeaf(); + bytes32[] memory leafProof = new bytes32[](0); + + // Complete full flow + vm.startPrank(relayer1); + wrapper.submitInitial(commitment, bitfield, proof); + + bytes32 commitmentHash = keccak256(abi.encode(commitment)); + wrapper.commitPrevRandao(commitmentHash); + wrapper.submitFinal(commitment, bitfield, proofs, leaf, leafProof, 0); + vm.stopPrank(); + + // Verify activeTicket is cleared + assertEq(wrapper.activeTicket(relayer1), bytes32(0)); + + // relayer1 can now submit again (it's relayer2's turn, so advance grace period) + vm.roll(block.number + GRACE_PERIOD_BLOCKS + 1); + + uint32 newBlockNumber2 = uint32(newBlockNumber + MIN_BLOCK_INCREMENT + 1); + IBeefyClient.Commitment memory commitment2 = createCommitment(newBlockNumber2); + + vm.prank(relayer1); + wrapper.submitInitial(commitment2, bitfield, proof); + + assertEq(mockBeefyClient.submitInitialCount(), 2); + } + + function test_activeTicketTracking() public { + uint32 newBlockNumber = uint32(INITIAL_BEEFY_BLOCK + MIN_BLOCK_INCREMENT + 1); + IBeefyClient.Commitment memory commitment = createCommitment(newBlockNumber); + uint256[] memory bitfield = new uint256[](1); + IBeefyClient.ValidatorProof memory proof = createValidatorProof(); + + // Before submission, activeTicket should be empty + assertEq(wrapper.activeTicket(relayer1), bytes32(0)); + + vm.prank(relayer1); + wrapper.submitInitial(commitment, bitfield, proof); + + // After submission, activeTicket should be set + bytes32 commitmentHash = keccak256(abi.encode(commitment)); + assertEq(wrapper.activeTicket(relayer1), commitmentHash); + } +} From 6bd9ca8141194e749a7d4f0fbbfef12195ff8b8a Mon Sep 17 00:00:00 2001 From: claravanstaden Date: Wed, 7 Jan 2026 14:56:15 +0200 Subject: [PATCH 02/17] relayer changes --- relayer/contracts/beefy_client.go | 33 +- relayer/contracts/beefy_client_wrapper.go | 2254 +++++++++++++++++++++ relayer/generate.go | 1 + relayer/relays/beefy/ethereum-writer.go | 90 + 4 files changed, 2377 insertions(+), 1 deletion(-) create mode 100644 relayer/contracts/beefy_client_wrapper.go diff --git a/relayer/contracts/beefy_client.go b/relayer/contracts/beefy_client.go index 3b64eb81f..7984c4ecf 100644 --- a/relayer/contracts/beefy_client.go +++ b/relayer/contracts/beefy_client.go @@ -78,7 +78,7 @@ type Uint16Array struct { // BeefyClientMetaData contains all meta data concerning the BeefyClient contract. var BeefyClientMetaData = &bind.MetaData{ - ABI: "[{\"type\":\"constructor\",\"inputs\":[{\"name\":\"_randaoCommitDelay\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_randaoCommitExpiration\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_minNumRequiredSignatures\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_fiatShamirRequiredSignatures\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_initialBeefyBlock\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"_initialValidatorSet\",\"type\":\"tuple\",\"internalType\":\"structBeefyClient.ValidatorSet\",\"components\":[{\"name\":\"id\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"length\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"root\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"name\":\"_nextValidatorSet\",\"type\":\"tuple\",\"internalType\":\"structBeefyClient.ValidatorSet\",\"components\":[{\"name\":\"id\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"length\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"root\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"MMR_ROOT_ID\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bytes2\",\"internalType\":\"bytes2\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"commitPrevRandao\",\"inputs\":[{\"name\":\"commitmentHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"createFiatShamirFinalBitfield\",\"inputs\":[{\"name\":\"commitment\",\"type\":\"tuple\",\"internalType\":\"structBeefyClient.Commitment\",\"components\":[{\"name\":\"blockNumber\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"validatorSetID\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"payload\",\"type\":\"tuple[]\",\"internalType\":\"structBeefyClient.PayloadItem[]\",\"components\":[{\"name\":\"payloadID\",\"type\":\"bytes2\",\"internalType\":\"bytes2\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]},{\"name\":\"bitfield\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"createFinalBitfield\",\"inputs\":[{\"name\":\"commitmentHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"bitfield\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"createInitialBitfield\",\"inputs\":[{\"name\":\"bitsToSet\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"},{\"name\":\"length\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"}],\"stateMutability\":\"pure\"},{\"type\":\"function\",\"name\":\"currentValidatorSet\",\"inputs\":[],\"outputs\":[{\"name\":\"id\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"length\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"root\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"usageCounters\",\"type\":\"tuple\",\"internalType\":\"structUint16Array\",\"components\":[{\"name\":\"data\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"},{\"name\":\"length\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"fiatShamirRequiredSignatures\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"latestBeefyBlock\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"latestMMRRoot\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"minNumRequiredSignatures\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"nextValidatorSet\",\"inputs\":[],\"outputs\":[{\"name\":\"id\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"length\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"root\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"usageCounters\",\"type\":\"tuple\",\"internalType\":\"structUint16Array\",\"components\":[{\"name\":\"data\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"},{\"name\":\"length\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"randaoCommitDelay\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"randaoCommitExpiration\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"submitFiatShamir\",\"inputs\":[{\"name\":\"commitment\",\"type\":\"tuple\",\"internalType\":\"structBeefyClient.Commitment\",\"components\":[{\"name\":\"blockNumber\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"validatorSetID\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"payload\",\"type\":\"tuple[]\",\"internalType\":\"structBeefyClient.PayloadItem[]\",\"components\":[{\"name\":\"payloadID\",\"type\":\"bytes2\",\"internalType\":\"bytes2\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]},{\"name\":\"bitfield\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"},{\"name\":\"proofs\",\"type\":\"tuple[]\",\"internalType\":\"structBeefyClient.ValidatorProof[]\",\"components\":[{\"name\":\"v\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"r\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"s\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"index\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"proof\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"}]},{\"name\":\"leaf\",\"type\":\"tuple\",\"internalType\":\"structBeefyClient.MMRLeaf\",\"components\":[{\"name\":\"version\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"parentNumber\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"parentHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"nextAuthoritySetID\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"nextAuthoritySetLen\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"nextAuthoritySetRoot\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"parachainHeadsRoot\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"name\":\"leafProof\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"},{\"name\":\"leafProofOrder\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"submitFinal\",\"inputs\":[{\"name\":\"commitment\",\"type\":\"tuple\",\"internalType\":\"structBeefyClient.Commitment\",\"components\":[{\"name\":\"blockNumber\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"validatorSetID\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"payload\",\"type\":\"tuple[]\",\"internalType\":\"structBeefyClient.PayloadItem[]\",\"components\":[{\"name\":\"payloadID\",\"type\":\"bytes2\",\"internalType\":\"bytes2\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]},{\"name\":\"bitfield\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"},{\"name\":\"proofs\",\"type\":\"tuple[]\",\"internalType\":\"structBeefyClient.ValidatorProof[]\",\"components\":[{\"name\":\"v\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"r\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"s\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"index\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"proof\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"}]},{\"name\":\"leaf\",\"type\":\"tuple\",\"internalType\":\"structBeefyClient.MMRLeaf\",\"components\":[{\"name\":\"version\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"parentNumber\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"parentHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"nextAuthoritySetID\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"nextAuthoritySetLen\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"nextAuthoritySetRoot\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"parachainHeadsRoot\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"name\":\"leafProof\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"},{\"name\":\"leafProofOrder\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"submitInitial\",\"inputs\":[{\"name\":\"commitment\",\"type\":\"tuple\",\"internalType\":\"structBeefyClient.Commitment\",\"components\":[{\"name\":\"blockNumber\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"validatorSetID\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"payload\",\"type\":\"tuple[]\",\"internalType\":\"structBeefyClient.PayloadItem[]\",\"components\":[{\"name\":\"payloadID\",\"type\":\"bytes2\",\"internalType\":\"bytes2\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]},{\"name\":\"bitfield\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"},{\"name\":\"proof\",\"type\":\"tuple\",\"internalType\":\"structBeefyClient.ValidatorProof\",\"components\":[{\"name\":\"v\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"r\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"s\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"index\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"proof\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"tickets\",\"inputs\":[{\"name\":\"ticketID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"blockNumber\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"validatorSetLen\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"numRequiredSignatures\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"prevRandao\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"bitfieldHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"verifyMMRLeafProof\",\"inputs\":[{\"name\":\"leafHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"proof\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"},{\"name\":\"proofOrder\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"event\",\"name\":\"NewMMRRoot\",\"inputs\":[{\"name\":\"mmrRoot\",\"type\":\"bytes32\",\"indexed\":false,\"internalType\":\"bytes32\"},{\"name\":\"blockNumber\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"NewTicket\",\"inputs\":[{\"name\":\"relayer\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"},{\"name\":\"blockNumber\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"TicketExpired\",\"inputs\":[],\"anonymous\":false},{\"type\":\"error\",\"name\":\"CommitmentNotRelevant\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"ECDSAInvalidSignature\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"ECDSAInvalidSignatureLength\",\"inputs\":[{\"name\":\"length\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"ECDSAInvalidSignatureS\",\"inputs\":[{\"name\":\"s\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"type\":\"error\",\"name\":\"IndexOutOfBounds\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidBitfield\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidBitfieldLength\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidCommitment\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidMMRLeaf\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidMMRLeafProof\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidMMRRootLength\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidSamplingParams\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidSignature\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidTicket\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidValidatorProof\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidValidatorProofLength\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"PrevRandaoAlreadyCaptured\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"PrevRandaoNotCaptured\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"ProofSizeExceeded\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"StaleCommitment\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"UnsupportedCompactEncoding\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"WaitPeriodNotOver\",\"inputs\":[]}]", + ABI: "[{\"type\":\"constructor\",\"inputs\":[{\"name\":\"_randaoCommitDelay\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_randaoCommitExpiration\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_minNumRequiredSignatures\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_fiatShamirRequiredSignatures\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_initialBeefyBlock\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"_initialValidatorSet\",\"type\":\"tuple\",\"internalType\":\"structBeefyClient.ValidatorSet\",\"components\":[{\"name\":\"id\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"length\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"root\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"name\":\"_nextValidatorSet\",\"type\":\"tuple\",\"internalType\":\"structBeefyClient.ValidatorSet\",\"components\":[{\"name\":\"id\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"length\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"root\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"FIAT_SHAMIR_DOMAIN_ID\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"MMR_ROOT_ID\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bytes2\",\"internalType\":\"bytes2\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"commitPrevRandao\",\"inputs\":[{\"name\":\"commitmentHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"createFiatShamirFinalBitfield\",\"inputs\":[{\"name\":\"commitment\",\"type\":\"tuple\",\"internalType\":\"structBeefyClient.Commitment\",\"components\":[{\"name\":\"blockNumber\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"validatorSetID\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"payload\",\"type\":\"tuple[]\",\"internalType\":\"structBeefyClient.PayloadItem[]\",\"components\":[{\"name\":\"payloadID\",\"type\":\"bytes2\",\"internalType\":\"bytes2\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]},{\"name\":\"bitfield\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"createFinalBitfield\",\"inputs\":[{\"name\":\"commitmentHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"bitfield\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"createInitialBitfield\",\"inputs\":[{\"name\":\"bitsToSet\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"},{\"name\":\"length\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"}],\"stateMutability\":\"pure\"},{\"type\":\"function\",\"name\":\"currentValidatorSet\",\"inputs\":[],\"outputs\":[{\"name\":\"id\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"length\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"root\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"usageCounters\",\"type\":\"tuple\",\"internalType\":\"structUint16Array\",\"components\":[{\"name\":\"data\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"},{\"name\":\"length\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"fiatShamirRequiredSignatures\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"latestBeefyBlock\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"latestMMRRoot\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"minNumRequiredSignatures\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"nextValidatorSet\",\"inputs\":[],\"outputs\":[{\"name\":\"id\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"length\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"root\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"usageCounters\",\"type\":\"tuple\",\"internalType\":\"structUint16Array\",\"components\":[{\"name\":\"data\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"},{\"name\":\"length\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"randaoCommitDelay\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"randaoCommitExpiration\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"submitFiatShamir\",\"inputs\":[{\"name\":\"commitment\",\"type\":\"tuple\",\"internalType\":\"structBeefyClient.Commitment\",\"components\":[{\"name\":\"blockNumber\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"validatorSetID\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"payload\",\"type\":\"tuple[]\",\"internalType\":\"structBeefyClient.PayloadItem[]\",\"components\":[{\"name\":\"payloadID\",\"type\":\"bytes2\",\"internalType\":\"bytes2\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]},{\"name\":\"bitfield\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"},{\"name\":\"proofs\",\"type\":\"tuple[]\",\"internalType\":\"structBeefyClient.ValidatorProof[]\",\"components\":[{\"name\":\"v\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"r\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"s\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"index\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"proof\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"}]},{\"name\":\"leaf\",\"type\":\"tuple\",\"internalType\":\"structBeefyClient.MMRLeaf\",\"components\":[{\"name\":\"version\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"parentNumber\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"parentHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"nextAuthoritySetID\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"nextAuthoritySetLen\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"nextAuthoritySetRoot\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"parachainHeadsRoot\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"name\":\"leafProof\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"},{\"name\":\"leafProofOrder\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"submitFinal\",\"inputs\":[{\"name\":\"commitment\",\"type\":\"tuple\",\"internalType\":\"structBeefyClient.Commitment\",\"components\":[{\"name\":\"blockNumber\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"validatorSetID\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"payload\",\"type\":\"tuple[]\",\"internalType\":\"structBeefyClient.PayloadItem[]\",\"components\":[{\"name\":\"payloadID\",\"type\":\"bytes2\",\"internalType\":\"bytes2\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]},{\"name\":\"bitfield\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"},{\"name\":\"proofs\",\"type\":\"tuple[]\",\"internalType\":\"structBeefyClient.ValidatorProof[]\",\"components\":[{\"name\":\"v\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"r\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"s\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"index\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"proof\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"}]},{\"name\":\"leaf\",\"type\":\"tuple\",\"internalType\":\"structBeefyClient.MMRLeaf\",\"components\":[{\"name\":\"version\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"parentNumber\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"parentHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"nextAuthoritySetID\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"nextAuthoritySetLen\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"nextAuthoritySetRoot\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"parachainHeadsRoot\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"name\":\"leafProof\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"},{\"name\":\"leafProofOrder\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"submitInitial\",\"inputs\":[{\"name\":\"commitment\",\"type\":\"tuple\",\"internalType\":\"structBeefyClient.Commitment\",\"components\":[{\"name\":\"blockNumber\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"validatorSetID\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"payload\",\"type\":\"tuple[]\",\"internalType\":\"structBeefyClient.PayloadItem[]\",\"components\":[{\"name\":\"payloadID\",\"type\":\"bytes2\",\"internalType\":\"bytes2\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]},{\"name\":\"bitfield\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"},{\"name\":\"proof\",\"type\":\"tuple\",\"internalType\":\"structBeefyClient.ValidatorProof\",\"components\":[{\"name\":\"v\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"r\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"s\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"index\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"proof\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"tickets\",\"inputs\":[{\"name\":\"ticketID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"blockNumber\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"validatorSetLen\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"numRequiredSignatures\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"prevRandao\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"bitfieldHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"verifyMMRLeafProof\",\"inputs\":[{\"name\":\"leafHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"proof\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"},{\"name\":\"proofOrder\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"event\",\"name\":\"NewMMRRoot\",\"inputs\":[{\"name\":\"mmrRoot\",\"type\":\"bytes32\",\"indexed\":false,\"internalType\":\"bytes32\"},{\"name\":\"blockNumber\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"NewTicket\",\"inputs\":[{\"name\":\"relayer\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"},{\"name\":\"blockNumber\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"TicketExpired\",\"inputs\":[],\"anonymous\":false},{\"type\":\"error\",\"name\":\"CommitmentNotRelevant\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"IndexOutOfBounds\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidBitfield\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidBitfieldLength\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidBitfieldPadding\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidCommitment\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidMMRLeaf\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidMMRLeafProof\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidMMRRootLength\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidSamplingParams\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidSignature\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidTicket\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidValidatorProof\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidValidatorProofLength\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"PrevRandaoAlreadyCaptured\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"PrevRandaoNotCaptured\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"ProofSizeExceeded\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"StaleCommitment\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"UnsupportedCompactEncoding\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"WaitPeriodNotOver\",\"inputs\":[]}]", } // BeefyClientABI is the input ABI used to generate the binding from. @@ -227,6 +227,37 @@ func (_BeefyClient *BeefyClientTransactorRaw) Transact(opts *bind.TransactOpts, return _BeefyClient.Contract.contract.Transact(opts, method, params...) } +// FIATSHAMIRDOMAINID is a free data retrieval call binding the contract method 0x15fac8c6. +// +// Solidity: function FIAT_SHAMIR_DOMAIN_ID() view returns(bytes) +func (_BeefyClient *BeefyClientCaller) FIATSHAMIRDOMAINID(opts *bind.CallOpts) ([]byte, error) { + var out []interface{} + err := _BeefyClient.contract.Call(opts, &out, "FIAT_SHAMIR_DOMAIN_ID") + + if err != nil { + return *new([]byte), err + } + + out0 := *abi.ConvertType(out[0], new([]byte)).(*[]byte) + + return out0, err + +} + +// FIATSHAMIRDOMAINID is a free data retrieval call binding the contract method 0x15fac8c6. +// +// Solidity: function FIAT_SHAMIR_DOMAIN_ID() view returns(bytes) +func (_BeefyClient *BeefyClientSession) FIATSHAMIRDOMAINID() ([]byte, error) { + return _BeefyClient.Contract.FIATSHAMIRDOMAINID(&_BeefyClient.CallOpts) +} + +// FIATSHAMIRDOMAINID is a free data retrieval call binding the contract method 0x15fac8c6. +// +// Solidity: function FIAT_SHAMIR_DOMAIN_ID() view returns(bytes) +func (_BeefyClient *BeefyClientCallerSession) FIATSHAMIRDOMAINID() ([]byte, error) { + return _BeefyClient.Contract.FIATSHAMIRDOMAINID(&_BeefyClient.CallOpts) +} + // MMRROOTID is a free data retrieval call binding the contract method 0x0a7c8faa. // // Solidity: function MMR_ROOT_ID() view returns(bytes2) diff --git a/relayer/contracts/beefy_client_wrapper.go b/relayer/contracts/beefy_client_wrapper.go new file mode 100644 index 000000000..8a4c2c88a --- /dev/null +++ b/relayer/contracts/beefy_client_wrapper.go @@ -0,0 +1,2254 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package contracts + +import ( + "errors" + "math/big" + "strings" + + ethereum "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/event" +) + +// Reference imports to suppress errors if they are not otherwise used. +var ( + _ = errors.New + _ = big.NewInt + _ = strings.NewReader + _ = ethereum.NotFound + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription + _ = abi.ConvertType +) + +// IBeefyClientCommitment is an auto generated low-level Go binding around an user-defined struct. +type IBeefyClientCommitment struct { + BlockNumber uint32 + ValidatorSetID uint64 + Payload []IBeefyClientPayloadItem +} + +// IBeefyClientMMRLeaf is an auto generated low-level Go binding around an user-defined struct. +type IBeefyClientMMRLeaf struct { + Version uint8 + ParentNumber uint32 + ParentHash [32]byte + NextAuthoritySetID uint64 + NextAuthoritySetLen uint32 + NextAuthoritySetRoot [32]byte + ParachainHeadsRoot [32]byte +} + +// IBeefyClientPayloadItem is an auto generated low-level Go binding around an user-defined struct. +type IBeefyClientPayloadItem struct { + PayloadID [2]byte + Data []byte +} + +// IBeefyClientValidatorProof is an auto generated low-level Go binding around an user-defined struct. +type IBeefyClientValidatorProof struct { + V uint8 + R [32]byte + S [32]byte + Index *big.Int + Account common.Address + Proof [][32]byte +} + +// BeefyClientWrapperMetaData contains all meta data concerning the BeefyClientWrapper contract. +var BeefyClientWrapperMetaData = &bind.MetaData{ + ABI: "[{\"type\":\"receive\",\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"activeTicket\",\"inputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"addRelayer\",\"inputs\":[{\"name\":\"relayer\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"beefyClient\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"contractIBeefyClient\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"clearTicket\",\"inputs\":[],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"commitPrevRandao\",\"inputs\":[{\"name\":\"commitmentHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"createFinalBitfield\",\"inputs\":[{\"name\":\"commitmentHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"bitfield\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"currentTurnIndex\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getBalance\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getCurrentTurnRelayer\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getRelayerCount\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getRelayers\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address[]\",\"internalType\":\"address[]\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"gracePeriodBlocks\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"implementation\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"initialize\",\"inputs\":[{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"isGracePeriodActive\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"isRelayer\",\"inputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"lastSubmissionBlock\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"latestBeefyBlock\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"maxGasPrice\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"minBlockIncrement\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"owner\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"relayers\",\"inputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"removeRelayer\",\"inputs\":[{\"name\":\"relayer\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setGracePeriod\",\"inputs\":[{\"name\":\"_gracePeriodBlocks\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setMaxGasPrice\",\"inputs\":[{\"name\":\"_maxGasPrice\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setMinBlockIncrement\",\"inputs\":[{\"name\":\"_minBlockIncrement\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"submitFinal\",\"inputs\":[{\"name\":\"commitment\",\"type\":\"tuple\",\"internalType\":\"structIBeefyClient.Commitment\",\"components\":[{\"name\":\"blockNumber\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"validatorSetID\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"payload\",\"type\":\"tuple[]\",\"internalType\":\"structIBeefyClient.PayloadItem[]\",\"components\":[{\"name\":\"payloadID\",\"type\":\"bytes2\",\"internalType\":\"bytes2\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]},{\"name\":\"bitfield\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"},{\"name\":\"proofs\",\"type\":\"tuple[]\",\"internalType\":\"structIBeefyClient.ValidatorProof[]\",\"components\":[{\"name\":\"v\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"r\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"s\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"index\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"proof\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"}]},{\"name\":\"leaf\",\"type\":\"tuple\",\"internalType\":\"structIBeefyClient.MMRLeaf\",\"components\":[{\"name\":\"version\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"parentNumber\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"parentHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"nextAuthoritySetID\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"nextAuthoritySetLen\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"nextAuthoritySetRoot\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"parachainHeadsRoot\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"name\":\"leafProof\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"},{\"name\":\"leafProofOrder\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"submitInitial\",\"inputs\":[{\"name\":\"commitment\",\"type\":\"tuple\",\"internalType\":\"structIBeefyClient.Commitment\",\"components\":[{\"name\":\"blockNumber\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"validatorSetID\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"payload\",\"type\":\"tuple[]\",\"internalType\":\"structIBeefyClient.PayloadItem[]\",\"components\":[{\"name\":\"payloadID\",\"type\":\"bytes2\",\"internalType\":\"bytes2\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]},{\"name\":\"bitfield\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"},{\"name\":\"proof\",\"type\":\"tuple\",\"internalType\":\"structIBeefyClient.ValidatorProof\",\"components\":[{\"name\":\"v\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"r\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"s\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"index\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"proof\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"ticketOwner\",\"inputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"transferOwnership\",\"inputs\":[{\"name\":\"newOwner\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"upgradeTo\",\"inputs\":[{\"name\":\"newImplementation\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"expectedCodeHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"withdrawFunds\",\"inputs\":[{\"name\":\"recipient\",\"type\":\"address\",\"internalType\":\"addresspayable\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"event\",\"name\":\"ConfigUpdated\",\"inputs\":[{\"name\":\"parameter\",\"type\":\"string\",\"indexed\":false,\"internalType\":\"string\"},{\"name\":\"value\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"FundsDeposited\",\"inputs\":[{\"name\":\"depositor\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"FundsWithdrawn\",\"inputs\":[{\"name\":\"recipient\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"RelayerAdded\",\"inputs\":[{\"name\":\"relayer\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"RelayerRemoved\",\"inputs\":[{\"name\":\"relayer\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"SubmissionRefunded\",\"inputs\":[{\"name\":\"relayer\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"},{\"name\":\"gasUsed\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"TurnAdvanced\",\"inputs\":[{\"name\":\"newTurnIndex\",\"type\":\"uint256\",\"indexed\":true,\"internalType\":\"uint256\"},{\"name\":\"nextRelayer\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Upgraded\",\"inputs\":[{\"name\":\"implementation\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"error\",\"name\":\"AlreadyInitialized\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InsufficientBlockIncrement\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidAddress\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidCodeHash\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidContract\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidTicket\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"NoRelayers\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"NotARelayer\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"NotTicketOwner\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"NotYourTurn\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"RelayerAlreadyExists\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"RelayerNotFound\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"TicketAlreadyActive\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"TransferFailed\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"Unauthorized\",\"inputs\":[]}]", +} + +// BeefyClientWrapperABI is the input ABI used to generate the binding from. +// Deprecated: Use BeefyClientWrapperMetaData.ABI instead. +var BeefyClientWrapperABI = BeefyClientWrapperMetaData.ABI + +// BeefyClientWrapper is an auto generated Go binding around an Ethereum contract. +type BeefyClientWrapper struct { + BeefyClientWrapperCaller // Read-only binding to the contract + BeefyClientWrapperTransactor // Write-only binding to the contract + BeefyClientWrapperFilterer // Log filterer for contract events +} + +// BeefyClientWrapperCaller is an auto generated read-only Go binding around an Ethereum contract. +type BeefyClientWrapperCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// BeefyClientWrapperTransactor is an auto generated write-only Go binding around an Ethereum contract. +type BeefyClientWrapperTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// BeefyClientWrapperFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type BeefyClientWrapperFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// BeefyClientWrapperSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type BeefyClientWrapperSession struct { + Contract *BeefyClientWrapper // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// BeefyClientWrapperCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type BeefyClientWrapperCallerSession struct { + Contract *BeefyClientWrapperCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// BeefyClientWrapperTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type BeefyClientWrapperTransactorSession struct { + Contract *BeefyClientWrapperTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// BeefyClientWrapperRaw is an auto generated low-level Go binding around an Ethereum contract. +type BeefyClientWrapperRaw struct { + Contract *BeefyClientWrapper // Generic contract binding to access the raw methods on +} + +// BeefyClientWrapperCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type BeefyClientWrapperCallerRaw struct { + Contract *BeefyClientWrapperCaller // Generic read-only contract binding to access the raw methods on +} + +// BeefyClientWrapperTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type BeefyClientWrapperTransactorRaw struct { + Contract *BeefyClientWrapperTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewBeefyClientWrapper creates a new instance of BeefyClientWrapper, bound to a specific deployed contract. +func NewBeefyClientWrapper(address common.Address, backend bind.ContractBackend) (*BeefyClientWrapper, error) { + contract, err := bindBeefyClientWrapper(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &BeefyClientWrapper{BeefyClientWrapperCaller: BeefyClientWrapperCaller{contract: contract}, BeefyClientWrapperTransactor: BeefyClientWrapperTransactor{contract: contract}, BeefyClientWrapperFilterer: BeefyClientWrapperFilterer{contract: contract}}, nil +} + +// NewBeefyClientWrapperCaller creates a new read-only instance of BeefyClientWrapper, bound to a specific deployed contract. +func NewBeefyClientWrapperCaller(address common.Address, caller bind.ContractCaller) (*BeefyClientWrapperCaller, error) { + contract, err := bindBeefyClientWrapper(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &BeefyClientWrapperCaller{contract: contract}, nil +} + +// NewBeefyClientWrapperTransactor creates a new write-only instance of BeefyClientWrapper, bound to a specific deployed contract. +func NewBeefyClientWrapperTransactor(address common.Address, transactor bind.ContractTransactor) (*BeefyClientWrapperTransactor, error) { + contract, err := bindBeefyClientWrapper(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &BeefyClientWrapperTransactor{contract: contract}, nil +} + +// NewBeefyClientWrapperFilterer creates a new log filterer instance of BeefyClientWrapper, bound to a specific deployed contract. +func NewBeefyClientWrapperFilterer(address common.Address, filterer bind.ContractFilterer) (*BeefyClientWrapperFilterer, error) { + contract, err := bindBeefyClientWrapper(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &BeefyClientWrapperFilterer{contract: contract}, nil +} + +// bindBeefyClientWrapper binds a generic wrapper to an already deployed contract. +func bindBeefyClientWrapper(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := BeefyClientWrapperMetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_BeefyClientWrapper *BeefyClientWrapperRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _BeefyClientWrapper.Contract.BeefyClientWrapperCaller.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_BeefyClientWrapper *BeefyClientWrapperRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _BeefyClientWrapper.Contract.BeefyClientWrapperTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_BeefyClientWrapper *BeefyClientWrapperRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _BeefyClientWrapper.Contract.BeefyClientWrapperTransactor.contract.Transact(opts, method, params...) +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_BeefyClientWrapper *BeefyClientWrapperCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _BeefyClientWrapper.Contract.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_BeefyClientWrapper *BeefyClientWrapperTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _BeefyClientWrapper.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_BeefyClientWrapper *BeefyClientWrapperTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _BeefyClientWrapper.Contract.contract.Transact(opts, method, params...) +} + +// ActiveTicket is a free data retrieval call binding the contract method 0x3b38c624. +// +// Solidity: function activeTicket(address ) view returns(bytes32) +func (_BeefyClientWrapper *BeefyClientWrapperCaller) ActiveTicket(opts *bind.CallOpts, arg0 common.Address) ([32]byte, error) { + var out []interface{} + err := _BeefyClientWrapper.contract.Call(opts, &out, "activeTicket", arg0) + + if err != nil { + return *new([32]byte), err + } + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + +} + +// ActiveTicket is a free data retrieval call binding the contract method 0x3b38c624. +// +// Solidity: function activeTicket(address ) view returns(bytes32) +func (_BeefyClientWrapper *BeefyClientWrapperSession) ActiveTicket(arg0 common.Address) ([32]byte, error) { + return _BeefyClientWrapper.Contract.ActiveTicket(&_BeefyClientWrapper.CallOpts, arg0) +} + +// ActiveTicket is a free data retrieval call binding the contract method 0x3b38c624. +// +// Solidity: function activeTicket(address ) view returns(bytes32) +func (_BeefyClientWrapper *BeefyClientWrapperCallerSession) ActiveTicket(arg0 common.Address) ([32]byte, error) { + return _BeefyClientWrapper.Contract.ActiveTicket(&_BeefyClientWrapper.CallOpts, arg0) +} + +// BeefyClient is a free data retrieval call binding the contract method 0x776c81c3. +// +// Solidity: function beefyClient() view returns(address) +func (_BeefyClientWrapper *BeefyClientWrapperCaller) BeefyClient(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _BeefyClientWrapper.contract.Call(opts, &out, "beefyClient") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// BeefyClient is a free data retrieval call binding the contract method 0x776c81c3. +// +// Solidity: function beefyClient() view returns(address) +func (_BeefyClientWrapper *BeefyClientWrapperSession) BeefyClient() (common.Address, error) { + return _BeefyClientWrapper.Contract.BeefyClient(&_BeefyClientWrapper.CallOpts) +} + +// BeefyClient is a free data retrieval call binding the contract method 0x776c81c3. +// +// Solidity: function beefyClient() view returns(address) +func (_BeefyClientWrapper *BeefyClientWrapperCallerSession) BeefyClient() (common.Address, error) { + return _BeefyClientWrapper.Contract.BeefyClient(&_BeefyClientWrapper.CallOpts) +} + +// CreateFinalBitfield is a free data retrieval call binding the contract method 0x8ab81d13. +// +// Solidity: function createFinalBitfield(bytes32 commitmentHash, uint256[] bitfield) view returns(uint256[]) +func (_BeefyClientWrapper *BeefyClientWrapperCaller) CreateFinalBitfield(opts *bind.CallOpts, commitmentHash [32]byte, bitfield []*big.Int) ([]*big.Int, error) { + var out []interface{} + err := _BeefyClientWrapper.contract.Call(opts, &out, "createFinalBitfield", commitmentHash, bitfield) + + if err != nil { + return *new([]*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new([]*big.Int)).(*[]*big.Int) + + return out0, err + +} + +// CreateFinalBitfield is a free data retrieval call binding the contract method 0x8ab81d13. +// +// Solidity: function createFinalBitfield(bytes32 commitmentHash, uint256[] bitfield) view returns(uint256[]) +func (_BeefyClientWrapper *BeefyClientWrapperSession) CreateFinalBitfield(commitmentHash [32]byte, bitfield []*big.Int) ([]*big.Int, error) { + return _BeefyClientWrapper.Contract.CreateFinalBitfield(&_BeefyClientWrapper.CallOpts, commitmentHash, bitfield) +} + +// CreateFinalBitfield is a free data retrieval call binding the contract method 0x8ab81d13. +// +// Solidity: function createFinalBitfield(bytes32 commitmentHash, uint256[] bitfield) view returns(uint256[]) +func (_BeefyClientWrapper *BeefyClientWrapperCallerSession) CreateFinalBitfield(commitmentHash [32]byte, bitfield []*big.Int) ([]*big.Int, error) { + return _BeefyClientWrapper.Contract.CreateFinalBitfield(&_BeefyClientWrapper.CallOpts, commitmentHash, bitfield) +} + +// CurrentTurnIndex is a free data retrieval call binding the contract method 0x50efd268. +// +// Solidity: function currentTurnIndex() view returns(uint256) +func (_BeefyClientWrapper *BeefyClientWrapperCaller) CurrentTurnIndex(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _BeefyClientWrapper.contract.Call(opts, &out, "currentTurnIndex") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// CurrentTurnIndex is a free data retrieval call binding the contract method 0x50efd268. +// +// Solidity: function currentTurnIndex() view returns(uint256) +func (_BeefyClientWrapper *BeefyClientWrapperSession) CurrentTurnIndex() (*big.Int, error) { + return _BeefyClientWrapper.Contract.CurrentTurnIndex(&_BeefyClientWrapper.CallOpts) +} + +// CurrentTurnIndex is a free data retrieval call binding the contract method 0x50efd268. +// +// Solidity: function currentTurnIndex() view returns(uint256) +func (_BeefyClientWrapper *BeefyClientWrapperCallerSession) CurrentTurnIndex() (*big.Int, error) { + return _BeefyClientWrapper.Contract.CurrentTurnIndex(&_BeefyClientWrapper.CallOpts) +} + +// GetBalance is a free data retrieval call binding the contract method 0x12065fe0. +// +// Solidity: function getBalance() view returns(uint256) +func (_BeefyClientWrapper *BeefyClientWrapperCaller) GetBalance(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _BeefyClientWrapper.contract.Call(opts, &out, "getBalance") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// GetBalance is a free data retrieval call binding the contract method 0x12065fe0. +// +// Solidity: function getBalance() view returns(uint256) +func (_BeefyClientWrapper *BeefyClientWrapperSession) GetBalance() (*big.Int, error) { + return _BeefyClientWrapper.Contract.GetBalance(&_BeefyClientWrapper.CallOpts) +} + +// GetBalance is a free data retrieval call binding the contract method 0x12065fe0. +// +// Solidity: function getBalance() view returns(uint256) +func (_BeefyClientWrapper *BeefyClientWrapperCallerSession) GetBalance() (*big.Int, error) { + return _BeefyClientWrapper.Contract.GetBalance(&_BeefyClientWrapper.CallOpts) +} + +// GetCurrentTurnRelayer is a free data retrieval call binding the contract method 0x5664b04f. +// +// Solidity: function getCurrentTurnRelayer() view returns(address) +func (_BeefyClientWrapper *BeefyClientWrapperCaller) GetCurrentTurnRelayer(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _BeefyClientWrapper.contract.Call(opts, &out, "getCurrentTurnRelayer") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// GetCurrentTurnRelayer is a free data retrieval call binding the contract method 0x5664b04f. +// +// Solidity: function getCurrentTurnRelayer() view returns(address) +func (_BeefyClientWrapper *BeefyClientWrapperSession) GetCurrentTurnRelayer() (common.Address, error) { + return _BeefyClientWrapper.Contract.GetCurrentTurnRelayer(&_BeefyClientWrapper.CallOpts) +} + +// GetCurrentTurnRelayer is a free data retrieval call binding the contract method 0x5664b04f. +// +// Solidity: function getCurrentTurnRelayer() view returns(address) +func (_BeefyClientWrapper *BeefyClientWrapperCallerSession) GetCurrentTurnRelayer() (common.Address, error) { + return _BeefyClientWrapper.Contract.GetCurrentTurnRelayer(&_BeefyClientWrapper.CallOpts) +} + +// GetRelayerCount is a free data retrieval call binding the contract method 0xe51ea0b5. +// +// Solidity: function getRelayerCount() view returns(uint256) +func (_BeefyClientWrapper *BeefyClientWrapperCaller) GetRelayerCount(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _BeefyClientWrapper.contract.Call(opts, &out, "getRelayerCount") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// GetRelayerCount is a free data retrieval call binding the contract method 0xe51ea0b5. +// +// Solidity: function getRelayerCount() view returns(uint256) +func (_BeefyClientWrapper *BeefyClientWrapperSession) GetRelayerCount() (*big.Int, error) { + return _BeefyClientWrapper.Contract.GetRelayerCount(&_BeefyClientWrapper.CallOpts) +} + +// GetRelayerCount is a free data retrieval call binding the contract method 0xe51ea0b5. +// +// Solidity: function getRelayerCount() view returns(uint256) +func (_BeefyClientWrapper *BeefyClientWrapperCallerSession) GetRelayerCount() (*big.Int, error) { + return _BeefyClientWrapper.Contract.GetRelayerCount(&_BeefyClientWrapper.CallOpts) +} + +// GetRelayers is a free data retrieval call binding the contract method 0x179ff4b2. +// +// Solidity: function getRelayers() view returns(address[]) +func (_BeefyClientWrapper *BeefyClientWrapperCaller) GetRelayers(opts *bind.CallOpts) ([]common.Address, error) { + var out []interface{} + err := _BeefyClientWrapper.contract.Call(opts, &out, "getRelayers") + + if err != nil { + return *new([]common.Address), err + } + + out0 := *abi.ConvertType(out[0], new([]common.Address)).(*[]common.Address) + + return out0, err + +} + +// GetRelayers is a free data retrieval call binding the contract method 0x179ff4b2. +// +// Solidity: function getRelayers() view returns(address[]) +func (_BeefyClientWrapper *BeefyClientWrapperSession) GetRelayers() ([]common.Address, error) { + return _BeefyClientWrapper.Contract.GetRelayers(&_BeefyClientWrapper.CallOpts) +} + +// GetRelayers is a free data retrieval call binding the contract method 0x179ff4b2. +// +// Solidity: function getRelayers() view returns(address[]) +func (_BeefyClientWrapper *BeefyClientWrapperCallerSession) GetRelayers() ([]common.Address, error) { + return _BeefyClientWrapper.Contract.GetRelayers(&_BeefyClientWrapper.CallOpts) +} + +// GracePeriodBlocks is a free data retrieval call binding the contract method 0xde2daaff. +// +// Solidity: function gracePeriodBlocks() view returns(uint256) +func (_BeefyClientWrapper *BeefyClientWrapperCaller) GracePeriodBlocks(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _BeefyClientWrapper.contract.Call(opts, &out, "gracePeriodBlocks") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// GracePeriodBlocks is a free data retrieval call binding the contract method 0xde2daaff. +// +// Solidity: function gracePeriodBlocks() view returns(uint256) +func (_BeefyClientWrapper *BeefyClientWrapperSession) GracePeriodBlocks() (*big.Int, error) { + return _BeefyClientWrapper.Contract.GracePeriodBlocks(&_BeefyClientWrapper.CallOpts) +} + +// GracePeriodBlocks is a free data retrieval call binding the contract method 0xde2daaff. +// +// Solidity: function gracePeriodBlocks() view returns(uint256) +func (_BeefyClientWrapper *BeefyClientWrapperCallerSession) GracePeriodBlocks() (*big.Int, error) { + return _BeefyClientWrapper.Contract.GracePeriodBlocks(&_BeefyClientWrapper.CallOpts) +} + +// Implementation is a free data retrieval call binding the contract method 0x5c60da1b. +// +// Solidity: function implementation() view returns(address) +func (_BeefyClientWrapper *BeefyClientWrapperCaller) Implementation(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _BeefyClientWrapper.contract.Call(opts, &out, "implementation") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// Implementation is a free data retrieval call binding the contract method 0x5c60da1b. +// +// Solidity: function implementation() view returns(address) +func (_BeefyClientWrapper *BeefyClientWrapperSession) Implementation() (common.Address, error) { + return _BeefyClientWrapper.Contract.Implementation(&_BeefyClientWrapper.CallOpts) +} + +// Implementation is a free data retrieval call binding the contract method 0x5c60da1b. +// +// Solidity: function implementation() view returns(address) +func (_BeefyClientWrapper *BeefyClientWrapperCallerSession) Implementation() (common.Address, error) { + return _BeefyClientWrapper.Contract.Implementation(&_BeefyClientWrapper.CallOpts) +} + +// IsGracePeriodActive is a free data retrieval call binding the contract method 0xb965655a. +// +// Solidity: function isGracePeriodActive() view returns(bool) +func (_BeefyClientWrapper *BeefyClientWrapperCaller) IsGracePeriodActive(opts *bind.CallOpts) (bool, error) { + var out []interface{} + err := _BeefyClientWrapper.contract.Call(opts, &out, "isGracePeriodActive") + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +// IsGracePeriodActive is a free data retrieval call binding the contract method 0xb965655a. +// +// Solidity: function isGracePeriodActive() view returns(bool) +func (_BeefyClientWrapper *BeefyClientWrapperSession) IsGracePeriodActive() (bool, error) { + return _BeefyClientWrapper.Contract.IsGracePeriodActive(&_BeefyClientWrapper.CallOpts) +} + +// IsGracePeriodActive is a free data retrieval call binding the contract method 0xb965655a. +// +// Solidity: function isGracePeriodActive() view returns(bool) +func (_BeefyClientWrapper *BeefyClientWrapperCallerSession) IsGracePeriodActive() (bool, error) { + return _BeefyClientWrapper.Contract.IsGracePeriodActive(&_BeefyClientWrapper.CallOpts) +} + +// IsRelayer is a free data retrieval call binding the contract method 0x541d5548. +// +// Solidity: function isRelayer(address ) view returns(bool) +func (_BeefyClientWrapper *BeefyClientWrapperCaller) IsRelayer(opts *bind.CallOpts, arg0 common.Address) (bool, error) { + var out []interface{} + err := _BeefyClientWrapper.contract.Call(opts, &out, "isRelayer", arg0) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +// IsRelayer is a free data retrieval call binding the contract method 0x541d5548. +// +// Solidity: function isRelayer(address ) view returns(bool) +func (_BeefyClientWrapper *BeefyClientWrapperSession) IsRelayer(arg0 common.Address) (bool, error) { + return _BeefyClientWrapper.Contract.IsRelayer(&_BeefyClientWrapper.CallOpts, arg0) +} + +// IsRelayer is a free data retrieval call binding the contract method 0x541d5548. +// +// Solidity: function isRelayer(address ) view returns(bool) +func (_BeefyClientWrapper *BeefyClientWrapperCallerSession) IsRelayer(arg0 common.Address) (bool, error) { + return _BeefyClientWrapper.Contract.IsRelayer(&_BeefyClientWrapper.CallOpts, arg0) +} + +// LastSubmissionBlock is a free data retrieval call binding the contract method 0x1f498355. +// +// Solidity: function lastSubmissionBlock() view returns(uint256) +func (_BeefyClientWrapper *BeefyClientWrapperCaller) LastSubmissionBlock(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _BeefyClientWrapper.contract.Call(opts, &out, "lastSubmissionBlock") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// LastSubmissionBlock is a free data retrieval call binding the contract method 0x1f498355. +// +// Solidity: function lastSubmissionBlock() view returns(uint256) +func (_BeefyClientWrapper *BeefyClientWrapperSession) LastSubmissionBlock() (*big.Int, error) { + return _BeefyClientWrapper.Contract.LastSubmissionBlock(&_BeefyClientWrapper.CallOpts) +} + +// LastSubmissionBlock is a free data retrieval call binding the contract method 0x1f498355. +// +// Solidity: function lastSubmissionBlock() view returns(uint256) +func (_BeefyClientWrapper *BeefyClientWrapperCallerSession) LastSubmissionBlock() (*big.Int, error) { + return _BeefyClientWrapper.Contract.LastSubmissionBlock(&_BeefyClientWrapper.CallOpts) +} + +// LatestBeefyBlock is a free data retrieval call binding the contract method 0x66ae69a0. +// +// Solidity: function latestBeefyBlock() view returns(uint64) +func (_BeefyClientWrapper *BeefyClientWrapperCaller) LatestBeefyBlock(opts *bind.CallOpts) (uint64, error) { + var out []interface{} + err := _BeefyClientWrapper.contract.Call(opts, &out, "latestBeefyBlock") + + if err != nil { + return *new(uint64), err + } + + out0 := *abi.ConvertType(out[0], new(uint64)).(*uint64) + + return out0, err + +} + +// LatestBeefyBlock is a free data retrieval call binding the contract method 0x66ae69a0. +// +// Solidity: function latestBeefyBlock() view returns(uint64) +func (_BeefyClientWrapper *BeefyClientWrapperSession) LatestBeefyBlock() (uint64, error) { + return _BeefyClientWrapper.Contract.LatestBeefyBlock(&_BeefyClientWrapper.CallOpts) +} + +// LatestBeefyBlock is a free data retrieval call binding the contract method 0x66ae69a0. +// +// Solidity: function latestBeefyBlock() view returns(uint64) +func (_BeefyClientWrapper *BeefyClientWrapperCallerSession) LatestBeefyBlock() (uint64, error) { + return _BeefyClientWrapper.Contract.LatestBeefyBlock(&_BeefyClientWrapper.CallOpts) +} + +// MaxGasPrice is a free data retrieval call binding the contract method 0x3de39c11. +// +// Solidity: function maxGasPrice() view returns(uint256) +func (_BeefyClientWrapper *BeefyClientWrapperCaller) MaxGasPrice(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _BeefyClientWrapper.contract.Call(opts, &out, "maxGasPrice") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// MaxGasPrice is a free data retrieval call binding the contract method 0x3de39c11. +// +// Solidity: function maxGasPrice() view returns(uint256) +func (_BeefyClientWrapper *BeefyClientWrapperSession) MaxGasPrice() (*big.Int, error) { + return _BeefyClientWrapper.Contract.MaxGasPrice(&_BeefyClientWrapper.CallOpts) +} + +// MaxGasPrice is a free data retrieval call binding the contract method 0x3de39c11. +// +// Solidity: function maxGasPrice() view returns(uint256) +func (_BeefyClientWrapper *BeefyClientWrapperCallerSession) MaxGasPrice() (*big.Int, error) { + return _BeefyClientWrapper.Contract.MaxGasPrice(&_BeefyClientWrapper.CallOpts) +} + +// MinBlockIncrement is a free data retrieval call binding the contract method 0x4bfcad80. +// +// Solidity: function minBlockIncrement() view returns(uint256) +func (_BeefyClientWrapper *BeefyClientWrapperCaller) MinBlockIncrement(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _BeefyClientWrapper.contract.Call(opts, &out, "minBlockIncrement") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// MinBlockIncrement is a free data retrieval call binding the contract method 0x4bfcad80. +// +// Solidity: function minBlockIncrement() view returns(uint256) +func (_BeefyClientWrapper *BeefyClientWrapperSession) MinBlockIncrement() (*big.Int, error) { + return _BeefyClientWrapper.Contract.MinBlockIncrement(&_BeefyClientWrapper.CallOpts) +} + +// MinBlockIncrement is a free data retrieval call binding the contract method 0x4bfcad80. +// +// Solidity: function minBlockIncrement() view returns(uint256) +func (_BeefyClientWrapper *BeefyClientWrapperCallerSession) MinBlockIncrement() (*big.Int, error) { + return _BeefyClientWrapper.Contract.MinBlockIncrement(&_BeefyClientWrapper.CallOpts) +} + +// Owner is a free data retrieval call binding the contract method 0x8da5cb5b. +// +// Solidity: function owner() view returns(address) +func (_BeefyClientWrapper *BeefyClientWrapperCaller) Owner(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _BeefyClientWrapper.contract.Call(opts, &out, "owner") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// Owner is a free data retrieval call binding the contract method 0x8da5cb5b. +// +// Solidity: function owner() view returns(address) +func (_BeefyClientWrapper *BeefyClientWrapperSession) Owner() (common.Address, error) { + return _BeefyClientWrapper.Contract.Owner(&_BeefyClientWrapper.CallOpts) +} + +// Owner is a free data retrieval call binding the contract method 0x8da5cb5b. +// +// Solidity: function owner() view returns(address) +func (_BeefyClientWrapper *BeefyClientWrapperCallerSession) Owner() (common.Address, error) { + return _BeefyClientWrapper.Contract.Owner(&_BeefyClientWrapper.CallOpts) +} + +// Relayers is a free data retrieval call binding the contract method 0x9a48e7f9. +// +// Solidity: function relayers(uint256 ) view returns(address) +func (_BeefyClientWrapper *BeefyClientWrapperCaller) Relayers(opts *bind.CallOpts, arg0 *big.Int) (common.Address, error) { + var out []interface{} + err := _BeefyClientWrapper.contract.Call(opts, &out, "relayers", arg0) + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// Relayers is a free data retrieval call binding the contract method 0x9a48e7f9. +// +// Solidity: function relayers(uint256 ) view returns(address) +func (_BeefyClientWrapper *BeefyClientWrapperSession) Relayers(arg0 *big.Int) (common.Address, error) { + return _BeefyClientWrapper.Contract.Relayers(&_BeefyClientWrapper.CallOpts, arg0) +} + +// Relayers is a free data retrieval call binding the contract method 0x9a48e7f9. +// +// Solidity: function relayers(uint256 ) view returns(address) +func (_BeefyClientWrapper *BeefyClientWrapperCallerSession) Relayers(arg0 *big.Int) (common.Address, error) { + return _BeefyClientWrapper.Contract.Relayers(&_BeefyClientWrapper.CallOpts, arg0) +} + +// TicketOwner is a free data retrieval call binding the contract method 0xd2e82bfe. +// +// Solidity: function ticketOwner(bytes32 ) view returns(address) +func (_BeefyClientWrapper *BeefyClientWrapperCaller) TicketOwner(opts *bind.CallOpts, arg0 [32]byte) (common.Address, error) { + var out []interface{} + err := _BeefyClientWrapper.contract.Call(opts, &out, "ticketOwner", arg0) + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// TicketOwner is a free data retrieval call binding the contract method 0xd2e82bfe. +// +// Solidity: function ticketOwner(bytes32 ) view returns(address) +func (_BeefyClientWrapper *BeefyClientWrapperSession) TicketOwner(arg0 [32]byte) (common.Address, error) { + return _BeefyClientWrapper.Contract.TicketOwner(&_BeefyClientWrapper.CallOpts, arg0) +} + +// TicketOwner is a free data retrieval call binding the contract method 0xd2e82bfe. +// +// Solidity: function ticketOwner(bytes32 ) view returns(address) +func (_BeefyClientWrapper *BeefyClientWrapperCallerSession) TicketOwner(arg0 [32]byte) (common.Address, error) { + return _BeefyClientWrapper.Contract.TicketOwner(&_BeefyClientWrapper.CallOpts, arg0) +} + +// AddRelayer is a paid mutator transaction binding the contract method 0xdd39f00d. +// +// Solidity: function addRelayer(address relayer) returns() +func (_BeefyClientWrapper *BeefyClientWrapperTransactor) AddRelayer(opts *bind.TransactOpts, relayer common.Address) (*types.Transaction, error) { + return _BeefyClientWrapper.contract.Transact(opts, "addRelayer", relayer) +} + +// AddRelayer is a paid mutator transaction binding the contract method 0xdd39f00d. +// +// Solidity: function addRelayer(address relayer) returns() +func (_BeefyClientWrapper *BeefyClientWrapperSession) AddRelayer(relayer common.Address) (*types.Transaction, error) { + return _BeefyClientWrapper.Contract.AddRelayer(&_BeefyClientWrapper.TransactOpts, relayer) +} + +// AddRelayer is a paid mutator transaction binding the contract method 0xdd39f00d. +// +// Solidity: function addRelayer(address relayer) returns() +func (_BeefyClientWrapper *BeefyClientWrapperTransactorSession) AddRelayer(relayer common.Address) (*types.Transaction, error) { + return _BeefyClientWrapper.Contract.AddRelayer(&_BeefyClientWrapper.TransactOpts, relayer) +} + +// ClearTicket is a paid mutator transaction binding the contract method 0x15738ab4. +// +// Solidity: function clearTicket() returns() +func (_BeefyClientWrapper *BeefyClientWrapperTransactor) ClearTicket(opts *bind.TransactOpts) (*types.Transaction, error) { + return _BeefyClientWrapper.contract.Transact(opts, "clearTicket") +} + +// ClearTicket is a paid mutator transaction binding the contract method 0x15738ab4. +// +// Solidity: function clearTicket() returns() +func (_BeefyClientWrapper *BeefyClientWrapperSession) ClearTicket() (*types.Transaction, error) { + return _BeefyClientWrapper.Contract.ClearTicket(&_BeefyClientWrapper.TransactOpts) +} + +// ClearTicket is a paid mutator transaction binding the contract method 0x15738ab4. +// +// Solidity: function clearTicket() returns() +func (_BeefyClientWrapper *BeefyClientWrapperTransactorSession) ClearTicket() (*types.Transaction, error) { + return _BeefyClientWrapper.Contract.ClearTicket(&_BeefyClientWrapper.TransactOpts) +} + +// CommitPrevRandao is a paid mutator transaction binding the contract method 0xa77cf3d2. +// +// Solidity: function commitPrevRandao(bytes32 commitmentHash) returns() +func (_BeefyClientWrapper *BeefyClientWrapperTransactor) CommitPrevRandao(opts *bind.TransactOpts, commitmentHash [32]byte) (*types.Transaction, error) { + return _BeefyClientWrapper.contract.Transact(opts, "commitPrevRandao", commitmentHash) +} + +// CommitPrevRandao is a paid mutator transaction binding the contract method 0xa77cf3d2. +// +// Solidity: function commitPrevRandao(bytes32 commitmentHash) returns() +func (_BeefyClientWrapper *BeefyClientWrapperSession) CommitPrevRandao(commitmentHash [32]byte) (*types.Transaction, error) { + return _BeefyClientWrapper.Contract.CommitPrevRandao(&_BeefyClientWrapper.TransactOpts, commitmentHash) +} + +// CommitPrevRandao is a paid mutator transaction binding the contract method 0xa77cf3d2. +// +// Solidity: function commitPrevRandao(bytes32 commitmentHash) returns() +func (_BeefyClientWrapper *BeefyClientWrapperTransactorSession) CommitPrevRandao(commitmentHash [32]byte) (*types.Transaction, error) { + return _BeefyClientWrapper.Contract.CommitPrevRandao(&_BeefyClientWrapper.TransactOpts, commitmentHash) +} + +// Initialize is a paid mutator transaction binding the contract method 0x439fab91. +// +// Solidity: function initialize(bytes data) returns() +func (_BeefyClientWrapper *BeefyClientWrapperTransactor) Initialize(opts *bind.TransactOpts, data []byte) (*types.Transaction, error) { + return _BeefyClientWrapper.contract.Transact(opts, "initialize", data) +} + +// Initialize is a paid mutator transaction binding the contract method 0x439fab91. +// +// Solidity: function initialize(bytes data) returns() +func (_BeefyClientWrapper *BeefyClientWrapperSession) Initialize(data []byte) (*types.Transaction, error) { + return _BeefyClientWrapper.Contract.Initialize(&_BeefyClientWrapper.TransactOpts, data) +} + +// Initialize is a paid mutator transaction binding the contract method 0x439fab91. +// +// Solidity: function initialize(bytes data) returns() +func (_BeefyClientWrapper *BeefyClientWrapperTransactorSession) Initialize(data []byte) (*types.Transaction, error) { + return _BeefyClientWrapper.Contract.Initialize(&_BeefyClientWrapper.TransactOpts, data) +} + +// RemoveRelayer is a paid mutator transaction binding the contract method 0x60f0a5ac. +// +// Solidity: function removeRelayer(address relayer) returns() +func (_BeefyClientWrapper *BeefyClientWrapperTransactor) RemoveRelayer(opts *bind.TransactOpts, relayer common.Address) (*types.Transaction, error) { + return _BeefyClientWrapper.contract.Transact(opts, "removeRelayer", relayer) +} + +// RemoveRelayer is a paid mutator transaction binding the contract method 0x60f0a5ac. +// +// Solidity: function removeRelayer(address relayer) returns() +func (_BeefyClientWrapper *BeefyClientWrapperSession) RemoveRelayer(relayer common.Address) (*types.Transaction, error) { + return _BeefyClientWrapper.Contract.RemoveRelayer(&_BeefyClientWrapper.TransactOpts, relayer) +} + +// RemoveRelayer is a paid mutator transaction binding the contract method 0x60f0a5ac. +// +// Solidity: function removeRelayer(address relayer) returns() +func (_BeefyClientWrapper *BeefyClientWrapperTransactorSession) RemoveRelayer(relayer common.Address) (*types.Transaction, error) { + return _BeefyClientWrapper.Contract.RemoveRelayer(&_BeefyClientWrapper.TransactOpts, relayer) +} + +// SetGracePeriod is a paid mutator transaction binding the contract method 0xf2f65960. +// +// Solidity: function setGracePeriod(uint256 _gracePeriodBlocks) returns() +func (_BeefyClientWrapper *BeefyClientWrapperTransactor) SetGracePeriod(opts *bind.TransactOpts, _gracePeriodBlocks *big.Int) (*types.Transaction, error) { + return _BeefyClientWrapper.contract.Transact(opts, "setGracePeriod", _gracePeriodBlocks) +} + +// SetGracePeriod is a paid mutator transaction binding the contract method 0xf2f65960. +// +// Solidity: function setGracePeriod(uint256 _gracePeriodBlocks) returns() +func (_BeefyClientWrapper *BeefyClientWrapperSession) SetGracePeriod(_gracePeriodBlocks *big.Int) (*types.Transaction, error) { + return _BeefyClientWrapper.Contract.SetGracePeriod(&_BeefyClientWrapper.TransactOpts, _gracePeriodBlocks) +} + +// SetGracePeriod is a paid mutator transaction binding the contract method 0xf2f65960. +// +// Solidity: function setGracePeriod(uint256 _gracePeriodBlocks) returns() +func (_BeefyClientWrapper *BeefyClientWrapperTransactorSession) SetGracePeriod(_gracePeriodBlocks *big.Int) (*types.Transaction, error) { + return _BeefyClientWrapper.Contract.SetGracePeriod(&_BeefyClientWrapper.TransactOpts, _gracePeriodBlocks) +} + +// SetMaxGasPrice is a paid mutator transaction binding the contract method 0xd2fa635e. +// +// Solidity: function setMaxGasPrice(uint256 _maxGasPrice) returns() +func (_BeefyClientWrapper *BeefyClientWrapperTransactor) SetMaxGasPrice(opts *bind.TransactOpts, _maxGasPrice *big.Int) (*types.Transaction, error) { + return _BeefyClientWrapper.contract.Transact(opts, "setMaxGasPrice", _maxGasPrice) +} + +// SetMaxGasPrice is a paid mutator transaction binding the contract method 0xd2fa635e. +// +// Solidity: function setMaxGasPrice(uint256 _maxGasPrice) returns() +func (_BeefyClientWrapper *BeefyClientWrapperSession) SetMaxGasPrice(_maxGasPrice *big.Int) (*types.Transaction, error) { + return _BeefyClientWrapper.Contract.SetMaxGasPrice(&_BeefyClientWrapper.TransactOpts, _maxGasPrice) +} + +// SetMaxGasPrice is a paid mutator transaction binding the contract method 0xd2fa635e. +// +// Solidity: function setMaxGasPrice(uint256 _maxGasPrice) returns() +func (_BeefyClientWrapper *BeefyClientWrapperTransactorSession) SetMaxGasPrice(_maxGasPrice *big.Int) (*types.Transaction, error) { + return _BeefyClientWrapper.Contract.SetMaxGasPrice(&_BeefyClientWrapper.TransactOpts, _maxGasPrice) +} + +// SetMinBlockIncrement is a paid mutator transaction binding the contract method 0x3f358a76. +// +// Solidity: function setMinBlockIncrement(uint256 _minBlockIncrement) returns() +func (_BeefyClientWrapper *BeefyClientWrapperTransactor) SetMinBlockIncrement(opts *bind.TransactOpts, _minBlockIncrement *big.Int) (*types.Transaction, error) { + return _BeefyClientWrapper.contract.Transact(opts, "setMinBlockIncrement", _minBlockIncrement) +} + +// SetMinBlockIncrement is a paid mutator transaction binding the contract method 0x3f358a76. +// +// Solidity: function setMinBlockIncrement(uint256 _minBlockIncrement) returns() +func (_BeefyClientWrapper *BeefyClientWrapperSession) SetMinBlockIncrement(_minBlockIncrement *big.Int) (*types.Transaction, error) { + return _BeefyClientWrapper.Contract.SetMinBlockIncrement(&_BeefyClientWrapper.TransactOpts, _minBlockIncrement) +} + +// SetMinBlockIncrement is a paid mutator transaction binding the contract method 0x3f358a76. +// +// Solidity: function setMinBlockIncrement(uint256 _minBlockIncrement) returns() +func (_BeefyClientWrapper *BeefyClientWrapperTransactorSession) SetMinBlockIncrement(_minBlockIncrement *big.Int) (*types.Transaction, error) { + return _BeefyClientWrapper.Contract.SetMinBlockIncrement(&_BeefyClientWrapper.TransactOpts, _minBlockIncrement) +} + +// SubmitFinal is a paid mutator transaction binding the contract method 0x623b223d. +// +// Solidity: function submitFinal((uint32,uint64,(bytes2,bytes)[]) commitment, uint256[] bitfield, (uint8,bytes32,bytes32,uint256,address,bytes32[])[] proofs, (uint8,uint32,bytes32,uint64,uint32,bytes32,bytes32) leaf, bytes32[] leafProof, uint256 leafProofOrder) returns() +func (_BeefyClientWrapper *BeefyClientWrapperTransactor) SubmitFinal(opts *bind.TransactOpts, commitment IBeefyClientCommitment, bitfield []*big.Int, proofs []IBeefyClientValidatorProof, leaf IBeefyClientMMRLeaf, leafProof [][32]byte, leafProofOrder *big.Int) (*types.Transaction, error) { + return _BeefyClientWrapper.contract.Transact(opts, "submitFinal", commitment, bitfield, proofs, leaf, leafProof, leafProofOrder) +} + +// SubmitFinal is a paid mutator transaction binding the contract method 0x623b223d. +// +// Solidity: function submitFinal((uint32,uint64,(bytes2,bytes)[]) commitment, uint256[] bitfield, (uint8,bytes32,bytes32,uint256,address,bytes32[])[] proofs, (uint8,uint32,bytes32,uint64,uint32,bytes32,bytes32) leaf, bytes32[] leafProof, uint256 leafProofOrder) returns() +func (_BeefyClientWrapper *BeefyClientWrapperSession) SubmitFinal(commitment IBeefyClientCommitment, bitfield []*big.Int, proofs []IBeefyClientValidatorProof, leaf IBeefyClientMMRLeaf, leafProof [][32]byte, leafProofOrder *big.Int) (*types.Transaction, error) { + return _BeefyClientWrapper.Contract.SubmitFinal(&_BeefyClientWrapper.TransactOpts, commitment, bitfield, proofs, leaf, leafProof, leafProofOrder) +} + +// SubmitFinal is a paid mutator transaction binding the contract method 0x623b223d. +// +// Solidity: function submitFinal((uint32,uint64,(bytes2,bytes)[]) commitment, uint256[] bitfield, (uint8,bytes32,bytes32,uint256,address,bytes32[])[] proofs, (uint8,uint32,bytes32,uint64,uint32,bytes32,bytes32) leaf, bytes32[] leafProof, uint256 leafProofOrder) returns() +func (_BeefyClientWrapper *BeefyClientWrapperTransactorSession) SubmitFinal(commitment IBeefyClientCommitment, bitfield []*big.Int, proofs []IBeefyClientValidatorProof, leaf IBeefyClientMMRLeaf, leafProof [][32]byte, leafProofOrder *big.Int) (*types.Transaction, error) { + return _BeefyClientWrapper.Contract.SubmitFinal(&_BeefyClientWrapper.TransactOpts, commitment, bitfield, proofs, leaf, leafProof, leafProofOrder) +} + +// SubmitInitial is a paid mutator transaction binding the contract method 0xbb51f1eb. +// +// Solidity: function submitInitial((uint32,uint64,(bytes2,bytes)[]) commitment, uint256[] bitfield, (uint8,bytes32,bytes32,uint256,address,bytes32[]) proof) returns() +func (_BeefyClientWrapper *BeefyClientWrapperTransactor) SubmitInitial(opts *bind.TransactOpts, commitment IBeefyClientCommitment, bitfield []*big.Int, proof IBeefyClientValidatorProof) (*types.Transaction, error) { + return _BeefyClientWrapper.contract.Transact(opts, "submitInitial", commitment, bitfield, proof) +} + +// SubmitInitial is a paid mutator transaction binding the contract method 0xbb51f1eb. +// +// Solidity: function submitInitial((uint32,uint64,(bytes2,bytes)[]) commitment, uint256[] bitfield, (uint8,bytes32,bytes32,uint256,address,bytes32[]) proof) returns() +func (_BeefyClientWrapper *BeefyClientWrapperSession) SubmitInitial(commitment IBeefyClientCommitment, bitfield []*big.Int, proof IBeefyClientValidatorProof) (*types.Transaction, error) { + return _BeefyClientWrapper.Contract.SubmitInitial(&_BeefyClientWrapper.TransactOpts, commitment, bitfield, proof) +} + +// SubmitInitial is a paid mutator transaction binding the contract method 0xbb51f1eb. +// +// Solidity: function submitInitial((uint32,uint64,(bytes2,bytes)[]) commitment, uint256[] bitfield, (uint8,bytes32,bytes32,uint256,address,bytes32[]) proof) returns() +func (_BeefyClientWrapper *BeefyClientWrapperTransactorSession) SubmitInitial(commitment IBeefyClientCommitment, bitfield []*big.Int, proof IBeefyClientValidatorProof) (*types.Transaction, error) { + return _BeefyClientWrapper.Contract.SubmitInitial(&_BeefyClientWrapper.TransactOpts, commitment, bitfield, proof) +} + +// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b. +// +// Solidity: function transferOwnership(address newOwner) returns() +func (_BeefyClientWrapper *BeefyClientWrapperTransactor) TransferOwnership(opts *bind.TransactOpts, newOwner common.Address) (*types.Transaction, error) { + return _BeefyClientWrapper.contract.Transact(opts, "transferOwnership", newOwner) +} + +// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b. +// +// Solidity: function transferOwnership(address newOwner) returns() +func (_BeefyClientWrapper *BeefyClientWrapperSession) TransferOwnership(newOwner common.Address) (*types.Transaction, error) { + return _BeefyClientWrapper.Contract.TransferOwnership(&_BeefyClientWrapper.TransactOpts, newOwner) +} + +// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b. +// +// Solidity: function transferOwnership(address newOwner) returns() +func (_BeefyClientWrapper *BeefyClientWrapperTransactorSession) TransferOwnership(newOwner common.Address) (*types.Transaction, error) { + return _BeefyClientWrapper.Contract.TransferOwnership(&_BeefyClientWrapper.TransactOpts, newOwner) +} + +// UpgradeTo is a paid mutator transaction binding the contract method 0x50747ac8. +// +// Solidity: function upgradeTo(address newImplementation, bytes32 expectedCodeHash) returns() +func (_BeefyClientWrapper *BeefyClientWrapperTransactor) UpgradeTo(opts *bind.TransactOpts, newImplementation common.Address, expectedCodeHash [32]byte) (*types.Transaction, error) { + return _BeefyClientWrapper.contract.Transact(opts, "upgradeTo", newImplementation, expectedCodeHash) +} + +// UpgradeTo is a paid mutator transaction binding the contract method 0x50747ac8. +// +// Solidity: function upgradeTo(address newImplementation, bytes32 expectedCodeHash) returns() +func (_BeefyClientWrapper *BeefyClientWrapperSession) UpgradeTo(newImplementation common.Address, expectedCodeHash [32]byte) (*types.Transaction, error) { + return _BeefyClientWrapper.Contract.UpgradeTo(&_BeefyClientWrapper.TransactOpts, newImplementation, expectedCodeHash) +} + +// UpgradeTo is a paid mutator transaction binding the contract method 0x50747ac8. +// +// Solidity: function upgradeTo(address newImplementation, bytes32 expectedCodeHash) returns() +func (_BeefyClientWrapper *BeefyClientWrapperTransactorSession) UpgradeTo(newImplementation common.Address, expectedCodeHash [32]byte) (*types.Transaction, error) { + return _BeefyClientWrapper.Contract.UpgradeTo(&_BeefyClientWrapper.TransactOpts, newImplementation, expectedCodeHash) +} + +// WithdrawFunds is a paid mutator transaction binding the contract method 0xc1075329. +// +// Solidity: function withdrawFunds(address recipient, uint256 amount) returns() +func (_BeefyClientWrapper *BeefyClientWrapperTransactor) WithdrawFunds(opts *bind.TransactOpts, recipient common.Address, amount *big.Int) (*types.Transaction, error) { + return _BeefyClientWrapper.contract.Transact(opts, "withdrawFunds", recipient, amount) +} + +// WithdrawFunds is a paid mutator transaction binding the contract method 0xc1075329. +// +// Solidity: function withdrawFunds(address recipient, uint256 amount) returns() +func (_BeefyClientWrapper *BeefyClientWrapperSession) WithdrawFunds(recipient common.Address, amount *big.Int) (*types.Transaction, error) { + return _BeefyClientWrapper.Contract.WithdrawFunds(&_BeefyClientWrapper.TransactOpts, recipient, amount) +} + +// WithdrawFunds is a paid mutator transaction binding the contract method 0xc1075329. +// +// Solidity: function withdrawFunds(address recipient, uint256 amount) returns() +func (_BeefyClientWrapper *BeefyClientWrapperTransactorSession) WithdrawFunds(recipient common.Address, amount *big.Int) (*types.Transaction, error) { + return _BeefyClientWrapper.Contract.WithdrawFunds(&_BeefyClientWrapper.TransactOpts, recipient, amount) +} + +// Receive is a paid mutator transaction binding the contract receive function. +// +// Solidity: receive() payable returns() +func (_BeefyClientWrapper *BeefyClientWrapperTransactor) Receive(opts *bind.TransactOpts) (*types.Transaction, error) { + return _BeefyClientWrapper.contract.RawTransact(opts, nil) // calldata is disallowed for receive function +} + +// Receive is a paid mutator transaction binding the contract receive function. +// +// Solidity: receive() payable returns() +func (_BeefyClientWrapper *BeefyClientWrapperSession) Receive() (*types.Transaction, error) { + return _BeefyClientWrapper.Contract.Receive(&_BeefyClientWrapper.TransactOpts) +} + +// Receive is a paid mutator transaction binding the contract receive function. +// +// Solidity: receive() payable returns() +func (_BeefyClientWrapper *BeefyClientWrapperTransactorSession) Receive() (*types.Transaction, error) { + return _BeefyClientWrapper.Contract.Receive(&_BeefyClientWrapper.TransactOpts) +} + +// BeefyClientWrapperConfigUpdatedIterator is returned from FilterConfigUpdated and is used to iterate over the raw logs and unpacked data for ConfigUpdated events raised by the BeefyClientWrapper contract. +type BeefyClientWrapperConfigUpdatedIterator struct { + Event *BeefyClientWrapperConfigUpdated // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *BeefyClientWrapperConfigUpdatedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(BeefyClientWrapperConfigUpdated) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(BeefyClientWrapperConfigUpdated) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *BeefyClientWrapperConfigUpdatedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *BeefyClientWrapperConfigUpdatedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// BeefyClientWrapperConfigUpdated represents a ConfigUpdated event raised by the BeefyClientWrapper contract. +type BeefyClientWrapperConfigUpdated struct { + Parameter string + Value *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterConfigUpdated is a free log retrieval operation binding the contract event 0x12c9dccd129ff783f1c8228eacdfa8e334ddecb7ec5c9a79ec662a4aed3d012a. +// +// Solidity: event ConfigUpdated(string parameter, uint256 value) +func (_BeefyClientWrapper *BeefyClientWrapperFilterer) FilterConfigUpdated(opts *bind.FilterOpts) (*BeefyClientWrapperConfigUpdatedIterator, error) { + + logs, sub, err := _BeefyClientWrapper.contract.FilterLogs(opts, "ConfigUpdated") + if err != nil { + return nil, err + } + return &BeefyClientWrapperConfigUpdatedIterator{contract: _BeefyClientWrapper.contract, event: "ConfigUpdated", logs: logs, sub: sub}, nil +} + +// WatchConfigUpdated is a free log subscription operation binding the contract event 0x12c9dccd129ff783f1c8228eacdfa8e334ddecb7ec5c9a79ec662a4aed3d012a. +// +// Solidity: event ConfigUpdated(string parameter, uint256 value) +func (_BeefyClientWrapper *BeefyClientWrapperFilterer) WatchConfigUpdated(opts *bind.WatchOpts, sink chan<- *BeefyClientWrapperConfigUpdated) (event.Subscription, error) { + + logs, sub, err := _BeefyClientWrapper.contract.WatchLogs(opts, "ConfigUpdated") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(BeefyClientWrapperConfigUpdated) + if err := _BeefyClientWrapper.contract.UnpackLog(event, "ConfigUpdated", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseConfigUpdated is a log parse operation binding the contract event 0x12c9dccd129ff783f1c8228eacdfa8e334ddecb7ec5c9a79ec662a4aed3d012a. +// +// Solidity: event ConfigUpdated(string parameter, uint256 value) +func (_BeefyClientWrapper *BeefyClientWrapperFilterer) ParseConfigUpdated(log types.Log) (*BeefyClientWrapperConfigUpdated, error) { + event := new(BeefyClientWrapperConfigUpdated) + if err := _BeefyClientWrapper.contract.UnpackLog(event, "ConfigUpdated", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// BeefyClientWrapperFundsDepositedIterator is returned from FilterFundsDeposited and is used to iterate over the raw logs and unpacked data for FundsDeposited events raised by the BeefyClientWrapper contract. +type BeefyClientWrapperFundsDepositedIterator struct { + Event *BeefyClientWrapperFundsDeposited // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *BeefyClientWrapperFundsDepositedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(BeefyClientWrapperFundsDeposited) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(BeefyClientWrapperFundsDeposited) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *BeefyClientWrapperFundsDepositedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *BeefyClientWrapperFundsDepositedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// BeefyClientWrapperFundsDeposited represents a FundsDeposited event raised by the BeefyClientWrapper contract. +type BeefyClientWrapperFundsDeposited struct { + Depositor common.Address + Amount *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterFundsDeposited is a free log retrieval operation binding the contract event 0x543ba50a5eec5e6178218e364b1d0f396157b3c8fa278522c2cb7fd99407d474. +// +// Solidity: event FundsDeposited(address indexed depositor, uint256 amount) +func (_BeefyClientWrapper *BeefyClientWrapperFilterer) FilterFundsDeposited(opts *bind.FilterOpts, depositor []common.Address) (*BeefyClientWrapperFundsDepositedIterator, error) { + + var depositorRule []interface{} + for _, depositorItem := range depositor { + depositorRule = append(depositorRule, depositorItem) + } + + logs, sub, err := _BeefyClientWrapper.contract.FilterLogs(opts, "FundsDeposited", depositorRule) + if err != nil { + return nil, err + } + return &BeefyClientWrapperFundsDepositedIterator{contract: _BeefyClientWrapper.contract, event: "FundsDeposited", logs: logs, sub: sub}, nil +} + +// WatchFundsDeposited is a free log subscription operation binding the contract event 0x543ba50a5eec5e6178218e364b1d0f396157b3c8fa278522c2cb7fd99407d474. +// +// Solidity: event FundsDeposited(address indexed depositor, uint256 amount) +func (_BeefyClientWrapper *BeefyClientWrapperFilterer) WatchFundsDeposited(opts *bind.WatchOpts, sink chan<- *BeefyClientWrapperFundsDeposited, depositor []common.Address) (event.Subscription, error) { + + var depositorRule []interface{} + for _, depositorItem := range depositor { + depositorRule = append(depositorRule, depositorItem) + } + + logs, sub, err := _BeefyClientWrapper.contract.WatchLogs(opts, "FundsDeposited", depositorRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(BeefyClientWrapperFundsDeposited) + if err := _BeefyClientWrapper.contract.UnpackLog(event, "FundsDeposited", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseFundsDeposited is a log parse operation binding the contract event 0x543ba50a5eec5e6178218e364b1d0f396157b3c8fa278522c2cb7fd99407d474. +// +// Solidity: event FundsDeposited(address indexed depositor, uint256 amount) +func (_BeefyClientWrapper *BeefyClientWrapperFilterer) ParseFundsDeposited(log types.Log) (*BeefyClientWrapperFundsDeposited, error) { + event := new(BeefyClientWrapperFundsDeposited) + if err := _BeefyClientWrapper.contract.UnpackLog(event, "FundsDeposited", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// BeefyClientWrapperFundsWithdrawnIterator is returned from FilterFundsWithdrawn and is used to iterate over the raw logs and unpacked data for FundsWithdrawn events raised by the BeefyClientWrapper contract. +type BeefyClientWrapperFundsWithdrawnIterator struct { + Event *BeefyClientWrapperFundsWithdrawn // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *BeefyClientWrapperFundsWithdrawnIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(BeefyClientWrapperFundsWithdrawn) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(BeefyClientWrapperFundsWithdrawn) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *BeefyClientWrapperFundsWithdrawnIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *BeefyClientWrapperFundsWithdrawnIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// BeefyClientWrapperFundsWithdrawn represents a FundsWithdrawn event raised by the BeefyClientWrapper contract. +type BeefyClientWrapperFundsWithdrawn struct { + Recipient common.Address + Amount *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterFundsWithdrawn is a free log retrieval operation binding the contract event 0xeaff4b37086828766ad3268786972c0cd24259d4c87a80f9d3963a3c3d999b0d. +// +// Solidity: event FundsWithdrawn(address indexed recipient, uint256 amount) +func (_BeefyClientWrapper *BeefyClientWrapperFilterer) FilterFundsWithdrawn(opts *bind.FilterOpts, recipient []common.Address) (*BeefyClientWrapperFundsWithdrawnIterator, error) { + + var recipientRule []interface{} + for _, recipientItem := range recipient { + recipientRule = append(recipientRule, recipientItem) + } + + logs, sub, err := _BeefyClientWrapper.contract.FilterLogs(opts, "FundsWithdrawn", recipientRule) + if err != nil { + return nil, err + } + return &BeefyClientWrapperFundsWithdrawnIterator{contract: _BeefyClientWrapper.contract, event: "FundsWithdrawn", logs: logs, sub: sub}, nil +} + +// WatchFundsWithdrawn is a free log subscription operation binding the contract event 0xeaff4b37086828766ad3268786972c0cd24259d4c87a80f9d3963a3c3d999b0d. +// +// Solidity: event FundsWithdrawn(address indexed recipient, uint256 amount) +func (_BeefyClientWrapper *BeefyClientWrapperFilterer) WatchFundsWithdrawn(opts *bind.WatchOpts, sink chan<- *BeefyClientWrapperFundsWithdrawn, recipient []common.Address) (event.Subscription, error) { + + var recipientRule []interface{} + for _, recipientItem := range recipient { + recipientRule = append(recipientRule, recipientItem) + } + + logs, sub, err := _BeefyClientWrapper.contract.WatchLogs(opts, "FundsWithdrawn", recipientRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(BeefyClientWrapperFundsWithdrawn) + if err := _BeefyClientWrapper.contract.UnpackLog(event, "FundsWithdrawn", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseFundsWithdrawn is a log parse operation binding the contract event 0xeaff4b37086828766ad3268786972c0cd24259d4c87a80f9d3963a3c3d999b0d. +// +// Solidity: event FundsWithdrawn(address indexed recipient, uint256 amount) +func (_BeefyClientWrapper *BeefyClientWrapperFilterer) ParseFundsWithdrawn(log types.Log) (*BeefyClientWrapperFundsWithdrawn, error) { + event := new(BeefyClientWrapperFundsWithdrawn) + if err := _BeefyClientWrapper.contract.UnpackLog(event, "FundsWithdrawn", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// BeefyClientWrapperRelayerAddedIterator is returned from FilterRelayerAdded and is used to iterate over the raw logs and unpacked data for RelayerAdded events raised by the BeefyClientWrapper contract. +type BeefyClientWrapperRelayerAddedIterator struct { + Event *BeefyClientWrapperRelayerAdded // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *BeefyClientWrapperRelayerAddedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(BeefyClientWrapperRelayerAdded) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(BeefyClientWrapperRelayerAdded) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *BeefyClientWrapperRelayerAddedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *BeefyClientWrapperRelayerAddedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// BeefyClientWrapperRelayerAdded represents a RelayerAdded event raised by the BeefyClientWrapper contract. +type BeefyClientWrapperRelayerAdded struct { + Relayer common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterRelayerAdded is a free log retrieval operation binding the contract event 0x03580ee9f53a62b7cb409a2cb56f9be87747dd15017afc5cef6eef321e4fb2c5. +// +// Solidity: event RelayerAdded(address indexed relayer) +func (_BeefyClientWrapper *BeefyClientWrapperFilterer) FilterRelayerAdded(opts *bind.FilterOpts, relayer []common.Address) (*BeefyClientWrapperRelayerAddedIterator, error) { + + var relayerRule []interface{} + for _, relayerItem := range relayer { + relayerRule = append(relayerRule, relayerItem) + } + + logs, sub, err := _BeefyClientWrapper.contract.FilterLogs(opts, "RelayerAdded", relayerRule) + if err != nil { + return nil, err + } + return &BeefyClientWrapperRelayerAddedIterator{contract: _BeefyClientWrapper.contract, event: "RelayerAdded", logs: logs, sub: sub}, nil +} + +// WatchRelayerAdded is a free log subscription operation binding the contract event 0x03580ee9f53a62b7cb409a2cb56f9be87747dd15017afc5cef6eef321e4fb2c5. +// +// Solidity: event RelayerAdded(address indexed relayer) +func (_BeefyClientWrapper *BeefyClientWrapperFilterer) WatchRelayerAdded(opts *bind.WatchOpts, sink chan<- *BeefyClientWrapperRelayerAdded, relayer []common.Address) (event.Subscription, error) { + + var relayerRule []interface{} + for _, relayerItem := range relayer { + relayerRule = append(relayerRule, relayerItem) + } + + logs, sub, err := _BeefyClientWrapper.contract.WatchLogs(opts, "RelayerAdded", relayerRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(BeefyClientWrapperRelayerAdded) + if err := _BeefyClientWrapper.contract.UnpackLog(event, "RelayerAdded", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseRelayerAdded is a log parse operation binding the contract event 0x03580ee9f53a62b7cb409a2cb56f9be87747dd15017afc5cef6eef321e4fb2c5. +// +// Solidity: event RelayerAdded(address indexed relayer) +func (_BeefyClientWrapper *BeefyClientWrapperFilterer) ParseRelayerAdded(log types.Log) (*BeefyClientWrapperRelayerAdded, error) { + event := new(BeefyClientWrapperRelayerAdded) + if err := _BeefyClientWrapper.contract.UnpackLog(event, "RelayerAdded", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// BeefyClientWrapperRelayerRemovedIterator is returned from FilterRelayerRemoved and is used to iterate over the raw logs and unpacked data for RelayerRemoved events raised by the BeefyClientWrapper contract. +type BeefyClientWrapperRelayerRemovedIterator struct { + Event *BeefyClientWrapperRelayerRemoved // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *BeefyClientWrapperRelayerRemovedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(BeefyClientWrapperRelayerRemoved) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(BeefyClientWrapperRelayerRemoved) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *BeefyClientWrapperRelayerRemovedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *BeefyClientWrapperRelayerRemovedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// BeefyClientWrapperRelayerRemoved represents a RelayerRemoved event raised by the BeefyClientWrapper contract. +type BeefyClientWrapperRelayerRemoved struct { + Relayer common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterRelayerRemoved is a free log retrieval operation binding the contract event 0x10e1f7ce9fd7d1b90a66d13a2ab3cb8dd7f29f3f8d520b143b063ccfbab6906b. +// +// Solidity: event RelayerRemoved(address indexed relayer) +func (_BeefyClientWrapper *BeefyClientWrapperFilterer) FilterRelayerRemoved(opts *bind.FilterOpts, relayer []common.Address) (*BeefyClientWrapperRelayerRemovedIterator, error) { + + var relayerRule []interface{} + for _, relayerItem := range relayer { + relayerRule = append(relayerRule, relayerItem) + } + + logs, sub, err := _BeefyClientWrapper.contract.FilterLogs(opts, "RelayerRemoved", relayerRule) + if err != nil { + return nil, err + } + return &BeefyClientWrapperRelayerRemovedIterator{contract: _BeefyClientWrapper.contract, event: "RelayerRemoved", logs: logs, sub: sub}, nil +} + +// WatchRelayerRemoved is a free log subscription operation binding the contract event 0x10e1f7ce9fd7d1b90a66d13a2ab3cb8dd7f29f3f8d520b143b063ccfbab6906b. +// +// Solidity: event RelayerRemoved(address indexed relayer) +func (_BeefyClientWrapper *BeefyClientWrapperFilterer) WatchRelayerRemoved(opts *bind.WatchOpts, sink chan<- *BeefyClientWrapperRelayerRemoved, relayer []common.Address) (event.Subscription, error) { + + var relayerRule []interface{} + for _, relayerItem := range relayer { + relayerRule = append(relayerRule, relayerItem) + } + + logs, sub, err := _BeefyClientWrapper.contract.WatchLogs(opts, "RelayerRemoved", relayerRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(BeefyClientWrapperRelayerRemoved) + if err := _BeefyClientWrapper.contract.UnpackLog(event, "RelayerRemoved", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseRelayerRemoved is a log parse operation binding the contract event 0x10e1f7ce9fd7d1b90a66d13a2ab3cb8dd7f29f3f8d520b143b063ccfbab6906b. +// +// Solidity: event RelayerRemoved(address indexed relayer) +func (_BeefyClientWrapper *BeefyClientWrapperFilterer) ParseRelayerRemoved(log types.Log) (*BeefyClientWrapperRelayerRemoved, error) { + event := new(BeefyClientWrapperRelayerRemoved) + if err := _BeefyClientWrapper.contract.UnpackLog(event, "RelayerRemoved", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// BeefyClientWrapperSubmissionRefundedIterator is returned from FilterSubmissionRefunded and is used to iterate over the raw logs and unpacked data for SubmissionRefunded events raised by the BeefyClientWrapper contract. +type BeefyClientWrapperSubmissionRefundedIterator struct { + Event *BeefyClientWrapperSubmissionRefunded // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *BeefyClientWrapperSubmissionRefundedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(BeefyClientWrapperSubmissionRefunded) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(BeefyClientWrapperSubmissionRefunded) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *BeefyClientWrapperSubmissionRefundedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *BeefyClientWrapperSubmissionRefundedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// BeefyClientWrapperSubmissionRefunded represents a SubmissionRefunded event raised by the BeefyClientWrapper contract. +type BeefyClientWrapperSubmissionRefunded struct { + Relayer common.Address + Amount *big.Int + GasUsed *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterSubmissionRefunded is a free log retrieval operation binding the contract event 0x103cb711554967fbeea0c6394a6dfedc44d0e729191e719d0976438783912f52. +// +// Solidity: event SubmissionRefunded(address indexed relayer, uint256 amount, uint256 gasUsed) +func (_BeefyClientWrapper *BeefyClientWrapperFilterer) FilterSubmissionRefunded(opts *bind.FilterOpts, relayer []common.Address) (*BeefyClientWrapperSubmissionRefundedIterator, error) { + + var relayerRule []interface{} + for _, relayerItem := range relayer { + relayerRule = append(relayerRule, relayerItem) + } + + logs, sub, err := _BeefyClientWrapper.contract.FilterLogs(opts, "SubmissionRefunded", relayerRule) + if err != nil { + return nil, err + } + return &BeefyClientWrapperSubmissionRefundedIterator{contract: _BeefyClientWrapper.contract, event: "SubmissionRefunded", logs: logs, sub: sub}, nil +} + +// WatchSubmissionRefunded is a free log subscription operation binding the contract event 0x103cb711554967fbeea0c6394a6dfedc44d0e729191e719d0976438783912f52. +// +// Solidity: event SubmissionRefunded(address indexed relayer, uint256 amount, uint256 gasUsed) +func (_BeefyClientWrapper *BeefyClientWrapperFilterer) WatchSubmissionRefunded(opts *bind.WatchOpts, sink chan<- *BeefyClientWrapperSubmissionRefunded, relayer []common.Address) (event.Subscription, error) { + + var relayerRule []interface{} + for _, relayerItem := range relayer { + relayerRule = append(relayerRule, relayerItem) + } + + logs, sub, err := _BeefyClientWrapper.contract.WatchLogs(opts, "SubmissionRefunded", relayerRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(BeefyClientWrapperSubmissionRefunded) + if err := _BeefyClientWrapper.contract.UnpackLog(event, "SubmissionRefunded", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseSubmissionRefunded is a log parse operation binding the contract event 0x103cb711554967fbeea0c6394a6dfedc44d0e729191e719d0976438783912f52. +// +// Solidity: event SubmissionRefunded(address indexed relayer, uint256 amount, uint256 gasUsed) +func (_BeefyClientWrapper *BeefyClientWrapperFilterer) ParseSubmissionRefunded(log types.Log) (*BeefyClientWrapperSubmissionRefunded, error) { + event := new(BeefyClientWrapperSubmissionRefunded) + if err := _BeefyClientWrapper.contract.UnpackLog(event, "SubmissionRefunded", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// BeefyClientWrapperTurnAdvancedIterator is returned from FilterTurnAdvanced and is used to iterate over the raw logs and unpacked data for TurnAdvanced events raised by the BeefyClientWrapper contract. +type BeefyClientWrapperTurnAdvancedIterator struct { + Event *BeefyClientWrapperTurnAdvanced // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *BeefyClientWrapperTurnAdvancedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(BeefyClientWrapperTurnAdvanced) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(BeefyClientWrapperTurnAdvanced) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *BeefyClientWrapperTurnAdvancedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *BeefyClientWrapperTurnAdvancedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// BeefyClientWrapperTurnAdvanced represents a TurnAdvanced event raised by the BeefyClientWrapper contract. +type BeefyClientWrapperTurnAdvanced struct { + NewTurnIndex *big.Int + NextRelayer common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterTurnAdvanced is a free log retrieval operation binding the contract event 0xa1fbd218639d21bc371d11c5d99434f6b493f6b7c3740271906c91b62a215434. +// +// Solidity: event TurnAdvanced(uint256 indexed newTurnIndex, address indexed nextRelayer) +func (_BeefyClientWrapper *BeefyClientWrapperFilterer) FilterTurnAdvanced(opts *bind.FilterOpts, newTurnIndex []*big.Int, nextRelayer []common.Address) (*BeefyClientWrapperTurnAdvancedIterator, error) { + + var newTurnIndexRule []interface{} + for _, newTurnIndexItem := range newTurnIndex { + newTurnIndexRule = append(newTurnIndexRule, newTurnIndexItem) + } + var nextRelayerRule []interface{} + for _, nextRelayerItem := range nextRelayer { + nextRelayerRule = append(nextRelayerRule, nextRelayerItem) + } + + logs, sub, err := _BeefyClientWrapper.contract.FilterLogs(opts, "TurnAdvanced", newTurnIndexRule, nextRelayerRule) + if err != nil { + return nil, err + } + return &BeefyClientWrapperTurnAdvancedIterator{contract: _BeefyClientWrapper.contract, event: "TurnAdvanced", logs: logs, sub: sub}, nil +} + +// WatchTurnAdvanced is a free log subscription operation binding the contract event 0xa1fbd218639d21bc371d11c5d99434f6b493f6b7c3740271906c91b62a215434. +// +// Solidity: event TurnAdvanced(uint256 indexed newTurnIndex, address indexed nextRelayer) +func (_BeefyClientWrapper *BeefyClientWrapperFilterer) WatchTurnAdvanced(opts *bind.WatchOpts, sink chan<- *BeefyClientWrapperTurnAdvanced, newTurnIndex []*big.Int, nextRelayer []common.Address) (event.Subscription, error) { + + var newTurnIndexRule []interface{} + for _, newTurnIndexItem := range newTurnIndex { + newTurnIndexRule = append(newTurnIndexRule, newTurnIndexItem) + } + var nextRelayerRule []interface{} + for _, nextRelayerItem := range nextRelayer { + nextRelayerRule = append(nextRelayerRule, nextRelayerItem) + } + + logs, sub, err := _BeefyClientWrapper.contract.WatchLogs(opts, "TurnAdvanced", newTurnIndexRule, nextRelayerRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(BeefyClientWrapperTurnAdvanced) + if err := _BeefyClientWrapper.contract.UnpackLog(event, "TurnAdvanced", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseTurnAdvanced is a log parse operation binding the contract event 0xa1fbd218639d21bc371d11c5d99434f6b493f6b7c3740271906c91b62a215434. +// +// Solidity: event TurnAdvanced(uint256 indexed newTurnIndex, address indexed nextRelayer) +func (_BeefyClientWrapper *BeefyClientWrapperFilterer) ParseTurnAdvanced(log types.Log) (*BeefyClientWrapperTurnAdvanced, error) { + event := new(BeefyClientWrapperTurnAdvanced) + if err := _BeefyClientWrapper.contract.UnpackLog(event, "TurnAdvanced", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// BeefyClientWrapperUpgradedIterator is returned from FilterUpgraded and is used to iterate over the raw logs and unpacked data for Upgraded events raised by the BeefyClientWrapper contract. +type BeefyClientWrapperUpgradedIterator struct { + Event *BeefyClientWrapperUpgraded // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *BeefyClientWrapperUpgradedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(BeefyClientWrapperUpgraded) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(BeefyClientWrapperUpgraded) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *BeefyClientWrapperUpgradedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *BeefyClientWrapperUpgradedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// BeefyClientWrapperUpgraded represents a Upgraded event raised by the BeefyClientWrapper contract. +type BeefyClientWrapperUpgraded struct { + Implementation common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterUpgraded is a free log retrieval operation binding the contract event 0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b. +// +// Solidity: event Upgraded(address indexed implementation) +func (_BeefyClientWrapper *BeefyClientWrapperFilterer) FilterUpgraded(opts *bind.FilterOpts, implementation []common.Address) (*BeefyClientWrapperUpgradedIterator, error) { + + var implementationRule []interface{} + for _, implementationItem := range implementation { + implementationRule = append(implementationRule, implementationItem) + } + + logs, sub, err := _BeefyClientWrapper.contract.FilterLogs(opts, "Upgraded", implementationRule) + if err != nil { + return nil, err + } + return &BeefyClientWrapperUpgradedIterator{contract: _BeefyClientWrapper.contract, event: "Upgraded", logs: logs, sub: sub}, nil +} + +// WatchUpgraded is a free log subscription operation binding the contract event 0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b. +// +// Solidity: event Upgraded(address indexed implementation) +func (_BeefyClientWrapper *BeefyClientWrapperFilterer) WatchUpgraded(opts *bind.WatchOpts, sink chan<- *BeefyClientWrapperUpgraded, implementation []common.Address) (event.Subscription, error) { + + var implementationRule []interface{} + for _, implementationItem := range implementation { + implementationRule = append(implementationRule, implementationItem) + } + + logs, sub, err := _BeefyClientWrapper.contract.WatchLogs(opts, "Upgraded", implementationRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(BeefyClientWrapperUpgraded) + if err := _BeefyClientWrapper.contract.UnpackLog(event, "Upgraded", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseUpgraded is a log parse operation binding the contract event 0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b. +// +// Solidity: event Upgraded(address indexed implementation) +func (_BeefyClientWrapper *BeefyClientWrapperFilterer) ParseUpgraded(log types.Log) (*BeefyClientWrapperUpgraded, error) { + event := new(BeefyClientWrapperUpgraded) + if err := _BeefyClientWrapper.contract.UnpackLog(event, "Upgraded", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} diff --git a/relayer/generate.go b/relayer/generate.go index 106b67a7d..fc93bcb42 100644 --- a/relayer/generate.go +++ b/relayer/generate.go @@ -1,4 +1,5 @@ //go:generate bash -c "jq .abi ../contracts/out/BeefyClient.sol/BeefyClient.json | abigen --abi - --type BeefyClient --pkg contracts --out contracts/beefy_client.go" +//go:generate bash -c "jq .abi ../contracts/out/BeefyClientWrapper.sol/BeefyClientWrapper.json | abigen --abi - --type BeefyClientWrapper --pkg contracts --out contracts/beefy_client_wrapper.go" //go:generate bash -c "jq .abi ../contracts/out/IGateway.sol/IGatewayV2.json | abigen --abi - --type Gateway --pkg contracts --out contracts/gateway.go" //go:generate bash -c "jq .abi ../contracts/out/IGateway.sol/IGatewayV1.json | abigen --abi - --type Gateway --pkg contracts --out contracts/v1/gateway.go" diff --git a/relayer/relays/beefy/ethereum-writer.go b/relayer/relays/beefy/ethereum-writer.go index d97bdaf87..2431d58a1 100644 --- a/relayer/relays/beefy/ethereum-writer.go +++ b/relayer/relays/beefy/ethereum-writer.go @@ -6,6 +6,7 @@ import ( "fmt" "math/big" "math/rand" + "time" "golang.org/x/sync/errgroup" @@ -26,6 +27,7 @@ type EthereumWriter struct { config *SinkConfig conn *ethereum.Connection contract *contracts.BeefyClient + wrapper *contracts.BeefyClientWrapper blockWaitPeriod uint64 } @@ -64,6 +66,12 @@ func (wr *EthereumWriter) Start(ctx context.Context, eg *errgroup.Group, request continue } + // Wait until we're eligible to submit (turn-based scheduling) + err = wr.waitForTurnEligibility(ctx) + if err != nil { + return fmt.Errorf("wait for turn eligibility: %w", err) + } + // Mandatory commitments are always signed by the next validator set recorded in // the beefy light client task.ValidatorsRoot = state.NextValidatorSetRoot @@ -300,6 +308,77 @@ func (wr *EthereumWriter) doSubmitFinal(ctx context.Context, commitmentHash [32] return tx, nil } +func (wr *EthereumWriter) waitForTurnEligibility(ctx context.Context) error { + for { + eligible, err := wr.checkTurnEligibility(ctx) + if err != nil { + return err + } + if eligible { + return nil + } + + // Wait before checking again + log.Debug("Not eligible yet, waiting 12 seconds before rechecking...") + select { + case <-ctx.Done(): + return ctx.Err() + case <-time.After(12 * time.Second): + // Check again + } + } +} + +func (wr *EthereumWriter) checkTurnEligibility(ctx context.Context) (bool, error) { + // If no wrapper configured, always eligible (backwards compatible) + if wr.wrapper == nil { + return true, nil + } + + callOpts := bind.CallOpts{ + Context: ctx, + } + + myAddress := wr.conn.Keypair().CommonAddress() + + // Check if it's our turn + currentTurnRelayer, err := wr.wrapper.GetCurrentTurnRelayer(&callOpts) + if err != nil { + return false, fmt.Errorf("get current turn relayer: %w", err) + } + + if currentTurnRelayer == myAddress { + log.WithFields(logrus.Fields{ + "currentTurnRelayer": currentTurnRelayer.Hex(), + "myAddress": myAddress.Hex(), + }).Debug("It's our turn to submit") + return true, nil + } + + // Not our turn, check if grace period is active + gracePeriodActive, err := wr.wrapper.IsGracePeriodActive(&callOpts) + if err != nil { + return false, fmt.Errorf("check grace period: %w", err) + } + + if gracePeriodActive { + log.WithFields(logrus.Fields{ + "currentTurnRelayer": currentTurnRelayer.Hex(), + "myAddress": myAddress.Hex(), + "gracePeriodActive": true, + }).Debug("Not our turn, but grace period is active - proceeding") + return true, nil + } + + log.WithFields(logrus.Fields{ + "currentTurnRelayer": currentTurnRelayer.Hex(), + "myAddress": myAddress.Hex(), + "gracePeriodActive": false, + }).Info("Not our turn and grace period not active - skipping submission") + + return false, nil +} + func (wr *EthereumWriter) initialize(ctx context.Context) error { address := common.HexToAddress(wr.config.Contracts.BeefyClient) contract, err := contracts.NewBeefyClient(address, wr.conn.Client()) @@ -308,6 +387,17 @@ func (wr *EthereumWriter) initialize(ctx context.Context) error { } wr.contract = contract + // Also create wrapper bindings for turn-checking functions + // This works whether BeefyClient points to the wrapper or the original contract + wrapper, err := contracts.NewBeefyClientWrapper(address, wr.conn.Client()) + if err != nil { + // If wrapper bindings fail, it means we're using the original BeefyClient + // which doesn't have turn-checking - that's fine, we'll skip eligibility checks + log.Debug("BeefyClientWrapper bindings not available - turn checking disabled") + } else { + wr.wrapper = wrapper + } + callOpts := bind.CallOpts{ Context: ctx, } From 919f503138ea66949563872471080953adc32733 Mon Sep 17 00:00:00 2001 From: claravanstaden Date: Thu, 8 Jan 2026 09:06:31 +0200 Subject: [PATCH 03/17] remove receive impl --- contracts/src/BeefyClientWrapperProxy.sol | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/contracts/src/BeefyClientWrapperProxy.sol b/contracts/src/BeefyClientWrapperProxy.sol index b6be6ac3e..23d671b3d 100644 --- a/contracts/src/BeefyClientWrapperProxy.sol +++ b/contracts/src/BeefyClientWrapperProxy.sol @@ -37,15 +37,6 @@ contract BeefyClientWrapperProxy is IInitializable { } } - // Accept ETH deposits to fund relayer refunds - receive() external payable { - address implementation = ERC1967.load(); - assembly { - let result := delegatecall(gas(), implementation, 0, 0, 0, 0) - returndatacopy(0, 0, returndatasize()) - switch result - case 0 { revert(0, returndatasize()) } - default { return(0, returndatasize()) } - } - } + // Note: No receive() needed - fallback() handles plain ETH transfers + // by delegating to the implementation's receive() function } From 58284126425e069a17655493667a17470245f232 Mon Sep 17 00:00:00 2001 From: claravanstaden Date: Thu, 8 Jan 2026 09:14:45 +0200 Subject: [PATCH 04/17] refund gas at end of interactive protocol --- contracts/src/BeefyClientWrapper.sol | 60 +++++++++++++++--- contracts/src/interfaces/IBeefyClient.sol | 17 +++++ contracts/test/BeefyClientWrapper.t.sol | 76 +++++++++++++++++++++-- 3 files changed, 140 insertions(+), 13 deletions(-) diff --git a/contracts/src/BeefyClientWrapper.sol b/contracts/src/BeefyClientWrapper.sol index b1e1696fb..7a5b3eec5 100644 --- a/contracts/src/BeefyClientWrapper.sol +++ b/contracts/src/BeefyClientWrapper.sol @@ -15,7 +15,8 @@ import {ERC1967} from "./utils/ERC1967.sol"; contract BeefyClientWrapper is IInitializable, IUpgradable { event RelayerAdded(address indexed relayer); event RelayerRemoved(address indexed relayer); - event SubmissionRefunded(address indexed relayer, uint256 amount, uint256 gasUsed); + event GasCredited(address indexed relayer, bytes32 indexed commitmentHash, uint256 gasUsed); + event SubmissionRefunded(address indexed relayer, uint256 amount, uint256 totalGasUsed); event TurnAdvanced(uint256 indexed newTurnIndex, address indexed nextRelayer); event FundsDeposited(address indexed depositor, uint256 amount); event FundsWithdrawn(address indexed recipient, uint256 amount); @@ -47,6 +48,7 @@ contract BeefyClientWrapper is IInitializable, IUpgradable { uint256 public minBlockIncrement; mapping(bytes32 => address) public ticketOwner; mapping(address => bytes32) public activeTicket; + mapping(bytes32 => uint256) public creditedGas; bool private initialized; function initialize(bytes calldata data) external override { @@ -98,7 +100,7 @@ contract BeefyClientWrapper is IInitializable, IUpgradable { ticketOwner[commitmentHash] = msg.sender; activeTicket[msg.sender] = commitmentHash; - _refundGas(startGas); + _creditGas(startGas, commitmentHash); } function commitPrevRandao(bytes32 commitmentHash) external { @@ -110,7 +112,7 @@ contract BeefyClientWrapper is IInitializable, IUpgradable { beefyClient.commitPrevRandao(commitmentHash); - _refundGas(startGas); + _creditGas(startGas, commitmentHash); } function submitFinal( @@ -130,10 +132,13 @@ contract BeefyClientWrapper is IInitializable, IUpgradable { beefyClient.submitFinal(commitment, bitfield, proofs, leaf, leafProof, leafProofOrder); + uint256 previousGas = creditedGas[commitmentHash]; + delete creditedGas[commitmentHash]; delete ticketOwner[commitmentHash]; delete activeTicket[msg.sender]; + _advanceTurn(); - _refundGas(startGas); + _refundGas(startGas, previousGas); } function createFinalBitfield(bytes32 commitmentHash, uint256[] calldata bitfield) @@ -148,12 +153,42 @@ contract BeefyClientWrapper is IInitializable, IUpgradable { return beefyClient.latestBeefyBlock(); } + function createInitialBitfield(uint256[] calldata bitsToSet, uint256 length) + external + view + returns (uint256[] memory) + { + return beefyClient.createInitialBitfield(bitsToSet, length); + } + + function randaoCommitDelay() external view returns (uint256) { + return beefyClient.randaoCommitDelay(); + } + + function currentValidatorSet() + external + view + returns (uint128 id, uint128 length, bytes32 root) + { + return beefyClient.currentValidatorSet(); + } + + function nextValidatorSet() + external + view + returns (uint128 id, uint128 length, bytes32 root) + { + return beefyClient.nextValidatorSet(); + } + function clearTicket() external { bytes32 commitmentHash = activeTicket[msg.sender]; if (commitmentHash == bytes32(0)) { revert InvalidTicket(); } + // Credited gas is forfeited when clearing a ticket + delete creditedGas[commitmentHash]; delete ticketOwner[commitmentHash]; delete activeTicket[msg.sender]; } @@ -182,15 +217,22 @@ contract BeefyClientWrapper is IInitializable, IUpgradable { } } - function _refundGas(uint256 startGas) internal { + function _creditGas(uint256 startGas, bytes32 commitmentHash) internal { uint256 gasUsed = startGas - gasleft() + 21000; + creditedGas[commitmentHash] += gasUsed; + emit GasCredited(msg.sender, commitmentHash, gasUsed); + } + + function _refundGas(uint256 startGas, uint256 previousGas) internal { + uint256 currentGas = startGas - gasleft() + 21000; + uint256 totalGasUsed = currentGas + previousGas; uint256 effectiveGasPrice = tx.gasprice < maxGasPrice ? tx.gasprice : maxGasPrice; - uint256 refundAmount = gasUsed * effectiveGasPrice; + uint256 refundAmount = totalGasUsed * effectiveGasPrice; if (address(this).balance >= refundAmount) { (bool success,) = payable(msg.sender).call{value: refundAmount}(""); if (success) { - emit SubmissionRefunded(msg.sender, refundAmount, gasUsed); + emit SubmissionRefunded(msg.sender, refundAmount, totalGasUsed); } } } @@ -329,6 +371,10 @@ contract BeefyClientWrapper is IInitializable, IUpgradable { return address(this).balance; } + function getCreditedGas(bytes32 commitmentHash) external view returns (uint256) { + return creditedGas[commitmentHash]; + } + receive() external payable { emit FundsDeposited(msg.sender, msg.value); } diff --git a/contracts/src/interfaces/IBeefyClient.sol b/contracts/src/interfaces/IBeefyClient.sol index b71e4e966..1fa15c3ec 100644 --- a/contracts/src/interfaces/IBeefyClient.sol +++ b/contracts/src/interfaces/IBeefyClient.sol @@ -60,4 +60,21 @@ interface IBeefyClient { external view returns (uint256[] memory); + + function createInitialBitfield(uint256[] calldata bitsToSet, uint256 length) + external + pure + returns (uint256[] memory); + + function randaoCommitDelay() external view returns (uint256); + + function currentValidatorSet() + external + view + returns (uint128 id, uint128 length, bytes32 root); + + function nextValidatorSet() + external + view + returns (uint128 id, uint128 length, bytes32 root); } diff --git a/contracts/test/BeefyClientWrapper.t.sol b/contracts/test/BeefyClientWrapper.t.sol index 1125b1184..79ca97939 100644 --- a/contracts/test/BeefyClientWrapper.t.sol +++ b/contracts/test/BeefyClientWrapper.t.sol @@ -354,7 +354,7 @@ contract BeefyClientWrapperTest is Test { /* Refund Tests */ - function test_refundsSentOnSubmission() public { + function test_gasCreditedOnSubmitInitial() public { uint32 newBlockNumber = uint32(INITIAL_BEEFY_BLOCK + MIN_BLOCK_INCREMENT + 1); IBeefyClient.Commitment memory commitment = createCommitment(newBlockNumber); uint256[] memory bitfield = new uint256[](1); @@ -366,8 +366,41 @@ contract BeefyClientWrapperTest is Test { vm.txGasPrice(50 gwei); wrapper.submitInitial(commitment, bitfield, proof); - // Relayer should have received a refund + // No immediate refund, gas is credited instead + assertEq(relayer1.balance, relayerBalanceBefore); + + // Gas should be credited + bytes32 commitmentHash = keccak256(abi.encode(commitment)); + assertGt(wrapper.getCreditedGas(commitmentHash), 0); + } + + function test_refundSentOnlyAfterSubmitFinal() public { + uint32 newBlockNumber = uint32(INITIAL_BEEFY_BLOCK + MIN_BLOCK_INCREMENT + 1); + IBeefyClient.Commitment memory commitment = createCommitment(newBlockNumber); + uint256[] memory bitfield = new uint256[](1); + IBeefyClient.ValidatorProof memory proof = createValidatorProof(); + IBeefyClient.ValidatorProof[] memory proofs = createValidatorProofs(1); + IBeefyClient.MMRLeaf memory leaf = createMMRLeaf(); + bytes32[] memory leafProof = new bytes32[](0); + + uint256 relayerBalanceBefore = relayer1.balance; + + vm.startPrank(relayer1); + vm.txGasPrice(50 gwei); + + wrapper.submitInitial(commitment, bitfield, proof); + assertEq(relayer1.balance, relayerBalanceBefore); + + bytes32 commitmentHash = keccak256(abi.encode(commitment)); + wrapper.commitPrevRandao(commitmentHash); + assertEq(relayer1.balance, relayerBalanceBefore); + + wrapper.submitFinal(commitment, bitfield, proofs, leaf, leafProof, 0); assertGt(relayer1.balance, relayerBalanceBefore); + + vm.stopPrank(); + + assertEq(wrapper.getCreditedGas(commitmentHash), 0); } function test_refundCappedAtMaxGasPrice() public { @@ -375,14 +408,21 @@ contract BeefyClientWrapperTest is Test { IBeefyClient.Commitment memory commitment = createCommitment(newBlockNumber); uint256[] memory bitfield = new uint256[](1); IBeefyClient.ValidatorProof memory proof = createValidatorProof(); + IBeefyClient.ValidatorProof[] memory proofs = createValidatorProofs(1); + IBeefyClient.MMRLeaf memory leaf = createMMRLeaf(); + bytes32[] memory leafProof = new bytes32[](0); uint256 relayerBalanceBefore = relayer1.balance; uint256 proxyBalanceBefore = address(proxy).balance; // Use gas price higher than max - vm.prank(relayer1); + vm.startPrank(relayer1); vm.txGasPrice(200 gwei); // Higher than MAX_GAS_PRICE (100 gwei) wrapper.submitInitial(commitment, bitfield, proof); + bytes32 commitmentHash = keccak256(abi.encode(commitment)); + wrapper.commitPrevRandao(commitmentHash); + wrapper.submitFinal(commitment, bitfield, proofs, leaf, leafProof, 0); + vm.stopPrank(); uint256 refundAmount = relayer1.balance - relayerBalanceBefore; uint256 proxySpent = proxyBalanceBefore - address(proxy).balance; @@ -400,15 +440,39 @@ contract BeefyClientWrapperTest is Test { IBeefyClient.Commitment memory commitment = createCommitment(newBlockNumber); uint256[] memory bitfield = new uint256[](1); IBeefyClient.ValidatorProof memory proof = createValidatorProof(); + IBeefyClient.ValidatorProof[] memory proofs = createValidatorProofs(1); + IBeefyClient.MMRLeaf memory leaf = createMMRLeaf(); + bytes32[] memory leafProof = new bytes32[](0); uint256 relayerBalanceBefore = relayer1.balance; - // Submission should still succeed, just no refund - vm.prank(relayer1); + vm.startPrank(relayer1); wrapper.submitInitial(commitment, bitfield, proof); + bytes32 commitmentHash = keccak256(abi.encode(commitment)); + wrapper.commitPrevRandao(commitmentHash); + wrapper.submitFinal(commitment, bitfield, proofs, leaf, leafProof, 0); + vm.stopPrank(); assertEq(relayer1.balance, relayerBalanceBefore); // No refund - assertEq(mockBeefyClient.submitInitialCount(), 1); // But submission succeeded + assertEq(mockBeefyClient.submitFinalCount(), 1); // Submission succeeded + } + + function test_creditedGasForfeitedOnClearTicket() public { + uint32 newBlockNumber = uint32(INITIAL_BEEFY_BLOCK + MIN_BLOCK_INCREMENT + 1); + IBeefyClient.Commitment memory commitment = createCommitment(newBlockNumber); + uint256[] memory bitfield = new uint256[](1); + IBeefyClient.ValidatorProof memory proof = createValidatorProof(); + + vm.startPrank(relayer1); + wrapper.submitInitial(commitment, bitfield, proof); + + bytes32 commitmentHash = keccak256(abi.encode(commitment)); + assertGt(wrapper.getCreditedGas(commitmentHash), 0); + + // Clear ticket - gas should be forfeited + wrapper.clearTicket(); + assertEq(wrapper.getCreditedGas(commitmentHash), 0); + vm.stopPrank(); } /* Admin Function Tests */ From e43ab5f2f57c66b83df7b2d2e36ba9b063750239 Mon Sep 17 00:00:00 2001 From: claravanstaden Date: Thu, 8 Jan 2026 09:27:52 +0200 Subject: [PATCH 05/17] set max refund amount --- contracts/src/BeefyClientWrapper.sol | 21 +++++++---- contracts/test/BeefyClientWrapper.t.sol | 47 +++++++++++++++++++++++-- 2 files changed, 60 insertions(+), 8 deletions(-) diff --git a/contracts/src/BeefyClientWrapper.sol b/contracts/src/BeefyClientWrapper.sol index 7a5b3eec5..3b93e0ea5 100644 --- a/contracts/src/BeefyClientWrapper.sol +++ b/contracts/src/BeefyClientWrapper.sol @@ -20,7 +20,6 @@ contract BeefyClientWrapper is IInitializable, IUpgradable { event TurnAdvanced(uint256 indexed newTurnIndex, address indexed nextRelayer); event FundsDeposited(address indexed depositor, uint256 amount); event FundsWithdrawn(address indexed recipient, uint256 amount); - event ConfigUpdated(string parameter, uint256 value); error Unauthorized(); error NotARelayer(); @@ -49,6 +48,7 @@ contract BeefyClientWrapper is IInitializable, IUpgradable { mapping(bytes32 => address) public ticketOwner; mapping(address => bytes32) public activeTicket; mapping(bytes32 => uint256) public creditedGas; + uint256 public maxRefundAmount; bool private initialized; function initialize(bytes calldata data) external override { @@ -62,8 +62,9 @@ contract BeefyClientWrapper is IInitializable, IUpgradable { address _owner, uint256 _maxGasPrice, uint256 _gracePeriodBlocks, - uint256 _minBlockIncrement - ) = abi.decode(data, (address, address, uint256, uint256, uint256)); + uint256 _minBlockIncrement, + uint256 _maxRefundAmount + ) = abi.decode(data, (address, address, uint256, uint256, uint256, uint256)); if (_beefyClient == address(0) || _owner == address(0)) { revert InvalidAddress(); @@ -74,6 +75,7 @@ contract BeefyClientWrapper is IInitializable, IUpgradable { maxGasPrice = _maxGasPrice; gracePeriodBlocks = _gracePeriodBlocks; minBlockIncrement = _minBlockIncrement; + maxRefundAmount = _maxRefundAmount; } /* Beefy Client Proxy Functions */ @@ -229,6 +231,11 @@ contract BeefyClientWrapper is IInitializable, IUpgradable { uint256 effectiveGasPrice = tx.gasprice < maxGasPrice ? tx.gasprice : maxGasPrice; uint256 refundAmount = totalGasUsed * effectiveGasPrice; + // Cap the refund to prevent draining the contract + if (refundAmount > maxRefundAmount) { + refundAmount = maxRefundAmount; + } + if (address(this).balance >= refundAmount) { (bool success,) = payable(msg.sender).call{value: refundAmount}(""); if (success) { @@ -290,19 +297,21 @@ contract BeefyClientWrapper is IInitializable, IUpgradable { function setMaxGasPrice(uint256 _maxGasPrice) external { _checkOwner(); maxGasPrice = _maxGasPrice; - emit ConfigUpdated("maxGasPrice", _maxGasPrice); } function setGracePeriod(uint256 _gracePeriodBlocks) external { _checkOwner(); gracePeriodBlocks = _gracePeriodBlocks; - emit ConfigUpdated("gracePeriodBlocks", _gracePeriodBlocks); } function setMinBlockIncrement(uint256 _minBlockIncrement) external { _checkOwner(); minBlockIncrement = _minBlockIncrement; - emit ConfigUpdated("minBlockIncrement", _minBlockIncrement); + } + + function setMaxRefundAmount(uint256 _maxRefundAmount) external { + _checkOwner(); + maxRefundAmount = _maxRefundAmount; } function withdrawFunds(address payable recipient, uint256 amount) external { diff --git a/contracts/test/BeefyClientWrapper.t.sol b/contracts/test/BeefyClientWrapper.t.sol index 79ca97939..f1691bba7 100644 --- a/contracts/test/BeefyClientWrapper.t.sol +++ b/contracts/test/BeefyClientWrapper.t.sol @@ -89,6 +89,7 @@ contract BeefyClientWrapperTest is Test { uint256 constant MAX_GAS_PRICE = 100 gwei; uint256 constant GRACE_PERIOD_BLOCKS = 10; uint256 constant MIN_BLOCK_INCREMENT = 100; + uint256 constant MAX_REFUND_AMOUNT = 1 ether; uint256 constant INITIAL_BEEFY_BLOCK = 1000; function setUp() public { @@ -104,7 +105,8 @@ contract BeefyClientWrapperTest is Test { owner, MAX_GAS_PRICE, GRACE_PERIOD_BLOCKS, - MIN_BLOCK_INCREMENT + MIN_BLOCK_INCREMENT, + MAX_REFUND_AMOUNT ); // Deploy proxy @@ -158,6 +160,7 @@ contract BeefyClientWrapperTest is Test { assertEq(wrapper.maxGasPrice(), MAX_GAS_PRICE); assertEq(wrapper.gracePeriodBlocks(), GRACE_PERIOD_BLOCKS); assertEq(wrapper.minBlockIncrement(), MIN_BLOCK_INCREMENT); + assertEq(wrapper.maxRefundAmount(), MAX_REFUND_AMOUNT); } function test_cannotReinitialize() public { @@ -166,7 +169,8 @@ contract BeefyClientWrapperTest is Test { owner, MAX_GAS_PRICE, GRACE_PERIOD_BLOCKS, - MIN_BLOCK_INCREMENT + MIN_BLOCK_INCREMENT, + MAX_REFUND_AMOUNT ); // The proxy blocks initialize() calls with Unauthorized() error @@ -457,6 +461,35 @@ contract BeefyClientWrapperTest is Test { assertEq(mockBeefyClient.submitFinalCount(), 1); // Submission succeeded } + function test_refundCappedAtMaxRefundAmount() public { + // Set a very low maxRefundAmount to test capping + vm.prank(owner); + wrapper.setMaxRefundAmount(0.0001 ether); + + uint32 newBlockNumber = uint32(INITIAL_BEEFY_BLOCK + MIN_BLOCK_INCREMENT + 1); + IBeefyClient.Commitment memory commitment = createCommitment(newBlockNumber); + uint256[] memory bitfield = new uint256[](1); + IBeefyClient.ValidatorProof memory proof = createValidatorProof(); + IBeefyClient.ValidatorProof[] memory proofs = createValidatorProofs(1); + IBeefyClient.MMRLeaf memory leaf = createMMRLeaf(); + bytes32[] memory leafProof = new bytes32[](0); + + uint256 relayerBalanceBefore = relayer1.balance; + + vm.startPrank(relayer1); + vm.txGasPrice(100 gwei); + wrapper.submitInitial(commitment, bitfield, proof); + bytes32 commitmentHash = keccak256(abi.encode(commitment)); + wrapper.commitPrevRandao(commitmentHash); + wrapper.submitFinal(commitment, bitfield, proofs, leaf, leafProof, 0); + vm.stopPrank(); + + uint256 refundAmount = relayer1.balance - relayerBalanceBefore; + + // Refund should be capped at maxRefundAmount + assertEq(refundAmount, 0.0001 ether); + } + function test_creditedGasForfeitedOnClearTicket() public { uint32 newBlockNumber = uint32(INITIAL_BEEFY_BLOCK + MIN_BLOCK_INCREMENT + 1); IBeefyClient.Commitment memory commitment = createCommitment(newBlockNumber); @@ -498,6 +531,13 @@ contract BeefyClientWrapperTest is Test { assertEq(wrapper.minBlockIncrement(), 200); } + function test_setMaxRefundAmount() public { + vm.prank(owner); + wrapper.setMaxRefundAmount(2 ether); + + assertEq(wrapper.maxRefundAmount(), 2 ether); + } + function test_withdrawFunds() public { uint256 ownerBalanceBefore = owner.balance; uint256 withdrawAmount = 10 ether; @@ -529,6 +569,9 @@ contract BeefyClientWrapperTest is Test { vm.expectRevert(BeefyClientWrapper.Unauthorized.selector); wrapper.setMinBlockIncrement(1); + vm.expectRevert(BeefyClientWrapper.Unauthorized.selector); + wrapper.setMaxRefundAmount(1); + vm.expectRevert(BeefyClientWrapper.Unauthorized.selector); wrapper.withdrawFunds(payable(nonRelayer), 1); From 39bf3fc18dd7a53bc180eb15cf633b49f0b426f2 Mon Sep 17 00:00:00 2001 From: claravanstaden Date: Thu, 8 Jan 2026 12:41:00 +0200 Subject: [PATCH 06/17] add block tips --- contracts/src/BeefyClientWrapper.sol | 45 ++++++- contracts/test/BeefyClientWrapper.t.sol | 162 +++++++++++++++++++++++- 2 files changed, 194 insertions(+), 13 deletions(-) diff --git a/contracts/src/BeefyClientWrapper.sol b/contracts/src/BeefyClientWrapper.sol index 3b93e0ea5..bd30486d0 100644 --- a/contracts/src/BeefyClientWrapper.sol +++ b/contracts/src/BeefyClientWrapper.sol @@ -20,6 +20,8 @@ contract BeefyClientWrapper is IInitializable, IUpgradable { event TurnAdvanced(uint256 indexed newTurnIndex, address indexed nextRelayer); event FundsDeposited(address indexed depositor, uint256 amount); event FundsWithdrawn(address indexed recipient, uint256 amount); + event TipAdded(address indexed tipper, uint32 indexed beefyBlockNumber, uint256 amount); + event TipsClaimed(address indexed relayer, uint256 totalAmount); error Unauthorized(); error NotARelayer(); @@ -49,6 +51,7 @@ contract BeefyClientWrapper is IInitializable, IUpgradable { mapping(address => bytes32) public activeTicket; mapping(bytes32 => uint256) public creditedGas; uint256 public maxRefundAmount; + mapping(uint32 => uint256) public tips; bool private initialized; function initialize(bytes calldata data) external override { @@ -123,9 +126,11 @@ contract BeefyClientWrapper is IInitializable, IUpgradable { IBeefyClient.ValidatorProof[] calldata proofs, IBeefyClient.MMRLeaf calldata leaf, bytes32[] calldata leafProof, - uint256 leafProofOrder + uint256 leafProofOrder, + uint32[] calldata claimTipBlocks ) external { uint256 startGas = gasleft(); + uint32 blockNumber = commitment.blockNumber; bytes32 commitmentHash = keccak256(abi.encode(commitment)); if (ticketOwner[commitmentHash] != msg.sender) { @@ -140,7 +145,7 @@ contract BeefyClientWrapper is IInitializable, IUpgradable { delete activeTicket[msg.sender]; _advanceTurn(); - _refundGas(startGas, previousGas); + _refundGas(startGas, previousGas, _claimTips(claimTipBlocks, blockNumber)); } function createFinalBitfield(bytes32 commitmentHash, uint256[] calldata bitfield) @@ -195,6 +200,15 @@ contract BeefyClientWrapper is IInitializable, IUpgradable { delete activeTicket[msg.sender]; } + function addTip(uint32 beefyBlockNumber) external payable { + tips[beefyBlockNumber] += msg.value; + emit TipAdded(msg.sender, beefyBlockNumber, msg.value); + } + + function getTip(uint32 beefyBlockNumber) external view returns (uint256) { + return tips[beefyBlockNumber]; + } + /* Internal Functions */ function _checkOwner() internal view { @@ -225,7 +239,23 @@ contract BeefyClientWrapper is IInitializable, IUpgradable { emit GasCredited(msg.sender, commitmentHash, gasUsed); } - function _refundGas(uint256 startGas, uint256 previousGas) internal { + function _claimTips(uint32[] calldata claimTipBlocks, uint32 newBeefyBlock) internal returns (uint256) { + uint256 totalTips = 0; + for (uint256 i = 0; i < claimTipBlocks.length; i++) { + uint32 tipBlock = claimTipBlocks[i]; + // Only claim tips for blocks that are now covered by this submission + if (tipBlock <= newBeefyBlock && tips[tipBlock] > 0) { + totalTips += tips[tipBlock]; + delete tips[tipBlock]; + } + } + if (totalTips > 0) { + emit TipsClaimed(msg.sender, totalTips); + } + return totalTips; + } + + function _refundGas(uint256 startGas, uint256 previousGas, uint256 tipAmount) internal { uint256 currentGas = startGas - gasleft() + 21000; uint256 totalGasUsed = currentGas + previousGas; uint256 effectiveGasPrice = tx.gasprice < maxGasPrice ? tx.gasprice : maxGasPrice; @@ -236,10 +266,13 @@ contract BeefyClientWrapper is IInitializable, IUpgradable { refundAmount = maxRefundAmount; } - if (address(this).balance >= refundAmount) { - (bool success,) = payable(msg.sender).call{value: refundAmount}(""); + // Add tips to refund + uint256 totalPayout = refundAmount + tipAmount; + + if (address(this).balance >= totalPayout) { + (bool success,) = payable(msg.sender).call{value: totalPayout}(""); if (success) { - emit SubmissionRefunded(msg.sender, refundAmount, totalGasUsed); + emit SubmissionRefunded(msg.sender, totalPayout, totalGasUsed); } } } diff --git a/contracts/test/BeefyClientWrapper.t.sol b/contracts/test/BeefyClientWrapper.t.sol index f1691bba7..10cd80107 100644 --- a/contracts/test/BeefyClientWrapper.t.sol +++ b/contracts/test/BeefyClientWrapper.t.sol @@ -283,7 +283,7 @@ contract BeefyClientWrapperTest is Test { // Step 3: submitFinal vm.prank(relayer1); - wrapper.submitFinal(commitment, bitfield, proofs, leaf, leafProof, 0); + wrapper.submitFinal(commitment, bitfield, proofs, leaf, leafProof, 0, new uint32[](0)); assertEq(mockBeefyClient.submitFinalCount(), 1); // Verify turn advanced @@ -327,7 +327,7 @@ contract BeefyClientWrapperTest is Test { // relayer2 tries to submit final (should fail) vm.prank(relayer2); vm.expectRevert(BeefyClientWrapper.NotTicketOwner.selector); - wrapper.submitFinal(commitment, bitfield, proofs, leaf, leafProof, 0); + wrapper.submitFinal(commitment, bitfield, proofs, leaf, leafProof, 0, new uint32[](0)); } /* Anti-Spam Tests */ @@ -399,7 +399,7 @@ contract BeefyClientWrapperTest is Test { wrapper.commitPrevRandao(commitmentHash); assertEq(relayer1.balance, relayerBalanceBefore); - wrapper.submitFinal(commitment, bitfield, proofs, leaf, leafProof, 0); + wrapper.submitFinal(commitment, bitfield, proofs, leaf, leafProof, 0, new uint32[](0)); assertGt(relayer1.balance, relayerBalanceBefore); vm.stopPrank(); @@ -425,7 +425,7 @@ contract BeefyClientWrapperTest is Test { wrapper.submitInitial(commitment, bitfield, proof); bytes32 commitmentHash = keccak256(abi.encode(commitment)); wrapper.commitPrevRandao(commitmentHash); - wrapper.submitFinal(commitment, bitfield, proofs, leaf, leafProof, 0); + wrapper.submitFinal(commitment, bitfield, proofs, leaf, leafProof, 0, new uint32[](0)); vm.stopPrank(); uint256 refundAmount = relayer1.balance - relayerBalanceBefore; @@ -454,7 +454,7 @@ contract BeefyClientWrapperTest is Test { wrapper.submitInitial(commitment, bitfield, proof); bytes32 commitmentHash = keccak256(abi.encode(commitment)); wrapper.commitPrevRandao(commitmentHash); - wrapper.submitFinal(commitment, bitfield, proofs, leaf, leafProof, 0); + wrapper.submitFinal(commitment, bitfield, proofs, leaf, leafProof, 0, new uint32[](0)); vm.stopPrank(); assertEq(relayer1.balance, relayerBalanceBefore); // No refund @@ -481,7 +481,7 @@ contract BeefyClientWrapperTest is Test { wrapper.submitInitial(commitment, bitfield, proof); bytes32 commitmentHash = keccak256(abi.encode(commitment)); wrapper.commitPrevRandao(commitmentHash); - wrapper.submitFinal(commitment, bitfield, proofs, leaf, leafProof, 0); + wrapper.submitFinal(commitment, bitfield, proofs, leaf, leafProof, 0, new uint32[](0)); vm.stopPrank(); uint256 refundAmount = relayer1.balance - relayerBalanceBefore; @@ -718,7 +718,7 @@ contract BeefyClientWrapperTest is Test { bytes32 commitmentHash = keccak256(abi.encode(commitment)); wrapper.commitPrevRandao(commitmentHash); - wrapper.submitFinal(commitment, bitfield, proofs, leaf, leafProof, 0); + wrapper.submitFinal(commitment, bitfield, proofs, leaf, leafProof, 0, new uint32[](0)); vm.stopPrank(); // Verify activeTicket is cleared @@ -752,4 +752,152 @@ contract BeefyClientWrapperTest is Test { bytes32 commitmentHash = keccak256(abi.encode(commitment)); assertEq(wrapper.activeTicket(relayer1), commitmentHash); } + + function test_addTip() public { + uint32 targetBlock = uint32(INITIAL_BEEFY_BLOCK + MIN_BLOCK_INCREMENT + 1); + + vm.deal(address(this), 1 ether); + wrapper.addTip{value: 0.5 ether}(targetBlock); + + assertEq(wrapper.getTip(targetBlock), 0.5 ether); + } + + function test_addTip_accumulates() public { + uint32 targetBlock = uint32(INITIAL_BEEFY_BLOCK + MIN_BLOCK_INCREMENT + 1); + + vm.deal(address(this), 2 ether); + wrapper.addTip{value: 0.5 ether}(targetBlock); + wrapper.addTip{value: 0.3 ether}(targetBlock); + + assertEq(wrapper.getTip(targetBlock), 0.8 ether); + } + + function test_claimTips_singleBlock() public { + uint32 newBlockNumber = uint32(INITIAL_BEEFY_BLOCK + MIN_BLOCK_INCREMENT + 1); + + // Add a tip for the target block + vm.deal(address(this), 1 ether); + wrapper.addTip{value: 0.5 ether}(newBlockNumber); + + IBeefyClient.Commitment memory commitment = createCommitment(newBlockNumber); + uint256[] memory bitfield = new uint256[](1); + IBeefyClient.ValidatorProof memory proof = createValidatorProof(); + IBeefyClient.ValidatorProof[] memory proofs = createValidatorProofs(1); + IBeefyClient.MMRLeaf memory leaf = createMMRLeaf(); + bytes32[] memory leafProof = new bytes32[](0); + + uint256 relayerBalanceBefore = relayer1.balance; + + vm.startPrank(relayer1); + vm.txGasPrice(50 gwei); + wrapper.submitInitial(commitment, bitfield, proof); + bytes32 commitmentHash = keccak256(abi.encode(commitment)); + wrapper.commitPrevRandao(commitmentHash); + + // Claim the tip for the block we're submitting + uint32[] memory claimBlocks = new uint32[](1); + claimBlocks[0] = newBlockNumber; + wrapper.submitFinal(commitment, bitfield, proofs, leaf, leafProof, 0, claimBlocks); + vm.stopPrank(); + + // Relayer should have received refund + tip + uint256 relayerBalanceAfter = relayer1.balance; + assertGt(relayerBalanceAfter - relayerBalanceBefore, 0.5 ether); + + // Tip should be cleared + assertEq(wrapper.getTip(newBlockNumber), 0); + } + + function test_claimTips_multipleBlocks() public { + uint32 newBlockNumber = uint32(INITIAL_BEEFY_BLOCK + MIN_BLOCK_INCREMENT + 1); + uint32 tipBlock1 = uint32(INITIAL_BEEFY_BLOCK + 50); + uint32 tipBlock2 = uint32(INITIAL_BEEFY_BLOCK + 75); + + // Add tips for blocks that will be covered by the submission + vm.deal(address(this), 2 ether); + wrapper.addTip{value: 0.3 ether}(tipBlock1); + wrapper.addTip{value: 0.2 ether}(tipBlock2); + + IBeefyClient.Commitment memory commitment = createCommitment(newBlockNumber); + uint256[] memory bitfield = new uint256[](1); + IBeefyClient.ValidatorProof memory proof = createValidatorProof(); + IBeefyClient.ValidatorProof[] memory proofs = createValidatorProofs(1); + IBeefyClient.MMRLeaf memory leaf = createMMRLeaf(); + bytes32[] memory leafProof = new bytes32[](0); + + uint256 relayerBalanceBefore = relayer1.balance; + + vm.startPrank(relayer1); + vm.txGasPrice(50 gwei); + wrapper.submitInitial(commitment, bitfield, proof); + bytes32 commitmentHash = keccak256(abi.encode(commitment)); + wrapper.commitPrevRandao(commitmentHash); + + // Claim tips for both blocks + uint32[] memory claimBlocks = new uint32[](2); + claimBlocks[0] = tipBlock1; + claimBlocks[1] = tipBlock2; + wrapper.submitFinal(commitment, bitfield, proofs, leaf, leafProof, 0, claimBlocks); + vm.stopPrank(); + + // Relayer should have received refund + both tips + uint256 relayerBalanceAfter = relayer1.balance; + assertGt(relayerBalanceAfter - relayerBalanceBefore, 0.5 ether); + + // Tips should be cleared + assertEq(wrapper.getTip(tipBlock1), 0); + assertEq(wrapper.getTip(tipBlock2), 0); + } + + function test_claimTips_ignoresFutureBlocks() public { + uint32 newBlockNumber = uint32(INITIAL_BEEFY_BLOCK + MIN_BLOCK_INCREMENT + 1); + uint32 futureBlock = uint32(newBlockNumber + 100); // Block after submission + + // Add tip for a future block + vm.deal(address(this), 1 ether); + wrapper.addTip{value: 0.5 ether}(futureBlock); + + IBeefyClient.Commitment memory commitment = createCommitment(newBlockNumber); + uint256[] memory bitfield = new uint256[](1); + IBeefyClient.ValidatorProof memory proof = createValidatorProof(); + IBeefyClient.ValidatorProof[] memory proofs = createValidatorProofs(1); + IBeefyClient.MMRLeaf memory leaf = createMMRLeaf(); + bytes32[] memory leafProof = new bytes32[](0); + + vm.startPrank(relayer1); + wrapper.submitInitial(commitment, bitfield, proof); + bytes32 commitmentHash = keccak256(abi.encode(commitment)); + wrapper.commitPrevRandao(commitmentHash); + + // Try to claim the future block tip + uint32[] memory claimBlocks = new uint32[](1); + claimBlocks[0] = futureBlock; + wrapper.submitFinal(commitment, bitfield, proofs, leaf, leafProof, 0, claimBlocks); + vm.stopPrank(); + + // Tip should NOT be claimed (block is in the future) + assertEq(wrapper.getTip(futureBlock), 0.5 ether); + } + + function test_claimTips_emptyArray() public { + uint32 newBlockNumber = uint32(INITIAL_BEEFY_BLOCK + MIN_BLOCK_INCREMENT + 1); + + IBeefyClient.Commitment memory commitment = createCommitment(newBlockNumber); + uint256[] memory bitfield = new uint256[](1); + IBeefyClient.ValidatorProof memory proof = createValidatorProof(); + IBeefyClient.ValidatorProof[] memory proofs = createValidatorProofs(1); + IBeefyClient.MMRLeaf memory leaf = createMMRLeaf(); + bytes32[] memory leafProof = new bytes32[](0); + + vm.startPrank(relayer1); + wrapper.submitInitial(commitment, bitfield, proof); + bytes32 commitmentHash = keccak256(abi.encode(commitment)); + wrapper.commitPrevRandao(commitmentHash); + + // Submit with empty claim array (should work fine) + wrapper.submitFinal(commitment, bitfield, proofs, leaf, leafProof, 0, new uint32[](0)); + vm.stopPrank(); + + assertEq(mockBeefyClient.submitFinalCount(), 1); + } } From c7da3c1635d3daf18119ae33110ae7d9fe7f664a Mon Sep 17 00:00:00 2001 From: claravanstaden Date: Wed, 14 Jan 2026 11:36:16 +0200 Subject: [PATCH 07/17] changes --- .../scripts/DeployBeefyClientWrapper.sol | 57 +- contracts/scripts/DeployLocal.sol | 16 +- contracts/src/BeefyClientWrapper.sol | 359 +++---- contracts/test/BeefyClientWrapper.t.sol | 839 +++++++--------- relayer/contracts/beefy_client_wrapper.go | 909 +++++++++++++++--- relayer/relays/beefy/ethereum-writer.go | 35 +- relayer/relays/beefy/parameters.go | 36 +- web/packages/test/scripts/set-env.sh | 11 + .../scripts/start-beefy-on-demand-relayer.sh | 4 +- web/packages/test/scripts/start-relayer.sh | 35 +- 10 files changed, 1386 insertions(+), 915 deletions(-) diff --git a/contracts/scripts/DeployBeefyClientWrapper.sol b/contracts/scripts/DeployBeefyClientWrapper.sol index 53a277e49..e1d4ee759 100644 --- a/contracts/scripts/DeployBeefyClientWrapper.sol +++ b/contracts/scripts/DeployBeefyClientWrapper.sol @@ -5,15 +5,15 @@ pragma solidity 0.8.28; import {Script} from "forge-std/Script.sol"; import {console} from "forge-std/console.sol"; import {BeefyClientWrapper} from "../src/BeefyClientWrapper.sol"; -import {BeefyClientWrapperProxy} from "../src/BeefyClientWrapperProxy.sol"; contract DeployBeefyClientWrapper is Script { struct Config { address beefyClient; address owner; uint256 maxGasPrice; - uint256 gracePeriodBlocks; - uint256 minBlockIncrement; + uint256 maxRefundAmount; + uint256 refundTarget; + uint256 rewardTarget; } function readConfig() internal returns (Config memory config) { @@ -21,8 +21,9 @@ contract DeployBeefyClientWrapper is Script { beefyClient: vm.envAddress("BEEFY_CLIENT_ADDRESS"), owner: vm.envAddress("REFUND_PROXY_OWNER"), maxGasPrice: vm.envOr("MAX_GAS_PRICE", uint256(100 gwei)), - gracePeriodBlocks: vm.envOr("GRACE_PERIOD_BLOCKS", uint256(10)), - minBlockIncrement: vm.envOr("MIN_BLOCK_INCREMENT", uint256(100)) + maxRefundAmount: vm.envOr("MAX_REFUND_AMOUNT", uint256(1 ether)), + refundTarget: vm.envOr("REFUND_TARGET", uint256(300)), // ~30 min for 100% refund + rewardTarget: vm.envOr("REWARD_TARGET", uint256(2400)) // ~4 hours for 100% reward }); } @@ -31,52 +32,16 @@ contract DeployBeefyClientWrapper is Script { Config memory config = readConfig(); - BeefyClientWrapper implementation = new BeefyClientWrapper(); - - bytes memory initParams = abi.encode( + BeefyClientWrapper wrapper = new BeefyClientWrapper( config.beefyClient, config.owner, config.maxGasPrice, - config.gracePeriodBlocks, - config.minBlockIncrement + config.maxRefundAmount, + config.refundTarget, + config.rewardTarget ); - BeefyClientWrapperProxy proxy = - new BeefyClientWrapperProxy(address(implementation), initParams); - - console.log("Implementation:", address(implementation)); - console.log("Proxy:", address(proxy)); - - vm.stopBroadcast(); - } - - function runWithRelayers(address[] calldata relayers) public { - vm.startBroadcast(); - - Config memory config = readConfig(); - - BeefyClientWrapper implementation = new BeefyClientWrapper(); - - bytes memory initParams = abi.encode( - config.beefyClient, - config.owner, - config.maxGasPrice, - config.gracePeriodBlocks, - config.minBlockIncrement - ); - - BeefyClientWrapperProxy proxy = - new BeefyClientWrapperProxy(address(implementation), initParams); - - BeefyClientWrapper refund = BeefyClientWrapper(payable(address(proxy))); - - for (uint256 i = 0; i < relayers.length; i++) { - refund.addRelayer(relayers[i]); - } - - console.log("Implementation:", address(implementation)); - console.log("Proxy:", address(proxy)); - console.log("Relayers added:", relayers.length); + console.log("BeefyClientWrapper:", address(wrapper)); vm.stopBroadcast(); } diff --git a/contracts/scripts/DeployLocal.sol b/contracts/scripts/DeployLocal.sol index f7732e7f9..f613e02fe 100644 --- a/contracts/scripts/DeployLocal.sol +++ b/contracts/scripts/DeployLocal.sol @@ -5,6 +5,7 @@ pragma solidity 0.8.28; import {WETH9} from "canonical-weth/WETH9.sol"; import {Script} from "forge-std/Script.sol"; import {BeefyClient} from "../src/BeefyClient.sol"; +import {BeefyClientWrapper} from "../src/BeefyClientWrapper.sol"; import {IGatewayV1} from "../src/v1/IGateway.sol"; import {GatewayProxy} from "../src/GatewayProxy.sol"; import {Gateway} from "../src/Gateway.sol"; @@ -61,6 +62,19 @@ contract DeployLocal is Script { next ); + // Deploy BeefyClientWrapper + BeefyClientWrapper beefyClientWrapper = new BeefyClientWrapper( + address(beefyClient), + deployer, + vm.envUint("BEEFY_WRAPPER_MAX_GAS_PRICE"), + vm.envUint("BEEFY_WRAPPER_MAX_REFUND_AMOUNT"), + vm.envUint("BEEFY_WRAPPER_REFUND_TARGET"), + vm.envUint("BEEFY_WRAPPER_REWARD_TARGET") + ); + + // Fund wrapper for refunds + payable(address(beefyClientWrapper)).call{value: vm.envUint("BEEFY_WRAPPER_INITIAL_DEPOSIT")}(""); + uint8 foreignTokenDecimals = uint8(vm.envUint("FOREIGN_TOKEN_DECIMALS")); uint128 maxDestinationFee = uint128(vm.envUint("RESERVE_TRANSFER_MAX_DESTINATION_FEE")); @@ -94,7 +108,7 @@ contract DeployLocal is Script { // For testing call contract new HelloWorld(); - // Deploy test token for registration testing + // Deploy test token for registration testing new Token("Test Token", "TEST", 18); // Fund the gateway proxy contract. Used to reward relayers diff --git a/contracts/src/BeefyClientWrapper.sol b/contracts/src/BeefyClientWrapper.sol index bd30486d0..a293fbcb6 100644 --- a/contracts/src/BeefyClientWrapper.sol +++ b/contracts/src/BeefyClientWrapper.sol @@ -3,72 +3,52 @@ pragma solidity 0.8.28; import {IBeefyClient} from "./interfaces/IBeefyClient.sol"; -import {IInitializable} from "./interfaces/IInitializable.sol"; -import {IUpgradable} from "./interfaces/IUpgradable.sol"; -import {ERC1967} from "./utils/ERC1967.sol"; +import {ScaleCodec} from "./utils/ScaleCodec.sol"; /** * @title BeefyClientWrapper - * @dev Forwards BeefyClient submissions and refunds gas costs to whitelisted relayers. - * Implements soft round-robin scheduling to prevent competition. + * @dev Forwards BeefyClient submissions and refunds gas costs to relayers. + * Anyone can relay. Uses progress-based refunds: the more blocks a relayer + * advances the light client, the higher percentage of gas refund and rewards they receive. */ -contract BeefyClientWrapper is IInitializable, IUpgradable { - event RelayerAdded(address indexed relayer); - event RelayerRemoved(address indexed relayer); +contract BeefyClientWrapper { event GasCredited(address indexed relayer, bytes32 indexed commitmentHash, uint256 gasUsed); - event SubmissionRefunded(address indexed relayer, uint256 amount, uint256 totalGasUsed); - event TurnAdvanced(uint256 indexed newTurnIndex, address indexed nextRelayer); + event SubmissionRefunded( + address indexed relayer, uint256 progress, uint256 refundAmount, uint256 rewardAmount, uint256 totalGasUsed + ); event FundsDeposited(address indexed depositor, uint256 amount); event FundsWithdrawn(address indexed recipient, uint256 amount); - event TipAdded(address indexed tipper, uint32 indexed beefyBlockNumber, uint256 amount); - event TipsClaimed(address indexed relayer, uint256 totalAmount); + event RewardPoolFunded(address indexed funder, uint256 amount); error Unauthorized(); - error NotARelayer(); - error NotYourTurn(); - error InsufficientBlockIncrement(); - error RelayerAlreadyExists(); - error RelayerNotFound(); - error NoRelayers(); error InvalidAddress(); - error InvalidTicket(); error NotTicketOwner(); error TransferFailed(); - error AlreadyInitialized(); - error TicketAlreadyActive(); address public owner; IBeefyClient public beefyClient; - uint256 public maxGasPrice; - address[] public relayers; - mapping(address => bool) public isRelayer; - mapping(address => uint256) private relayerIndex; - uint256 public currentTurnIndex; - uint256 public lastSubmissionBlock; - uint256 public gracePeriodBlocks; - uint256 public minBlockIncrement; + + // Ticket tracking (for multi-step submission) mapping(bytes32 => address) public ticketOwner; - mapping(address => bytes32) public activeTicket; mapping(bytes32 => uint256) public creditedGas; - uint256 public maxRefundAmount; - mapping(uint32 => uint256) public tips; - bool private initialized; - function initialize(bytes calldata data) external override { - if (initialized) { - revert AlreadyInitialized(); - } - initialized = true; - - ( - address _beefyClient, - address _owner, - uint256 _maxGasPrice, - uint256 _gracePeriodBlocks, - uint256 _minBlockIncrement, - uint256 _maxRefundAmount - ) = abi.decode(data, (address, address, uint256, uint256, uint256, uint256)); + // Refund configuration + uint256 public maxGasPrice; + uint256 public maxRefundAmount; + // Progress-based refund/reward targets + uint256 public refundTarget; // Blocks of progress for 100% gas refund (e.g., 300 = ~30 min) + uint256 public rewardTarget; // Blocks of progress for 100% reward (e.g., 2400 = ~4 hours) + uint256 public rewardPool; // Available reward pool + + constructor( + address _beefyClient, + address _owner, + uint256 _maxGasPrice, + uint256 _maxRefundAmount, + uint256 _refundTarget, + uint256 _rewardTarget + ) { if (_beefyClient == address(0) || _owner == address(0)) { revert InvalidAddress(); } @@ -76,9 +56,9 @@ contract BeefyClientWrapper is IInitializable, IUpgradable { beefyClient = IBeefyClient(_beefyClient); owner = _owner; maxGasPrice = _maxGasPrice; - gracePeriodBlocks = _gracePeriodBlocks; - minBlockIncrement = _minBlockIncrement; maxRefundAmount = _maxRefundAmount; + refundTarget = _refundTarget; + rewardTarget = _rewardTarget; } /* Beefy Client Proxy Functions */ @@ -88,22 +68,12 @@ contract BeefyClientWrapper is IInitializable, IUpgradable { uint256[] calldata bitfield, IBeefyClient.ValidatorProof calldata proof ) external { - _checkEligibleRelayer(); - if (activeTicket[msg.sender] != bytes32(0)) { - revert TicketAlreadyActive(); - } uint256 startGas = gasleft(); - uint64 latestBlock = beefyClient.latestBeefyBlock(); - if (commitment.blockNumber < latestBlock + minBlockIncrement) { - revert InsufficientBlockIncrement(); - } - beefyClient.submitInitial(commitment, bitfield, proof); - bytes32 commitmentHash = keccak256(abi.encode(commitment)); + bytes32 commitmentHash = keccak256(_encodeCommitment(commitment)); ticketOwner[commitmentHash] = msg.sender; - activeTicket[msg.sender] = commitmentHash; _creditGas(startGas, commitmentHash); } @@ -126,26 +96,28 @@ contract BeefyClientWrapper is IInitializable, IUpgradable { IBeefyClient.ValidatorProof[] calldata proofs, IBeefyClient.MMRLeaf calldata leaf, bytes32[] calldata leafProof, - uint256 leafProofOrder, - uint32[] calldata claimTipBlocks + uint256 leafProofOrder ) external { uint256 startGas = gasleft(); - uint32 blockNumber = commitment.blockNumber; - bytes32 commitmentHash = keccak256(abi.encode(commitment)); + // Capture previous state for progress calculation + uint64 previousBeefyBlock = beefyClient.latestBeefyBlock(); + + bytes32 commitmentHash = keccak256(_encodeCommitment(commitment)); if (ticketOwner[commitmentHash] != msg.sender) { revert NotTicketOwner(); } beefyClient.submitFinal(commitment, bitfield, proofs, leaf, leafProof, leafProofOrder); + // Calculate progress + uint256 progress = commitment.blockNumber - previousBeefyBlock; + uint256 previousGas = creditedGas[commitmentHash]; delete creditedGas[commitmentHash]; delete ticketOwner[commitmentHash]; - delete activeTicket[msg.sender]; - _advanceTurn(); - _refundGas(startGas, previousGas, _claimTips(claimTipBlocks, blockNumber)); + _refundWithProgress(startGas, previousGas, progress); } function createFinalBitfield(bytes32 commitmentHash, uint256[] calldata bitfield) @@ -172,41 +144,33 @@ contract BeefyClientWrapper is IInitializable, IUpgradable { return beefyClient.randaoCommitDelay(); } - function currentValidatorSet() - external - view - returns (uint128 id, uint128 length, bytes32 root) - { + function currentValidatorSet() external view returns (uint128 id, uint128 length, bytes32 root) { return beefyClient.currentValidatorSet(); } - function nextValidatorSet() - external - view - returns (uint128 id, uint128 length, bytes32 root) - { + function nextValidatorSet() external view returns (uint128 id, uint128 length, bytes32 root) { return beefyClient.nextValidatorSet(); } - function clearTicket() external { - bytes32 commitmentHash = activeTicket[msg.sender]; - if (commitmentHash == bytes32(0)) { - revert InvalidTicket(); + /** + * @dev Abandon a ticket. Useful if another relayer is competing for the same commitment. + * Credited gas is forfeited when clearing a ticket. + */ + function clearTicket(bytes32 commitmentHash) external { + if (ticketOwner[commitmentHash] != msg.sender) { + revert NotTicketOwner(); } - // Credited gas is forfeited when clearing a ticket delete creditedGas[commitmentHash]; delete ticketOwner[commitmentHash]; - delete activeTicket[msg.sender]; - } - - function addTip(uint32 beefyBlockNumber) external payable { - tips[beefyBlockNumber] += msg.value; - emit TipAdded(msg.sender, beefyBlockNumber, msg.value); } - function getTip(uint32 beefyBlockNumber) external view returns (uint256) { - return tips[beefyBlockNumber]; + /** + * @dev Fund the reward pool. Anyone can contribute. + */ + function fundRewardPool() external payable { + rewardPool += msg.value; + emit RewardPoolFunded(msg.sender, msg.value); } /* Internal Functions */ @@ -217,134 +181,102 @@ contract BeefyClientWrapper is IInitializable, IUpgradable { } } - function _checkEligibleRelayer() internal view { - if (!isRelayer[msg.sender]) { - revert NotARelayer(); - } - - if (relayers.length > 0) { - address assignedRelayer = relayers[currentTurnIndex % relayers.length]; - bool isAssignedRelayer = (msg.sender == assignedRelayer); - bool gracePeriodActive = block.number > lastSubmissionBlock + gracePeriodBlocks; - - if (!isAssignedRelayer && !gracePeriodActive) { - revert NotYourTurn(); - } - } - } - function _creditGas(uint256 startGas, bytes32 commitmentHash) internal { uint256 gasUsed = startGas - gasleft() + 21000; creditedGas[commitmentHash] += gasUsed; emit GasCredited(msg.sender, commitmentHash, gasUsed); } - function _claimTips(uint32[] calldata claimTipBlocks, uint32 newBeefyBlock) internal returns (uint256) { - uint256 totalTips = 0; - for (uint256 i = 0; i < claimTipBlocks.length; i++) { - uint32 tipBlock = claimTipBlocks[i]; - // Only claim tips for blocks that are now covered by this submission - if (tipBlock <= newBeefyBlock && tips[tipBlock] > 0) { - totalTips += tips[tipBlock]; - delete tips[tipBlock]; - } - } - if (totalTips > 0) { - emit TipsClaimed(msg.sender, totalTips); - } - return totalTips; - } - - function _refundGas(uint256 startGas, uint256 previousGas, uint256 tipAmount) internal { + /** + * @dev Calculate and send refund + reward based on progress made. + * + * Refund: Scales from 0% to 100% as progress goes from 0 to refundTarget. + * Reward: Kicks in after refundTarget, scales to 100% at rewardTarget. + * + * Example with refundTarget=300, rewardTarget=2400: + * - 150 blocks progress: 50% gas refund, 0% reward + * - 300 blocks progress: 100% gas refund, 0% reward + * - 600 blocks progress: 100% gas refund, 14.3% reward (300/2100) + * - 2400+ blocks progress: 100% gas refund, 100% reward + */ + function _refundWithProgress(uint256 startGas, uint256 previousGas, uint256 progress) internal { uint256 currentGas = startGas - gasleft() + 21000; uint256 totalGasUsed = currentGas + previousGas; uint256 effectiveGasPrice = tx.gasprice < maxGasPrice ? tx.gasprice : maxGasPrice; - uint256 refundAmount = totalGasUsed * effectiveGasPrice; + uint256 baseRefund = totalGasUsed * effectiveGasPrice; - // Cap the refund to prevent draining the contract - if (refundAmount > maxRefundAmount) { - refundAmount = maxRefundAmount; + // Cap base refund + if (baseRefund > maxRefundAmount) { + baseRefund = maxRefundAmount; } - // Add tips to refund - uint256 totalPayout = refundAmount + tipAmount; + // Calculate refund ratio (0-100%) + uint256 refundRatio = progress >= refundTarget ? 100 : (progress * 100) / refundTarget; + uint256 refundAmount = (baseRefund * refundRatio) / 100; + + // Calculate reward ratio (0-100%, only kicks in after refundTarget) + uint256 rewardAmount = 0; + if (progress > refundTarget && rewardPool > 0 && rewardTarget > refundTarget) { + uint256 extraProgress = progress - refundTarget; + uint256 rewardWindow = rewardTarget - refundTarget; + uint256 rewardRatio = extraProgress >= rewardWindow ? 100 : (extraProgress * 100) / rewardWindow; + rewardAmount = (rewardPool * rewardRatio) / 100; + + // Deduct from reward pool + if (rewardAmount > rewardPool) { + rewardAmount = rewardPool; + } + rewardPool -= rewardAmount; + } - if (address(this).balance >= totalPayout) { + uint256 totalPayout = refundAmount + rewardAmount; + + if (totalPayout > 0 && address(this).balance >= totalPayout) { (bool success,) = payable(msg.sender).call{value: totalPayout}(""); if (success) { - emit SubmissionRefunded(msg.sender, totalPayout, totalGasUsed); + emit SubmissionRefunded(msg.sender, progress, refundAmount, rewardAmount, totalGasUsed); } } } - function _advanceTurn() internal { - currentTurnIndex++; - lastSubmissionBlock = block.number; - - if (relayers.length > 0) { - address nextRelayer = relayers[currentTurnIndex % relayers.length]; - emit TurnAdvanced(currentTurnIndex, nextRelayer); - } + function _encodeCommitment(IBeefyClient.Commitment calldata commitment) internal pure returns (bytes memory) { + return bytes.concat( + _encodeCommitmentPayload(commitment.payload), + ScaleCodec.encodeU32(commitment.blockNumber), + ScaleCodec.encodeU64(commitment.validatorSetID) + ); } - /* Admin Functions */ - - function addRelayer(address relayer) external { - _checkOwner(); - if (relayer == address(0)) { - revert InvalidAddress(); + function _encodeCommitmentPayload(IBeefyClient.PayloadItem[] calldata items) internal pure returns (bytes memory) { + bytes memory payload = ScaleCodec.checkedEncodeCompactU32(items.length); + for (uint256 i = 0; i < items.length; i++) { + payload = bytes.concat( + payload, items[i].payloadID, ScaleCodec.checkedEncodeCompactU32(items[i].data.length), items[i].data + ); } - if (isRelayer[relayer]) { - revert RelayerAlreadyExists(); - } - - relayerIndex[relayer] = relayers.length; - relayers.push(relayer); - isRelayer[relayer] = true; - - emit RelayerAdded(relayer); + return payload; } - function removeRelayer(address relayer) external { - _checkOwner(); - if (!isRelayer[relayer]) { - revert RelayerNotFound(); - } - - uint256 indexToRemove = relayerIndex[relayer]; - uint256 lastIndex = relayers.length - 1; - - if (indexToRemove != lastIndex) { - address lastRelayer = relayers[lastIndex]; - relayers[indexToRemove] = lastRelayer; - relayerIndex[lastRelayer] = indexToRemove; - } - - relayers.pop(); - delete isRelayer[relayer]; - delete relayerIndex[relayer]; - - emit RelayerRemoved(relayer); - } + /* Admin Functions */ function setMaxGasPrice(uint256 _maxGasPrice) external { _checkOwner(); maxGasPrice = _maxGasPrice; } - function setGracePeriod(uint256 _gracePeriodBlocks) external { + function setMaxRefundAmount(uint256 _maxRefundAmount) external { _checkOwner(); - gracePeriodBlocks = _gracePeriodBlocks; + maxRefundAmount = _maxRefundAmount; } - function setMinBlockIncrement(uint256 _minBlockIncrement) external { + function setRefundTarget(uint256 _refundTarget) external { _checkOwner(); - minBlockIncrement = _minBlockIncrement; + refundTarget = _refundTarget; } - function setMaxRefundAmount(uint256 _maxRefundAmount) external { + function setRewardTarget(uint256 _rewardTarget) external { _checkOwner(); - maxRefundAmount = _maxRefundAmount; + rewardTarget = _rewardTarget; } function withdrawFunds(address payable recipient, uint256 amount) external { @@ -369,52 +301,45 @@ contract BeefyClientWrapper is IInitializable, IUpgradable { owner = newOwner; } - /* Upgrade Functions */ - - function upgradeTo(address newImplementation, bytes32 expectedCodeHash) external { - _checkOwner(); - if (newImplementation.code.length == 0) { - revert InvalidContract(); - } - if (newImplementation.codehash != expectedCodeHash) { - revert InvalidCodeHash(); - } - - ERC1967.store(newImplementation); - emit Upgraded(newImplementation); - } - - function implementation() external view override returns (address) { - return ERC1967.load(); - } - /* View Functions */ - function getCurrentTurnRelayer() external view returns (address) { - if (relayers.length == 0) { - return address(0); - } - return relayers[currentTurnIndex % relayers.length]; + function getBalance() external view returns (uint256) { + return address(this).balance; } - function isGracePeriodActive() external view returns (bool) { - return block.number > lastSubmissionBlock + gracePeriodBlocks; + function getCreditedGas(bytes32 commitmentHash) external view returns (uint256) { + return creditedGas[commitmentHash]; } - function getRelayers() external view returns (address[] memory) { - return relayers; + function getRewardPool() external view returns (uint256) { + return rewardPool; } - function getRelayerCount() external view returns (uint256) { - return relayers.length; - } + /** + * @dev Calculate expected refund and reward for a given progress. + * Useful for relayers to estimate payouts before submitting. + */ + function estimatePayout(uint256 gasUsed, uint256 gasPrice, uint256 progress) + external + view + returns (uint256 refundAmount, uint256 rewardAmount) + { + uint256 effectiveGasPrice = gasPrice < maxGasPrice ? gasPrice : maxGasPrice; + uint256 baseRefund = gasUsed * effectiveGasPrice; - function getBalance() external view returns (uint256) { - return address(this).balance; - } + if (baseRefund > maxRefundAmount) { + baseRefund = maxRefundAmount; + } - function getCreditedGas(bytes32 commitmentHash) external view returns (uint256) { - return creditedGas[commitmentHash]; + uint256 refundRatio = progress >= refundTarget ? 100 : (progress * 100) / refundTarget; + refundAmount = (baseRefund * refundRatio) / 100; + + if (progress > refundTarget && rewardPool > 0 && rewardTarget > refundTarget) { + uint256 extraProgress = progress - refundTarget; + uint256 rewardWindow = rewardTarget - refundTarget; + uint256 rewardRatio = extraProgress >= rewardWindow ? 100 : (extraProgress * 100) / rewardWindow; + rewardAmount = (rewardPool * rewardRatio) / 100; + } } receive() external payable { diff --git a/contracts/test/BeefyClientWrapper.t.sol b/contracts/test/BeefyClientWrapper.t.sol index 10cd80107..05baf6b10 100644 --- a/contracts/test/BeefyClientWrapper.t.sol +++ b/contracts/test/BeefyClientWrapper.t.sol @@ -5,13 +5,12 @@ import {Test} from "forge-std/Test.sol"; import {console} from "forge-std/console.sol"; import {BeefyClientWrapper} from "../src/BeefyClientWrapper.sol"; -import {BeefyClientWrapperProxy} from "../src/BeefyClientWrapperProxy.sol"; import {IBeefyClient} from "../src/interfaces/IBeefyClient.sol"; -import {IUpgradable} from "../src/interfaces/IUpgradable.sol"; +import {ScaleCodec} from "../src/utils/ScaleCodec.sol"; /** * @title MockBeefyClient - * @dev A simplified mock of BeefyClient for testing the refund proxy + * @dev A simplified mock of BeefyClient for testing the wrapper */ contract MockBeefyClient { uint64 public latestBeefyBlock; @@ -35,7 +34,7 @@ contract MockBeefyClient { ) external { // Just track that it was called and create a ticket submitInitialCount++; - bytes32 commitmentHash = keccak256(abi.encode(commitment)); + bytes32 commitmentHash = keccak256(_encodeCommitment(commitment)); ticketExists[commitmentHash] = true; } @@ -52,7 +51,7 @@ contract MockBeefyClient { bytes32[] calldata, uint256 ) external { - bytes32 commitmentHash = keccak256(abi.encode(commitment)); + bytes32 commitmentHash = keccak256(_encodeCommitment(commitment)); require(ticketExists[commitmentHash], "No ticket"); submitFinalCount++; delete ticketExists[commitmentHash]; @@ -69,61 +68,87 @@ contract MockBeefyClient { return bitfield; } + function createInitialBitfield(uint256[] calldata, uint256) external pure returns (uint256[] memory) { + return new uint256[](1); + } + + function randaoCommitDelay() external pure returns (uint256) { + return 4; + } + + function currentValidatorSet() external pure returns (uint128 id, uint128 length, bytes32 root) { + return (1, 100, bytes32(0)); + } + + function nextValidatorSet() external pure returns (uint128 id, uint128 length, bytes32 root) { + return (2, 100, bytes32(0)); + } + function setLatestBeefyBlock(uint64 _block) external { latestBeefyBlock = _block; } + + function _encodeCommitment(IBeefyClient.Commitment calldata commitment) + internal + pure + returns (bytes memory) + { + return bytes.concat( + _encodeCommitmentPayload(commitment.payload), + ScaleCodec.encodeU32(commitment.blockNumber), + ScaleCodec.encodeU64(commitment.validatorSetID) + ); + } + + function _encodeCommitmentPayload(IBeefyClient.PayloadItem[] calldata items) + internal + pure + returns (bytes memory) + { + bytes memory payload = ScaleCodec.checkedEncodeCompactU32(items.length); + for (uint256 i = 0; i < items.length; i++) { + payload = bytes.concat( + payload, + items[i].payloadID, + ScaleCodec.checkedEncodeCompactU32(items[i].data.length), + items[i].data + ); + } + return payload; + } } contract BeefyClientWrapperTest is Test { - BeefyClientWrapper implementation; - BeefyClientWrapperProxy proxy; BeefyClientWrapper wrapper; MockBeefyClient mockBeefyClient; address owner = address(0x1); address relayer1 = address(0x2); address relayer2 = address(0x3); - address relayer3 = address(0x4); - address nonRelayer = address(0x5); + address anyone = address(0x5); uint256 constant MAX_GAS_PRICE = 100 gwei; - uint256 constant GRACE_PERIOD_BLOCKS = 10; - uint256 constant MIN_BLOCK_INCREMENT = 100; uint256 constant MAX_REFUND_AMOUNT = 1 ether; + uint256 constant REFUND_TARGET = 300; // 300 blocks for 100% refund + uint256 constant REWARD_TARGET = 2400; // 2400 blocks for 100% reward uint256 constant INITIAL_BEEFY_BLOCK = 1000; function setUp() public { // Deploy mock BeefyClient mockBeefyClient = new MockBeefyClient(uint64(INITIAL_BEEFY_BLOCK)); - // Deploy implementation - implementation = new BeefyClientWrapper(); - - // Encode initialization parameters - bytes memory initParams = abi.encode( + // Deploy wrapper directly (no proxy) + wrapper = new BeefyClientWrapper( address(mockBeefyClient), owner, MAX_GAS_PRICE, - GRACE_PERIOD_BLOCKS, - MIN_BLOCK_INCREMENT, - MAX_REFUND_AMOUNT + MAX_REFUND_AMOUNT, + REFUND_TARGET, + REWARD_TARGET ); - // Deploy proxy - proxy = new BeefyClientWrapperProxy(address(implementation), initParams); - - // Get interface to proxy - wrapper = BeefyClientWrapper(payable(address(proxy))); - - // Fund the proxy with ETH for refunds - vm.deal(address(proxy), 100 ether); - - // Add relayers - vm.startPrank(owner); - wrapper.addRelayer(relayer1); - wrapper.addRelayer(relayer2); - wrapper.addRelayer(relayer3); - vm.stopPrank(); + // Fund the wrapper with ETH for refunds + vm.deal(address(wrapper), 100 ether); } /* Helper Functions */ @@ -152,117 +177,64 @@ contract BeefyClientWrapperTest is Test { return IBeefyClient.MMRLeaf(1, 0, bytes32(0), 1, 100, bytes32(0), bytes32(0)); } + function computeCommitmentHash(IBeefyClient.Commitment memory commitment) internal pure returns (bytes32) { + bytes memory payload = ScaleCodec.checkedEncodeCompactU32(commitment.payload.length); + for (uint256 i = 0; i < commitment.payload.length; i++) { + payload = bytes.concat( + payload, + commitment.payload[i].payloadID, + ScaleCodec.checkedEncodeCompactU32(commitment.payload[i].data.length), + commitment.payload[i].data + ); + } + return keccak256( + bytes.concat( + payload, + ScaleCodec.encodeU32(commitment.blockNumber), + ScaleCodec.encodeU64(commitment.validatorSetID) + ) + ); + } + /* Initialization Tests */ function test_initialization() public { assertEq(wrapper.owner(), owner); assertEq(address(wrapper.beefyClient()), address(mockBeefyClient)); assertEq(wrapper.maxGasPrice(), MAX_GAS_PRICE); - assertEq(wrapper.gracePeriodBlocks(), GRACE_PERIOD_BLOCKS); - assertEq(wrapper.minBlockIncrement(), MIN_BLOCK_INCREMENT); assertEq(wrapper.maxRefundAmount(), MAX_REFUND_AMOUNT); + assertEq(wrapper.refundTarget(), REFUND_TARGET); + assertEq(wrapper.rewardTarget(), REWARD_TARGET); } - function test_cannotReinitialize() public { - bytes memory initParams = abi.encode( - address(mockBeefyClient), + function test_invalidBeefyClientAddress() public { + vm.expectRevert(BeefyClientWrapper.InvalidAddress.selector); + new BeefyClientWrapper( + address(0), owner, MAX_GAS_PRICE, - GRACE_PERIOD_BLOCKS, - MIN_BLOCK_INCREMENT, - MAX_REFUND_AMOUNT + MAX_REFUND_AMOUNT, + REFUND_TARGET, + REWARD_TARGET ); - - // The proxy blocks initialize() calls with Unauthorized() error - // This prevents reinitialization attempts through the proxy - vm.expectRevert(BeefyClientWrapperProxy.Unauthorized.selector); - wrapper.initialize(initParams); - } - - /* Relayer Management Tests */ - - function test_addRelayer() public { - address newRelayer = address(0x100); - - vm.prank(owner); - wrapper.addRelayer(newRelayer); - - assertTrue(wrapper.isRelayer(newRelayer)); - assertEq(wrapper.getRelayerCount(), 4); - } - - function test_addRelayer_onlyOwner() public { - vm.prank(nonRelayer); - vm.expectRevert(BeefyClientWrapper.Unauthorized.selector); - wrapper.addRelayer(address(0x100)); - } - - function test_addRelayer_alreadyExists() public { - vm.prank(owner); - vm.expectRevert(BeefyClientWrapper.RelayerAlreadyExists.selector); - wrapper.addRelayer(relayer1); - } - - function test_removeRelayer() public { - vm.prank(owner); - wrapper.removeRelayer(relayer2); - - assertFalse(wrapper.isRelayer(relayer2)); - assertEq(wrapper.getRelayerCount(), 2); - } - - function test_removeRelayer_notFound() public { - vm.prank(owner); - vm.expectRevert(BeefyClientWrapper.RelayerNotFound.selector); - wrapper.removeRelayer(nonRelayer); - } - - /* Round-Robin Tests */ - - function test_getCurrentTurnRelayer() public { - address currentRelayer = wrapper.getCurrentTurnRelayer(); - assertEq(currentRelayer, relayer1); // First relayer at index 0 - } - - function test_onlyAssignedRelayerCanSubmit() public { - uint32 newBlockNumber = uint32(INITIAL_BEEFY_BLOCK + MIN_BLOCK_INCREMENT + 1); - IBeefyClient.Commitment memory commitment = createCommitment(newBlockNumber); - uint256[] memory bitfield = new uint256[](1); - IBeefyClient.ValidatorProof memory proof = createValidatorProof(); - - // relayer2 is not the assigned relayer (relayer1 is) - vm.prank(relayer2); - vm.expectRevert(BeefyClientWrapper.NotYourTurn.selector); - wrapper.submitInitial(commitment, bitfield, proof); - } - - function test_gracePeriodAllowsAnyRelayer() public { - // Advance past grace period - vm.roll(block.number + GRACE_PERIOD_BLOCKS + 1); - - uint32 newBlockNumber = uint32(INITIAL_BEEFY_BLOCK + MIN_BLOCK_INCREMENT + 1); - IBeefyClient.Commitment memory commitment = createCommitment(newBlockNumber); - uint256[] memory bitfield = new uint256[](1); - IBeefyClient.ValidatorProof memory proof = createValidatorProof(); - - // relayer2 can submit during grace period - vm.prank(relayer2); - wrapper.submitInitial(commitment, bitfield, proof); - - assertEq(mockBeefyClient.submitInitialCount(), 1); } - function test_isGracePeriodActive() public { - assertFalse(wrapper.isGracePeriodActive()); - - vm.roll(block.number + GRACE_PERIOD_BLOCKS + 1); - assertTrue(wrapper.isGracePeriodActive()); + function test_invalidOwnerAddress() public { + vm.expectRevert(BeefyClientWrapper.InvalidAddress.selector); + new BeefyClientWrapper( + address(mockBeefyClient), + address(0), + MAX_GAS_PRICE, + MAX_REFUND_AMOUNT, + REFUND_TARGET, + REWARD_TARGET + ); } /* Submission Flow Tests */ function test_fullSubmissionFlow() public { - uint32 newBlockNumber = uint32(INITIAL_BEEFY_BLOCK + MIN_BLOCK_INCREMENT + 1); + uint32 newBlockNumber = uint32(INITIAL_BEEFY_BLOCK + 100); IBeefyClient.Commitment memory commitment = createCommitment(newBlockNumber); uint256[] memory bitfield = new uint256[](1); IBeefyClient.ValidatorProof memory proof = createValidatorProof(); @@ -276,23 +248,33 @@ contract BeefyClientWrapperTest is Test { assertEq(mockBeefyClient.submitInitialCount(), 1); // Step 2: commitPrevRandao - bytes32 commitmentHash = keccak256(abi.encode(commitment)); + bytes32 commitmentHash = computeCommitmentHash(commitment); vm.prank(relayer1); wrapper.commitPrevRandao(commitmentHash); assertEq(mockBeefyClient.commitPrevRandaoCount(), 1); // Step 3: submitFinal vm.prank(relayer1); - wrapper.submitFinal(commitment, bitfield, proofs, leaf, leafProof, 0, new uint32[](0)); + wrapper.submitFinal(commitment, bitfield, proofs, leaf, leafProof, 0); assertEq(mockBeefyClient.submitFinalCount(), 1); + } + + function test_anyoneCanSubmit() public { + // Anyone can submit - no whitelist + uint32 newBlockNumber = uint32(INITIAL_BEEFY_BLOCK + 100); + IBeefyClient.Commitment memory commitment = createCommitment(newBlockNumber); + uint256[] memory bitfield = new uint256[](1); + IBeefyClient.ValidatorProof memory proof = createValidatorProof(); + + // Random address can submit + vm.prank(anyone); + wrapper.submitInitial(commitment, bitfield, proof); - // Verify turn advanced - assertEq(wrapper.currentTurnIndex(), 1); - assertEq(wrapper.getCurrentTurnRelayer(), relayer2); + assertEq(mockBeefyClient.submitInitialCount(), 1); } function test_onlyTicketOwnerCanCommitPrevRandao() public { - uint32 newBlockNumber = uint32(INITIAL_BEEFY_BLOCK + MIN_BLOCK_INCREMENT + 1); + uint32 newBlockNumber = uint32(INITIAL_BEEFY_BLOCK + 100); IBeefyClient.Commitment memory commitment = createCommitment(newBlockNumber); uint256[] memory bitfield = new uint256[](1); IBeefyClient.ValidatorProof memory proof = createValidatorProof(); @@ -302,14 +284,14 @@ contract BeefyClientWrapperTest is Test { wrapper.submitInitial(commitment, bitfield, proof); // relayer2 tries to commit (should fail) - bytes32 commitmentHash = keccak256(abi.encode(commitment)); + bytes32 commitmentHash = computeCommitmentHash(commitment); vm.prank(relayer2); vm.expectRevert(BeefyClientWrapper.NotTicketOwner.selector); wrapper.commitPrevRandao(commitmentHash); } function test_onlyTicketOwnerCanSubmitFinal() public { - uint32 newBlockNumber = uint32(INITIAL_BEEFY_BLOCK + MIN_BLOCK_INCREMENT + 1); + uint32 newBlockNumber = uint32(INITIAL_BEEFY_BLOCK + 100); IBeefyClient.Commitment memory commitment = createCommitment(newBlockNumber); uint256[] memory bitfield = new uint256[](1); IBeefyClient.ValidatorProof memory proof = createValidatorProof(); @@ -320,32 +302,38 @@ contract BeefyClientWrapperTest is Test { // relayer1 submits initial and commits vm.startPrank(relayer1); wrapper.submitInitial(commitment, bitfield, proof); - bytes32 commitmentHash = keccak256(abi.encode(commitment)); + bytes32 commitmentHash = computeCommitmentHash(commitment); wrapper.commitPrevRandao(commitmentHash); vm.stopPrank(); // relayer2 tries to submit final (should fail) vm.prank(relayer2); vm.expectRevert(BeefyClientWrapper.NotTicketOwner.selector); - wrapper.submitFinal(commitment, bitfield, proofs, leaf, leafProof, 0, new uint32[](0)); + wrapper.submitFinal(commitment, bitfield, proofs, leaf, leafProof, 0); } - /* Anti-Spam Tests */ - - function test_minBlockIncrementEnforced() public { - // Try to submit with insufficient block increment - uint32 newBlockNumber = uint32(INITIAL_BEEFY_BLOCK + MIN_BLOCK_INCREMENT - 1); + function test_clearTicket() public { + uint32 newBlockNumber = uint32(INITIAL_BEEFY_BLOCK + 100); IBeefyClient.Commitment memory commitment = createCommitment(newBlockNumber); uint256[] memory bitfield = new uint256[](1); IBeefyClient.ValidatorProof memory proof = createValidatorProof(); - vm.prank(relayer1); - vm.expectRevert(BeefyClientWrapper.InsufficientBlockIncrement.selector); + vm.startPrank(relayer1); wrapper.submitInitial(commitment, bitfield, proof); + + bytes32 commitmentHash = computeCommitmentHash(commitment); + assertEq(wrapper.ticketOwner(commitmentHash), relayer1); + assertGt(wrapper.getCreditedGas(commitmentHash), 0); + + // Clear ticket - gas should be forfeited + wrapper.clearTicket(commitmentHash); + assertEq(wrapper.ticketOwner(commitmentHash), address(0)); + assertEq(wrapper.getCreditedGas(commitmentHash), 0); + vm.stopPrank(); } - function test_validBlockIncrementSucceeds() public { - uint32 newBlockNumber = uint32(INITIAL_BEEFY_BLOCK + MIN_BLOCK_INCREMENT); + function test_clearTicket_notOwner() public { + uint32 newBlockNumber = uint32(INITIAL_BEEFY_BLOCK + 100); IBeefyClient.Commitment memory commitment = createCommitment(newBlockNumber); uint256[] memory bitfield = new uint256[](1); IBeefyClient.ValidatorProof memory proof = createValidatorProof(); @@ -353,13 +341,16 @@ contract BeefyClientWrapperTest is Test { vm.prank(relayer1); wrapper.submitInitial(commitment, bitfield, proof); - assertEq(mockBeefyClient.submitInitialCount(), 1); + bytes32 commitmentHash = computeCommitmentHash(commitment); + vm.prank(relayer2); + vm.expectRevert(BeefyClientWrapper.NotTicketOwner.selector); + wrapper.clearTicket(commitmentHash); } - /* Refund Tests */ + /* Progress-Based Refund Tests */ function test_gasCreditedOnSubmitInitial() public { - uint32 newBlockNumber = uint32(INITIAL_BEEFY_BLOCK + MIN_BLOCK_INCREMENT + 1); + uint32 newBlockNumber = uint32(INITIAL_BEEFY_BLOCK + 100); IBeefyClient.Commitment memory commitment = createCommitment(newBlockNumber); uint256[] memory bitfield = new uint256[](1); IBeefyClient.ValidatorProof memory proof = createValidatorProof(); @@ -374,12 +365,12 @@ contract BeefyClientWrapperTest is Test { assertEq(relayer1.balance, relayerBalanceBefore); // Gas should be credited - bytes32 commitmentHash = keccak256(abi.encode(commitment)); + bytes32 commitmentHash = computeCommitmentHash(commitment); assertGt(wrapper.getCreditedGas(commitmentHash), 0); } function test_refundSentOnlyAfterSubmitFinal() public { - uint32 newBlockNumber = uint32(INITIAL_BEEFY_BLOCK + MIN_BLOCK_INCREMENT + 1); + uint32 newBlockNumber = uint32(INITIAL_BEEFY_BLOCK + REFUND_TARGET); // 100% refund IBeefyClient.Commitment memory commitment = createCommitment(newBlockNumber); uint256[] memory bitfield = new uint256[](1); IBeefyClient.ValidatorProof memory proof = createValidatorProof(); @@ -395,11 +386,11 @@ contract BeefyClientWrapperTest is Test { wrapper.submitInitial(commitment, bitfield, proof); assertEq(relayer1.balance, relayerBalanceBefore); - bytes32 commitmentHash = keccak256(abi.encode(commitment)); + bytes32 commitmentHash = computeCommitmentHash(commitment); wrapper.commitPrevRandao(commitmentHash); assertEq(relayer1.balance, relayerBalanceBefore); - wrapper.submitFinal(commitment, bitfield, proofs, leaf, leafProof, 0, new uint32[](0)); + wrapper.submitFinal(commitment, bitfield, proofs, leaf, leafProof, 0); assertGt(relayer1.balance, relayerBalanceBefore); vm.stopPrank(); @@ -407,8 +398,10 @@ contract BeefyClientWrapperTest is Test { assertEq(wrapper.getCreditedGas(commitmentHash), 0); } - function test_refundCappedAtMaxGasPrice() public { - uint32 newBlockNumber = uint32(INITIAL_BEEFY_BLOCK + MIN_BLOCK_INCREMENT + 1); + function test_partialRefundForLowProgress() public { + // 50% of refund target = 50% refund + uint32 progress = uint32(REFUND_TARGET / 2); // 150 blocks + uint32 newBlockNumber = uint32(INITIAL_BEEFY_BLOCK + progress); IBeefyClient.Commitment memory commitment = createCommitment(newBlockNumber); uint256[] memory bitfield = new uint256[](1); IBeefyClient.ValidatorProof memory proof = createValidatorProof(); @@ -417,30 +410,50 @@ contract BeefyClientWrapperTest is Test { bytes32[] memory leafProof = new bytes32[](0); uint256 relayerBalanceBefore = relayer1.balance; - uint256 proxyBalanceBefore = address(proxy).balance; + uint256 wrapperBalanceBefore = address(wrapper).balance; - // Use gas price higher than max vm.startPrank(relayer1); - vm.txGasPrice(200 gwei); // Higher than MAX_GAS_PRICE (100 gwei) + vm.txGasPrice(50 gwei); wrapper.submitInitial(commitment, bitfield, proof); - bytes32 commitmentHash = keccak256(abi.encode(commitment)); + bytes32 commitmentHash = computeCommitmentHash(commitment); wrapper.commitPrevRandao(commitmentHash); - wrapper.submitFinal(commitment, bitfield, proofs, leaf, leafProof, 0, new uint32[](0)); + wrapper.submitFinal(commitment, bitfield, proofs, leaf, leafProof, 0); vm.stopPrank(); uint256 refundAmount = relayer1.balance - relayerBalanceBefore; - uint256 proxySpent = proxyBalanceBefore - address(proxy).balance; + uint256 wrapperSpent = wrapperBalanceBefore - address(wrapper).balance; - // Refund should be based on maxGasPrice, not actual tx.gasprice - assertEq(refundAmount, proxySpent); + // Verify refund was paid + assertGt(refundAmount, 0); + assertEq(refundAmount, wrapperSpent); } - function test_noRefundWhenInsufficientBalance() public { - // Drain wrapper balance - vm.prank(owner); - wrapper.withdrawFunds(payable(owner), address(proxy).balance); + function test_fullRefundAt100PercentProgress() public { + // 100% of refund target = 100% refund + uint32 newBlockNumber = uint32(INITIAL_BEEFY_BLOCK + REFUND_TARGET); + IBeefyClient.Commitment memory commitment = createCommitment(newBlockNumber); + uint256[] memory bitfield = new uint256[](1); + IBeefyClient.ValidatorProof memory proof = createValidatorProof(); + IBeefyClient.ValidatorProof[] memory proofs = createValidatorProofs(1); + IBeefyClient.MMRLeaf memory leaf = createMMRLeaf(); + bytes32[] memory leafProof = new bytes32[](0); + + uint256 relayerBalanceBefore = relayer1.balance; - uint32 newBlockNumber = uint32(INITIAL_BEEFY_BLOCK + MIN_BLOCK_INCREMENT + 1); + vm.startPrank(relayer1); + vm.txGasPrice(50 gwei); + wrapper.submitInitial(commitment, bitfield, proof); + bytes32 commitmentHash = computeCommitmentHash(commitment); + wrapper.commitPrevRandao(commitmentHash); + wrapper.submitFinal(commitment, bitfield, proofs, leaf, leafProof, 0); + vm.stopPrank(); + + uint256 refundAmount = relayer1.balance - relayerBalanceBefore; + assertGt(refundAmount, 0); + } + + function test_refundCappedAtMaxGasPrice() public { + uint32 newBlockNumber = uint32(INITIAL_BEEFY_BLOCK + REFUND_TARGET); IBeefyClient.Commitment memory commitment = createCommitment(newBlockNumber); uint256[] memory bitfield = new uint256[](1); IBeefyClient.ValidatorProof memory proof = createValidatorProof(); @@ -449,16 +462,22 @@ contract BeefyClientWrapperTest is Test { bytes32[] memory leafProof = new bytes32[](0); uint256 relayerBalanceBefore = relayer1.balance; + uint256 wrapperBalanceBefore = address(wrapper).balance; + // Use gas price higher than max vm.startPrank(relayer1); + vm.txGasPrice(200 gwei); // Higher than MAX_GAS_PRICE (100 gwei) wrapper.submitInitial(commitment, bitfield, proof); - bytes32 commitmentHash = keccak256(abi.encode(commitment)); + bytes32 commitmentHash = computeCommitmentHash(commitment); wrapper.commitPrevRandao(commitmentHash); - wrapper.submitFinal(commitment, bitfield, proofs, leaf, leafProof, 0, new uint32[](0)); + wrapper.submitFinal(commitment, bitfield, proofs, leaf, leafProof, 0); vm.stopPrank(); - assertEq(relayer1.balance, relayerBalanceBefore); // No refund - assertEq(mockBeefyClient.submitFinalCount(), 1); // Submission succeeded + uint256 refundAmount = relayer1.balance - relayerBalanceBefore; + uint256 wrapperSpent = wrapperBalanceBefore - address(wrapper).balance; + + // Refund should be based on maxGasPrice, not actual tx.gasprice + assertEq(refundAmount, wrapperSpent); } function test_refundCappedAtMaxRefundAmount() public { @@ -466,7 +485,7 @@ contract BeefyClientWrapperTest is Test { vm.prank(owner); wrapper.setMaxRefundAmount(0.0001 ether); - uint32 newBlockNumber = uint32(INITIAL_BEEFY_BLOCK + MIN_BLOCK_INCREMENT + 1); + uint32 newBlockNumber = uint32(INITIAL_BEEFY_BLOCK + REFUND_TARGET); IBeefyClient.Commitment memory commitment = createCommitment(newBlockNumber); uint256[] memory bitfield = new uint256[](1); IBeefyClient.ValidatorProof memory proof = createValidatorProof(); @@ -479,9 +498,9 @@ contract BeefyClientWrapperTest is Test { vm.startPrank(relayer1); vm.txGasPrice(100 gwei); wrapper.submitInitial(commitment, bitfield, proof); - bytes32 commitmentHash = keccak256(abi.encode(commitment)); + bytes32 commitmentHash = computeCommitmentHash(commitment); wrapper.commitPrevRandao(commitmentHash); - wrapper.submitFinal(commitment, bitfield, proofs, leaf, leafProof, 0, new uint32[](0)); + wrapper.submitFinal(commitment, bitfield, proofs, leaf, leafProof, 0); vm.stopPrank(); uint256 refundAmount = relayer1.balance - relayerBalanceBefore; @@ -490,22 +509,133 @@ contract BeefyClientWrapperTest is Test { assertEq(refundAmount, 0.0001 ether); } - function test_creditedGasForfeitedOnClearTicket() public { - uint32 newBlockNumber = uint32(INITIAL_BEEFY_BLOCK + MIN_BLOCK_INCREMENT + 1); + function test_noRefundWhenInsufficientBalance() public { + // Drain wrapper balance + vm.prank(owner); + wrapper.withdrawFunds(payable(owner), address(wrapper).balance); + + uint32 newBlockNumber = uint32(INITIAL_BEEFY_BLOCK + REFUND_TARGET); IBeefyClient.Commitment memory commitment = createCommitment(newBlockNumber); uint256[] memory bitfield = new uint256[](1); IBeefyClient.ValidatorProof memory proof = createValidatorProof(); + IBeefyClient.ValidatorProof[] memory proofs = createValidatorProofs(1); + IBeefyClient.MMRLeaf memory leaf = createMMRLeaf(); + bytes32[] memory leafProof = new bytes32[](0); + + uint256 relayerBalanceBefore = relayer1.balance; vm.startPrank(relayer1); wrapper.submitInitial(commitment, bitfield, proof); + bytes32 commitmentHash = computeCommitmentHash(commitment); + wrapper.commitPrevRandao(commitmentHash); + wrapper.submitFinal(commitment, bitfield, proofs, leaf, leafProof, 0); + vm.stopPrank(); - bytes32 commitmentHash = keccak256(abi.encode(commitment)); - assertGt(wrapper.getCreditedGas(commitmentHash), 0); + assertEq(relayer1.balance, relayerBalanceBefore); // No refund + assertEq(mockBeefyClient.submitFinalCount(), 1); // Submission succeeded + } - // Clear ticket - gas should be forfeited - wrapper.clearTicket(); - assertEq(wrapper.getCreditedGas(commitmentHash), 0); + /* Reward Pool Tests */ + + function test_fundRewardPool() public { + vm.deal(address(this), 10 ether); + + wrapper.fundRewardPool{value: 5 ether}(); + + assertEq(wrapper.getRewardPool(), 5 ether); + } + + function test_rewardPaidForHighProgress() public { + // Fund the reward pool + vm.deal(address(this), 10 ether); + wrapper.fundRewardPool{value: 5 ether}(); + + // Progress beyond refundTarget triggers rewards + uint32 progress = uint32(REWARD_TARGET); // Max progress = max reward + uint32 newBlockNumber = uint32(INITIAL_BEEFY_BLOCK + progress); + IBeefyClient.Commitment memory commitment = createCommitment(newBlockNumber); + uint256[] memory bitfield = new uint256[](1); + IBeefyClient.ValidatorProof memory proof = createValidatorProof(); + IBeefyClient.ValidatorProof[] memory proofs = createValidatorProofs(1); + IBeefyClient.MMRLeaf memory leaf = createMMRLeaf(); + bytes32[] memory leafProof = new bytes32[](0); + + uint256 relayerBalanceBefore = relayer1.balance; + uint256 rewardPoolBefore = wrapper.getRewardPool(); + + vm.startPrank(relayer1); + vm.txGasPrice(50 gwei); + wrapper.submitInitial(commitment, bitfield, proof); + bytes32 commitmentHash = computeCommitmentHash(commitment); + wrapper.commitPrevRandao(commitmentHash); + wrapper.submitFinal(commitment, bitfield, proofs, leaf, leafProof, 0); + vm.stopPrank(); + + uint256 relayerPayout = relayer1.balance - relayerBalanceBefore; + uint256 rewardPoolAfter = wrapper.getRewardPool(); + + // Relayer should receive refund + reward + assertGt(relayerPayout, 0); + // Reward pool should be depleted + assertLt(rewardPoolAfter, rewardPoolBefore); + } + + function test_noRewardForLowProgress() public { + // Fund the reward pool + vm.deal(address(this), 10 ether); + wrapper.fundRewardPool{value: 5 ether}(); + + // Progress below refundTarget = no reward (only partial refund) + uint32 progress = uint32(REFUND_TARGET / 2); + uint32 newBlockNumber = uint32(INITIAL_BEEFY_BLOCK + progress); + IBeefyClient.Commitment memory commitment = createCommitment(newBlockNumber); + uint256[] memory bitfield = new uint256[](1); + IBeefyClient.ValidatorProof memory proof = createValidatorProof(); + IBeefyClient.ValidatorProof[] memory proofs = createValidatorProofs(1); + IBeefyClient.MMRLeaf memory leaf = createMMRLeaf(); + bytes32[] memory leafProof = new bytes32[](0); + + uint256 rewardPoolBefore = wrapper.getRewardPool(); + + vm.startPrank(relayer1); + vm.txGasPrice(50 gwei); + wrapper.submitInitial(commitment, bitfield, proof); + bytes32 commitmentHash = computeCommitmentHash(commitment); + wrapper.commitPrevRandao(commitmentHash); + wrapper.submitFinal(commitment, bitfield, proofs, leaf, leafProof, 0); vm.stopPrank(); + + // Reward pool should be unchanged (no reward paid) + assertEq(wrapper.getRewardPool(), rewardPoolBefore); + } + + function test_estimatePayout() public { + uint256 gasUsed = 500000; + uint256 gasPrice = 50 gwei; + + // Test 50% progress (50% refund, 0% reward) + (uint256 refund50, uint256 reward50) = wrapper.estimatePayout(gasUsed, gasPrice, REFUND_TARGET / 2); + assertEq(refund50, (gasUsed * gasPrice * 50) / 100); + assertEq(reward50, 0); + + // Test 100% refund progress (100% refund, 0% reward) + (uint256 refund100, uint256 reward100) = wrapper.estimatePayout(gasUsed, gasPrice, REFUND_TARGET); + assertEq(refund100, gasUsed * gasPrice); + assertEq(reward100, 0); + } + + function test_estimatePayout_withRewardPool() public { + // Fund the reward pool + vm.deal(address(this), 10 ether); + wrapper.fundRewardPool{value: 5 ether}(); + + uint256 gasUsed = 500000; + uint256 gasPrice = 50 gwei; + + // Test max progress (100% refund, 100% reward) + (uint256 refundMax, uint256 rewardMax) = wrapper.estimatePayout(gasUsed, gasPrice, REWARD_TARGET); + assertEq(refundMax, gasUsed * gasPrice); + assertEq(rewardMax, 5 ether); // Full reward pool } /* Admin Function Tests */ @@ -517,25 +647,25 @@ contract BeefyClientWrapperTest is Test { assertEq(wrapper.maxGasPrice(), 200 gwei); } - function test_setGracePeriod() public { + function test_setMaxRefundAmount() public { vm.prank(owner); - wrapper.setGracePeriod(20); + wrapper.setMaxRefundAmount(2 ether); - assertEq(wrapper.gracePeriodBlocks(), 20); + assertEq(wrapper.maxRefundAmount(), 2 ether); } - function test_setMinBlockIncrement() public { + function test_setRefundTarget() public { vm.prank(owner); - wrapper.setMinBlockIncrement(200); + wrapper.setRefundTarget(600); - assertEq(wrapper.minBlockIncrement(), 200); + assertEq(wrapper.refundTarget(), 600); } - function test_setMaxRefundAmount() public { + function test_setRewardTarget() public { vm.prank(owner); - wrapper.setMaxRefundAmount(2 ether); + wrapper.setRewardTarget(4800); - assertEq(wrapper.maxRefundAmount(), 2 ether); + assertEq(wrapper.rewardTarget(), 4800); } function test_withdrawFunds() public { @@ -558,25 +688,25 @@ contract BeefyClientWrapperTest is Test { } function test_adminFunctions_onlyOwner() public { - vm.startPrank(nonRelayer); + vm.startPrank(anyone); vm.expectRevert(BeefyClientWrapper.Unauthorized.selector); wrapper.setMaxGasPrice(1); vm.expectRevert(BeefyClientWrapper.Unauthorized.selector); - wrapper.setGracePeriod(1); + wrapper.setMaxRefundAmount(1); vm.expectRevert(BeefyClientWrapper.Unauthorized.selector); - wrapper.setMinBlockIncrement(1); + wrapper.setRefundTarget(1); vm.expectRevert(BeefyClientWrapper.Unauthorized.selector); - wrapper.setMaxRefundAmount(1); + wrapper.setRewardTarget(1); vm.expectRevert(BeefyClientWrapper.Unauthorized.selector); - wrapper.withdrawFunds(payable(nonRelayer), 1); + wrapper.withdrawFunds(payable(anyone), 1); vm.expectRevert(BeefyClientWrapper.Unauthorized.selector); - wrapper.transferOwnership(nonRelayer); + wrapper.transferOwnership(anyone); vm.stopPrank(); } @@ -584,320 +714,59 @@ contract BeefyClientWrapperTest is Test { /* Deposit Tests */ function test_acceptsDeposits() public { - uint256 balanceBefore = address(proxy).balance; + uint256 balanceBefore = address(wrapper).balance; vm.deal(address(this), 1 ether); - (bool success,) = address(proxy).call{value: 1 ether}(""); + (bool success,) = address(wrapper).call{value: 1 ether}(""); assertTrue(success); - assertEq(address(proxy).balance, balanceBefore + 1 ether); - } - - /* Non-Relayer Tests */ - - function test_nonRelayerCannotSubmit() public { - uint32 newBlockNumber = uint32(INITIAL_BEEFY_BLOCK + MIN_BLOCK_INCREMENT + 1); - IBeefyClient.Commitment memory commitment = createCommitment(newBlockNumber); - uint256[] memory bitfield = new uint256[](1); - IBeefyClient.ValidatorProof memory proof = createValidatorProof(); - - vm.prank(nonRelayer); - vm.expectRevert(BeefyClientWrapper.NotARelayer.selector); - wrapper.submitInitial(commitment, bitfield, proof); + assertEq(address(wrapper).balance, balanceBefore + 1 ether); } /* View Function Tests */ - function test_getRelayers() public { - address[] memory allRelayers = wrapper.getRelayers(); - assertEq(allRelayers.length, 3); - assertEq(allRelayers[0], relayer1); - assertEq(allRelayers[1], relayer2); - assertEq(allRelayers[2], relayer3); - } - function test_getBalance() public { assertEq(wrapper.getBalance(), 100 ether); } - /* Upgrade Tests */ - - function test_implementation() public { - assertEq(wrapper.implementation(), address(implementation)); - } - - function test_upgradeTo() public { - BeefyClientWrapper newImpl = new BeefyClientWrapper(); - - vm.prank(owner); - wrapper.upgradeTo(address(newImpl), address(newImpl).codehash); - - assertEq(wrapper.implementation(), address(newImpl)); - } - - function test_upgradeTo_invalidContract() public { - vm.prank(owner); - vm.expectRevert(IUpgradable.InvalidContract.selector); - wrapper.upgradeTo(address(0x123), bytes32(0)); - } - - function test_upgradeTo_invalidCodeHash() public { - BeefyClientWrapper newImpl = new BeefyClientWrapper(); - - vm.prank(owner); - vm.expectRevert(IUpgradable.InvalidCodeHash.selector); - wrapper.upgradeTo(address(newImpl), bytes32(uint256(0x123))); + function test_latestBeefyBlock() public { + assertEq(wrapper.latestBeefyBlock(), INITIAL_BEEFY_BLOCK); } - /* One Ticket Per Relayer Tests */ + /* Proxy View Function Tests */ - function test_cannotSubmitSecondTicketWhileActive() public { - uint32 newBlockNumber = uint32(INITIAL_BEEFY_BLOCK + MIN_BLOCK_INCREMENT + 1); - IBeefyClient.Commitment memory commitment1 = createCommitment(newBlockNumber); + function test_createFinalBitfield() public { + bytes32 commitmentHash = bytes32(uint256(1)); uint256[] memory bitfield = new uint256[](1); - IBeefyClient.ValidatorProof memory proof = createValidatorProof(); - - // relayer1 submits first ticket - vm.prank(relayer1); - wrapper.submitInitial(commitment1, bitfield, proof); - - // Update mock to allow another submission - mockBeefyClient.setLatestBeefyBlock(uint64(newBlockNumber)); + bitfield[0] = 123; - // relayer1 tries to submit second ticket (should fail) - uint32 newBlockNumber2 = uint32(newBlockNumber + MIN_BLOCK_INCREMENT + 1); - IBeefyClient.Commitment memory commitment2 = createCommitment(newBlockNumber2); - - vm.prank(relayer1); - vm.expectRevert(BeefyClientWrapper.TicketAlreadyActive.selector); - wrapper.submitInitial(commitment2, bitfield, proof); + uint256[] memory result = wrapper.createFinalBitfield(commitmentHash, bitfield); + assertEq(result[0], 123); } - function test_clearTicketAllowsNewSubmission() public { - uint32 newBlockNumber = uint32(INITIAL_BEEFY_BLOCK + MIN_BLOCK_INCREMENT + 1); - IBeefyClient.Commitment memory commitment1 = createCommitment(newBlockNumber); - uint256[] memory bitfield = new uint256[](1); - IBeefyClient.ValidatorProof memory proof = createValidatorProof(); - - // relayer1 submits first ticket - vm.prank(relayer1); - wrapper.submitInitial(commitment1, bitfield, proof); - - // relayer1 clears their ticket - vm.prank(relayer1); - wrapper.clearTicket(); - - // Now relayer1 can submit again - uint32 newBlockNumber2 = uint32(newBlockNumber + 1); - IBeefyClient.Commitment memory commitment2 = createCommitment(newBlockNumber2); - - vm.prank(relayer1); - wrapper.submitInitial(commitment2, bitfield, proof); + function test_createInitialBitfield() public { + uint256[] memory bitsToSet = new uint256[](1); + bitsToSet[0] = 5; - assertEq(mockBeefyClient.submitInitialCount(), 2); + uint256[] memory result = wrapper.createInitialBitfield(bitsToSet, 100); + assertEq(result.length, 1); } - function test_clearTicketRevertsIfNoActiveTicket() public { - vm.prank(relayer1); - vm.expectRevert(BeefyClientWrapper.InvalidTicket.selector); - wrapper.clearTicket(); + function test_randaoCommitDelay() public { + assertEq(wrapper.randaoCommitDelay(), 4); } - function test_submitFinalClearsActiveTicket() public { - uint32 newBlockNumber = uint32(INITIAL_BEEFY_BLOCK + MIN_BLOCK_INCREMENT + 1); - IBeefyClient.Commitment memory commitment = createCommitment(newBlockNumber); - uint256[] memory bitfield = new uint256[](1); - IBeefyClient.ValidatorProof memory proof = createValidatorProof(); - IBeefyClient.ValidatorProof[] memory proofs = createValidatorProofs(1); - IBeefyClient.MMRLeaf memory leaf = createMMRLeaf(); - bytes32[] memory leafProof = new bytes32[](0); - - // Complete full flow - vm.startPrank(relayer1); - wrapper.submitInitial(commitment, bitfield, proof); - - bytes32 commitmentHash = keccak256(abi.encode(commitment)); - wrapper.commitPrevRandao(commitmentHash); - wrapper.submitFinal(commitment, bitfield, proofs, leaf, leafProof, 0, new uint32[](0)); - vm.stopPrank(); - - // Verify activeTicket is cleared - assertEq(wrapper.activeTicket(relayer1), bytes32(0)); - - // relayer1 can now submit again (it's relayer2's turn, so advance grace period) - vm.roll(block.number + GRACE_PERIOD_BLOCKS + 1); - - uint32 newBlockNumber2 = uint32(newBlockNumber + MIN_BLOCK_INCREMENT + 1); - IBeefyClient.Commitment memory commitment2 = createCommitment(newBlockNumber2); - - vm.prank(relayer1); - wrapper.submitInitial(commitment2, bitfield, proof); - - assertEq(mockBeefyClient.submitInitialCount(), 2); + function test_currentValidatorSet() public { + (uint128 id, uint128 length, bytes32 root) = wrapper.currentValidatorSet(); + assertEq(id, 1); + assertEq(length, 100); + assertEq(root, bytes32(0)); } - function test_activeTicketTracking() public { - uint32 newBlockNumber = uint32(INITIAL_BEEFY_BLOCK + MIN_BLOCK_INCREMENT + 1); - IBeefyClient.Commitment memory commitment = createCommitment(newBlockNumber); - uint256[] memory bitfield = new uint256[](1); - IBeefyClient.ValidatorProof memory proof = createValidatorProof(); - - // Before submission, activeTicket should be empty - assertEq(wrapper.activeTicket(relayer1), bytes32(0)); - - vm.prank(relayer1); - wrapper.submitInitial(commitment, bitfield, proof); - - // After submission, activeTicket should be set - bytes32 commitmentHash = keccak256(abi.encode(commitment)); - assertEq(wrapper.activeTicket(relayer1), commitmentHash); - } - - function test_addTip() public { - uint32 targetBlock = uint32(INITIAL_BEEFY_BLOCK + MIN_BLOCK_INCREMENT + 1); - - vm.deal(address(this), 1 ether); - wrapper.addTip{value: 0.5 ether}(targetBlock); - - assertEq(wrapper.getTip(targetBlock), 0.5 ether); - } - - function test_addTip_accumulates() public { - uint32 targetBlock = uint32(INITIAL_BEEFY_BLOCK + MIN_BLOCK_INCREMENT + 1); - - vm.deal(address(this), 2 ether); - wrapper.addTip{value: 0.5 ether}(targetBlock); - wrapper.addTip{value: 0.3 ether}(targetBlock); - - assertEq(wrapper.getTip(targetBlock), 0.8 ether); - } - - function test_claimTips_singleBlock() public { - uint32 newBlockNumber = uint32(INITIAL_BEEFY_BLOCK + MIN_BLOCK_INCREMENT + 1); - - // Add a tip for the target block - vm.deal(address(this), 1 ether); - wrapper.addTip{value: 0.5 ether}(newBlockNumber); - - IBeefyClient.Commitment memory commitment = createCommitment(newBlockNumber); - uint256[] memory bitfield = new uint256[](1); - IBeefyClient.ValidatorProof memory proof = createValidatorProof(); - IBeefyClient.ValidatorProof[] memory proofs = createValidatorProofs(1); - IBeefyClient.MMRLeaf memory leaf = createMMRLeaf(); - bytes32[] memory leafProof = new bytes32[](0); - - uint256 relayerBalanceBefore = relayer1.balance; - - vm.startPrank(relayer1); - vm.txGasPrice(50 gwei); - wrapper.submitInitial(commitment, bitfield, proof); - bytes32 commitmentHash = keccak256(abi.encode(commitment)); - wrapper.commitPrevRandao(commitmentHash); - - // Claim the tip for the block we're submitting - uint32[] memory claimBlocks = new uint32[](1); - claimBlocks[0] = newBlockNumber; - wrapper.submitFinal(commitment, bitfield, proofs, leaf, leafProof, 0, claimBlocks); - vm.stopPrank(); - - // Relayer should have received refund + tip - uint256 relayerBalanceAfter = relayer1.balance; - assertGt(relayerBalanceAfter - relayerBalanceBefore, 0.5 ether); - - // Tip should be cleared - assertEq(wrapper.getTip(newBlockNumber), 0); - } - - function test_claimTips_multipleBlocks() public { - uint32 newBlockNumber = uint32(INITIAL_BEEFY_BLOCK + MIN_BLOCK_INCREMENT + 1); - uint32 tipBlock1 = uint32(INITIAL_BEEFY_BLOCK + 50); - uint32 tipBlock2 = uint32(INITIAL_BEEFY_BLOCK + 75); - - // Add tips for blocks that will be covered by the submission - vm.deal(address(this), 2 ether); - wrapper.addTip{value: 0.3 ether}(tipBlock1); - wrapper.addTip{value: 0.2 ether}(tipBlock2); - - IBeefyClient.Commitment memory commitment = createCommitment(newBlockNumber); - uint256[] memory bitfield = new uint256[](1); - IBeefyClient.ValidatorProof memory proof = createValidatorProof(); - IBeefyClient.ValidatorProof[] memory proofs = createValidatorProofs(1); - IBeefyClient.MMRLeaf memory leaf = createMMRLeaf(); - bytes32[] memory leafProof = new bytes32[](0); - - uint256 relayerBalanceBefore = relayer1.balance; - - vm.startPrank(relayer1); - vm.txGasPrice(50 gwei); - wrapper.submitInitial(commitment, bitfield, proof); - bytes32 commitmentHash = keccak256(abi.encode(commitment)); - wrapper.commitPrevRandao(commitmentHash); - - // Claim tips for both blocks - uint32[] memory claimBlocks = new uint32[](2); - claimBlocks[0] = tipBlock1; - claimBlocks[1] = tipBlock2; - wrapper.submitFinal(commitment, bitfield, proofs, leaf, leafProof, 0, claimBlocks); - vm.stopPrank(); - - // Relayer should have received refund + both tips - uint256 relayerBalanceAfter = relayer1.balance; - assertGt(relayerBalanceAfter - relayerBalanceBefore, 0.5 ether); - - // Tips should be cleared - assertEq(wrapper.getTip(tipBlock1), 0); - assertEq(wrapper.getTip(tipBlock2), 0); - } - - function test_claimTips_ignoresFutureBlocks() public { - uint32 newBlockNumber = uint32(INITIAL_BEEFY_BLOCK + MIN_BLOCK_INCREMENT + 1); - uint32 futureBlock = uint32(newBlockNumber + 100); // Block after submission - - // Add tip for a future block - vm.deal(address(this), 1 ether); - wrapper.addTip{value: 0.5 ether}(futureBlock); - - IBeefyClient.Commitment memory commitment = createCommitment(newBlockNumber); - uint256[] memory bitfield = new uint256[](1); - IBeefyClient.ValidatorProof memory proof = createValidatorProof(); - IBeefyClient.ValidatorProof[] memory proofs = createValidatorProofs(1); - IBeefyClient.MMRLeaf memory leaf = createMMRLeaf(); - bytes32[] memory leafProof = new bytes32[](0); - - vm.startPrank(relayer1); - wrapper.submitInitial(commitment, bitfield, proof); - bytes32 commitmentHash = keccak256(abi.encode(commitment)); - wrapper.commitPrevRandao(commitmentHash); - - // Try to claim the future block tip - uint32[] memory claimBlocks = new uint32[](1); - claimBlocks[0] = futureBlock; - wrapper.submitFinal(commitment, bitfield, proofs, leaf, leafProof, 0, claimBlocks); - vm.stopPrank(); - - // Tip should NOT be claimed (block is in the future) - assertEq(wrapper.getTip(futureBlock), 0.5 ether); - } - - function test_claimTips_emptyArray() public { - uint32 newBlockNumber = uint32(INITIAL_BEEFY_BLOCK + MIN_BLOCK_INCREMENT + 1); - - IBeefyClient.Commitment memory commitment = createCommitment(newBlockNumber); - uint256[] memory bitfield = new uint256[](1); - IBeefyClient.ValidatorProof memory proof = createValidatorProof(); - IBeefyClient.ValidatorProof[] memory proofs = createValidatorProofs(1); - IBeefyClient.MMRLeaf memory leaf = createMMRLeaf(); - bytes32[] memory leafProof = new bytes32[](0); - - vm.startPrank(relayer1); - wrapper.submitInitial(commitment, bitfield, proof); - bytes32 commitmentHash = keccak256(abi.encode(commitment)); - wrapper.commitPrevRandao(commitmentHash); - - // Submit with empty claim array (should work fine) - wrapper.submitFinal(commitment, bitfield, proofs, leaf, leafProof, 0, new uint32[](0)); - vm.stopPrank(); - - assertEq(mockBeefyClient.submitFinalCount(), 1); + function test_nextValidatorSet() public { + (uint128 id, uint128 length, bytes32 root) = wrapper.nextValidatorSet(); + assertEq(id, 2); + assertEq(length, 100); + assertEq(root, bytes32(0)); } } diff --git a/relayer/contracts/beefy_client_wrapper.go b/relayer/contracts/beefy_client_wrapper.go index 8a4c2c88a..6b2f45d26 100644 --- a/relayer/contracts/beefy_client_wrapper.go +++ b/relayer/contracts/beefy_client_wrapper.go @@ -65,7 +65,7 @@ type IBeefyClientValidatorProof struct { // BeefyClientWrapperMetaData contains all meta data concerning the BeefyClientWrapper contract. var BeefyClientWrapperMetaData = &bind.MetaData{ - ABI: "[{\"type\":\"receive\",\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"activeTicket\",\"inputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"addRelayer\",\"inputs\":[{\"name\":\"relayer\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"beefyClient\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"contractIBeefyClient\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"clearTicket\",\"inputs\":[],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"commitPrevRandao\",\"inputs\":[{\"name\":\"commitmentHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"createFinalBitfield\",\"inputs\":[{\"name\":\"commitmentHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"bitfield\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"currentTurnIndex\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getBalance\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getCurrentTurnRelayer\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getRelayerCount\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getRelayers\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address[]\",\"internalType\":\"address[]\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"gracePeriodBlocks\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"implementation\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"initialize\",\"inputs\":[{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"isGracePeriodActive\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"isRelayer\",\"inputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"lastSubmissionBlock\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"latestBeefyBlock\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"maxGasPrice\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"minBlockIncrement\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"owner\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"relayers\",\"inputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"removeRelayer\",\"inputs\":[{\"name\":\"relayer\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setGracePeriod\",\"inputs\":[{\"name\":\"_gracePeriodBlocks\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setMaxGasPrice\",\"inputs\":[{\"name\":\"_maxGasPrice\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setMinBlockIncrement\",\"inputs\":[{\"name\":\"_minBlockIncrement\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"submitFinal\",\"inputs\":[{\"name\":\"commitment\",\"type\":\"tuple\",\"internalType\":\"structIBeefyClient.Commitment\",\"components\":[{\"name\":\"blockNumber\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"validatorSetID\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"payload\",\"type\":\"tuple[]\",\"internalType\":\"structIBeefyClient.PayloadItem[]\",\"components\":[{\"name\":\"payloadID\",\"type\":\"bytes2\",\"internalType\":\"bytes2\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]},{\"name\":\"bitfield\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"},{\"name\":\"proofs\",\"type\":\"tuple[]\",\"internalType\":\"structIBeefyClient.ValidatorProof[]\",\"components\":[{\"name\":\"v\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"r\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"s\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"index\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"proof\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"}]},{\"name\":\"leaf\",\"type\":\"tuple\",\"internalType\":\"structIBeefyClient.MMRLeaf\",\"components\":[{\"name\":\"version\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"parentNumber\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"parentHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"nextAuthoritySetID\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"nextAuthoritySetLen\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"nextAuthoritySetRoot\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"parachainHeadsRoot\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"name\":\"leafProof\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"},{\"name\":\"leafProofOrder\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"submitInitial\",\"inputs\":[{\"name\":\"commitment\",\"type\":\"tuple\",\"internalType\":\"structIBeefyClient.Commitment\",\"components\":[{\"name\":\"blockNumber\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"validatorSetID\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"payload\",\"type\":\"tuple[]\",\"internalType\":\"structIBeefyClient.PayloadItem[]\",\"components\":[{\"name\":\"payloadID\",\"type\":\"bytes2\",\"internalType\":\"bytes2\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]},{\"name\":\"bitfield\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"},{\"name\":\"proof\",\"type\":\"tuple\",\"internalType\":\"structIBeefyClient.ValidatorProof\",\"components\":[{\"name\":\"v\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"r\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"s\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"index\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"proof\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"ticketOwner\",\"inputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"transferOwnership\",\"inputs\":[{\"name\":\"newOwner\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"upgradeTo\",\"inputs\":[{\"name\":\"newImplementation\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"expectedCodeHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"withdrawFunds\",\"inputs\":[{\"name\":\"recipient\",\"type\":\"address\",\"internalType\":\"addresspayable\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"event\",\"name\":\"ConfigUpdated\",\"inputs\":[{\"name\":\"parameter\",\"type\":\"string\",\"indexed\":false,\"internalType\":\"string\"},{\"name\":\"value\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"FundsDeposited\",\"inputs\":[{\"name\":\"depositor\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"FundsWithdrawn\",\"inputs\":[{\"name\":\"recipient\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"RelayerAdded\",\"inputs\":[{\"name\":\"relayer\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"RelayerRemoved\",\"inputs\":[{\"name\":\"relayer\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"SubmissionRefunded\",\"inputs\":[{\"name\":\"relayer\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"},{\"name\":\"gasUsed\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"TurnAdvanced\",\"inputs\":[{\"name\":\"newTurnIndex\",\"type\":\"uint256\",\"indexed\":true,\"internalType\":\"uint256\"},{\"name\":\"nextRelayer\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Upgraded\",\"inputs\":[{\"name\":\"implementation\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"error\",\"name\":\"AlreadyInitialized\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InsufficientBlockIncrement\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidAddress\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidCodeHash\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidContract\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidTicket\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"NoRelayers\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"NotARelayer\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"NotTicketOwner\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"NotYourTurn\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"RelayerAlreadyExists\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"RelayerNotFound\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"TicketAlreadyActive\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"TransferFailed\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"Unauthorized\",\"inputs\":[]}]", + ABI: "[{\"type\":\"receive\",\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"activeTicket\",\"inputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"addRelayer\",\"inputs\":[{\"name\":\"relayer\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"addTip\",\"inputs\":[{\"name\":\"beefyBlockNumber\",\"type\":\"uint32\",\"internalType\":\"uint32\"}],\"outputs\":[],\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"beefyClient\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"contractIBeefyClient\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"clearTicket\",\"inputs\":[],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"commitPrevRandao\",\"inputs\":[{\"name\":\"commitmentHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"createFinalBitfield\",\"inputs\":[{\"name\":\"commitmentHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"bitfield\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"createInitialBitfield\",\"inputs\":[{\"name\":\"bitsToSet\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"},{\"name\":\"length\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"creditedGas\",\"inputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"currentTurnIndex\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"currentValidatorSet\",\"inputs\":[],\"outputs\":[{\"name\":\"id\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"length\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"root\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getBalance\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getCreditedGas\",\"inputs\":[{\"name\":\"commitmentHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getCurrentTurnRelayer\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getRelayerCount\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getRelayers\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address[]\",\"internalType\":\"address[]\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getTip\",\"inputs\":[{\"name\":\"beefyBlockNumber\",\"type\":\"uint32\",\"internalType\":\"uint32\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"gracePeriodBlocks\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"implementation\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"initialize\",\"inputs\":[{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"isGracePeriodActive\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"isRelayer\",\"inputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"lastSubmissionBlock\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"latestBeefyBlock\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"maxGasPrice\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"maxRefundAmount\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"minBlockIncrement\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"nextValidatorSet\",\"inputs\":[],\"outputs\":[{\"name\":\"id\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"length\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"root\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"owner\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"randaoCommitDelay\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"relayers\",\"inputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"removeRelayer\",\"inputs\":[{\"name\":\"relayer\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setGracePeriod\",\"inputs\":[{\"name\":\"_gracePeriodBlocks\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setMaxGasPrice\",\"inputs\":[{\"name\":\"_maxGasPrice\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setMaxRefundAmount\",\"inputs\":[{\"name\":\"_maxRefundAmount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setMinBlockIncrement\",\"inputs\":[{\"name\":\"_minBlockIncrement\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"submitFinal\",\"inputs\":[{\"name\":\"commitment\",\"type\":\"tuple\",\"internalType\":\"structIBeefyClient.Commitment\",\"components\":[{\"name\":\"blockNumber\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"validatorSetID\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"payload\",\"type\":\"tuple[]\",\"internalType\":\"structIBeefyClient.PayloadItem[]\",\"components\":[{\"name\":\"payloadID\",\"type\":\"bytes2\",\"internalType\":\"bytes2\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]},{\"name\":\"bitfield\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"},{\"name\":\"proofs\",\"type\":\"tuple[]\",\"internalType\":\"structIBeefyClient.ValidatorProof[]\",\"components\":[{\"name\":\"v\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"r\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"s\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"index\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"proof\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"}]},{\"name\":\"leaf\",\"type\":\"tuple\",\"internalType\":\"structIBeefyClient.MMRLeaf\",\"components\":[{\"name\":\"version\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"parentNumber\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"parentHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"nextAuthoritySetID\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"nextAuthoritySetLen\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"nextAuthoritySetRoot\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"parachainHeadsRoot\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"name\":\"leafProof\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"},{\"name\":\"leafProofOrder\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"claimTipBlocks\",\"type\":\"uint32[]\",\"internalType\":\"uint32[]\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"submitInitial\",\"inputs\":[{\"name\":\"commitment\",\"type\":\"tuple\",\"internalType\":\"structIBeefyClient.Commitment\",\"components\":[{\"name\":\"blockNumber\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"validatorSetID\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"payload\",\"type\":\"tuple[]\",\"internalType\":\"structIBeefyClient.PayloadItem[]\",\"components\":[{\"name\":\"payloadID\",\"type\":\"bytes2\",\"internalType\":\"bytes2\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]},{\"name\":\"bitfield\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"},{\"name\":\"proof\",\"type\":\"tuple\",\"internalType\":\"structIBeefyClient.ValidatorProof\",\"components\":[{\"name\":\"v\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"r\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"s\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"index\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"proof\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"ticketOwner\",\"inputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"tips\",\"inputs\":[{\"name\":\"\",\"type\":\"uint32\",\"internalType\":\"uint32\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"transferOwnership\",\"inputs\":[{\"name\":\"newOwner\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"upgradeTo\",\"inputs\":[{\"name\":\"newImplementation\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"expectedCodeHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"withdrawFunds\",\"inputs\":[{\"name\":\"recipient\",\"type\":\"address\",\"internalType\":\"addresspayable\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"event\",\"name\":\"FundsDeposited\",\"inputs\":[{\"name\":\"depositor\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"FundsWithdrawn\",\"inputs\":[{\"name\":\"recipient\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"GasCredited\",\"inputs\":[{\"name\":\"relayer\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"commitmentHash\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"gasUsed\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"RelayerAdded\",\"inputs\":[{\"name\":\"relayer\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"RelayerRemoved\",\"inputs\":[{\"name\":\"relayer\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"SubmissionRefunded\",\"inputs\":[{\"name\":\"relayer\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"},{\"name\":\"totalGasUsed\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"TipAdded\",\"inputs\":[{\"name\":\"tipper\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"beefyBlockNumber\",\"type\":\"uint32\",\"indexed\":true,\"internalType\":\"uint32\"},{\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"TipsClaimed\",\"inputs\":[{\"name\":\"relayer\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"totalAmount\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"TurnAdvanced\",\"inputs\":[{\"name\":\"newTurnIndex\",\"type\":\"uint256\",\"indexed\":true,\"internalType\":\"uint256\"},{\"name\":\"nextRelayer\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Upgraded\",\"inputs\":[{\"name\":\"implementation\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"error\",\"name\":\"AlreadyInitialized\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InsufficientBlockIncrement\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidAddress\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidCodeHash\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidContract\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidTicket\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"NoRelayers\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"NotARelayer\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"NotTicketOwner\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"NotYourTurn\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"RelayerAlreadyExists\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"RelayerNotFound\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"TicketAlreadyActive\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"TransferFailed\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"Unauthorized\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"UnsupportedCompactEncoding\",\"inputs\":[]}]", } // BeefyClientWrapperABI is the input ABI used to generate the binding from. @@ -307,6 +307,68 @@ func (_BeefyClientWrapper *BeefyClientWrapperCallerSession) CreateFinalBitfield( return _BeefyClientWrapper.Contract.CreateFinalBitfield(&_BeefyClientWrapper.CallOpts, commitmentHash, bitfield) } +// CreateInitialBitfield is a free data retrieval call binding the contract method 0x5da57fe9. +// +// Solidity: function createInitialBitfield(uint256[] bitsToSet, uint256 length) view returns(uint256[]) +func (_BeefyClientWrapper *BeefyClientWrapperCaller) CreateInitialBitfield(opts *bind.CallOpts, bitsToSet []*big.Int, length *big.Int) ([]*big.Int, error) { + var out []interface{} + err := _BeefyClientWrapper.contract.Call(opts, &out, "createInitialBitfield", bitsToSet, length) + + if err != nil { + return *new([]*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new([]*big.Int)).(*[]*big.Int) + + return out0, err + +} + +// CreateInitialBitfield is a free data retrieval call binding the contract method 0x5da57fe9. +// +// Solidity: function createInitialBitfield(uint256[] bitsToSet, uint256 length) view returns(uint256[]) +func (_BeefyClientWrapper *BeefyClientWrapperSession) CreateInitialBitfield(bitsToSet []*big.Int, length *big.Int) ([]*big.Int, error) { + return _BeefyClientWrapper.Contract.CreateInitialBitfield(&_BeefyClientWrapper.CallOpts, bitsToSet, length) +} + +// CreateInitialBitfield is a free data retrieval call binding the contract method 0x5da57fe9. +// +// Solidity: function createInitialBitfield(uint256[] bitsToSet, uint256 length) view returns(uint256[]) +func (_BeefyClientWrapper *BeefyClientWrapperCallerSession) CreateInitialBitfield(bitsToSet []*big.Int, length *big.Int) ([]*big.Int, error) { + return _BeefyClientWrapper.Contract.CreateInitialBitfield(&_BeefyClientWrapper.CallOpts, bitsToSet, length) +} + +// CreditedGas is a free data retrieval call binding the contract method 0x660b2928. +// +// Solidity: function creditedGas(bytes32 ) view returns(uint256) +func (_BeefyClientWrapper *BeefyClientWrapperCaller) CreditedGas(opts *bind.CallOpts, arg0 [32]byte) (*big.Int, error) { + var out []interface{} + err := _BeefyClientWrapper.contract.Call(opts, &out, "creditedGas", arg0) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// CreditedGas is a free data retrieval call binding the contract method 0x660b2928. +// +// Solidity: function creditedGas(bytes32 ) view returns(uint256) +func (_BeefyClientWrapper *BeefyClientWrapperSession) CreditedGas(arg0 [32]byte) (*big.Int, error) { + return _BeefyClientWrapper.Contract.CreditedGas(&_BeefyClientWrapper.CallOpts, arg0) +} + +// CreditedGas is a free data retrieval call binding the contract method 0x660b2928. +// +// Solidity: function creditedGas(bytes32 ) view returns(uint256) +func (_BeefyClientWrapper *BeefyClientWrapperCallerSession) CreditedGas(arg0 [32]byte) (*big.Int, error) { + return _BeefyClientWrapper.Contract.CreditedGas(&_BeefyClientWrapper.CallOpts, arg0) +} + // CurrentTurnIndex is a free data retrieval call binding the contract method 0x50efd268. // // Solidity: function currentTurnIndex() view returns(uint256) @@ -338,6 +400,56 @@ func (_BeefyClientWrapper *BeefyClientWrapperCallerSession) CurrentTurnIndex() ( return _BeefyClientWrapper.Contract.CurrentTurnIndex(&_BeefyClientWrapper.CallOpts) } +// CurrentValidatorSet is a free data retrieval call binding the contract method 0x2cdea717. +// +// Solidity: function currentValidatorSet() view returns(uint128 id, uint128 length, bytes32 root) +func (_BeefyClientWrapper *BeefyClientWrapperCaller) CurrentValidatorSet(opts *bind.CallOpts) (struct { + Id *big.Int + Length *big.Int + Root [32]byte +}, error) { + var out []interface{} + err := _BeefyClientWrapper.contract.Call(opts, &out, "currentValidatorSet") + + outstruct := new(struct { + Id *big.Int + Length *big.Int + Root [32]byte + }) + if err != nil { + return *outstruct, err + } + + outstruct.Id = *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + outstruct.Length = *abi.ConvertType(out[1], new(*big.Int)).(**big.Int) + outstruct.Root = *abi.ConvertType(out[2], new([32]byte)).(*[32]byte) + + return *outstruct, err + +} + +// CurrentValidatorSet is a free data retrieval call binding the contract method 0x2cdea717. +// +// Solidity: function currentValidatorSet() view returns(uint128 id, uint128 length, bytes32 root) +func (_BeefyClientWrapper *BeefyClientWrapperSession) CurrentValidatorSet() (struct { + Id *big.Int + Length *big.Int + Root [32]byte +}, error) { + return _BeefyClientWrapper.Contract.CurrentValidatorSet(&_BeefyClientWrapper.CallOpts) +} + +// CurrentValidatorSet is a free data retrieval call binding the contract method 0x2cdea717. +// +// Solidity: function currentValidatorSet() view returns(uint128 id, uint128 length, bytes32 root) +func (_BeefyClientWrapper *BeefyClientWrapperCallerSession) CurrentValidatorSet() (struct { + Id *big.Int + Length *big.Int + Root [32]byte +}, error) { + return _BeefyClientWrapper.Contract.CurrentValidatorSet(&_BeefyClientWrapper.CallOpts) +} + // GetBalance is a free data retrieval call binding the contract method 0x12065fe0. // // Solidity: function getBalance() view returns(uint256) @@ -369,6 +481,37 @@ func (_BeefyClientWrapper *BeefyClientWrapperCallerSession) GetBalance() (*big.I return _BeefyClientWrapper.Contract.GetBalance(&_BeefyClientWrapper.CallOpts) } +// GetCreditedGas is a free data retrieval call binding the contract method 0xfd635f1c. +// +// Solidity: function getCreditedGas(bytes32 commitmentHash) view returns(uint256) +func (_BeefyClientWrapper *BeefyClientWrapperCaller) GetCreditedGas(opts *bind.CallOpts, commitmentHash [32]byte) (*big.Int, error) { + var out []interface{} + err := _BeefyClientWrapper.contract.Call(opts, &out, "getCreditedGas", commitmentHash) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// GetCreditedGas is a free data retrieval call binding the contract method 0xfd635f1c. +// +// Solidity: function getCreditedGas(bytes32 commitmentHash) view returns(uint256) +func (_BeefyClientWrapper *BeefyClientWrapperSession) GetCreditedGas(commitmentHash [32]byte) (*big.Int, error) { + return _BeefyClientWrapper.Contract.GetCreditedGas(&_BeefyClientWrapper.CallOpts, commitmentHash) +} + +// GetCreditedGas is a free data retrieval call binding the contract method 0xfd635f1c. +// +// Solidity: function getCreditedGas(bytes32 commitmentHash) view returns(uint256) +func (_BeefyClientWrapper *BeefyClientWrapperCallerSession) GetCreditedGas(commitmentHash [32]byte) (*big.Int, error) { + return _BeefyClientWrapper.Contract.GetCreditedGas(&_BeefyClientWrapper.CallOpts, commitmentHash) +} + // GetCurrentTurnRelayer is a free data retrieval call binding the contract method 0x5664b04f. // // Solidity: function getCurrentTurnRelayer() view returns(address) @@ -462,6 +605,37 @@ func (_BeefyClientWrapper *BeefyClientWrapperCallerSession) GetRelayers() ([]com return _BeefyClientWrapper.Contract.GetRelayers(&_BeefyClientWrapper.CallOpts) } +// GetTip is a free data retrieval call binding the contract method 0xa7e7353c. +// +// Solidity: function getTip(uint32 beefyBlockNumber) view returns(uint256) +func (_BeefyClientWrapper *BeefyClientWrapperCaller) GetTip(opts *bind.CallOpts, beefyBlockNumber uint32) (*big.Int, error) { + var out []interface{} + err := _BeefyClientWrapper.contract.Call(opts, &out, "getTip", beefyBlockNumber) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// GetTip is a free data retrieval call binding the contract method 0xa7e7353c. +// +// Solidity: function getTip(uint32 beefyBlockNumber) view returns(uint256) +func (_BeefyClientWrapper *BeefyClientWrapperSession) GetTip(beefyBlockNumber uint32) (*big.Int, error) { + return _BeefyClientWrapper.Contract.GetTip(&_BeefyClientWrapper.CallOpts, beefyBlockNumber) +} + +// GetTip is a free data retrieval call binding the contract method 0xa7e7353c. +// +// Solidity: function getTip(uint32 beefyBlockNumber) view returns(uint256) +func (_BeefyClientWrapper *BeefyClientWrapperCallerSession) GetTip(beefyBlockNumber uint32) (*big.Int, error) { + return _BeefyClientWrapper.Contract.GetTip(&_BeefyClientWrapper.CallOpts, beefyBlockNumber) +} + // GracePeriodBlocks is a free data retrieval call binding the contract method 0xde2daaff. // // Solidity: function gracePeriodBlocks() view returns(uint256) @@ -679,6 +853,37 @@ func (_BeefyClientWrapper *BeefyClientWrapperCallerSession) MaxGasPrice() (*big. return _BeefyClientWrapper.Contract.MaxGasPrice(&_BeefyClientWrapper.CallOpts) } +// MaxRefundAmount is a free data retrieval call binding the contract method 0x28bbc5c1. +// +// Solidity: function maxRefundAmount() view returns(uint256) +func (_BeefyClientWrapper *BeefyClientWrapperCaller) MaxRefundAmount(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _BeefyClientWrapper.contract.Call(opts, &out, "maxRefundAmount") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// MaxRefundAmount is a free data retrieval call binding the contract method 0x28bbc5c1. +// +// Solidity: function maxRefundAmount() view returns(uint256) +func (_BeefyClientWrapper *BeefyClientWrapperSession) MaxRefundAmount() (*big.Int, error) { + return _BeefyClientWrapper.Contract.MaxRefundAmount(&_BeefyClientWrapper.CallOpts) +} + +// MaxRefundAmount is a free data retrieval call binding the contract method 0x28bbc5c1. +// +// Solidity: function maxRefundAmount() view returns(uint256) +func (_BeefyClientWrapper *BeefyClientWrapperCallerSession) MaxRefundAmount() (*big.Int, error) { + return _BeefyClientWrapper.Contract.MaxRefundAmount(&_BeefyClientWrapper.CallOpts) +} + // MinBlockIncrement is a free data retrieval call binding the contract method 0x4bfcad80. // // Solidity: function minBlockIncrement() view returns(uint256) @@ -710,6 +915,56 @@ func (_BeefyClientWrapper *BeefyClientWrapperCallerSession) MinBlockIncrement() return _BeefyClientWrapper.Contract.MinBlockIncrement(&_BeefyClientWrapper.CallOpts) } +// NextValidatorSet is a free data retrieval call binding the contract method 0x36667513. +// +// Solidity: function nextValidatorSet() view returns(uint128 id, uint128 length, bytes32 root) +func (_BeefyClientWrapper *BeefyClientWrapperCaller) NextValidatorSet(opts *bind.CallOpts) (struct { + Id *big.Int + Length *big.Int + Root [32]byte +}, error) { + var out []interface{} + err := _BeefyClientWrapper.contract.Call(opts, &out, "nextValidatorSet") + + outstruct := new(struct { + Id *big.Int + Length *big.Int + Root [32]byte + }) + if err != nil { + return *outstruct, err + } + + outstruct.Id = *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + outstruct.Length = *abi.ConvertType(out[1], new(*big.Int)).(**big.Int) + outstruct.Root = *abi.ConvertType(out[2], new([32]byte)).(*[32]byte) + + return *outstruct, err + +} + +// NextValidatorSet is a free data retrieval call binding the contract method 0x36667513. +// +// Solidity: function nextValidatorSet() view returns(uint128 id, uint128 length, bytes32 root) +func (_BeefyClientWrapper *BeefyClientWrapperSession) NextValidatorSet() (struct { + Id *big.Int + Length *big.Int + Root [32]byte +}, error) { + return _BeefyClientWrapper.Contract.NextValidatorSet(&_BeefyClientWrapper.CallOpts) +} + +// NextValidatorSet is a free data retrieval call binding the contract method 0x36667513. +// +// Solidity: function nextValidatorSet() view returns(uint128 id, uint128 length, bytes32 root) +func (_BeefyClientWrapper *BeefyClientWrapperCallerSession) NextValidatorSet() (struct { + Id *big.Int + Length *big.Int + Root [32]byte +}, error) { + return _BeefyClientWrapper.Contract.NextValidatorSet(&_BeefyClientWrapper.CallOpts) +} + // Owner is a free data retrieval call binding the contract method 0x8da5cb5b. // // Solidity: function owner() view returns(address) @@ -741,6 +996,37 @@ func (_BeefyClientWrapper *BeefyClientWrapperCallerSession) Owner() (common.Addr return _BeefyClientWrapper.Contract.Owner(&_BeefyClientWrapper.CallOpts) } +// RandaoCommitDelay is a free data retrieval call binding the contract method 0x591d99ee. +// +// Solidity: function randaoCommitDelay() view returns(uint256) +func (_BeefyClientWrapper *BeefyClientWrapperCaller) RandaoCommitDelay(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _BeefyClientWrapper.contract.Call(opts, &out, "randaoCommitDelay") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// RandaoCommitDelay is a free data retrieval call binding the contract method 0x591d99ee. +// +// Solidity: function randaoCommitDelay() view returns(uint256) +func (_BeefyClientWrapper *BeefyClientWrapperSession) RandaoCommitDelay() (*big.Int, error) { + return _BeefyClientWrapper.Contract.RandaoCommitDelay(&_BeefyClientWrapper.CallOpts) +} + +// RandaoCommitDelay is a free data retrieval call binding the contract method 0x591d99ee. +// +// Solidity: function randaoCommitDelay() view returns(uint256) +func (_BeefyClientWrapper *BeefyClientWrapperCallerSession) RandaoCommitDelay() (*big.Int, error) { + return _BeefyClientWrapper.Contract.RandaoCommitDelay(&_BeefyClientWrapper.CallOpts) +} + // Relayers is a free data retrieval call binding the contract method 0x9a48e7f9. // // Solidity: function relayers(uint256 ) view returns(address) @@ -803,6 +1089,37 @@ func (_BeefyClientWrapper *BeefyClientWrapperCallerSession) TicketOwner(arg0 [32 return _BeefyClientWrapper.Contract.TicketOwner(&_BeefyClientWrapper.CallOpts, arg0) } +// Tips is a free data retrieval call binding the contract method 0x1756fe14. +// +// Solidity: function tips(uint32 ) view returns(uint256) +func (_BeefyClientWrapper *BeefyClientWrapperCaller) Tips(opts *bind.CallOpts, arg0 uint32) (*big.Int, error) { + var out []interface{} + err := _BeefyClientWrapper.contract.Call(opts, &out, "tips", arg0) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// Tips is a free data retrieval call binding the contract method 0x1756fe14. +// +// Solidity: function tips(uint32 ) view returns(uint256) +func (_BeefyClientWrapper *BeefyClientWrapperSession) Tips(arg0 uint32) (*big.Int, error) { + return _BeefyClientWrapper.Contract.Tips(&_BeefyClientWrapper.CallOpts, arg0) +} + +// Tips is a free data retrieval call binding the contract method 0x1756fe14. +// +// Solidity: function tips(uint32 ) view returns(uint256) +func (_BeefyClientWrapper *BeefyClientWrapperCallerSession) Tips(arg0 uint32) (*big.Int, error) { + return _BeefyClientWrapper.Contract.Tips(&_BeefyClientWrapper.CallOpts, arg0) +} + // AddRelayer is a paid mutator transaction binding the contract method 0xdd39f00d. // // Solidity: function addRelayer(address relayer) returns() @@ -824,6 +1141,27 @@ func (_BeefyClientWrapper *BeefyClientWrapperTransactorSession) AddRelayer(relay return _BeefyClientWrapper.Contract.AddRelayer(&_BeefyClientWrapper.TransactOpts, relayer) } +// AddTip is a paid mutator transaction binding the contract method 0x9f404590. +// +// Solidity: function addTip(uint32 beefyBlockNumber) payable returns() +func (_BeefyClientWrapper *BeefyClientWrapperTransactor) AddTip(opts *bind.TransactOpts, beefyBlockNumber uint32) (*types.Transaction, error) { + return _BeefyClientWrapper.contract.Transact(opts, "addTip", beefyBlockNumber) +} + +// AddTip is a paid mutator transaction binding the contract method 0x9f404590. +// +// Solidity: function addTip(uint32 beefyBlockNumber) payable returns() +func (_BeefyClientWrapper *BeefyClientWrapperSession) AddTip(beefyBlockNumber uint32) (*types.Transaction, error) { + return _BeefyClientWrapper.Contract.AddTip(&_BeefyClientWrapper.TransactOpts, beefyBlockNumber) +} + +// AddTip is a paid mutator transaction binding the contract method 0x9f404590. +// +// Solidity: function addTip(uint32 beefyBlockNumber) payable returns() +func (_BeefyClientWrapper *BeefyClientWrapperTransactorSession) AddTip(beefyBlockNumber uint32) (*types.Transaction, error) { + return _BeefyClientWrapper.Contract.AddTip(&_BeefyClientWrapper.TransactOpts, beefyBlockNumber) +} + // ClearTicket is a paid mutator transaction binding the contract method 0x15738ab4. // // Solidity: function clearTicket() returns() @@ -950,6 +1288,27 @@ func (_BeefyClientWrapper *BeefyClientWrapperTransactorSession) SetMaxGasPrice(_ return _BeefyClientWrapper.Contract.SetMaxGasPrice(&_BeefyClientWrapper.TransactOpts, _maxGasPrice) } +// SetMaxRefundAmount is a paid mutator transaction binding the contract method 0x2efbeccd. +// +// Solidity: function setMaxRefundAmount(uint256 _maxRefundAmount) returns() +func (_BeefyClientWrapper *BeefyClientWrapperTransactor) SetMaxRefundAmount(opts *bind.TransactOpts, _maxRefundAmount *big.Int) (*types.Transaction, error) { + return _BeefyClientWrapper.contract.Transact(opts, "setMaxRefundAmount", _maxRefundAmount) +} + +// SetMaxRefundAmount is a paid mutator transaction binding the contract method 0x2efbeccd. +// +// Solidity: function setMaxRefundAmount(uint256 _maxRefundAmount) returns() +func (_BeefyClientWrapper *BeefyClientWrapperSession) SetMaxRefundAmount(_maxRefundAmount *big.Int) (*types.Transaction, error) { + return _BeefyClientWrapper.Contract.SetMaxRefundAmount(&_BeefyClientWrapper.TransactOpts, _maxRefundAmount) +} + +// SetMaxRefundAmount is a paid mutator transaction binding the contract method 0x2efbeccd. +// +// Solidity: function setMaxRefundAmount(uint256 _maxRefundAmount) returns() +func (_BeefyClientWrapper *BeefyClientWrapperTransactorSession) SetMaxRefundAmount(_maxRefundAmount *big.Int) (*types.Transaction, error) { + return _BeefyClientWrapper.Contract.SetMaxRefundAmount(&_BeefyClientWrapper.TransactOpts, _maxRefundAmount) +} + // SetMinBlockIncrement is a paid mutator transaction binding the contract method 0x3f358a76. // // Solidity: function setMinBlockIncrement(uint256 _minBlockIncrement) returns() @@ -971,25 +1330,25 @@ func (_BeefyClientWrapper *BeefyClientWrapperTransactorSession) SetMinBlockIncre return _BeefyClientWrapper.Contract.SetMinBlockIncrement(&_BeefyClientWrapper.TransactOpts, _minBlockIncrement) } -// SubmitFinal is a paid mutator transaction binding the contract method 0x623b223d. +// SubmitFinal is a paid mutator transaction binding the contract method 0xfafd0631. // -// Solidity: function submitFinal((uint32,uint64,(bytes2,bytes)[]) commitment, uint256[] bitfield, (uint8,bytes32,bytes32,uint256,address,bytes32[])[] proofs, (uint8,uint32,bytes32,uint64,uint32,bytes32,bytes32) leaf, bytes32[] leafProof, uint256 leafProofOrder) returns() -func (_BeefyClientWrapper *BeefyClientWrapperTransactor) SubmitFinal(opts *bind.TransactOpts, commitment IBeefyClientCommitment, bitfield []*big.Int, proofs []IBeefyClientValidatorProof, leaf IBeefyClientMMRLeaf, leafProof [][32]byte, leafProofOrder *big.Int) (*types.Transaction, error) { - return _BeefyClientWrapper.contract.Transact(opts, "submitFinal", commitment, bitfield, proofs, leaf, leafProof, leafProofOrder) +// Solidity: function submitFinal((uint32,uint64,(bytes2,bytes)[]) commitment, uint256[] bitfield, (uint8,bytes32,bytes32,uint256,address,bytes32[])[] proofs, (uint8,uint32,bytes32,uint64,uint32,bytes32,bytes32) leaf, bytes32[] leafProof, uint256 leafProofOrder, uint32[] claimTipBlocks) returns() +func (_BeefyClientWrapper *BeefyClientWrapperTransactor) SubmitFinal(opts *bind.TransactOpts, commitment IBeefyClientCommitment, bitfield []*big.Int, proofs []IBeefyClientValidatorProof, leaf IBeefyClientMMRLeaf, leafProof [][32]byte, leafProofOrder *big.Int, claimTipBlocks []uint32) (*types.Transaction, error) { + return _BeefyClientWrapper.contract.Transact(opts, "submitFinal", commitment, bitfield, proofs, leaf, leafProof, leafProofOrder, claimTipBlocks) } -// SubmitFinal is a paid mutator transaction binding the contract method 0x623b223d. +// SubmitFinal is a paid mutator transaction binding the contract method 0xfafd0631. // -// Solidity: function submitFinal((uint32,uint64,(bytes2,bytes)[]) commitment, uint256[] bitfield, (uint8,bytes32,bytes32,uint256,address,bytes32[])[] proofs, (uint8,uint32,bytes32,uint64,uint32,bytes32,bytes32) leaf, bytes32[] leafProof, uint256 leafProofOrder) returns() -func (_BeefyClientWrapper *BeefyClientWrapperSession) SubmitFinal(commitment IBeefyClientCommitment, bitfield []*big.Int, proofs []IBeefyClientValidatorProof, leaf IBeefyClientMMRLeaf, leafProof [][32]byte, leafProofOrder *big.Int) (*types.Transaction, error) { - return _BeefyClientWrapper.Contract.SubmitFinal(&_BeefyClientWrapper.TransactOpts, commitment, bitfield, proofs, leaf, leafProof, leafProofOrder) +// Solidity: function submitFinal((uint32,uint64,(bytes2,bytes)[]) commitment, uint256[] bitfield, (uint8,bytes32,bytes32,uint256,address,bytes32[])[] proofs, (uint8,uint32,bytes32,uint64,uint32,bytes32,bytes32) leaf, bytes32[] leafProof, uint256 leafProofOrder, uint32[] claimTipBlocks) returns() +func (_BeefyClientWrapper *BeefyClientWrapperSession) SubmitFinal(commitment IBeefyClientCommitment, bitfield []*big.Int, proofs []IBeefyClientValidatorProof, leaf IBeefyClientMMRLeaf, leafProof [][32]byte, leafProofOrder *big.Int, claimTipBlocks []uint32) (*types.Transaction, error) { + return _BeefyClientWrapper.Contract.SubmitFinal(&_BeefyClientWrapper.TransactOpts, commitment, bitfield, proofs, leaf, leafProof, leafProofOrder, claimTipBlocks) } -// SubmitFinal is a paid mutator transaction binding the contract method 0x623b223d. +// SubmitFinal is a paid mutator transaction binding the contract method 0xfafd0631. // -// Solidity: function submitFinal((uint32,uint64,(bytes2,bytes)[]) commitment, uint256[] bitfield, (uint8,bytes32,bytes32,uint256,address,bytes32[])[] proofs, (uint8,uint32,bytes32,uint64,uint32,bytes32,bytes32) leaf, bytes32[] leafProof, uint256 leafProofOrder) returns() -func (_BeefyClientWrapper *BeefyClientWrapperTransactorSession) SubmitFinal(commitment IBeefyClientCommitment, bitfield []*big.Int, proofs []IBeefyClientValidatorProof, leaf IBeefyClientMMRLeaf, leafProof [][32]byte, leafProofOrder *big.Int) (*types.Transaction, error) { - return _BeefyClientWrapper.Contract.SubmitFinal(&_BeefyClientWrapper.TransactOpts, commitment, bitfield, proofs, leaf, leafProof, leafProofOrder) +// Solidity: function submitFinal((uint32,uint64,(bytes2,bytes)[]) commitment, uint256[] bitfield, (uint8,bytes32,bytes32,uint256,address,bytes32[])[] proofs, (uint8,uint32,bytes32,uint64,uint32,bytes32,bytes32) leaf, bytes32[] leafProof, uint256 leafProofOrder, uint32[] claimTipBlocks) returns() +func (_BeefyClientWrapper *BeefyClientWrapperTransactorSession) SubmitFinal(commitment IBeefyClientCommitment, bitfield []*big.Int, proofs []IBeefyClientValidatorProof, leaf IBeefyClientMMRLeaf, leafProof [][32]byte, leafProofOrder *big.Int, claimTipBlocks []uint32) (*types.Transaction, error) { + return _BeefyClientWrapper.Contract.SubmitFinal(&_BeefyClientWrapper.TransactOpts, commitment, bitfield, proofs, leaf, leafProof, leafProofOrder, claimTipBlocks) } // SubmitInitial is a paid mutator transaction binding the contract method 0xbb51f1eb. @@ -1097,9 +1456,9 @@ func (_BeefyClientWrapper *BeefyClientWrapperTransactorSession) Receive() (*type return _BeefyClientWrapper.Contract.Receive(&_BeefyClientWrapper.TransactOpts) } -// BeefyClientWrapperConfigUpdatedIterator is returned from FilterConfigUpdated and is used to iterate over the raw logs and unpacked data for ConfigUpdated events raised by the BeefyClientWrapper contract. -type BeefyClientWrapperConfigUpdatedIterator struct { - Event *BeefyClientWrapperConfigUpdated // Event containing the contract specifics and raw log +// BeefyClientWrapperFundsDepositedIterator is returned from FilterFundsDeposited and is used to iterate over the raw logs and unpacked data for FundsDeposited events raised by the BeefyClientWrapper contract. +type BeefyClientWrapperFundsDepositedIterator struct { + Event *BeefyClientWrapperFundsDeposited // Event containing the contract specifics and raw log contract *bind.BoundContract // Generic contract to use for unpacking event data event string // Event name to use for unpacking event data @@ -1113,7 +1472,7 @@ type BeefyClientWrapperConfigUpdatedIterator struct { // Next advances the iterator to the subsequent event, returning whether there // are any more events found. In case of a retrieval or parsing error, false is // returned and Error() can be queried for the exact failure. -func (it *BeefyClientWrapperConfigUpdatedIterator) Next() bool { +func (it *BeefyClientWrapperFundsDepositedIterator) Next() bool { // If the iterator failed, stop iterating if it.fail != nil { return false @@ -1122,7 +1481,7 @@ func (it *BeefyClientWrapperConfigUpdatedIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(BeefyClientWrapperConfigUpdated) + it.Event = new(BeefyClientWrapperFundsDeposited) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -1137,7 +1496,7 @@ func (it *BeefyClientWrapperConfigUpdatedIterator) Next() bool { // Iterator still in progress, wait for either a data or an error event select { case log := <-it.logs: - it.Event = new(BeefyClientWrapperConfigUpdated) + it.Event = new(BeefyClientWrapperFundsDeposited) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -1153,42 +1512,52 @@ func (it *BeefyClientWrapperConfigUpdatedIterator) Next() bool { } // Error returns any retrieval or parsing error occurred during filtering. -func (it *BeefyClientWrapperConfigUpdatedIterator) Error() error { +func (it *BeefyClientWrapperFundsDepositedIterator) Error() error { return it.fail } // Close terminates the iteration process, releasing any pending underlying // resources. -func (it *BeefyClientWrapperConfigUpdatedIterator) Close() error { +func (it *BeefyClientWrapperFundsDepositedIterator) Close() error { it.sub.Unsubscribe() return nil } -// BeefyClientWrapperConfigUpdated represents a ConfigUpdated event raised by the BeefyClientWrapper contract. -type BeefyClientWrapperConfigUpdated struct { - Parameter string - Value *big.Int +// BeefyClientWrapperFundsDeposited represents a FundsDeposited event raised by the BeefyClientWrapper contract. +type BeefyClientWrapperFundsDeposited struct { + Depositor common.Address + Amount *big.Int Raw types.Log // Blockchain specific contextual infos } -// FilterConfigUpdated is a free log retrieval operation binding the contract event 0x12c9dccd129ff783f1c8228eacdfa8e334ddecb7ec5c9a79ec662a4aed3d012a. +// FilterFundsDeposited is a free log retrieval operation binding the contract event 0x543ba50a5eec5e6178218e364b1d0f396157b3c8fa278522c2cb7fd99407d474. // -// Solidity: event ConfigUpdated(string parameter, uint256 value) -func (_BeefyClientWrapper *BeefyClientWrapperFilterer) FilterConfigUpdated(opts *bind.FilterOpts) (*BeefyClientWrapperConfigUpdatedIterator, error) { +// Solidity: event FundsDeposited(address indexed depositor, uint256 amount) +func (_BeefyClientWrapper *BeefyClientWrapperFilterer) FilterFundsDeposited(opts *bind.FilterOpts, depositor []common.Address) (*BeefyClientWrapperFundsDepositedIterator, error) { + + var depositorRule []interface{} + for _, depositorItem := range depositor { + depositorRule = append(depositorRule, depositorItem) + } - logs, sub, err := _BeefyClientWrapper.contract.FilterLogs(opts, "ConfigUpdated") + logs, sub, err := _BeefyClientWrapper.contract.FilterLogs(opts, "FundsDeposited", depositorRule) if err != nil { return nil, err } - return &BeefyClientWrapperConfigUpdatedIterator{contract: _BeefyClientWrapper.contract, event: "ConfigUpdated", logs: logs, sub: sub}, nil + return &BeefyClientWrapperFundsDepositedIterator{contract: _BeefyClientWrapper.contract, event: "FundsDeposited", logs: logs, sub: sub}, nil } -// WatchConfigUpdated is a free log subscription operation binding the contract event 0x12c9dccd129ff783f1c8228eacdfa8e334ddecb7ec5c9a79ec662a4aed3d012a. +// WatchFundsDeposited is a free log subscription operation binding the contract event 0x543ba50a5eec5e6178218e364b1d0f396157b3c8fa278522c2cb7fd99407d474. // -// Solidity: event ConfigUpdated(string parameter, uint256 value) -func (_BeefyClientWrapper *BeefyClientWrapperFilterer) WatchConfigUpdated(opts *bind.WatchOpts, sink chan<- *BeefyClientWrapperConfigUpdated) (event.Subscription, error) { +// Solidity: event FundsDeposited(address indexed depositor, uint256 amount) +func (_BeefyClientWrapper *BeefyClientWrapperFilterer) WatchFundsDeposited(opts *bind.WatchOpts, sink chan<- *BeefyClientWrapperFundsDeposited, depositor []common.Address) (event.Subscription, error) { - logs, sub, err := _BeefyClientWrapper.contract.WatchLogs(opts, "ConfigUpdated") + var depositorRule []interface{} + for _, depositorItem := range depositor { + depositorRule = append(depositorRule, depositorItem) + } + + logs, sub, err := _BeefyClientWrapper.contract.WatchLogs(opts, "FundsDeposited", depositorRule) if err != nil { return nil, err } @@ -1198,8 +1567,8 @@ func (_BeefyClientWrapper *BeefyClientWrapperFilterer) WatchConfigUpdated(opts * select { case log := <-logs: // New log arrived, parse the event and forward to the user - event := new(BeefyClientWrapperConfigUpdated) - if err := _BeefyClientWrapper.contract.UnpackLog(event, "ConfigUpdated", log); err != nil { + event := new(BeefyClientWrapperFundsDeposited) + if err := _BeefyClientWrapper.contract.UnpackLog(event, "FundsDeposited", log); err != nil { return err } event.Raw = log @@ -1220,21 +1589,21 @@ func (_BeefyClientWrapper *BeefyClientWrapperFilterer) WatchConfigUpdated(opts * }), nil } -// ParseConfigUpdated is a log parse operation binding the contract event 0x12c9dccd129ff783f1c8228eacdfa8e334ddecb7ec5c9a79ec662a4aed3d012a. +// ParseFundsDeposited is a log parse operation binding the contract event 0x543ba50a5eec5e6178218e364b1d0f396157b3c8fa278522c2cb7fd99407d474. // -// Solidity: event ConfigUpdated(string parameter, uint256 value) -func (_BeefyClientWrapper *BeefyClientWrapperFilterer) ParseConfigUpdated(log types.Log) (*BeefyClientWrapperConfigUpdated, error) { - event := new(BeefyClientWrapperConfigUpdated) - if err := _BeefyClientWrapper.contract.UnpackLog(event, "ConfigUpdated", log); err != nil { +// Solidity: event FundsDeposited(address indexed depositor, uint256 amount) +func (_BeefyClientWrapper *BeefyClientWrapperFilterer) ParseFundsDeposited(log types.Log) (*BeefyClientWrapperFundsDeposited, error) { + event := new(BeefyClientWrapperFundsDeposited) + if err := _BeefyClientWrapper.contract.UnpackLog(event, "FundsDeposited", log); err != nil { return nil, err } event.Raw = log return event, nil } -// BeefyClientWrapperFundsDepositedIterator is returned from FilterFundsDeposited and is used to iterate over the raw logs and unpacked data for FundsDeposited events raised by the BeefyClientWrapper contract. -type BeefyClientWrapperFundsDepositedIterator struct { - Event *BeefyClientWrapperFundsDeposited // Event containing the contract specifics and raw log +// BeefyClientWrapperFundsWithdrawnIterator is returned from FilterFundsWithdrawn and is used to iterate over the raw logs and unpacked data for FundsWithdrawn events raised by the BeefyClientWrapper contract. +type BeefyClientWrapperFundsWithdrawnIterator struct { + Event *BeefyClientWrapperFundsWithdrawn // Event containing the contract specifics and raw log contract *bind.BoundContract // Generic contract to use for unpacking event data event string // Event name to use for unpacking event data @@ -1248,7 +1617,7 @@ type BeefyClientWrapperFundsDepositedIterator struct { // Next advances the iterator to the subsequent event, returning whether there // are any more events found. In case of a retrieval or parsing error, false is // returned and Error() can be queried for the exact failure. -func (it *BeefyClientWrapperFundsDepositedIterator) Next() bool { +func (it *BeefyClientWrapperFundsWithdrawnIterator) Next() bool { // If the iterator failed, stop iterating if it.fail != nil { return false @@ -1257,7 +1626,7 @@ func (it *BeefyClientWrapperFundsDepositedIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(BeefyClientWrapperFundsDeposited) + it.Event = new(BeefyClientWrapperFundsWithdrawn) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -1272,7 +1641,7 @@ func (it *BeefyClientWrapperFundsDepositedIterator) Next() bool { // Iterator still in progress, wait for either a data or an error event select { case log := <-it.logs: - it.Event = new(BeefyClientWrapperFundsDeposited) + it.Event = new(BeefyClientWrapperFundsWithdrawn) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -1288,52 +1657,52 @@ func (it *BeefyClientWrapperFundsDepositedIterator) Next() bool { } // Error returns any retrieval or parsing error occurred during filtering. -func (it *BeefyClientWrapperFundsDepositedIterator) Error() error { +func (it *BeefyClientWrapperFundsWithdrawnIterator) Error() error { return it.fail } // Close terminates the iteration process, releasing any pending underlying // resources. -func (it *BeefyClientWrapperFundsDepositedIterator) Close() error { +func (it *BeefyClientWrapperFundsWithdrawnIterator) Close() error { it.sub.Unsubscribe() return nil } -// BeefyClientWrapperFundsDeposited represents a FundsDeposited event raised by the BeefyClientWrapper contract. -type BeefyClientWrapperFundsDeposited struct { - Depositor common.Address +// BeefyClientWrapperFundsWithdrawn represents a FundsWithdrawn event raised by the BeefyClientWrapper contract. +type BeefyClientWrapperFundsWithdrawn struct { + Recipient common.Address Amount *big.Int Raw types.Log // Blockchain specific contextual infos } -// FilterFundsDeposited is a free log retrieval operation binding the contract event 0x543ba50a5eec5e6178218e364b1d0f396157b3c8fa278522c2cb7fd99407d474. +// FilterFundsWithdrawn is a free log retrieval operation binding the contract event 0xeaff4b37086828766ad3268786972c0cd24259d4c87a80f9d3963a3c3d999b0d. // -// Solidity: event FundsDeposited(address indexed depositor, uint256 amount) -func (_BeefyClientWrapper *BeefyClientWrapperFilterer) FilterFundsDeposited(opts *bind.FilterOpts, depositor []common.Address) (*BeefyClientWrapperFundsDepositedIterator, error) { +// Solidity: event FundsWithdrawn(address indexed recipient, uint256 amount) +func (_BeefyClientWrapper *BeefyClientWrapperFilterer) FilterFundsWithdrawn(opts *bind.FilterOpts, recipient []common.Address) (*BeefyClientWrapperFundsWithdrawnIterator, error) { - var depositorRule []interface{} - for _, depositorItem := range depositor { - depositorRule = append(depositorRule, depositorItem) + var recipientRule []interface{} + for _, recipientItem := range recipient { + recipientRule = append(recipientRule, recipientItem) } - logs, sub, err := _BeefyClientWrapper.contract.FilterLogs(opts, "FundsDeposited", depositorRule) + logs, sub, err := _BeefyClientWrapper.contract.FilterLogs(opts, "FundsWithdrawn", recipientRule) if err != nil { return nil, err } - return &BeefyClientWrapperFundsDepositedIterator{contract: _BeefyClientWrapper.contract, event: "FundsDeposited", logs: logs, sub: sub}, nil + return &BeefyClientWrapperFundsWithdrawnIterator{contract: _BeefyClientWrapper.contract, event: "FundsWithdrawn", logs: logs, sub: sub}, nil } -// WatchFundsDeposited is a free log subscription operation binding the contract event 0x543ba50a5eec5e6178218e364b1d0f396157b3c8fa278522c2cb7fd99407d474. +// WatchFundsWithdrawn is a free log subscription operation binding the contract event 0xeaff4b37086828766ad3268786972c0cd24259d4c87a80f9d3963a3c3d999b0d. // -// Solidity: event FundsDeposited(address indexed depositor, uint256 amount) -func (_BeefyClientWrapper *BeefyClientWrapperFilterer) WatchFundsDeposited(opts *bind.WatchOpts, sink chan<- *BeefyClientWrapperFundsDeposited, depositor []common.Address) (event.Subscription, error) { +// Solidity: event FundsWithdrawn(address indexed recipient, uint256 amount) +func (_BeefyClientWrapper *BeefyClientWrapperFilterer) WatchFundsWithdrawn(opts *bind.WatchOpts, sink chan<- *BeefyClientWrapperFundsWithdrawn, recipient []common.Address) (event.Subscription, error) { - var depositorRule []interface{} - for _, depositorItem := range depositor { - depositorRule = append(depositorRule, depositorItem) + var recipientRule []interface{} + for _, recipientItem := range recipient { + recipientRule = append(recipientRule, recipientItem) } - logs, sub, err := _BeefyClientWrapper.contract.WatchLogs(opts, "FundsDeposited", depositorRule) + logs, sub, err := _BeefyClientWrapper.contract.WatchLogs(opts, "FundsWithdrawn", recipientRule) if err != nil { return nil, err } @@ -1343,8 +1712,8 @@ func (_BeefyClientWrapper *BeefyClientWrapperFilterer) WatchFundsDeposited(opts select { case log := <-logs: // New log arrived, parse the event and forward to the user - event := new(BeefyClientWrapperFundsDeposited) - if err := _BeefyClientWrapper.contract.UnpackLog(event, "FundsDeposited", log); err != nil { + event := new(BeefyClientWrapperFundsWithdrawn) + if err := _BeefyClientWrapper.contract.UnpackLog(event, "FundsWithdrawn", log); err != nil { return err } event.Raw = log @@ -1365,21 +1734,21 @@ func (_BeefyClientWrapper *BeefyClientWrapperFilterer) WatchFundsDeposited(opts }), nil } -// ParseFundsDeposited is a log parse operation binding the contract event 0x543ba50a5eec5e6178218e364b1d0f396157b3c8fa278522c2cb7fd99407d474. +// ParseFundsWithdrawn is a log parse operation binding the contract event 0xeaff4b37086828766ad3268786972c0cd24259d4c87a80f9d3963a3c3d999b0d. // -// Solidity: event FundsDeposited(address indexed depositor, uint256 amount) -func (_BeefyClientWrapper *BeefyClientWrapperFilterer) ParseFundsDeposited(log types.Log) (*BeefyClientWrapperFundsDeposited, error) { - event := new(BeefyClientWrapperFundsDeposited) - if err := _BeefyClientWrapper.contract.UnpackLog(event, "FundsDeposited", log); err != nil { +// Solidity: event FundsWithdrawn(address indexed recipient, uint256 amount) +func (_BeefyClientWrapper *BeefyClientWrapperFilterer) ParseFundsWithdrawn(log types.Log) (*BeefyClientWrapperFundsWithdrawn, error) { + event := new(BeefyClientWrapperFundsWithdrawn) + if err := _BeefyClientWrapper.contract.UnpackLog(event, "FundsWithdrawn", log); err != nil { return nil, err } event.Raw = log return event, nil } -// BeefyClientWrapperFundsWithdrawnIterator is returned from FilterFundsWithdrawn and is used to iterate over the raw logs and unpacked data for FundsWithdrawn events raised by the BeefyClientWrapper contract. -type BeefyClientWrapperFundsWithdrawnIterator struct { - Event *BeefyClientWrapperFundsWithdrawn // Event containing the contract specifics and raw log +// BeefyClientWrapperGasCreditedIterator is returned from FilterGasCredited and is used to iterate over the raw logs and unpacked data for GasCredited events raised by the BeefyClientWrapper contract. +type BeefyClientWrapperGasCreditedIterator struct { + Event *BeefyClientWrapperGasCredited // Event containing the contract specifics and raw log contract *bind.BoundContract // Generic contract to use for unpacking event data event string // Event name to use for unpacking event data @@ -1393,7 +1762,7 @@ type BeefyClientWrapperFundsWithdrawnIterator struct { // Next advances the iterator to the subsequent event, returning whether there // are any more events found. In case of a retrieval or parsing error, false is // returned and Error() can be queried for the exact failure. -func (it *BeefyClientWrapperFundsWithdrawnIterator) Next() bool { +func (it *BeefyClientWrapperGasCreditedIterator) Next() bool { // If the iterator failed, stop iterating if it.fail != nil { return false @@ -1402,7 +1771,7 @@ func (it *BeefyClientWrapperFundsWithdrawnIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(BeefyClientWrapperFundsWithdrawn) + it.Event = new(BeefyClientWrapperGasCredited) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -1417,7 +1786,7 @@ func (it *BeefyClientWrapperFundsWithdrawnIterator) Next() bool { // Iterator still in progress, wait for either a data or an error event select { case log := <-it.logs: - it.Event = new(BeefyClientWrapperFundsWithdrawn) + it.Event = new(BeefyClientWrapperGasCredited) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -1433,52 +1802,61 @@ func (it *BeefyClientWrapperFundsWithdrawnIterator) Next() bool { } // Error returns any retrieval or parsing error occurred during filtering. -func (it *BeefyClientWrapperFundsWithdrawnIterator) Error() error { +func (it *BeefyClientWrapperGasCreditedIterator) Error() error { return it.fail } // Close terminates the iteration process, releasing any pending underlying // resources. -func (it *BeefyClientWrapperFundsWithdrawnIterator) Close() error { +func (it *BeefyClientWrapperGasCreditedIterator) Close() error { it.sub.Unsubscribe() return nil } -// BeefyClientWrapperFundsWithdrawn represents a FundsWithdrawn event raised by the BeefyClientWrapper contract. -type BeefyClientWrapperFundsWithdrawn struct { - Recipient common.Address - Amount *big.Int - Raw types.Log // Blockchain specific contextual infos +// BeefyClientWrapperGasCredited represents a GasCredited event raised by the BeefyClientWrapper contract. +type BeefyClientWrapperGasCredited struct { + Relayer common.Address + CommitmentHash [32]byte + GasUsed *big.Int + Raw types.Log // Blockchain specific contextual infos } -// FilterFundsWithdrawn is a free log retrieval operation binding the contract event 0xeaff4b37086828766ad3268786972c0cd24259d4c87a80f9d3963a3c3d999b0d. +// FilterGasCredited is a free log retrieval operation binding the contract event 0xa96627e523aafcce96e4a95478ed8181042d6fcd32fd0892e1743408da8948e2. // -// Solidity: event FundsWithdrawn(address indexed recipient, uint256 amount) -func (_BeefyClientWrapper *BeefyClientWrapperFilterer) FilterFundsWithdrawn(opts *bind.FilterOpts, recipient []common.Address) (*BeefyClientWrapperFundsWithdrawnIterator, error) { +// Solidity: event GasCredited(address indexed relayer, bytes32 indexed commitmentHash, uint256 gasUsed) +func (_BeefyClientWrapper *BeefyClientWrapperFilterer) FilterGasCredited(opts *bind.FilterOpts, relayer []common.Address, commitmentHash [][32]byte) (*BeefyClientWrapperGasCreditedIterator, error) { - var recipientRule []interface{} - for _, recipientItem := range recipient { - recipientRule = append(recipientRule, recipientItem) + var relayerRule []interface{} + for _, relayerItem := range relayer { + relayerRule = append(relayerRule, relayerItem) + } + var commitmentHashRule []interface{} + for _, commitmentHashItem := range commitmentHash { + commitmentHashRule = append(commitmentHashRule, commitmentHashItem) } - logs, sub, err := _BeefyClientWrapper.contract.FilterLogs(opts, "FundsWithdrawn", recipientRule) + logs, sub, err := _BeefyClientWrapper.contract.FilterLogs(opts, "GasCredited", relayerRule, commitmentHashRule) if err != nil { return nil, err } - return &BeefyClientWrapperFundsWithdrawnIterator{contract: _BeefyClientWrapper.contract, event: "FundsWithdrawn", logs: logs, sub: sub}, nil + return &BeefyClientWrapperGasCreditedIterator{contract: _BeefyClientWrapper.contract, event: "GasCredited", logs: logs, sub: sub}, nil } -// WatchFundsWithdrawn is a free log subscription operation binding the contract event 0xeaff4b37086828766ad3268786972c0cd24259d4c87a80f9d3963a3c3d999b0d. +// WatchGasCredited is a free log subscription operation binding the contract event 0xa96627e523aafcce96e4a95478ed8181042d6fcd32fd0892e1743408da8948e2. // -// Solidity: event FundsWithdrawn(address indexed recipient, uint256 amount) -func (_BeefyClientWrapper *BeefyClientWrapperFilterer) WatchFundsWithdrawn(opts *bind.WatchOpts, sink chan<- *BeefyClientWrapperFundsWithdrawn, recipient []common.Address) (event.Subscription, error) { +// Solidity: event GasCredited(address indexed relayer, bytes32 indexed commitmentHash, uint256 gasUsed) +func (_BeefyClientWrapper *BeefyClientWrapperFilterer) WatchGasCredited(opts *bind.WatchOpts, sink chan<- *BeefyClientWrapperGasCredited, relayer []common.Address, commitmentHash [][32]byte) (event.Subscription, error) { - var recipientRule []interface{} - for _, recipientItem := range recipient { - recipientRule = append(recipientRule, recipientItem) + var relayerRule []interface{} + for _, relayerItem := range relayer { + relayerRule = append(relayerRule, relayerItem) + } + var commitmentHashRule []interface{} + for _, commitmentHashItem := range commitmentHash { + commitmentHashRule = append(commitmentHashRule, commitmentHashItem) } - logs, sub, err := _BeefyClientWrapper.contract.WatchLogs(opts, "FundsWithdrawn", recipientRule) + logs, sub, err := _BeefyClientWrapper.contract.WatchLogs(opts, "GasCredited", relayerRule, commitmentHashRule) if err != nil { return nil, err } @@ -1488,8 +1866,8 @@ func (_BeefyClientWrapper *BeefyClientWrapperFilterer) WatchFundsWithdrawn(opts select { case log := <-logs: // New log arrived, parse the event and forward to the user - event := new(BeefyClientWrapperFundsWithdrawn) - if err := _BeefyClientWrapper.contract.UnpackLog(event, "FundsWithdrawn", log); err != nil { + event := new(BeefyClientWrapperGasCredited) + if err := _BeefyClientWrapper.contract.UnpackLog(event, "GasCredited", log); err != nil { return err } event.Raw = log @@ -1510,12 +1888,12 @@ func (_BeefyClientWrapper *BeefyClientWrapperFilterer) WatchFundsWithdrawn(opts }), nil } -// ParseFundsWithdrawn is a log parse operation binding the contract event 0xeaff4b37086828766ad3268786972c0cd24259d4c87a80f9d3963a3c3d999b0d. +// ParseGasCredited is a log parse operation binding the contract event 0xa96627e523aafcce96e4a95478ed8181042d6fcd32fd0892e1743408da8948e2. // -// Solidity: event FundsWithdrawn(address indexed recipient, uint256 amount) -func (_BeefyClientWrapper *BeefyClientWrapperFilterer) ParseFundsWithdrawn(log types.Log) (*BeefyClientWrapperFundsWithdrawn, error) { - event := new(BeefyClientWrapperFundsWithdrawn) - if err := _BeefyClientWrapper.contract.UnpackLog(event, "FundsWithdrawn", log); err != nil { +// Solidity: event GasCredited(address indexed relayer, bytes32 indexed commitmentHash, uint256 gasUsed) +func (_BeefyClientWrapper *BeefyClientWrapperFilterer) ParseGasCredited(log types.Log) (*BeefyClientWrapperGasCredited, error) { + event := new(BeefyClientWrapperGasCredited) + if err := _BeefyClientWrapper.contract.UnpackLog(event, "GasCredited", log); err != nil { return nil, err } event.Raw = log @@ -1879,15 +2257,15 @@ func (it *BeefyClientWrapperSubmissionRefundedIterator) Close() error { // BeefyClientWrapperSubmissionRefunded represents a SubmissionRefunded event raised by the BeefyClientWrapper contract. type BeefyClientWrapperSubmissionRefunded struct { - Relayer common.Address - Amount *big.Int - GasUsed *big.Int - Raw types.Log // Blockchain specific contextual infos + Relayer common.Address + Amount *big.Int + TotalGasUsed *big.Int + Raw types.Log // Blockchain specific contextual infos } // FilterSubmissionRefunded is a free log retrieval operation binding the contract event 0x103cb711554967fbeea0c6394a6dfedc44d0e729191e719d0976438783912f52. // -// Solidity: event SubmissionRefunded(address indexed relayer, uint256 amount, uint256 gasUsed) +// Solidity: event SubmissionRefunded(address indexed relayer, uint256 amount, uint256 totalGasUsed) func (_BeefyClientWrapper *BeefyClientWrapperFilterer) FilterSubmissionRefunded(opts *bind.FilterOpts, relayer []common.Address) (*BeefyClientWrapperSubmissionRefundedIterator, error) { var relayerRule []interface{} @@ -1904,7 +2282,7 @@ func (_BeefyClientWrapper *BeefyClientWrapperFilterer) FilterSubmissionRefunded( // WatchSubmissionRefunded is a free log subscription operation binding the contract event 0x103cb711554967fbeea0c6394a6dfedc44d0e729191e719d0976438783912f52. // -// Solidity: event SubmissionRefunded(address indexed relayer, uint256 amount, uint256 gasUsed) +// Solidity: event SubmissionRefunded(address indexed relayer, uint256 amount, uint256 totalGasUsed) func (_BeefyClientWrapper *BeefyClientWrapperFilterer) WatchSubmissionRefunded(opts *bind.WatchOpts, sink chan<- *BeefyClientWrapperSubmissionRefunded, relayer []common.Address) (event.Subscription, error) { var relayerRule []interface{} @@ -1946,7 +2324,7 @@ func (_BeefyClientWrapper *BeefyClientWrapperFilterer) WatchSubmissionRefunded(o // ParseSubmissionRefunded is a log parse operation binding the contract event 0x103cb711554967fbeea0c6394a6dfedc44d0e729191e719d0976438783912f52. // -// Solidity: event SubmissionRefunded(address indexed relayer, uint256 amount, uint256 gasUsed) +// Solidity: event SubmissionRefunded(address indexed relayer, uint256 amount, uint256 totalGasUsed) func (_BeefyClientWrapper *BeefyClientWrapperFilterer) ParseSubmissionRefunded(log types.Log) (*BeefyClientWrapperSubmissionRefunded, error) { event := new(BeefyClientWrapperSubmissionRefunded) if err := _BeefyClientWrapper.contract.UnpackLog(event, "SubmissionRefunded", log); err != nil { @@ -1956,6 +2334,305 @@ func (_BeefyClientWrapper *BeefyClientWrapperFilterer) ParseSubmissionRefunded(l return event, nil } +// BeefyClientWrapperTipAddedIterator is returned from FilterTipAdded and is used to iterate over the raw logs and unpacked data for TipAdded events raised by the BeefyClientWrapper contract. +type BeefyClientWrapperTipAddedIterator struct { + Event *BeefyClientWrapperTipAdded // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *BeefyClientWrapperTipAddedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(BeefyClientWrapperTipAdded) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(BeefyClientWrapperTipAdded) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *BeefyClientWrapperTipAddedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *BeefyClientWrapperTipAddedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// BeefyClientWrapperTipAdded represents a TipAdded event raised by the BeefyClientWrapper contract. +type BeefyClientWrapperTipAdded struct { + Tipper common.Address + BeefyBlockNumber uint32 + Amount *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterTipAdded is a free log retrieval operation binding the contract event 0x534f476b78e1964cad3783848d29e18156e2e9a2a3cfe8f93735b141d8c1285a. +// +// Solidity: event TipAdded(address indexed tipper, uint32 indexed beefyBlockNumber, uint256 amount) +func (_BeefyClientWrapper *BeefyClientWrapperFilterer) FilterTipAdded(opts *bind.FilterOpts, tipper []common.Address, beefyBlockNumber []uint32) (*BeefyClientWrapperTipAddedIterator, error) { + + var tipperRule []interface{} + for _, tipperItem := range tipper { + tipperRule = append(tipperRule, tipperItem) + } + var beefyBlockNumberRule []interface{} + for _, beefyBlockNumberItem := range beefyBlockNumber { + beefyBlockNumberRule = append(beefyBlockNumberRule, beefyBlockNumberItem) + } + + logs, sub, err := _BeefyClientWrapper.contract.FilterLogs(opts, "TipAdded", tipperRule, beefyBlockNumberRule) + if err != nil { + return nil, err + } + return &BeefyClientWrapperTipAddedIterator{contract: _BeefyClientWrapper.contract, event: "TipAdded", logs: logs, sub: sub}, nil +} + +// WatchTipAdded is a free log subscription operation binding the contract event 0x534f476b78e1964cad3783848d29e18156e2e9a2a3cfe8f93735b141d8c1285a. +// +// Solidity: event TipAdded(address indexed tipper, uint32 indexed beefyBlockNumber, uint256 amount) +func (_BeefyClientWrapper *BeefyClientWrapperFilterer) WatchTipAdded(opts *bind.WatchOpts, sink chan<- *BeefyClientWrapperTipAdded, tipper []common.Address, beefyBlockNumber []uint32) (event.Subscription, error) { + + var tipperRule []interface{} + for _, tipperItem := range tipper { + tipperRule = append(tipperRule, tipperItem) + } + var beefyBlockNumberRule []interface{} + for _, beefyBlockNumberItem := range beefyBlockNumber { + beefyBlockNumberRule = append(beefyBlockNumberRule, beefyBlockNumberItem) + } + + logs, sub, err := _BeefyClientWrapper.contract.WatchLogs(opts, "TipAdded", tipperRule, beefyBlockNumberRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(BeefyClientWrapperTipAdded) + if err := _BeefyClientWrapper.contract.UnpackLog(event, "TipAdded", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseTipAdded is a log parse operation binding the contract event 0x534f476b78e1964cad3783848d29e18156e2e9a2a3cfe8f93735b141d8c1285a. +// +// Solidity: event TipAdded(address indexed tipper, uint32 indexed beefyBlockNumber, uint256 amount) +func (_BeefyClientWrapper *BeefyClientWrapperFilterer) ParseTipAdded(log types.Log) (*BeefyClientWrapperTipAdded, error) { + event := new(BeefyClientWrapperTipAdded) + if err := _BeefyClientWrapper.contract.UnpackLog(event, "TipAdded", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// BeefyClientWrapperTipsClaimedIterator is returned from FilterTipsClaimed and is used to iterate over the raw logs and unpacked data for TipsClaimed events raised by the BeefyClientWrapper contract. +type BeefyClientWrapperTipsClaimedIterator struct { + Event *BeefyClientWrapperTipsClaimed // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *BeefyClientWrapperTipsClaimedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(BeefyClientWrapperTipsClaimed) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(BeefyClientWrapperTipsClaimed) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *BeefyClientWrapperTipsClaimedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *BeefyClientWrapperTipsClaimedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// BeefyClientWrapperTipsClaimed represents a TipsClaimed event raised by the BeefyClientWrapper contract. +type BeefyClientWrapperTipsClaimed struct { + Relayer common.Address + TotalAmount *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterTipsClaimed is a free log retrieval operation binding the contract event 0xf5e7a62133aaed5c8783583a823343c7c0c0f51f0e2e8c76ec50feffc002b1f3. +// +// Solidity: event TipsClaimed(address indexed relayer, uint256 totalAmount) +func (_BeefyClientWrapper *BeefyClientWrapperFilterer) FilterTipsClaimed(opts *bind.FilterOpts, relayer []common.Address) (*BeefyClientWrapperTipsClaimedIterator, error) { + + var relayerRule []interface{} + for _, relayerItem := range relayer { + relayerRule = append(relayerRule, relayerItem) + } + + logs, sub, err := _BeefyClientWrapper.contract.FilterLogs(opts, "TipsClaimed", relayerRule) + if err != nil { + return nil, err + } + return &BeefyClientWrapperTipsClaimedIterator{contract: _BeefyClientWrapper.contract, event: "TipsClaimed", logs: logs, sub: sub}, nil +} + +// WatchTipsClaimed is a free log subscription operation binding the contract event 0xf5e7a62133aaed5c8783583a823343c7c0c0f51f0e2e8c76ec50feffc002b1f3. +// +// Solidity: event TipsClaimed(address indexed relayer, uint256 totalAmount) +func (_BeefyClientWrapper *BeefyClientWrapperFilterer) WatchTipsClaimed(opts *bind.WatchOpts, sink chan<- *BeefyClientWrapperTipsClaimed, relayer []common.Address) (event.Subscription, error) { + + var relayerRule []interface{} + for _, relayerItem := range relayer { + relayerRule = append(relayerRule, relayerItem) + } + + logs, sub, err := _BeefyClientWrapper.contract.WatchLogs(opts, "TipsClaimed", relayerRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(BeefyClientWrapperTipsClaimed) + if err := _BeefyClientWrapper.contract.UnpackLog(event, "TipsClaimed", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseTipsClaimed is a log parse operation binding the contract event 0xf5e7a62133aaed5c8783583a823343c7c0c0f51f0e2e8c76ec50feffc002b1f3. +// +// Solidity: event TipsClaimed(address indexed relayer, uint256 totalAmount) +func (_BeefyClientWrapper *BeefyClientWrapperFilterer) ParseTipsClaimed(log types.Log) (*BeefyClientWrapperTipsClaimed, error) { + event := new(BeefyClientWrapperTipsClaimed) + if err := _BeefyClientWrapper.contract.UnpackLog(event, "TipsClaimed", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + // BeefyClientWrapperTurnAdvancedIterator is returned from FilterTurnAdvanced and is used to iterate over the raw logs and unpacked data for TurnAdvanced events raised by the BeefyClientWrapper contract. type BeefyClientWrapperTurnAdvancedIterator struct { Event *BeefyClientWrapperTurnAdvanced // Event containing the contract specifics and raw log diff --git a/relayer/relays/beefy/ethereum-writer.go b/relayer/relays/beefy/ethereum-writer.go index 2431d58a1..95f5241ec 100644 --- a/relayer/relays/beefy/ethereum-writer.go +++ b/relayer/relays/beefy/ethereum-writer.go @@ -26,8 +26,7 @@ import ( type EthereumWriter struct { config *SinkConfig conn *ethereum.Connection - contract *contracts.BeefyClient - wrapper *contracts.BeefyClientWrapper + contract *contracts.BeefyClientWrapper blockWaitPeriod uint64 } @@ -296,6 +295,7 @@ func (wr *EthereumWriter) doSubmitFinal(ctx context.Context, commitmentHash [32] params.Leaf, params.LeafProof, params.LeafProofOrder, + []uint32{}, // claimTipBlocks - empty for now, can be populated to claim tips ) if err != nil { return nil, fmt.Errorf("final submission: %w", err) @@ -330,19 +330,13 @@ func (wr *EthereumWriter) waitForTurnEligibility(ctx context.Context) error { } func (wr *EthereumWriter) checkTurnEligibility(ctx context.Context) (bool, error) { - // If no wrapper configured, always eligible (backwards compatible) - if wr.wrapper == nil { - return true, nil - } - callOpts := bind.CallOpts{ Context: ctx, } myAddress := wr.conn.Keypair().CommonAddress() - // Check if it's our turn - currentTurnRelayer, err := wr.wrapper.GetCurrentTurnRelayer(&callOpts) + currentTurnRelayer, err := wr.contract.GetCurrentTurnRelayer(&callOpts) if err != nil { return false, fmt.Errorf("get current turn relayer: %w", err) } @@ -355,8 +349,7 @@ func (wr *EthereumWriter) checkTurnEligibility(ctx context.Context) (bool, error return true, nil } - // Not our turn, check if grace period is active - gracePeriodActive, err := wr.wrapper.IsGracePeriodActive(&callOpts) + gracePeriodActive, err := wr.contract.IsGracePeriodActive(&callOpts) if err != nil { return false, fmt.Errorf("check grace period: %w", err) } @@ -374,36 +367,26 @@ func (wr *EthereumWriter) checkTurnEligibility(ctx context.Context) (bool, error "currentTurnRelayer": currentTurnRelayer.Hex(), "myAddress": myAddress.Hex(), "gracePeriodActive": false, - }).Info("Not our turn and grace period not active - skipping submission") + }).Info("Not our turn and grace period not active - waiting") return false, nil } func (wr *EthereumWriter) initialize(ctx context.Context) error { address := common.HexToAddress(wr.config.Contracts.BeefyClient) - contract, err := contracts.NewBeefyClient(address, wr.conn.Client()) - if err != nil { - return fmt.Errorf("create beefy client: %w", err) - } - wr.contract = contract - // Also create wrapper bindings for turn-checking functions - // This works whether BeefyClient points to the wrapper or the original contract - wrapper, err := contracts.NewBeefyClientWrapper(address, wr.conn.Client()) + contract, err := contracts.NewBeefyClientWrapper(address, wr.conn.Client()) if err != nil { - // If wrapper bindings fail, it means we're using the original BeefyClient - // which doesn't have turn-checking - that's fine, we'll skip eligibility checks - log.Debug("BeefyClientWrapper bindings not available - turn checking disabled") - } else { - wr.wrapper = wrapper + return fmt.Errorf("create beefy client wrapper: %w", err) } + wr.contract = contract callOpts := bind.CallOpts{ Context: ctx, } blockWaitPeriod, err := wr.contract.RandaoCommitDelay(&callOpts) if err != nil { - return fmt.Errorf("create randao commit delay: %w", err) + return fmt.Errorf("get randao commit delay: %w", err) } wr.blockWaitPeriod = blockWaitPeriod.Uint64() log.WithField("randaoCommitDelay", wr.blockWaitPeriod).Trace("Fetched randaoCommitDelay") diff --git a/relayer/relays/beefy/parameters.go b/relayer/relays/beefy/parameters.go index 4023e8984..d1a006364 100644 --- a/relayer/relays/beefy/parameters.go +++ b/relayer/relays/beefy/parameters.go @@ -16,16 +16,16 @@ import ( ) type InitialRequestParams struct { - Commitment contracts.BeefyClientCommitment + Commitment contracts.IBeefyClientCommitment Bitfield []*big.Int - Proof contracts.BeefyClientValidatorProof + Proof contracts.IBeefyClientValidatorProof } type FinalRequestParams struct { - Commitment contracts.BeefyClientCommitment + Commitment contracts.IBeefyClientCommitment Bitfield []*big.Int - Proofs []contracts.BeefyClientValidatorProof - Leaf contracts.BeefyClientMMRLeaf + Proofs []contracts.IBeefyClientValidatorProof + Leaf contracts.IBeefyClientMMRLeaf LeafProof [][32]byte LeafProofOrder *big.Int } @@ -72,7 +72,7 @@ func (r *Request) MakeSubmitInitialParams(valAddrIndex int64, initialBitfield [] msg := InitialRequestParams{ Commitment: *commitment, Bitfield: initialBitfield, - Proof: contracts.BeefyClientValidatorProof{ + Proof: contracts.IBeefyClientValidatorProof{ V: v, R: _r, S: s, @@ -85,8 +85,8 @@ func (r *Request) MakeSubmitInitialParams(valAddrIndex int64, initialBitfield [] return &msg, nil } -func toBeefyClientCommitment(c *types.Commitment) *contracts.BeefyClientCommitment { - return &contracts.BeefyClientCommitment{ +func toBeefyClientCommitment(c *types.Commitment) *contracts.IBeefyClientCommitment { + return &contracts.IBeefyClientCommitment{ BlockNumber: c.BlockNumber, ValidatorSetID: c.ValidatorSetID, Payload: toBeefyPayload(c.Payload), @@ -158,7 +158,7 @@ func (r *Request) generateValidatorAddressProof(validatorIndex int64) ([][32]byt } func (r *Request) MakeSubmitFinalParams(validatorIndices []uint64, initialBitfield []*big.Int) (*FinalRequestParams, error) { - validatorProofs := []contracts.BeefyClientValidatorProof{} + validatorProofs := []contracts.IBeefyClientValidatorProof{} for _, validatorIndex := range validatorIndices { ok, beefySig := r.SignedCommitment.Signatures[validatorIndex].Unwrap() @@ -180,7 +180,7 @@ func (r *Request) MakeSubmitFinalParams(validatorIndices []uint64, initialBitfie return nil, err } - validatorProofs = append(validatorProofs, contracts.BeefyClientValidatorProof{ + validatorProofs = append(validatorProofs, contracts.IBeefyClientValidatorProof{ V: v, R: _r, S: s, @@ -190,18 +190,18 @@ func (r *Request) MakeSubmitFinalParams(validatorIndices []uint64, initialBitfie }) } - commitment := contracts.BeefyClientCommitment{ + commitment := contracts.IBeefyClientCommitment{ Payload: toBeefyPayload(r.SignedCommitment.Commitment.Payload), BlockNumber: r.SignedCommitment.Commitment.BlockNumber, ValidatorSetID: r.SignedCommitment.Commitment.ValidatorSetID, } - inputLeaf := contracts.BeefyClientMMRLeaf{} + inputLeaf := contracts.IBeefyClientMMRLeaf{} var merkleProofItems [][32]byte proofOrder := new(big.Int) - inputLeaf = contracts.BeefyClientMMRLeaf{ + inputLeaf = contracts.IBeefyClientMMRLeaf{ Version: uint8(r.Proof.Leaf.Version), ParentNumber: uint32(r.Proof.Leaf.ParentNumberAndHash.ParentNumber), ParentHash: r.Proof.Leaf.ParentNumberAndHash.Hash, @@ -227,10 +227,10 @@ func (r *Request) MakeSubmitFinalParams(validatorIndices []uint64, initialBitfie return &msg, nil } -func toBeefyPayload(items []types.PayloadItem) []contracts.BeefyClientPayloadItem { - beefyItems := make([]contracts.BeefyClientPayloadItem, len(items)) +func toBeefyPayload(items []types.PayloadItem) []contracts.IBeefyClientPayloadItem { + beefyItems := make([]contracts.IBeefyClientPayloadItem, len(items)) for i, item := range items { - beefyItems[i] = contracts.BeefyClientPayloadItem{ + beefyItems[i] = contracts.IBeefyClientPayloadItem{ PayloadID: item.ID, Data: item.Data, } @@ -239,7 +239,7 @@ func toBeefyPayload(items []types.PayloadItem) []contracts.BeefyClientPayloadIte return beefyItems } -func commitmentToLog(commitment contracts.BeefyClientCommitment) logrus.Fields { +func commitmentToLog(commitment contracts.IBeefyClientCommitment) logrus.Fields { payloadFields := make([]logrus.Fields, len(commitment.Payload)) for i, payloadItem := range commitment.Payload { payloadFields[i] = logrus.Fields{ @@ -264,7 +264,7 @@ func bitfieldToStrings(bitfield []*big.Int) []string { return strings } -func proofToLog(proof contracts.BeefyClientValidatorProof) logrus.Fields { +func proofToLog(proof contracts.IBeefyClientValidatorProof) logrus.Fields { hexProof := make([]string, len(proof.Proof)) for i, proof := range proof.Proof { hexProof[i] = Hex(proof[:]) diff --git a/web/packages/test/scripts/set-env.sh b/web/packages/test/scripts/set-env.sh index c9598e9e4..f5791296a 100755 --- a/web/packages/test/scripts/set-env.sh +++ b/web/packages/test/scripts/set-env.sh @@ -36,6 +36,7 @@ parachain_relay_primary_gov_eth_key="${PARACHAIN_RELAY_PRIMARY_GOV_ETH_KEY:-0x80 parachain_relay_secondary_gov_eth_key="${PARACHAIN_RELAY_SECONDARY_GOV_ETH_KEY:-0xe699de86629f0e795b27e26b33c343876f9282c821a62086b21aef0baa7d7ca7}" parachain_relay_assethub_eth_key="${PARACHAIN_RELAY_ASSETHUB_ETH_KEY:-0x3646505e08a0f3a61417d91db18f2911b2d17c01563044f3e2f106bf36679a6a}" beefy_relay_eth_key="${BEEFY_RELAY_ETH_KEY:-0x935b65c833ced92c43ef9de6bff30703d941bd92a2637cb00cfad389f5862109}" +beefy_relay_eth_key_2="${BEEFY_RELAY_ETH_KEY_2:-0x27ae0c7b8d7c698e41b173265490a4c64b4e39ae78599166e003f868f12140fd}" beacon_endpoint_http="${BEACON_HTTP_ENDPOINT:-http://127.0.0.1:9596}" @@ -117,6 +118,16 @@ export REMOTE_REWARD="${REMOTE_REWARD:-1000000000000000}" ## Vault export GATEWAY_PROXY_INITIAL_DEPOSIT="${GATEWAY_PROXY_INITIAL_DEPOSIT:-10000000000000000000}" +## BeefyClientWrapper +export BEEFY_WRAPPER_MAX_GAS_PRICE="${BEEFY_WRAPPER_MAX_GAS_PRICE:-100000000000}" +export BEEFY_WRAPPER_MAX_REFUND_AMOUNT="${BEEFY_WRAPPER_MAX_REFUND_AMOUNT:-1000000000000000000}" +export BEEFY_WRAPPER_REFUND_TARGET="${BEEFY_WRAPPER_REFUND_TARGET:-300}" +export BEEFY_WRAPPER_REWARD_TARGET="${BEEFY_WRAPPER_REWARD_TARGET:-2400}" +export BEEFY_WRAPPER_INITIAL_DEPOSIT="${BEEFY_WRAPPER_INITIAL_DEPOSIT:-10000000000000000000}" +# Relayer addresses (derived from private keys) +export BEEFY_RELAY_ETH_ADDRESS_1="${BEEFY_RELAY_ETH_ADDRESS_1:-0x87D987206180B8f3807Dd90455606eEa85cdB87a}" +export BEEFY_RELAY_ETH_ADDRESS_2="${BEEFY_RELAY_ETH_ADDRESS_2:-0xACbd24742b87c34dED607FB87b22401B2Ede167E}" + export GATEWAY_STORAGE_KEY="${GATEWAY_STORAGE_KEY:-0xaed97c7854d601808b98ae43079dafb3}" export GATEWAY_PROXY_CONTRACT="${GATEWAY_PROXY_CONTRACT:-0xb1185ede04202fe62d38f5db72f71e38ff3e8305}" diff --git a/web/packages/test/scripts/start-beefy-on-demand-relayer.sh b/web/packages/test/scripts/start-beefy-on-demand-relayer.sh index f36b99367..94dd66c67 100755 --- a/web/packages/test/scripts/start-beefy-on-demand-relayer.sh +++ b/web/packages/test/scripts/start-beefy-on-demand-relayer.sh @@ -4,9 +4,9 @@ set -eu source scripts/set-env.sh config_relayer() { - # Configure beefy relay + # Configure beefy relay (uses wrapper address) jq \ - --arg k1 "$(address_for BeefyClient)" \ + --arg k1 "$(address_for BeefyClientWrapperProxy)" \ --arg k2 "$(address_for GatewayProxy)" \ --arg eth_endpoint_ws $eth_endpoint_ws \ --arg eth_gas_limit $eth_gas_limit \ diff --git a/web/packages/test/scripts/start-relayer.sh b/web/packages/test/scripts/start-relayer.sh index 680370790..612bf0dd2 100755 --- a/web/packages/test/scripts/start-relayer.sh +++ b/web/packages/test/scripts/start-relayer.sh @@ -6,9 +6,9 @@ source scripts/set-env.sh config_relayer() { local electra_forked_epoch=0 local fulu_forked_epoch=50000000 - # Configure beefy relay + # Configure beefy relay 1 (uses wrapper address) jq \ - --arg k1 "$(address_for BeefyClient)" \ + --arg k1 "$(address_for BeefyClientWrapperProxy)" \ --arg k2 "$(address_for GatewayProxy)" \ --arg eth_endpoint_ws $eth_endpoint_ws \ --arg eth_gas_limit $eth_gas_limit \ @@ -20,6 +20,20 @@ config_relayer() { ' \ config/beefy-relay.json >$output_dir/beefy-relay.json + # Configure beefy relay 2 (uses wrapper address) + jq \ + --arg k1 "$(address_for BeefyClientWrapperProxy)" \ + --arg k2 "$(address_for GatewayProxy)" \ + --arg eth_endpoint_ws $eth_endpoint_ws \ + --arg eth_gas_limit $eth_gas_limit \ + ' + .sink.contracts.BeefyClient = $k1 + | .sink.contracts.Gateway = $k2 + | .sink.ethereum.endpoint = $eth_endpoint_ws + | .sink.ethereum."gas-limit" = $eth_gas_limit + ' \ + config/beefy-relay.json >$output_dir/beefy-relay-2.json + # Configure parachain relay v1 jq \ --arg k1 "$(address_for GatewayProxy)" \ @@ -170,11 +184,11 @@ config_relayer() { start_relayer() { echo "Starting relay services" - # Launch beefy relay + # Launch beefy relay 1 ( : >"$output_dir"/beefy-relay.log while :; do - echo "Starting beefy relay at $(date)" + echo "Starting beefy relay 1 at $(date)" "${relayer_v2}" run beefy \ --config "$output_dir/beefy-relay.json" \ --ethereum.private-key $beefy_relay_eth_key \ @@ -183,6 +197,19 @@ start_relayer() { done ) & + # Launch beefy relay 2 + ( + : >"$output_dir"/beefy-relay-2.log + while :; do + echo "Starting beefy relay 2 at $(date)" + "${relayer_v2}" run beefy \ + --config "$output_dir/beefy-relay-2.json" \ + --ethereum.private-key $beefy_relay_eth_key_2 \ + >>"$output_dir"/beefy-relay-2.log 2>&1 || true + sleep 20 + done + ) & + # Launch parachain relay v1 ( : >"$output_dir"/parachain-relay-v1.log From 1d3e81db059ec89f07504d15551754a2327964cc Mon Sep 17 00:00:00 2001 From: claravanstaden Date: Wed, 4 Feb 2026 15:25:20 +0200 Subject: [PATCH 08/17] simplify --- .../scripts/DeployBeefyClientWrapper.sol | 11 +- contracts/scripts/DeployLocal.sol | 3 +- contracts/src/BeefyClientWrapper.sol | 90 +- contracts/src/BeefyClientWrapperProxy.sol | 2 +- contracts/src/interfaces/IBeefyClient.sol | 2 +- contracts/test/BeefyClientWrapper.t.sol | 137 +- relayer/contracts/beefy_client_wrapper.go | 1627 +---------------- relayer/relays/beefy/config.go | 5 +- relayer/relays/beefy/ethereum-writer.go | 165 +- relayer/relays/beefy/on-demand-sync.go | 6 +- 10 files changed, 135 insertions(+), 1913 deletions(-) diff --git a/contracts/scripts/DeployBeefyClientWrapper.sol b/contracts/scripts/DeployBeefyClientWrapper.sol index e1d4ee759..5e3bb549b 100644 --- a/contracts/scripts/DeployBeefyClientWrapper.sol +++ b/contracts/scripts/DeployBeefyClientWrapper.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: Apache-2.0 // SPDX-FileCopyrightText: 2023 Snowfork -pragma solidity 0.8.28; +pragma solidity 0.8.33; import {Script} from "forge-std/Script.sol"; import {console} from "forge-std/console.sol"; @@ -13,7 +13,6 @@ contract DeployBeefyClientWrapper is Script { uint256 maxGasPrice; uint256 maxRefundAmount; uint256 refundTarget; - uint256 rewardTarget; } function readConfig() internal returns (Config memory config) { @@ -21,9 +20,8 @@ contract DeployBeefyClientWrapper is Script { beefyClient: vm.envAddress("BEEFY_CLIENT_ADDRESS"), owner: vm.envAddress("REFUND_PROXY_OWNER"), maxGasPrice: vm.envOr("MAX_GAS_PRICE", uint256(100 gwei)), - maxRefundAmount: vm.envOr("MAX_REFUND_AMOUNT", uint256(1 ether)), - refundTarget: vm.envOr("REFUND_TARGET", uint256(300)), // ~30 min for 100% refund - rewardTarget: vm.envOr("REWARD_TARGET", uint256(2400)) // ~4 hours for 100% reward + maxRefundAmount: vm.envOr("MAX_REFUND_AMOUNT", uint256(0.05 ether)), + refundTarget: vm.envOr("REFUND_TARGET", uint256(300)) // ~30 min for 100% refund }); } @@ -37,8 +35,7 @@ contract DeployBeefyClientWrapper is Script { config.owner, config.maxGasPrice, config.maxRefundAmount, - config.refundTarget, - config.rewardTarget + config.refundTarget ); console.log("BeefyClientWrapper:", address(wrapper)); diff --git a/contracts/scripts/DeployLocal.sol b/contracts/scripts/DeployLocal.sol index e405c2611..d52c59f91 100644 --- a/contracts/scripts/DeployLocal.sol +++ b/contracts/scripts/DeployLocal.sol @@ -68,8 +68,7 @@ contract DeployLocal is Script { deployer, vm.envUint("BEEFY_WRAPPER_MAX_GAS_PRICE"), vm.envUint("BEEFY_WRAPPER_MAX_REFUND_AMOUNT"), - vm.envUint("BEEFY_WRAPPER_REFUND_TARGET"), - vm.envUint("BEEFY_WRAPPER_REWARD_TARGET") + vm.envUint("BEEFY_WRAPPER_REFUND_TARGET") ); // Fund wrapper for refunds diff --git a/contracts/src/BeefyClientWrapper.sol b/contracts/src/BeefyClientWrapper.sol index a293fbcb6..34df42f80 100644 --- a/contracts/src/BeefyClientWrapper.sol +++ b/contracts/src/BeefyClientWrapper.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: Apache-2.0 // SPDX-FileCopyrightText: 2023 Snowfork -pragma solidity 0.8.28; +pragma solidity 0.8.33; import {IBeefyClient} from "./interfaces/IBeefyClient.sol"; import {ScaleCodec} from "./utils/ScaleCodec.sol"; @@ -9,16 +9,13 @@ import {ScaleCodec} from "./utils/ScaleCodec.sol"; * @title BeefyClientWrapper * @dev Forwards BeefyClient submissions and refunds gas costs to relayers. * Anyone can relay. Uses progress-based refunds: the more blocks a relayer - * advances the light client, the higher percentage of gas refund and rewards they receive. + * advances the light client, the higher percentage of gas refund they receive. */ contract BeefyClientWrapper { event GasCredited(address indexed relayer, bytes32 indexed commitmentHash, uint256 gasUsed); - event SubmissionRefunded( - address indexed relayer, uint256 progress, uint256 refundAmount, uint256 rewardAmount, uint256 totalGasUsed - ); + event SubmissionRefunded(address indexed relayer, uint256 progress, uint256 refundAmount, uint256 totalGasUsed); event FundsDeposited(address indexed depositor, uint256 amount); event FundsWithdrawn(address indexed recipient, uint256 amount); - event RewardPoolFunded(address indexed funder, uint256 amount); error Unauthorized(); error InvalidAddress(); @@ -36,18 +33,15 @@ contract BeefyClientWrapper { uint256 public maxGasPrice; uint256 public maxRefundAmount; - // Progress-based refund/reward targets + // Progress-based refund target uint256 public refundTarget; // Blocks of progress for 100% gas refund (e.g., 300 = ~30 min) - uint256 public rewardTarget; // Blocks of progress for 100% reward (e.g., 2400 = ~4 hours) - uint256 public rewardPool; // Available reward pool constructor( address _beefyClient, address _owner, uint256 _maxGasPrice, uint256 _maxRefundAmount, - uint256 _refundTarget, - uint256 _rewardTarget + uint256 _refundTarget ) { if (_beefyClient == address(0) || _owner == address(0)) { revert InvalidAddress(); @@ -58,7 +52,6 @@ contract BeefyClientWrapper { maxGasPrice = _maxGasPrice; maxRefundAmount = _maxRefundAmount; refundTarget = _refundTarget; - rewardTarget = _rewardTarget; } /* Beefy Client Proxy Functions */ @@ -165,14 +158,6 @@ contract BeefyClientWrapper { delete ticketOwner[commitmentHash]; } - /** - * @dev Fund the reward pool. Anyone can contribute. - */ - function fundRewardPool() external payable { - rewardPool += msg.value; - emit RewardPoolFunded(msg.sender, msg.value); - } - /* Internal Functions */ function _checkOwner() internal view { @@ -188,16 +173,14 @@ contract BeefyClientWrapper { } /** - * @dev Calculate and send refund + reward based on progress made. + * @dev Calculate and send refund based on progress made. * * Refund: Scales from 0% to 100% as progress goes from 0 to refundTarget. - * Reward: Kicks in after refundTarget, scales to 100% at rewardTarget. * - * Example with refundTarget=300, rewardTarget=2400: - * - 150 blocks progress: 50% gas refund, 0% reward - * - 300 blocks progress: 100% gas refund, 0% reward - * - 600 blocks progress: 100% gas refund, 14.3% reward (300/2100) - * - 2400+ blocks progress: 100% gas refund, 100% reward + * Example with refundTarget=300: + * - 150 blocks progress: 50% gas refund + * - 300 blocks progress: 100% gas refund + * - 600 blocks progress: 100% gas refund (capped) */ function _refundWithProgress(uint256 startGas, uint256 previousGas, uint256 progress) internal { uint256 currentGas = startGas - gasleft() + 21000; @@ -214,27 +197,10 @@ contract BeefyClientWrapper { uint256 refundRatio = progress >= refundTarget ? 100 : (progress * 100) / refundTarget; uint256 refundAmount = (baseRefund * refundRatio) / 100; - // Calculate reward ratio (0-100%, only kicks in after refundTarget) - uint256 rewardAmount = 0; - if (progress > refundTarget && rewardPool > 0 && rewardTarget > refundTarget) { - uint256 extraProgress = progress - refundTarget; - uint256 rewardWindow = rewardTarget - refundTarget; - uint256 rewardRatio = extraProgress >= rewardWindow ? 100 : (extraProgress * 100) / rewardWindow; - rewardAmount = (rewardPool * rewardRatio) / 100; - - // Deduct from reward pool - if (rewardAmount > rewardPool) { - rewardAmount = rewardPool; - } - rewardPool -= rewardAmount; - } - - uint256 totalPayout = refundAmount + rewardAmount; - - if (totalPayout > 0 && address(this).balance >= totalPayout) { - (bool success,) = payable(msg.sender).call{value: totalPayout}(""); + if (refundAmount > 0 && address(this).balance >= refundAmount) { + (bool success,) = payable(msg.sender).call{value: refundAmount}(""); if (success) { - emit SubmissionRefunded(msg.sender, progress, refundAmount, rewardAmount, totalGasUsed); + emit SubmissionRefunded(msg.sender, progress, refundAmount, totalGasUsed); } } } @@ -274,11 +240,6 @@ contract BeefyClientWrapper { refundTarget = _refundTarget; } - function setRewardTarget(uint256 _rewardTarget) external { - _checkOwner(); - rewardTarget = _rewardTarget; - } - function withdrawFunds(address payable recipient, uint256 amount) external { _checkOwner(); if (recipient == address(0)) { @@ -303,26 +264,14 @@ contract BeefyClientWrapper { /* View Functions */ - function getBalance() external view returns (uint256) { - return address(this).balance; - } - - function getCreditedGas(bytes32 commitmentHash) external view returns (uint256) { - return creditedGas[commitmentHash]; - } - - function getRewardPool() external view returns (uint256) { - return rewardPool; - } - /** - * @dev Calculate expected refund and reward for a given progress. + * @dev Calculate expected refund for a given progress. * Useful for relayers to estimate payouts before submitting. */ function estimatePayout(uint256 gasUsed, uint256 gasPrice, uint256 progress) external view - returns (uint256 refundAmount, uint256 rewardAmount) + returns (uint256 refundAmount) { uint256 effectiveGasPrice = gasPrice < maxGasPrice ? gasPrice : maxGasPrice; uint256 baseRefund = gasUsed * effectiveGasPrice; @@ -333,16 +282,9 @@ contract BeefyClientWrapper { uint256 refundRatio = progress >= refundTarget ? 100 : (progress * 100) / refundTarget; refundAmount = (baseRefund * refundRatio) / 100; - - if (progress > refundTarget && rewardPool > 0 && rewardTarget > refundTarget) { - uint256 extraProgress = progress - refundTarget; - uint256 rewardWindow = rewardTarget - refundTarget; - uint256 rewardRatio = extraProgress >= rewardWindow ? 100 : (extraProgress * 100) / rewardWindow; - rewardAmount = (rewardPool * rewardRatio) / 100; - } } receive() external payable { emit FundsDeposited(msg.sender, msg.value); } -} +} \ No newline at end of file diff --git a/contracts/src/BeefyClientWrapperProxy.sol b/contracts/src/BeefyClientWrapperProxy.sol index 23d671b3d..c618cd0cf 100644 --- a/contracts/src/BeefyClientWrapperProxy.sol +++ b/contracts/src/BeefyClientWrapperProxy.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: Apache-2.0 // SPDX-FileCopyrightText: 2023 Snowfork -pragma solidity 0.8.28; +pragma solidity 0.8.33; import {ERC1967} from "./utils/ERC1967.sol"; import {Call} from "./utils/Call.sol"; diff --git a/contracts/src/interfaces/IBeefyClient.sol b/contracts/src/interfaces/IBeefyClient.sol index 1fa15c3ec..5410d88d5 100644 --- a/contracts/src/interfaces/IBeefyClient.sol +++ b/contracts/src/interfaces/IBeefyClient.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: Apache-2.0 // SPDX-FileCopyrightText: 2023 Snowfork -pragma solidity 0.8.28; +pragma solidity 0.8.33; interface IBeefyClient { /* Types */ diff --git a/contracts/test/BeefyClientWrapper.t.sol b/contracts/test/BeefyClientWrapper.t.sol index 05baf6b10..f8d6305ca 100644 --- a/contracts/test/BeefyClientWrapper.t.sol +++ b/contracts/test/BeefyClientWrapper.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: Apache-2.0 -pragma solidity 0.8.28; +pragma solidity 0.8.33; import {Test} from "forge-std/Test.sol"; import {console} from "forge-std/console.sol"; @@ -128,9 +128,8 @@ contract BeefyClientWrapperTest is Test { address anyone = address(0x5); uint256 constant MAX_GAS_PRICE = 100 gwei; - uint256 constant MAX_REFUND_AMOUNT = 1 ether; + uint256 constant MAX_REFUND_AMOUNT = 0.05 ether; uint256 constant REFUND_TARGET = 300; // 300 blocks for 100% refund - uint256 constant REWARD_TARGET = 2400; // 2400 blocks for 100% reward uint256 constant INITIAL_BEEFY_BLOCK = 1000; function setUp() public { @@ -143,8 +142,7 @@ contract BeefyClientWrapperTest is Test { owner, MAX_GAS_PRICE, MAX_REFUND_AMOUNT, - REFUND_TARGET, - REWARD_TARGET + REFUND_TARGET ); // Fund the wrapper with ETH for refunds @@ -204,7 +202,6 @@ contract BeefyClientWrapperTest is Test { assertEq(wrapper.maxGasPrice(), MAX_GAS_PRICE); assertEq(wrapper.maxRefundAmount(), MAX_REFUND_AMOUNT); assertEq(wrapper.refundTarget(), REFUND_TARGET); - assertEq(wrapper.rewardTarget(), REWARD_TARGET); } function test_invalidBeefyClientAddress() public { @@ -214,8 +211,7 @@ contract BeefyClientWrapperTest is Test { owner, MAX_GAS_PRICE, MAX_REFUND_AMOUNT, - REFUND_TARGET, - REWARD_TARGET + REFUND_TARGET ); } @@ -226,8 +222,7 @@ contract BeefyClientWrapperTest is Test { address(0), MAX_GAS_PRICE, MAX_REFUND_AMOUNT, - REFUND_TARGET, - REWARD_TARGET + REFUND_TARGET ); } @@ -323,12 +318,12 @@ contract BeefyClientWrapperTest is Test { bytes32 commitmentHash = computeCommitmentHash(commitment); assertEq(wrapper.ticketOwner(commitmentHash), relayer1); - assertGt(wrapper.getCreditedGas(commitmentHash), 0); + assertGt(wrapper.creditedGas(commitmentHash), 0); // Clear ticket - gas should be forfeited wrapper.clearTicket(commitmentHash); assertEq(wrapper.ticketOwner(commitmentHash), address(0)); - assertEq(wrapper.getCreditedGas(commitmentHash), 0); + assertEq(wrapper.creditedGas(commitmentHash), 0); vm.stopPrank(); } @@ -366,7 +361,7 @@ contract BeefyClientWrapperTest is Test { // Gas should be credited bytes32 commitmentHash = computeCommitmentHash(commitment); - assertGt(wrapper.getCreditedGas(commitmentHash), 0); + assertGt(wrapper.creditedGas(commitmentHash), 0); } function test_refundSentOnlyAfterSubmitFinal() public { @@ -395,7 +390,7 @@ contract BeefyClientWrapperTest is Test { vm.stopPrank(); - assertEq(wrapper.getCreditedGas(commitmentHash), 0); + assertEq(wrapper.creditedGas(commitmentHash), 0); } function test_partialRefundForLowProgress() public { @@ -535,107 +530,21 @@ contract BeefyClientWrapperTest is Test { assertEq(mockBeefyClient.submitFinalCount(), 1); // Submission succeeded } - /* Reward Pool Tests */ - - function test_fundRewardPool() public { - vm.deal(address(this), 10 ether); - - wrapper.fundRewardPool{value: 5 ether}(); - - assertEq(wrapper.getRewardPool(), 5 ether); - } - - function test_rewardPaidForHighProgress() public { - // Fund the reward pool - vm.deal(address(this), 10 ether); - wrapper.fundRewardPool{value: 5 ether}(); - - // Progress beyond refundTarget triggers rewards - uint32 progress = uint32(REWARD_TARGET); // Max progress = max reward - uint32 newBlockNumber = uint32(INITIAL_BEEFY_BLOCK + progress); - IBeefyClient.Commitment memory commitment = createCommitment(newBlockNumber); - uint256[] memory bitfield = new uint256[](1); - IBeefyClient.ValidatorProof memory proof = createValidatorProof(); - IBeefyClient.ValidatorProof[] memory proofs = createValidatorProofs(1); - IBeefyClient.MMRLeaf memory leaf = createMMRLeaf(); - bytes32[] memory leafProof = new bytes32[](0); - - uint256 relayerBalanceBefore = relayer1.balance; - uint256 rewardPoolBefore = wrapper.getRewardPool(); - - vm.startPrank(relayer1); - vm.txGasPrice(50 gwei); - wrapper.submitInitial(commitment, bitfield, proof); - bytes32 commitmentHash = computeCommitmentHash(commitment); - wrapper.commitPrevRandao(commitmentHash); - wrapper.submitFinal(commitment, bitfield, proofs, leaf, leafProof, 0); - vm.stopPrank(); - - uint256 relayerPayout = relayer1.balance - relayerBalanceBefore; - uint256 rewardPoolAfter = wrapper.getRewardPool(); - - // Relayer should receive refund + reward - assertGt(relayerPayout, 0); - // Reward pool should be depleted - assertLt(rewardPoolAfter, rewardPoolBefore); - } - - function test_noRewardForLowProgress() public { - // Fund the reward pool - vm.deal(address(this), 10 ether); - wrapper.fundRewardPool{value: 5 ether}(); - - // Progress below refundTarget = no reward (only partial refund) - uint32 progress = uint32(REFUND_TARGET / 2); - uint32 newBlockNumber = uint32(INITIAL_BEEFY_BLOCK + progress); - IBeefyClient.Commitment memory commitment = createCommitment(newBlockNumber); - uint256[] memory bitfield = new uint256[](1); - IBeefyClient.ValidatorProof memory proof = createValidatorProof(); - IBeefyClient.ValidatorProof[] memory proofs = createValidatorProofs(1); - IBeefyClient.MMRLeaf memory leaf = createMMRLeaf(); - bytes32[] memory leafProof = new bytes32[](0); - - uint256 rewardPoolBefore = wrapper.getRewardPool(); - - vm.startPrank(relayer1); - vm.txGasPrice(50 gwei); - wrapper.submitInitial(commitment, bitfield, proof); - bytes32 commitmentHash = computeCommitmentHash(commitment); - wrapper.commitPrevRandao(commitmentHash); - wrapper.submitFinal(commitment, bitfield, proofs, leaf, leafProof, 0); - vm.stopPrank(); - - // Reward pool should be unchanged (no reward paid) - assertEq(wrapper.getRewardPool(), rewardPoolBefore); - } - function test_estimatePayout() public { uint256 gasUsed = 500000; uint256 gasPrice = 50 gwei; - // Test 50% progress (50% refund, 0% reward) - (uint256 refund50, uint256 reward50) = wrapper.estimatePayout(gasUsed, gasPrice, REFUND_TARGET / 2); + // Test 50% progress (50% refund) + uint256 refund50 = wrapper.estimatePayout(gasUsed, gasPrice, REFUND_TARGET / 2); assertEq(refund50, (gasUsed * gasPrice * 50) / 100); - assertEq(reward50, 0); - // Test 100% refund progress (100% refund, 0% reward) - (uint256 refund100, uint256 reward100) = wrapper.estimatePayout(gasUsed, gasPrice, REFUND_TARGET); + // Test 100% refund progress (100% refund) + uint256 refund100 = wrapper.estimatePayout(gasUsed, gasPrice, REFUND_TARGET); assertEq(refund100, gasUsed * gasPrice); - assertEq(reward100, 0); - } - - function test_estimatePayout_withRewardPool() public { - // Fund the reward pool - vm.deal(address(this), 10 ether); - wrapper.fundRewardPool{value: 5 ether}(); - uint256 gasUsed = 500000; - uint256 gasPrice = 50 gwei; - - // Test max progress (100% refund, 100% reward) - (uint256 refundMax, uint256 rewardMax) = wrapper.estimatePayout(gasUsed, gasPrice, REWARD_TARGET); - assertEq(refundMax, gasUsed * gasPrice); - assertEq(rewardMax, 5 ether); // Full reward pool + // Test > 100% progress (still capped at 100% refund) + uint256 refund200 = wrapper.estimatePayout(gasUsed, gasPrice, REFUND_TARGET * 2); + assertEq(refund200, gasUsed * gasPrice); } /* Admin Function Tests */ @@ -661,13 +570,6 @@ contract BeefyClientWrapperTest is Test { assertEq(wrapper.refundTarget(), 600); } - function test_setRewardTarget() public { - vm.prank(owner); - wrapper.setRewardTarget(4800); - - assertEq(wrapper.rewardTarget(), 4800); - } - function test_withdrawFunds() public { uint256 ownerBalanceBefore = owner.balance; uint256 withdrawAmount = 10 ether; @@ -699,9 +601,6 @@ contract BeefyClientWrapperTest is Test { vm.expectRevert(BeefyClientWrapper.Unauthorized.selector); wrapper.setRefundTarget(1); - vm.expectRevert(BeefyClientWrapper.Unauthorized.selector); - wrapper.setRewardTarget(1); - vm.expectRevert(BeefyClientWrapper.Unauthorized.selector); wrapper.withdrawFunds(payable(anyone), 1); @@ -725,10 +624,6 @@ contract BeefyClientWrapperTest is Test { /* View Function Tests */ - function test_getBalance() public { - assertEq(wrapper.getBalance(), 100 ether); - } - function test_latestBeefyBlock() public { assertEq(wrapper.latestBeefyBlock(), INITIAL_BEEFY_BLOCK); } diff --git a/relayer/contracts/beefy_client_wrapper.go b/relayer/contracts/beefy_client_wrapper.go index 6b2f45d26..43dd3dc77 100644 --- a/relayer/contracts/beefy_client_wrapper.go +++ b/relayer/contracts/beefy_client_wrapper.go @@ -65,7 +65,7 @@ type IBeefyClientValidatorProof struct { // BeefyClientWrapperMetaData contains all meta data concerning the BeefyClientWrapper contract. var BeefyClientWrapperMetaData = &bind.MetaData{ - ABI: "[{\"type\":\"receive\",\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"activeTicket\",\"inputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"addRelayer\",\"inputs\":[{\"name\":\"relayer\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"addTip\",\"inputs\":[{\"name\":\"beefyBlockNumber\",\"type\":\"uint32\",\"internalType\":\"uint32\"}],\"outputs\":[],\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"beefyClient\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"contractIBeefyClient\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"clearTicket\",\"inputs\":[],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"commitPrevRandao\",\"inputs\":[{\"name\":\"commitmentHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"createFinalBitfield\",\"inputs\":[{\"name\":\"commitmentHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"bitfield\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"createInitialBitfield\",\"inputs\":[{\"name\":\"bitsToSet\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"},{\"name\":\"length\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"creditedGas\",\"inputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"currentTurnIndex\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"currentValidatorSet\",\"inputs\":[],\"outputs\":[{\"name\":\"id\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"length\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"root\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getBalance\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getCreditedGas\",\"inputs\":[{\"name\":\"commitmentHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getCurrentTurnRelayer\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getRelayerCount\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getRelayers\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address[]\",\"internalType\":\"address[]\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getTip\",\"inputs\":[{\"name\":\"beefyBlockNumber\",\"type\":\"uint32\",\"internalType\":\"uint32\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"gracePeriodBlocks\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"implementation\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"initialize\",\"inputs\":[{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"isGracePeriodActive\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"isRelayer\",\"inputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"lastSubmissionBlock\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"latestBeefyBlock\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"maxGasPrice\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"maxRefundAmount\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"minBlockIncrement\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"nextValidatorSet\",\"inputs\":[],\"outputs\":[{\"name\":\"id\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"length\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"root\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"owner\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"randaoCommitDelay\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"relayers\",\"inputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"removeRelayer\",\"inputs\":[{\"name\":\"relayer\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setGracePeriod\",\"inputs\":[{\"name\":\"_gracePeriodBlocks\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setMaxGasPrice\",\"inputs\":[{\"name\":\"_maxGasPrice\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setMaxRefundAmount\",\"inputs\":[{\"name\":\"_maxRefundAmount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setMinBlockIncrement\",\"inputs\":[{\"name\":\"_minBlockIncrement\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"submitFinal\",\"inputs\":[{\"name\":\"commitment\",\"type\":\"tuple\",\"internalType\":\"structIBeefyClient.Commitment\",\"components\":[{\"name\":\"blockNumber\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"validatorSetID\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"payload\",\"type\":\"tuple[]\",\"internalType\":\"structIBeefyClient.PayloadItem[]\",\"components\":[{\"name\":\"payloadID\",\"type\":\"bytes2\",\"internalType\":\"bytes2\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]},{\"name\":\"bitfield\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"},{\"name\":\"proofs\",\"type\":\"tuple[]\",\"internalType\":\"structIBeefyClient.ValidatorProof[]\",\"components\":[{\"name\":\"v\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"r\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"s\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"index\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"proof\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"}]},{\"name\":\"leaf\",\"type\":\"tuple\",\"internalType\":\"structIBeefyClient.MMRLeaf\",\"components\":[{\"name\":\"version\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"parentNumber\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"parentHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"nextAuthoritySetID\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"nextAuthoritySetLen\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"nextAuthoritySetRoot\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"parachainHeadsRoot\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"name\":\"leafProof\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"},{\"name\":\"leafProofOrder\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"claimTipBlocks\",\"type\":\"uint32[]\",\"internalType\":\"uint32[]\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"submitInitial\",\"inputs\":[{\"name\":\"commitment\",\"type\":\"tuple\",\"internalType\":\"structIBeefyClient.Commitment\",\"components\":[{\"name\":\"blockNumber\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"validatorSetID\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"payload\",\"type\":\"tuple[]\",\"internalType\":\"structIBeefyClient.PayloadItem[]\",\"components\":[{\"name\":\"payloadID\",\"type\":\"bytes2\",\"internalType\":\"bytes2\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]},{\"name\":\"bitfield\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"},{\"name\":\"proof\",\"type\":\"tuple\",\"internalType\":\"structIBeefyClient.ValidatorProof\",\"components\":[{\"name\":\"v\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"r\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"s\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"index\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"proof\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"ticketOwner\",\"inputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"tips\",\"inputs\":[{\"name\":\"\",\"type\":\"uint32\",\"internalType\":\"uint32\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"transferOwnership\",\"inputs\":[{\"name\":\"newOwner\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"upgradeTo\",\"inputs\":[{\"name\":\"newImplementation\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"expectedCodeHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"withdrawFunds\",\"inputs\":[{\"name\":\"recipient\",\"type\":\"address\",\"internalType\":\"addresspayable\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"event\",\"name\":\"FundsDeposited\",\"inputs\":[{\"name\":\"depositor\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"FundsWithdrawn\",\"inputs\":[{\"name\":\"recipient\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"GasCredited\",\"inputs\":[{\"name\":\"relayer\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"commitmentHash\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"gasUsed\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"RelayerAdded\",\"inputs\":[{\"name\":\"relayer\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"RelayerRemoved\",\"inputs\":[{\"name\":\"relayer\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"SubmissionRefunded\",\"inputs\":[{\"name\":\"relayer\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"},{\"name\":\"totalGasUsed\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"TipAdded\",\"inputs\":[{\"name\":\"tipper\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"beefyBlockNumber\",\"type\":\"uint32\",\"indexed\":true,\"internalType\":\"uint32\"},{\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"TipsClaimed\",\"inputs\":[{\"name\":\"relayer\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"totalAmount\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"TurnAdvanced\",\"inputs\":[{\"name\":\"newTurnIndex\",\"type\":\"uint256\",\"indexed\":true,\"internalType\":\"uint256\"},{\"name\":\"nextRelayer\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Upgraded\",\"inputs\":[{\"name\":\"implementation\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"error\",\"name\":\"AlreadyInitialized\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InsufficientBlockIncrement\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidAddress\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidCodeHash\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidContract\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidTicket\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"NoRelayers\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"NotARelayer\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"NotTicketOwner\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"NotYourTurn\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"RelayerAlreadyExists\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"RelayerNotFound\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"TicketAlreadyActive\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"TransferFailed\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"Unauthorized\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"UnsupportedCompactEncoding\",\"inputs\":[]}]", + ABI: "[{\"type\":\"constructor\",\"inputs\":[{\"name\":\"_beefyClient\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"_owner\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"_maxGasPrice\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_maxRefundAmount\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_refundTarget\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"receive\",\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"beefyClient\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"contractIBeefyClient\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"clearTicket\",\"inputs\":[{\"name\":\"commitmentHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"commitPrevRandao\",\"inputs\":[{\"name\":\"commitmentHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"createFinalBitfield\",\"inputs\":[{\"name\":\"commitmentHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"bitfield\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"createInitialBitfield\",\"inputs\":[{\"name\":\"bitsToSet\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"},{\"name\":\"length\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"creditedGas\",\"inputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"currentValidatorSet\",\"inputs\":[],\"outputs\":[{\"name\":\"id\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"length\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"root\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"estimatePayout\",\"inputs\":[{\"name\":\"gasUsed\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"gasPrice\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"progress\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"refundAmount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"latestBeefyBlock\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"maxGasPrice\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"maxRefundAmount\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"nextValidatorSet\",\"inputs\":[],\"outputs\":[{\"name\":\"id\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"length\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"root\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"owner\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"randaoCommitDelay\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"refundTarget\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"setMaxGasPrice\",\"inputs\":[{\"name\":\"_maxGasPrice\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setMaxRefundAmount\",\"inputs\":[{\"name\":\"_maxRefundAmount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setRefundTarget\",\"inputs\":[{\"name\":\"_refundTarget\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"submitFinal\",\"inputs\":[{\"name\":\"commitment\",\"type\":\"tuple\",\"internalType\":\"structIBeefyClient.Commitment\",\"components\":[{\"name\":\"blockNumber\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"validatorSetID\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"payload\",\"type\":\"tuple[]\",\"internalType\":\"structIBeefyClient.PayloadItem[]\",\"components\":[{\"name\":\"payloadID\",\"type\":\"bytes2\",\"internalType\":\"bytes2\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]},{\"name\":\"bitfield\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"},{\"name\":\"proofs\",\"type\":\"tuple[]\",\"internalType\":\"structIBeefyClient.ValidatorProof[]\",\"components\":[{\"name\":\"v\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"r\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"s\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"index\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"proof\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"}]},{\"name\":\"leaf\",\"type\":\"tuple\",\"internalType\":\"structIBeefyClient.MMRLeaf\",\"components\":[{\"name\":\"version\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"parentNumber\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"parentHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"nextAuthoritySetID\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"nextAuthoritySetLen\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"nextAuthoritySetRoot\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"parachainHeadsRoot\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"name\":\"leafProof\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"},{\"name\":\"leafProofOrder\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"submitInitial\",\"inputs\":[{\"name\":\"commitment\",\"type\":\"tuple\",\"internalType\":\"structIBeefyClient.Commitment\",\"components\":[{\"name\":\"blockNumber\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"validatorSetID\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"payload\",\"type\":\"tuple[]\",\"internalType\":\"structIBeefyClient.PayloadItem[]\",\"components\":[{\"name\":\"payloadID\",\"type\":\"bytes2\",\"internalType\":\"bytes2\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]},{\"name\":\"bitfield\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"},{\"name\":\"proof\",\"type\":\"tuple\",\"internalType\":\"structIBeefyClient.ValidatorProof\",\"components\":[{\"name\":\"v\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"r\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"s\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"index\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"proof\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"ticketOwner\",\"inputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"transferOwnership\",\"inputs\":[{\"name\":\"newOwner\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"withdrawFunds\",\"inputs\":[{\"name\":\"recipient\",\"type\":\"address\",\"internalType\":\"addresspayable\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"event\",\"name\":\"FundsDeposited\",\"inputs\":[{\"name\":\"depositor\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"FundsWithdrawn\",\"inputs\":[{\"name\":\"recipient\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"GasCredited\",\"inputs\":[{\"name\":\"relayer\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"commitmentHash\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"gasUsed\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"SubmissionRefunded\",\"inputs\":[{\"name\":\"relayer\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"progress\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"},{\"name\":\"refundAmount\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"},{\"name\":\"totalGasUsed\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"error\",\"name\":\"InvalidAddress\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"NotTicketOwner\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"TransferFailed\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"Unauthorized\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"UnsupportedCompactEncoding\",\"inputs\":[]}]", } // BeefyClientWrapperABI is the input ABI used to generate the binding from. @@ -214,37 +214,6 @@ func (_BeefyClientWrapper *BeefyClientWrapperTransactorRaw) Transact(opts *bind. return _BeefyClientWrapper.Contract.contract.Transact(opts, method, params...) } -// ActiveTicket is a free data retrieval call binding the contract method 0x3b38c624. -// -// Solidity: function activeTicket(address ) view returns(bytes32) -func (_BeefyClientWrapper *BeefyClientWrapperCaller) ActiveTicket(opts *bind.CallOpts, arg0 common.Address) ([32]byte, error) { - var out []interface{} - err := _BeefyClientWrapper.contract.Call(opts, &out, "activeTicket", arg0) - - if err != nil { - return *new([32]byte), err - } - - out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) - - return out0, err - -} - -// ActiveTicket is a free data retrieval call binding the contract method 0x3b38c624. -// -// Solidity: function activeTicket(address ) view returns(bytes32) -func (_BeefyClientWrapper *BeefyClientWrapperSession) ActiveTicket(arg0 common.Address) ([32]byte, error) { - return _BeefyClientWrapper.Contract.ActiveTicket(&_BeefyClientWrapper.CallOpts, arg0) -} - -// ActiveTicket is a free data retrieval call binding the contract method 0x3b38c624. -// -// Solidity: function activeTicket(address ) view returns(bytes32) -func (_BeefyClientWrapper *BeefyClientWrapperCallerSession) ActiveTicket(arg0 common.Address) ([32]byte, error) { - return _BeefyClientWrapper.Contract.ActiveTicket(&_BeefyClientWrapper.CallOpts, arg0) -} - // BeefyClient is a free data retrieval call binding the contract method 0x776c81c3. // // Solidity: function beefyClient() view returns(address) @@ -369,37 +338,6 @@ func (_BeefyClientWrapper *BeefyClientWrapperCallerSession) CreditedGas(arg0 [32 return _BeefyClientWrapper.Contract.CreditedGas(&_BeefyClientWrapper.CallOpts, arg0) } -// CurrentTurnIndex is a free data retrieval call binding the contract method 0x50efd268. -// -// Solidity: function currentTurnIndex() view returns(uint256) -func (_BeefyClientWrapper *BeefyClientWrapperCaller) CurrentTurnIndex(opts *bind.CallOpts) (*big.Int, error) { - var out []interface{} - err := _BeefyClientWrapper.contract.Call(opts, &out, "currentTurnIndex") - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -// CurrentTurnIndex is a free data retrieval call binding the contract method 0x50efd268. -// -// Solidity: function currentTurnIndex() view returns(uint256) -func (_BeefyClientWrapper *BeefyClientWrapperSession) CurrentTurnIndex() (*big.Int, error) { - return _BeefyClientWrapper.Contract.CurrentTurnIndex(&_BeefyClientWrapper.CallOpts) -} - -// CurrentTurnIndex is a free data retrieval call binding the contract method 0x50efd268. -// -// Solidity: function currentTurnIndex() view returns(uint256) -func (_BeefyClientWrapper *BeefyClientWrapperCallerSession) CurrentTurnIndex() (*big.Int, error) { - return _BeefyClientWrapper.Contract.CurrentTurnIndex(&_BeefyClientWrapper.CallOpts) -} - // CurrentValidatorSet is a free data retrieval call binding the contract method 0x2cdea717. // // Solidity: function currentValidatorSet() view returns(uint128 id, uint128 length, bytes32 root) @@ -450,322 +388,12 @@ func (_BeefyClientWrapper *BeefyClientWrapperCallerSession) CurrentValidatorSet( return _BeefyClientWrapper.Contract.CurrentValidatorSet(&_BeefyClientWrapper.CallOpts) } -// GetBalance is a free data retrieval call binding the contract method 0x12065fe0. -// -// Solidity: function getBalance() view returns(uint256) -func (_BeefyClientWrapper *BeefyClientWrapperCaller) GetBalance(opts *bind.CallOpts) (*big.Int, error) { - var out []interface{} - err := _BeefyClientWrapper.contract.Call(opts, &out, "getBalance") - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -// GetBalance is a free data retrieval call binding the contract method 0x12065fe0. -// -// Solidity: function getBalance() view returns(uint256) -func (_BeefyClientWrapper *BeefyClientWrapperSession) GetBalance() (*big.Int, error) { - return _BeefyClientWrapper.Contract.GetBalance(&_BeefyClientWrapper.CallOpts) -} - -// GetBalance is a free data retrieval call binding the contract method 0x12065fe0. -// -// Solidity: function getBalance() view returns(uint256) -func (_BeefyClientWrapper *BeefyClientWrapperCallerSession) GetBalance() (*big.Int, error) { - return _BeefyClientWrapper.Contract.GetBalance(&_BeefyClientWrapper.CallOpts) -} - -// GetCreditedGas is a free data retrieval call binding the contract method 0xfd635f1c. -// -// Solidity: function getCreditedGas(bytes32 commitmentHash) view returns(uint256) -func (_BeefyClientWrapper *BeefyClientWrapperCaller) GetCreditedGas(opts *bind.CallOpts, commitmentHash [32]byte) (*big.Int, error) { - var out []interface{} - err := _BeefyClientWrapper.contract.Call(opts, &out, "getCreditedGas", commitmentHash) - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -// GetCreditedGas is a free data retrieval call binding the contract method 0xfd635f1c. -// -// Solidity: function getCreditedGas(bytes32 commitmentHash) view returns(uint256) -func (_BeefyClientWrapper *BeefyClientWrapperSession) GetCreditedGas(commitmentHash [32]byte) (*big.Int, error) { - return _BeefyClientWrapper.Contract.GetCreditedGas(&_BeefyClientWrapper.CallOpts, commitmentHash) -} - -// GetCreditedGas is a free data retrieval call binding the contract method 0xfd635f1c. -// -// Solidity: function getCreditedGas(bytes32 commitmentHash) view returns(uint256) -func (_BeefyClientWrapper *BeefyClientWrapperCallerSession) GetCreditedGas(commitmentHash [32]byte) (*big.Int, error) { - return _BeefyClientWrapper.Contract.GetCreditedGas(&_BeefyClientWrapper.CallOpts, commitmentHash) -} - -// GetCurrentTurnRelayer is a free data retrieval call binding the contract method 0x5664b04f. -// -// Solidity: function getCurrentTurnRelayer() view returns(address) -func (_BeefyClientWrapper *BeefyClientWrapperCaller) GetCurrentTurnRelayer(opts *bind.CallOpts) (common.Address, error) { - var out []interface{} - err := _BeefyClientWrapper.contract.Call(opts, &out, "getCurrentTurnRelayer") - - if err != nil { - return *new(common.Address), err - } - - out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) - - return out0, err - -} - -// GetCurrentTurnRelayer is a free data retrieval call binding the contract method 0x5664b04f. -// -// Solidity: function getCurrentTurnRelayer() view returns(address) -func (_BeefyClientWrapper *BeefyClientWrapperSession) GetCurrentTurnRelayer() (common.Address, error) { - return _BeefyClientWrapper.Contract.GetCurrentTurnRelayer(&_BeefyClientWrapper.CallOpts) -} - -// GetCurrentTurnRelayer is a free data retrieval call binding the contract method 0x5664b04f. -// -// Solidity: function getCurrentTurnRelayer() view returns(address) -func (_BeefyClientWrapper *BeefyClientWrapperCallerSession) GetCurrentTurnRelayer() (common.Address, error) { - return _BeefyClientWrapper.Contract.GetCurrentTurnRelayer(&_BeefyClientWrapper.CallOpts) -} - -// GetRelayerCount is a free data retrieval call binding the contract method 0xe51ea0b5. -// -// Solidity: function getRelayerCount() view returns(uint256) -func (_BeefyClientWrapper *BeefyClientWrapperCaller) GetRelayerCount(opts *bind.CallOpts) (*big.Int, error) { - var out []interface{} - err := _BeefyClientWrapper.contract.Call(opts, &out, "getRelayerCount") - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -// GetRelayerCount is a free data retrieval call binding the contract method 0xe51ea0b5. -// -// Solidity: function getRelayerCount() view returns(uint256) -func (_BeefyClientWrapper *BeefyClientWrapperSession) GetRelayerCount() (*big.Int, error) { - return _BeefyClientWrapper.Contract.GetRelayerCount(&_BeefyClientWrapper.CallOpts) -} - -// GetRelayerCount is a free data retrieval call binding the contract method 0xe51ea0b5. -// -// Solidity: function getRelayerCount() view returns(uint256) -func (_BeefyClientWrapper *BeefyClientWrapperCallerSession) GetRelayerCount() (*big.Int, error) { - return _BeefyClientWrapper.Contract.GetRelayerCount(&_BeefyClientWrapper.CallOpts) -} - -// GetRelayers is a free data retrieval call binding the contract method 0x179ff4b2. -// -// Solidity: function getRelayers() view returns(address[]) -func (_BeefyClientWrapper *BeefyClientWrapperCaller) GetRelayers(opts *bind.CallOpts) ([]common.Address, error) { - var out []interface{} - err := _BeefyClientWrapper.contract.Call(opts, &out, "getRelayers") - - if err != nil { - return *new([]common.Address), err - } - - out0 := *abi.ConvertType(out[0], new([]common.Address)).(*[]common.Address) - - return out0, err - -} - -// GetRelayers is a free data retrieval call binding the contract method 0x179ff4b2. -// -// Solidity: function getRelayers() view returns(address[]) -func (_BeefyClientWrapper *BeefyClientWrapperSession) GetRelayers() ([]common.Address, error) { - return _BeefyClientWrapper.Contract.GetRelayers(&_BeefyClientWrapper.CallOpts) -} - -// GetRelayers is a free data retrieval call binding the contract method 0x179ff4b2. -// -// Solidity: function getRelayers() view returns(address[]) -func (_BeefyClientWrapper *BeefyClientWrapperCallerSession) GetRelayers() ([]common.Address, error) { - return _BeefyClientWrapper.Contract.GetRelayers(&_BeefyClientWrapper.CallOpts) -} - -// GetTip is a free data retrieval call binding the contract method 0xa7e7353c. -// -// Solidity: function getTip(uint32 beefyBlockNumber) view returns(uint256) -func (_BeefyClientWrapper *BeefyClientWrapperCaller) GetTip(opts *bind.CallOpts, beefyBlockNumber uint32) (*big.Int, error) { - var out []interface{} - err := _BeefyClientWrapper.contract.Call(opts, &out, "getTip", beefyBlockNumber) - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -// GetTip is a free data retrieval call binding the contract method 0xa7e7353c. -// -// Solidity: function getTip(uint32 beefyBlockNumber) view returns(uint256) -func (_BeefyClientWrapper *BeefyClientWrapperSession) GetTip(beefyBlockNumber uint32) (*big.Int, error) { - return _BeefyClientWrapper.Contract.GetTip(&_BeefyClientWrapper.CallOpts, beefyBlockNumber) -} - -// GetTip is a free data retrieval call binding the contract method 0xa7e7353c. -// -// Solidity: function getTip(uint32 beefyBlockNumber) view returns(uint256) -func (_BeefyClientWrapper *BeefyClientWrapperCallerSession) GetTip(beefyBlockNumber uint32) (*big.Int, error) { - return _BeefyClientWrapper.Contract.GetTip(&_BeefyClientWrapper.CallOpts, beefyBlockNumber) -} - -// GracePeriodBlocks is a free data retrieval call binding the contract method 0xde2daaff. -// -// Solidity: function gracePeriodBlocks() view returns(uint256) -func (_BeefyClientWrapper *BeefyClientWrapperCaller) GracePeriodBlocks(opts *bind.CallOpts) (*big.Int, error) { - var out []interface{} - err := _BeefyClientWrapper.contract.Call(opts, &out, "gracePeriodBlocks") - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -// GracePeriodBlocks is a free data retrieval call binding the contract method 0xde2daaff. -// -// Solidity: function gracePeriodBlocks() view returns(uint256) -func (_BeefyClientWrapper *BeefyClientWrapperSession) GracePeriodBlocks() (*big.Int, error) { - return _BeefyClientWrapper.Contract.GracePeriodBlocks(&_BeefyClientWrapper.CallOpts) -} - -// GracePeriodBlocks is a free data retrieval call binding the contract method 0xde2daaff. -// -// Solidity: function gracePeriodBlocks() view returns(uint256) -func (_BeefyClientWrapper *BeefyClientWrapperCallerSession) GracePeriodBlocks() (*big.Int, error) { - return _BeefyClientWrapper.Contract.GracePeriodBlocks(&_BeefyClientWrapper.CallOpts) -} - -// Implementation is a free data retrieval call binding the contract method 0x5c60da1b. -// -// Solidity: function implementation() view returns(address) -func (_BeefyClientWrapper *BeefyClientWrapperCaller) Implementation(opts *bind.CallOpts) (common.Address, error) { - var out []interface{} - err := _BeefyClientWrapper.contract.Call(opts, &out, "implementation") - - if err != nil { - return *new(common.Address), err - } - - out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) - - return out0, err - -} - -// Implementation is a free data retrieval call binding the contract method 0x5c60da1b. -// -// Solidity: function implementation() view returns(address) -func (_BeefyClientWrapper *BeefyClientWrapperSession) Implementation() (common.Address, error) { - return _BeefyClientWrapper.Contract.Implementation(&_BeefyClientWrapper.CallOpts) -} - -// Implementation is a free data retrieval call binding the contract method 0x5c60da1b. -// -// Solidity: function implementation() view returns(address) -func (_BeefyClientWrapper *BeefyClientWrapperCallerSession) Implementation() (common.Address, error) { - return _BeefyClientWrapper.Contract.Implementation(&_BeefyClientWrapper.CallOpts) -} - -// IsGracePeriodActive is a free data retrieval call binding the contract method 0xb965655a. -// -// Solidity: function isGracePeriodActive() view returns(bool) -func (_BeefyClientWrapper *BeefyClientWrapperCaller) IsGracePeriodActive(opts *bind.CallOpts) (bool, error) { - var out []interface{} - err := _BeefyClientWrapper.contract.Call(opts, &out, "isGracePeriodActive") - - if err != nil { - return *new(bool), err - } - - out0 := *abi.ConvertType(out[0], new(bool)).(*bool) - - return out0, err - -} - -// IsGracePeriodActive is a free data retrieval call binding the contract method 0xb965655a. -// -// Solidity: function isGracePeriodActive() view returns(bool) -func (_BeefyClientWrapper *BeefyClientWrapperSession) IsGracePeriodActive() (bool, error) { - return _BeefyClientWrapper.Contract.IsGracePeriodActive(&_BeefyClientWrapper.CallOpts) -} - -// IsGracePeriodActive is a free data retrieval call binding the contract method 0xb965655a. -// -// Solidity: function isGracePeriodActive() view returns(bool) -func (_BeefyClientWrapper *BeefyClientWrapperCallerSession) IsGracePeriodActive() (bool, error) { - return _BeefyClientWrapper.Contract.IsGracePeriodActive(&_BeefyClientWrapper.CallOpts) -} - -// IsRelayer is a free data retrieval call binding the contract method 0x541d5548. -// -// Solidity: function isRelayer(address ) view returns(bool) -func (_BeefyClientWrapper *BeefyClientWrapperCaller) IsRelayer(opts *bind.CallOpts, arg0 common.Address) (bool, error) { - var out []interface{} - err := _BeefyClientWrapper.contract.Call(opts, &out, "isRelayer", arg0) - - if err != nil { - return *new(bool), err - } - - out0 := *abi.ConvertType(out[0], new(bool)).(*bool) - - return out0, err - -} - -// IsRelayer is a free data retrieval call binding the contract method 0x541d5548. -// -// Solidity: function isRelayer(address ) view returns(bool) -func (_BeefyClientWrapper *BeefyClientWrapperSession) IsRelayer(arg0 common.Address) (bool, error) { - return _BeefyClientWrapper.Contract.IsRelayer(&_BeefyClientWrapper.CallOpts, arg0) -} - -// IsRelayer is a free data retrieval call binding the contract method 0x541d5548. -// -// Solidity: function isRelayer(address ) view returns(bool) -func (_BeefyClientWrapper *BeefyClientWrapperCallerSession) IsRelayer(arg0 common.Address) (bool, error) { - return _BeefyClientWrapper.Contract.IsRelayer(&_BeefyClientWrapper.CallOpts, arg0) -} - -// LastSubmissionBlock is a free data retrieval call binding the contract method 0x1f498355. +// EstimatePayout is a free data retrieval call binding the contract method 0x83d29b40. // -// Solidity: function lastSubmissionBlock() view returns(uint256) -func (_BeefyClientWrapper *BeefyClientWrapperCaller) LastSubmissionBlock(opts *bind.CallOpts) (*big.Int, error) { +// Solidity: function estimatePayout(uint256 gasUsed, uint256 gasPrice, uint256 progress) view returns(uint256 refundAmount) +func (_BeefyClientWrapper *BeefyClientWrapperCaller) EstimatePayout(opts *bind.CallOpts, gasUsed *big.Int, gasPrice *big.Int, progress *big.Int) (*big.Int, error) { var out []interface{} - err := _BeefyClientWrapper.contract.Call(opts, &out, "lastSubmissionBlock") + err := _BeefyClientWrapper.contract.Call(opts, &out, "estimatePayout", gasUsed, gasPrice, progress) if err != nil { return *new(*big.Int), err @@ -777,18 +405,18 @@ func (_BeefyClientWrapper *BeefyClientWrapperCaller) LastSubmissionBlock(opts *b } -// LastSubmissionBlock is a free data retrieval call binding the contract method 0x1f498355. +// EstimatePayout is a free data retrieval call binding the contract method 0x83d29b40. // -// Solidity: function lastSubmissionBlock() view returns(uint256) -func (_BeefyClientWrapper *BeefyClientWrapperSession) LastSubmissionBlock() (*big.Int, error) { - return _BeefyClientWrapper.Contract.LastSubmissionBlock(&_BeefyClientWrapper.CallOpts) +// Solidity: function estimatePayout(uint256 gasUsed, uint256 gasPrice, uint256 progress) view returns(uint256 refundAmount) +func (_BeefyClientWrapper *BeefyClientWrapperSession) EstimatePayout(gasUsed *big.Int, gasPrice *big.Int, progress *big.Int) (*big.Int, error) { + return _BeefyClientWrapper.Contract.EstimatePayout(&_BeefyClientWrapper.CallOpts, gasUsed, gasPrice, progress) } -// LastSubmissionBlock is a free data retrieval call binding the contract method 0x1f498355. +// EstimatePayout is a free data retrieval call binding the contract method 0x83d29b40. // -// Solidity: function lastSubmissionBlock() view returns(uint256) -func (_BeefyClientWrapper *BeefyClientWrapperCallerSession) LastSubmissionBlock() (*big.Int, error) { - return _BeefyClientWrapper.Contract.LastSubmissionBlock(&_BeefyClientWrapper.CallOpts) +// Solidity: function estimatePayout(uint256 gasUsed, uint256 gasPrice, uint256 progress) view returns(uint256 refundAmount) +func (_BeefyClientWrapper *BeefyClientWrapperCallerSession) EstimatePayout(gasUsed *big.Int, gasPrice *big.Int, progress *big.Int) (*big.Int, error) { + return _BeefyClientWrapper.Contract.EstimatePayout(&_BeefyClientWrapper.CallOpts, gasUsed, gasPrice, progress) } // LatestBeefyBlock is a free data retrieval call binding the contract method 0x66ae69a0. @@ -884,37 +512,6 @@ func (_BeefyClientWrapper *BeefyClientWrapperCallerSession) MaxRefundAmount() (* return _BeefyClientWrapper.Contract.MaxRefundAmount(&_BeefyClientWrapper.CallOpts) } -// MinBlockIncrement is a free data retrieval call binding the contract method 0x4bfcad80. -// -// Solidity: function minBlockIncrement() view returns(uint256) -func (_BeefyClientWrapper *BeefyClientWrapperCaller) MinBlockIncrement(opts *bind.CallOpts) (*big.Int, error) { - var out []interface{} - err := _BeefyClientWrapper.contract.Call(opts, &out, "minBlockIncrement") - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -// MinBlockIncrement is a free data retrieval call binding the contract method 0x4bfcad80. -// -// Solidity: function minBlockIncrement() view returns(uint256) -func (_BeefyClientWrapper *BeefyClientWrapperSession) MinBlockIncrement() (*big.Int, error) { - return _BeefyClientWrapper.Contract.MinBlockIncrement(&_BeefyClientWrapper.CallOpts) -} - -// MinBlockIncrement is a free data retrieval call binding the contract method 0x4bfcad80. -// -// Solidity: function minBlockIncrement() view returns(uint256) -func (_BeefyClientWrapper *BeefyClientWrapperCallerSession) MinBlockIncrement() (*big.Int, error) { - return _BeefyClientWrapper.Contract.MinBlockIncrement(&_BeefyClientWrapper.CallOpts) -} - // NextValidatorSet is a free data retrieval call binding the contract method 0x36667513. // // Solidity: function nextValidatorSet() view returns(uint128 id, uint128 length, bytes32 root) @@ -1027,35 +624,35 @@ func (_BeefyClientWrapper *BeefyClientWrapperCallerSession) RandaoCommitDelay() return _BeefyClientWrapper.Contract.RandaoCommitDelay(&_BeefyClientWrapper.CallOpts) } -// Relayers is a free data retrieval call binding the contract method 0x9a48e7f9. +// RefundTarget is a free data retrieval call binding the contract method 0xd679e02a. // -// Solidity: function relayers(uint256 ) view returns(address) -func (_BeefyClientWrapper *BeefyClientWrapperCaller) Relayers(opts *bind.CallOpts, arg0 *big.Int) (common.Address, error) { +// Solidity: function refundTarget() view returns(uint256) +func (_BeefyClientWrapper *BeefyClientWrapperCaller) RefundTarget(opts *bind.CallOpts) (*big.Int, error) { var out []interface{} - err := _BeefyClientWrapper.contract.Call(opts, &out, "relayers", arg0) + err := _BeefyClientWrapper.contract.Call(opts, &out, "refundTarget") if err != nil { - return *new(common.Address), err + return *new(*big.Int), err } - out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) return out0, err } -// Relayers is a free data retrieval call binding the contract method 0x9a48e7f9. +// RefundTarget is a free data retrieval call binding the contract method 0xd679e02a. // -// Solidity: function relayers(uint256 ) view returns(address) -func (_BeefyClientWrapper *BeefyClientWrapperSession) Relayers(arg0 *big.Int) (common.Address, error) { - return _BeefyClientWrapper.Contract.Relayers(&_BeefyClientWrapper.CallOpts, arg0) +// Solidity: function refundTarget() view returns(uint256) +func (_BeefyClientWrapper *BeefyClientWrapperSession) RefundTarget() (*big.Int, error) { + return _BeefyClientWrapper.Contract.RefundTarget(&_BeefyClientWrapper.CallOpts) } -// Relayers is a free data retrieval call binding the contract method 0x9a48e7f9. +// RefundTarget is a free data retrieval call binding the contract method 0xd679e02a. // -// Solidity: function relayers(uint256 ) view returns(address) -func (_BeefyClientWrapper *BeefyClientWrapperCallerSession) Relayers(arg0 *big.Int) (common.Address, error) { - return _BeefyClientWrapper.Contract.Relayers(&_BeefyClientWrapper.CallOpts, arg0) +// Solidity: function refundTarget() view returns(uint256) +func (_BeefyClientWrapper *BeefyClientWrapperCallerSession) RefundTarget() (*big.Int, error) { + return _BeefyClientWrapper.Contract.RefundTarget(&_BeefyClientWrapper.CallOpts) } // TicketOwner is a free data retrieval call binding the contract method 0xd2e82bfe. @@ -1089,101 +686,28 @@ func (_BeefyClientWrapper *BeefyClientWrapperCallerSession) TicketOwner(arg0 [32 return _BeefyClientWrapper.Contract.TicketOwner(&_BeefyClientWrapper.CallOpts, arg0) } -// Tips is a free data retrieval call binding the contract method 0x1756fe14. +// ClearTicket is a paid mutator transaction binding the contract method 0xa82218ed. // -// Solidity: function tips(uint32 ) view returns(uint256) -func (_BeefyClientWrapper *BeefyClientWrapperCaller) Tips(opts *bind.CallOpts, arg0 uint32) (*big.Int, error) { - var out []interface{} - err := _BeefyClientWrapper.contract.Call(opts, &out, "tips", arg0) - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - +// Solidity: function clearTicket(bytes32 commitmentHash) returns() +func (_BeefyClientWrapper *BeefyClientWrapperTransactor) ClearTicket(opts *bind.TransactOpts, commitmentHash [32]byte) (*types.Transaction, error) { + return _BeefyClientWrapper.contract.Transact(opts, "clearTicket", commitmentHash) } -// Tips is a free data retrieval call binding the contract method 0x1756fe14. +// ClearTicket is a paid mutator transaction binding the contract method 0xa82218ed. // -// Solidity: function tips(uint32 ) view returns(uint256) -func (_BeefyClientWrapper *BeefyClientWrapperSession) Tips(arg0 uint32) (*big.Int, error) { - return _BeefyClientWrapper.Contract.Tips(&_BeefyClientWrapper.CallOpts, arg0) +// Solidity: function clearTicket(bytes32 commitmentHash) returns() +func (_BeefyClientWrapper *BeefyClientWrapperSession) ClearTicket(commitmentHash [32]byte) (*types.Transaction, error) { + return _BeefyClientWrapper.Contract.ClearTicket(&_BeefyClientWrapper.TransactOpts, commitmentHash) } -// Tips is a free data retrieval call binding the contract method 0x1756fe14. +// ClearTicket is a paid mutator transaction binding the contract method 0xa82218ed. // -// Solidity: function tips(uint32 ) view returns(uint256) -func (_BeefyClientWrapper *BeefyClientWrapperCallerSession) Tips(arg0 uint32) (*big.Int, error) { - return _BeefyClientWrapper.Contract.Tips(&_BeefyClientWrapper.CallOpts, arg0) +// Solidity: function clearTicket(bytes32 commitmentHash) returns() +func (_BeefyClientWrapper *BeefyClientWrapperTransactorSession) ClearTicket(commitmentHash [32]byte) (*types.Transaction, error) { + return _BeefyClientWrapper.Contract.ClearTicket(&_BeefyClientWrapper.TransactOpts, commitmentHash) } -// AddRelayer is a paid mutator transaction binding the contract method 0xdd39f00d. -// -// Solidity: function addRelayer(address relayer) returns() -func (_BeefyClientWrapper *BeefyClientWrapperTransactor) AddRelayer(opts *bind.TransactOpts, relayer common.Address) (*types.Transaction, error) { - return _BeefyClientWrapper.contract.Transact(opts, "addRelayer", relayer) -} - -// AddRelayer is a paid mutator transaction binding the contract method 0xdd39f00d. -// -// Solidity: function addRelayer(address relayer) returns() -func (_BeefyClientWrapper *BeefyClientWrapperSession) AddRelayer(relayer common.Address) (*types.Transaction, error) { - return _BeefyClientWrapper.Contract.AddRelayer(&_BeefyClientWrapper.TransactOpts, relayer) -} - -// AddRelayer is a paid mutator transaction binding the contract method 0xdd39f00d. -// -// Solidity: function addRelayer(address relayer) returns() -func (_BeefyClientWrapper *BeefyClientWrapperTransactorSession) AddRelayer(relayer common.Address) (*types.Transaction, error) { - return _BeefyClientWrapper.Contract.AddRelayer(&_BeefyClientWrapper.TransactOpts, relayer) -} - -// AddTip is a paid mutator transaction binding the contract method 0x9f404590. -// -// Solidity: function addTip(uint32 beefyBlockNumber) payable returns() -func (_BeefyClientWrapper *BeefyClientWrapperTransactor) AddTip(opts *bind.TransactOpts, beefyBlockNumber uint32) (*types.Transaction, error) { - return _BeefyClientWrapper.contract.Transact(opts, "addTip", beefyBlockNumber) -} - -// AddTip is a paid mutator transaction binding the contract method 0x9f404590. -// -// Solidity: function addTip(uint32 beefyBlockNumber) payable returns() -func (_BeefyClientWrapper *BeefyClientWrapperSession) AddTip(beefyBlockNumber uint32) (*types.Transaction, error) { - return _BeefyClientWrapper.Contract.AddTip(&_BeefyClientWrapper.TransactOpts, beefyBlockNumber) -} - -// AddTip is a paid mutator transaction binding the contract method 0x9f404590. -// -// Solidity: function addTip(uint32 beefyBlockNumber) payable returns() -func (_BeefyClientWrapper *BeefyClientWrapperTransactorSession) AddTip(beefyBlockNumber uint32) (*types.Transaction, error) { - return _BeefyClientWrapper.Contract.AddTip(&_BeefyClientWrapper.TransactOpts, beefyBlockNumber) -} - -// ClearTicket is a paid mutator transaction binding the contract method 0x15738ab4. -// -// Solidity: function clearTicket() returns() -func (_BeefyClientWrapper *BeefyClientWrapperTransactor) ClearTicket(opts *bind.TransactOpts) (*types.Transaction, error) { - return _BeefyClientWrapper.contract.Transact(opts, "clearTicket") -} - -// ClearTicket is a paid mutator transaction binding the contract method 0x15738ab4. -// -// Solidity: function clearTicket() returns() -func (_BeefyClientWrapper *BeefyClientWrapperSession) ClearTicket() (*types.Transaction, error) { - return _BeefyClientWrapper.Contract.ClearTicket(&_BeefyClientWrapper.TransactOpts) -} - -// ClearTicket is a paid mutator transaction binding the contract method 0x15738ab4. -// -// Solidity: function clearTicket() returns() -func (_BeefyClientWrapper *BeefyClientWrapperTransactorSession) ClearTicket() (*types.Transaction, error) { - return _BeefyClientWrapper.Contract.ClearTicket(&_BeefyClientWrapper.TransactOpts) -} - -// CommitPrevRandao is a paid mutator transaction binding the contract method 0xa77cf3d2. +// CommitPrevRandao is a paid mutator transaction binding the contract method 0xa77cf3d2. // // Solidity: function commitPrevRandao(bytes32 commitmentHash) returns() func (_BeefyClientWrapper *BeefyClientWrapperTransactor) CommitPrevRandao(opts *bind.TransactOpts, commitmentHash [32]byte) (*types.Transaction, error) { @@ -1204,69 +728,6 @@ func (_BeefyClientWrapper *BeefyClientWrapperTransactorSession) CommitPrevRandao return _BeefyClientWrapper.Contract.CommitPrevRandao(&_BeefyClientWrapper.TransactOpts, commitmentHash) } -// Initialize is a paid mutator transaction binding the contract method 0x439fab91. -// -// Solidity: function initialize(bytes data) returns() -func (_BeefyClientWrapper *BeefyClientWrapperTransactor) Initialize(opts *bind.TransactOpts, data []byte) (*types.Transaction, error) { - return _BeefyClientWrapper.contract.Transact(opts, "initialize", data) -} - -// Initialize is a paid mutator transaction binding the contract method 0x439fab91. -// -// Solidity: function initialize(bytes data) returns() -func (_BeefyClientWrapper *BeefyClientWrapperSession) Initialize(data []byte) (*types.Transaction, error) { - return _BeefyClientWrapper.Contract.Initialize(&_BeefyClientWrapper.TransactOpts, data) -} - -// Initialize is a paid mutator transaction binding the contract method 0x439fab91. -// -// Solidity: function initialize(bytes data) returns() -func (_BeefyClientWrapper *BeefyClientWrapperTransactorSession) Initialize(data []byte) (*types.Transaction, error) { - return _BeefyClientWrapper.Contract.Initialize(&_BeefyClientWrapper.TransactOpts, data) -} - -// RemoveRelayer is a paid mutator transaction binding the contract method 0x60f0a5ac. -// -// Solidity: function removeRelayer(address relayer) returns() -func (_BeefyClientWrapper *BeefyClientWrapperTransactor) RemoveRelayer(opts *bind.TransactOpts, relayer common.Address) (*types.Transaction, error) { - return _BeefyClientWrapper.contract.Transact(opts, "removeRelayer", relayer) -} - -// RemoveRelayer is a paid mutator transaction binding the contract method 0x60f0a5ac. -// -// Solidity: function removeRelayer(address relayer) returns() -func (_BeefyClientWrapper *BeefyClientWrapperSession) RemoveRelayer(relayer common.Address) (*types.Transaction, error) { - return _BeefyClientWrapper.Contract.RemoveRelayer(&_BeefyClientWrapper.TransactOpts, relayer) -} - -// RemoveRelayer is a paid mutator transaction binding the contract method 0x60f0a5ac. -// -// Solidity: function removeRelayer(address relayer) returns() -func (_BeefyClientWrapper *BeefyClientWrapperTransactorSession) RemoveRelayer(relayer common.Address) (*types.Transaction, error) { - return _BeefyClientWrapper.Contract.RemoveRelayer(&_BeefyClientWrapper.TransactOpts, relayer) -} - -// SetGracePeriod is a paid mutator transaction binding the contract method 0xf2f65960. -// -// Solidity: function setGracePeriod(uint256 _gracePeriodBlocks) returns() -func (_BeefyClientWrapper *BeefyClientWrapperTransactor) SetGracePeriod(opts *bind.TransactOpts, _gracePeriodBlocks *big.Int) (*types.Transaction, error) { - return _BeefyClientWrapper.contract.Transact(opts, "setGracePeriod", _gracePeriodBlocks) -} - -// SetGracePeriod is a paid mutator transaction binding the contract method 0xf2f65960. -// -// Solidity: function setGracePeriod(uint256 _gracePeriodBlocks) returns() -func (_BeefyClientWrapper *BeefyClientWrapperSession) SetGracePeriod(_gracePeriodBlocks *big.Int) (*types.Transaction, error) { - return _BeefyClientWrapper.Contract.SetGracePeriod(&_BeefyClientWrapper.TransactOpts, _gracePeriodBlocks) -} - -// SetGracePeriod is a paid mutator transaction binding the contract method 0xf2f65960. -// -// Solidity: function setGracePeriod(uint256 _gracePeriodBlocks) returns() -func (_BeefyClientWrapper *BeefyClientWrapperTransactorSession) SetGracePeriod(_gracePeriodBlocks *big.Int) (*types.Transaction, error) { - return _BeefyClientWrapper.Contract.SetGracePeriod(&_BeefyClientWrapper.TransactOpts, _gracePeriodBlocks) -} - // SetMaxGasPrice is a paid mutator transaction binding the contract method 0xd2fa635e. // // Solidity: function setMaxGasPrice(uint256 _maxGasPrice) returns() @@ -1309,46 +770,46 @@ func (_BeefyClientWrapper *BeefyClientWrapperTransactorSession) SetMaxRefundAmou return _BeefyClientWrapper.Contract.SetMaxRefundAmount(&_BeefyClientWrapper.TransactOpts, _maxRefundAmount) } -// SetMinBlockIncrement is a paid mutator transaction binding the contract method 0x3f358a76. +// SetRefundTarget is a paid mutator transaction binding the contract method 0xc15ea4b5. // -// Solidity: function setMinBlockIncrement(uint256 _minBlockIncrement) returns() -func (_BeefyClientWrapper *BeefyClientWrapperTransactor) SetMinBlockIncrement(opts *bind.TransactOpts, _minBlockIncrement *big.Int) (*types.Transaction, error) { - return _BeefyClientWrapper.contract.Transact(opts, "setMinBlockIncrement", _minBlockIncrement) +// Solidity: function setRefundTarget(uint256 _refundTarget) returns() +func (_BeefyClientWrapper *BeefyClientWrapperTransactor) SetRefundTarget(opts *bind.TransactOpts, _refundTarget *big.Int) (*types.Transaction, error) { + return _BeefyClientWrapper.contract.Transact(opts, "setRefundTarget", _refundTarget) } -// SetMinBlockIncrement is a paid mutator transaction binding the contract method 0x3f358a76. +// SetRefundTarget is a paid mutator transaction binding the contract method 0xc15ea4b5. // -// Solidity: function setMinBlockIncrement(uint256 _minBlockIncrement) returns() -func (_BeefyClientWrapper *BeefyClientWrapperSession) SetMinBlockIncrement(_minBlockIncrement *big.Int) (*types.Transaction, error) { - return _BeefyClientWrapper.Contract.SetMinBlockIncrement(&_BeefyClientWrapper.TransactOpts, _minBlockIncrement) +// Solidity: function setRefundTarget(uint256 _refundTarget) returns() +func (_BeefyClientWrapper *BeefyClientWrapperSession) SetRefundTarget(_refundTarget *big.Int) (*types.Transaction, error) { + return _BeefyClientWrapper.Contract.SetRefundTarget(&_BeefyClientWrapper.TransactOpts, _refundTarget) } -// SetMinBlockIncrement is a paid mutator transaction binding the contract method 0x3f358a76. +// SetRefundTarget is a paid mutator transaction binding the contract method 0xc15ea4b5. // -// Solidity: function setMinBlockIncrement(uint256 _minBlockIncrement) returns() -func (_BeefyClientWrapper *BeefyClientWrapperTransactorSession) SetMinBlockIncrement(_minBlockIncrement *big.Int) (*types.Transaction, error) { - return _BeefyClientWrapper.Contract.SetMinBlockIncrement(&_BeefyClientWrapper.TransactOpts, _minBlockIncrement) +// Solidity: function setRefundTarget(uint256 _refundTarget) returns() +func (_BeefyClientWrapper *BeefyClientWrapperTransactorSession) SetRefundTarget(_refundTarget *big.Int) (*types.Transaction, error) { + return _BeefyClientWrapper.Contract.SetRefundTarget(&_BeefyClientWrapper.TransactOpts, _refundTarget) } -// SubmitFinal is a paid mutator transaction binding the contract method 0xfafd0631. +// SubmitFinal is a paid mutator transaction binding the contract method 0x623b223d. // -// Solidity: function submitFinal((uint32,uint64,(bytes2,bytes)[]) commitment, uint256[] bitfield, (uint8,bytes32,bytes32,uint256,address,bytes32[])[] proofs, (uint8,uint32,bytes32,uint64,uint32,bytes32,bytes32) leaf, bytes32[] leafProof, uint256 leafProofOrder, uint32[] claimTipBlocks) returns() -func (_BeefyClientWrapper *BeefyClientWrapperTransactor) SubmitFinal(opts *bind.TransactOpts, commitment IBeefyClientCommitment, bitfield []*big.Int, proofs []IBeefyClientValidatorProof, leaf IBeefyClientMMRLeaf, leafProof [][32]byte, leafProofOrder *big.Int, claimTipBlocks []uint32) (*types.Transaction, error) { - return _BeefyClientWrapper.contract.Transact(opts, "submitFinal", commitment, bitfield, proofs, leaf, leafProof, leafProofOrder, claimTipBlocks) +// Solidity: function submitFinal((uint32,uint64,(bytes2,bytes)[]) commitment, uint256[] bitfield, (uint8,bytes32,bytes32,uint256,address,bytes32[])[] proofs, (uint8,uint32,bytes32,uint64,uint32,bytes32,bytes32) leaf, bytes32[] leafProof, uint256 leafProofOrder) returns() +func (_BeefyClientWrapper *BeefyClientWrapperTransactor) SubmitFinal(opts *bind.TransactOpts, commitment IBeefyClientCommitment, bitfield []*big.Int, proofs []IBeefyClientValidatorProof, leaf IBeefyClientMMRLeaf, leafProof [][32]byte, leafProofOrder *big.Int) (*types.Transaction, error) { + return _BeefyClientWrapper.contract.Transact(opts, "submitFinal", commitment, bitfield, proofs, leaf, leafProof, leafProofOrder) } -// SubmitFinal is a paid mutator transaction binding the contract method 0xfafd0631. +// SubmitFinal is a paid mutator transaction binding the contract method 0x623b223d. // -// Solidity: function submitFinal((uint32,uint64,(bytes2,bytes)[]) commitment, uint256[] bitfield, (uint8,bytes32,bytes32,uint256,address,bytes32[])[] proofs, (uint8,uint32,bytes32,uint64,uint32,bytes32,bytes32) leaf, bytes32[] leafProof, uint256 leafProofOrder, uint32[] claimTipBlocks) returns() -func (_BeefyClientWrapper *BeefyClientWrapperSession) SubmitFinal(commitment IBeefyClientCommitment, bitfield []*big.Int, proofs []IBeefyClientValidatorProof, leaf IBeefyClientMMRLeaf, leafProof [][32]byte, leafProofOrder *big.Int, claimTipBlocks []uint32) (*types.Transaction, error) { - return _BeefyClientWrapper.Contract.SubmitFinal(&_BeefyClientWrapper.TransactOpts, commitment, bitfield, proofs, leaf, leafProof, leafProofOrder, claimTipBlocks) +// Solidity: function submitFinal((uint32,uint64,(bytes2,bytes)[]) commitment, uint256[] bitfield, (uint8,bytes32,bytes32,uint256,address,bytes32[])[] proofs, (uint8,uint32,bytes32,uint64,uint32,bytes32,bytes32) leaf, bytes32[] leafProof, uint256 leafProofOrder) returns() +func (_BeefyClientWrapper *BeefyClientWrapperSession) SubmitFinal(commitment IBeefyClientCommitment, bitfield []*big.Int, proofs []IBeefyClientValidatorProof, leaf IBeefyClientMMRLeaf, leafProof [][32]byte, leafProofOrder *big.Int) (*types.Transaction, error) { + return _BeefyClientWrapper.Contract.SubmitFinal(&_BeefyClientWrapper.TransactOpts, commitment, bitfield, proofs, leaf, leafProof, leafProofOrder) } -// SubmitFinal is a paid mutator transaction binding the contract method 0xfafd0631. +// SubmitFinal is a paid mutator transaction binding the contract method 0x623b223d. // -// Solidity: function submitFinal((uint32,uint64,(bytes2,bytes)[]) commitment, uint256[] bitfield, (uint8,bytes32,bytes32,uint256,address,bytes32[])[] proofs, (uint8,uint32,bytes32,uint64,uint32,bytes32,bytes32) leaf, bytes32[] leafProof, uint256 leafProofOrder, uint32[] claimTipBlocks) returns() -func (_BeefyClientWrapper *BeefyClientWrapperTransactorSession) SubmitFinal(commitment IBeefyClientCommitment, bitfield []*big.Int, proofs []IBeefyClientValidatorProof, leaf IBeefyClientMMRLeaf, leafProof [][32]byte, leafProofOrder *big.Int, claimTipBlocks []uint32) (*types.Transaction, error) { - return _BeefyClientWrapper.Contract.SubmitFinal(&_BeefyClientWrapper.TransactOpts, commitment, bitfield, proofs, leaf, leafProof, leafProofOrder, claimTipBlocks) +// Solidity: function submitFinal((uint32,uint64,(bytes2,bytes)[]) commitment, uint256[] bitfield, (uint8,bytes32,bytes32,uint256,address,bytes32[])[] proofs, (uint8,uint32,bytes32,uint64,uint32,bytes32,bytes32) leaf, bytes32[] leafProof, uint256 leafProofOrder) returns() +func (_BeefyClientWrapper *BeefyClientWrapperTransactorSession) SubmitFinal(commitment IBeefyClientCommitment, bitfield []*big.Int, proofs []IBeefyClientValidatorProof, leaf IBeefyClientMMRLeaf, leafProof [][32]byte, leafProofOrder *big.Int) (*types.Transaction, error) { + return _BeefyClientWrapper.Contract.SubmitFinal(&_BeefyClientWrapper.TransactOpts, commitment, bitfield, proofs, leaf, leafProof, leafProofOrder) } // SubmitInitial is a paid mutator transaction binding the contract method 0xbb51f1eb. @@ -1393,27 +854,6 @@ func (_BeefyClientWrapper *BeefyClientWrapperTransactorSession) TransferOwnershi return _BeefyClientWrapper.Contract.TransferOwnership(&_BeefyClientWrapper.TransactOpts, newOwner) } -// UpgradeTo is a paid mutator transaction binding the contract method 0x50747ac8. -// -// Solidity: function upgradeTo(address newImplementation, bytes32 expectedCodeHash) returns() -func (_BeefyClientWrapper *BeefyClientWrapperTransactor) UpgradeTo(opts *bind.TransactOpts, newImplementation common.Address, expectedCodeHash [32]byte) (*types.Transaction, error) { - return _BeefyClientWrapper.contract.Transact(opts, "upgradeTo", newImplementation, expectedCodeHash) -} - -// UpgradeTo is a paid mutator transaction binding the contract method 0x50747ac8. -// -// Solidity: function upgradeTo(address newImplementation, bytes32 expectedCodeHash) returns() -func (_BeefyClientWrapper *BeefyClientWrapperSession) UpgradeTo(newImplementation common.Address, expectedCodeHash [32]byte) (*types.Transaction, error) { - return _BeefyClientWrapper.Contract.UpgradeTo(&_BeefyClientWrapper.TransactOpts, newImplementation, expectedCodeHash) -} - -// UpgradeTo is a paid mutator transaction binding the contract method 0x50747ac8. -// -// Solidity: function upgradeTo(address newImplementation, bytes32 expectedCodeHash) returns() -func (_BeefyClientWrapper *BeefyClientWrapperTransactorSession) UpgradeTo(newImplementation common.Address, expectedCodeHash [32]byte) (*types.Transaction, error) { - return _BeefyClientWrapper.Contract.UpgradeTo(&_BeefyClientWrapper.TransactOpts, newImplementation, expectedCodeHash) -} - // WithdrawFunds is a paid mutator transaction binding the contract method 0xc1075329. // // Solidity: function withdrawFunds(address recipient, uint256 amount) returns() @@ -1900,153 +1340,9 @@ func (_BeefyClientWrapper *BeefyClientWrapperFilterer) ParseGasCredited(log type return event, nil } -// BeefyClientWrapperRelayerAddedIterator is returned from FilterRelayerAdded and is used to iterate over the raw logs and unpacked data for RelayerAdded events raised by the BeefyClientWrapper contract. -type BeefyClientWrapperRelayerAddedIterator struct { - Event *BeefyClientWrapperRelayerAdded // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration -} - -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *BeefyClientWrapperRelayerAddedIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(BeefyClientWrapperRelayerAdded) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(BeefyClientWrapperRelayerAdded) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -// Error returns any retrieval or parsing error occurred during filtering. -func (it *BeefyClientWrapperRelayerAddedIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *BeefyClientWrapperRelayerAddedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// BeefyClientWrapperRelayerAdded represents a RelayerAdded event raised by the BeefyClientWrapper contract. -type BeefyClientWrapperRelayerAdded struct { - Relayer common.Address - Raw types.Log // Blockchain specific contextual infos -} - -// FilterRelayerAdded is a free log retrieval operation binding the contract event 0x03580ee9f53a62b7cb409a2cb56f9be87747dd15017afc5cef6eef321e4fb2c5. -// -// Solidity: event RelayerAdded(address indexed relayer) -func (_BeefyClientWrapper *BeefyClientWrapperFilterer) FilterRelayerAdded(opts *bind.FilterOpts, relayer []common.Address) (*BeefyClientWrapperRelayerAddedIterator, error) { - - var relayerRule []interface{} - for _, relayerItem := range relayer { - relayerRule = append(relayerRule, relayerItem) - } - - logs, sub, err := _BeefyClientWrapper.contract.FilterLogs(opts, "RelayerAdded", relayerRule) - if err != nil { - return nil, err - } - return &BeefyClientWrapperRelayerAddedIterator{contract: _BeefyClientWrapper.contract, event: "RelayerAdded", logs: logs, sub: sub}, nil -} - -// WatchRelayerAdded is a free log subscription operation binding the contract event 0x03580ee9f53a62b7cb409a2cb56f9be87747dd15017afc5cef6eef321e4fb2c5. -// -// Solidity: event RelayerAdded(address indexed relayer) -func (_BeefyClientWrapper *BeefyClientWrapperFilterer) WatchRelayerAdded(opts *bind.WatchOpts, sink chan<- *BeefyClientWrapperRelayerAdded, relayer []common.Address) (event.Subscription, error) { - - var relayerRule []interface{} - for _, relayerItem := range relayer { - relayerRule = append(relayerRule, relayerItem) - } - - logs, sub, err := _BeefyClientWrapper.contract.WatchLogs(opts, "RelayerAdded", relayerRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(BeefyClientWrapperRelayerAdded) - if err := _BeefyClientWrapper.contract.UnpackLog(event, "RelayerAdded", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -// ParseRelayerAdded is a log parse operation binding the contract event 0x03580ee9f53a62b7cb409a2cb56f9be87747dd15017afc5cef6eef321e4fb2c5. -// -// Solidity: event RelayerAdded(address indexed relayer) -func (_BeefyClientWrapper *BeefyClientWrapperFilterer) ParseRelayerAdded(log types.Log) (*BeefyClientWrapperRelayerAdded, error) { - event := new(BeefyClientWrapperRelayerAdded) - if err := _BeefyClientWrapper.contract.UnpackLog(event, "RelayerAdded", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -// BeefyClientWrapperRelayerRemovedIterator is returned from FilterRelayerRemoved and is used to iterate over the raw logs and unpacked data for RelayerRemoved events raised by the BeefyClientWrapper contract. -type BeefyClientWrapperRelayerRemovedIterator struct { - Event *BeefyClientWrapperRelayerRemoved // Event containing the contract specifics and raw log +// BeefyClientWrapperSubmissionRefundedIterator is returned from FilterSubmissionRefunded and is used to iterate over the raw logs and unpacked data for SubmissionRefunded events raised by the BeefyClientWrapper contract. +type BeefyClientWrapperSubmissionRefundedIterator struct { + Event *BeefyClientWrapperSubmissionRefunded // Event containing the contract specifics and raw log contract *bind.BoundContract // Generic contract to use for unpacking event data event string // Event name to use for unpacking event data @@ -2060,7 +1356,7 @@ type BeefyClientWrapperRelayerRemovedIterator struct { // Next advances the iterator to the subsequent event, returning whether there // are any more events found. In case of a retrieval or parsing error, false is // returned and Error() can be queried for the exact failure. -func (it *BeefyClientWrapperRelayerRemovedIterator) Next() bool { +func (it *BeefyClientWrapperSubmissionRefundedIterator) Next() bool { // If the iterator failed, stop iterating if it.fail != nil { return false @@ -2069,7 +1365,7 @@ func (it *BeefyClientWrapperRelayerRemovedIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(BeefyClientWrapperRelayerRemoved) + it.Event = new(BeefyClientWrapperSubmissionRefunded) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -2084,7 +1380,7 @@ func (it *BeefyClientWrapperRelayerRemovedIterator) Next() bool { // Iterator still in progress, wait for either a data or an error event select { case log := <-it.logs: - it.Event = new(BeefyClientWrapperRelayerRemoved) + it.Event = new(BeefyClientWrapperSubmissionRefunded) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -2100,51 +1396,54 @@ func (it *BeefyClientWrapperRelayerRemovedIterator) Next() bool { } // Error returns any retrieval or parsing error occurred during filtering. -func (it *BeefyClientWrapperRelayerRemovedIterator) Error() error { +func (it *BeefyClientWrapperSubmissionRefundedIterator) Error() error { return it.fail } // Close terminates the iteration process, releasing any pending underlying // resources. -func (it *BeefyClientWrapperRelayerRemovedIterator) Close() error { +func (it *BeefyClientWrapperSubmissionRefundedIterator) Close() error { it.sub.Unsubscribe() return nil } -// BeefyClientWrapperRelayerRemoved represents a RelayerRemoved event raised by the BeefyClientWrapper contract. -type BeefyClientWrapperRelayerRemoved struct { - Relayer common.Address - Raw types.Log // Blockchain specific contextual infos +// BeefyClientWrapperSubmissionRefunded represents a SubmissionRefunded event raised by the BeefyClientWrapper contract. +type BeefyClientWrapperSubmissionRefunded struct { + Relayer common.Address + Progress *big.Int + RefundAmount *big.Int + TotalGasUsed *big.Int + Raw types.Log // Blockchain specific contextual infos } -// FilterRelayerRemoved is a free log retrieval operation binding the contract event 0x10e1f7ce9fd7d1b90a66d13a2ab3cb8dd7f29f3f8d520b143b063ccfbab6906b. +// FilterSubmissionRefunded is a free log retrieval operation binding the contract event 0x9e15c83bdb5f5cd34d28652d4d4f05f485bcbc3f54404fd5b830fc9aad6dfd1c. // -// Solidity: event RelayerRemoved(address indexed relayer) -func (_BeefyClientWrapper *BeefyClientWrapperFilterer) FilterRelayerRemoved(opts *bind.FilterOpts, relayer []common.Address) (*BeefyClientWrapperRelayerRemovedIterator, error) { +// Solidity: event SubmissionRefunded(address indexed relayer, uint256 progress, uint256 refundAmount, uint256 totalGasUsed) +func (_BeefyClientWrapper *BeefyClientWrapperFilterer) FilterSubmissionRefunded(opts *bind.FilterOpts, relayer []common.Address) (*BeefyClientWrapperSubmissionRefundedIterator, error) { var relayerRule []interface{} for _, relayerItem := range relayer { relayerRule = append(relayerRule, relayerItem) } - logs, sub, err := _BeefyClientWrapper.contract.FilterLogs(opts, "RelayerRemoved", relayerRule) + logs, sub, err := _BeefyClientWrapper.contract.FilterLogs(opts, "SubmissionRefunded", relayerRule) if err != nil { return nil, err } - return &BeefyClientWrapperRelayerRemovedIterator{contract: _BeefyClientWrapper.contract, event: "RelayerRemoved", logs: logs, sub: sub}, nil + return &BeefyClientWrapperSubmissionRefundedIterator{contract: _BeefyClientWrapper.contract, event: "SubmissionRefunded", logs: logs, sub: sub}, nil } -// WatchRelayerRemoved is a free log subscription operation binding the contract event 0x10e1f7ce9fd7d1b90a66d13a2ab3cb8dd7f29f3f8d520b143b063ccfbab6906b. +// WatchSubmissionRefunded is a free log subscription operation binding the contract event 0x9e15c83bdb5f5cd34d28652d4d4f05f485bcbc3f54404fd5b830fc9aad6dfd1c. // -// Solidity: event RelayerRemoved(address indexed relayer) -func (_BeefyClientWrapper *BeefyClientWrapperFilterer) WatchRelayerRemoved(opts *bind.WatchOpts, sink chan<- *BeefyClientWrapperRelayerRemoved, relayer []common.Address) (event.Subscription, error) { +// Solidity: event SubmissionRefunded(address indexed relayer, uint256 progress, uint256 refundAmount, uint256 totalGasUsed) +func (_BeefyClientWrapper *BeefyClientWrapperFilterer) WatchSubmissionRefunded(opts *bind.WatchOpts, sink chan<- *BeefyClientWrapperSubmissionRefunded, relayer []common.Address) (event.Subscription, error) { var relayerRule []interface{} for _, relayerItem := range relayer { relayerRule = append(relayerRule, relayerItem) } - logs, sub, err := _BeefyClientWrapper.contract.WatchLogs(opts, "RelayerRemoved", relayerRule) + logs, sub, err := _BeefyClientWrapper.contract.WatchLogs(opts, "SubmissionRefunded", relayerRule) if err != nil { return nil, err } @@ -2154,8 +1453,8 @@ func (_BeefyClientWrapper *BeefyClientWrapperFilterer) WatchRelayerRemoved(opts select { case log := <-logs: // New log arrived, parse the event and forward to the user - event := new(BeefyClientWrapperRelayerRemoved) - if err := _BeefyClientWrapper.contract.UnpackLog(event, "RelayerRemoved", log); err != nil { + event := new(BeefyClientWrapperSubmissionRefunded) + if err := _BeefyClientWrapper.contract.UnpackLog(event, "SubmissionRefunded", log); err != nil { return err } event.Raw = log @@ -2176,155 +1475,9 @@ func (_BeefyClientWrapper *BeefyClientWrapperFilterer) WatchRelayerRemoved(opts }), nil } -// ParseRelayerRemoved is a log parse operation binding the contract event 0x10e1f7ce9fd7d1b90a66d13a2ab3cb8dd7f29f3f8d520b143b063ccfbab6906b. +// ParseSubmissionRefunded is a log parse operation binding the contract event 0x9e15c83bdb5f5cd34d28652d4d4f05f485bcbc3f54404fd5b830fc9aad6dfd1c. // -// Solidity: event RelayerRemoved(address indexed relayer) -func (_BeefyClientWrapper *BeefyClientWrapperFilterer) ParseRelayerRemoved(log types.Log) (*BeefyClientWrapperRelayerRemoved, error) { - event := new(BeefyClientWrapperRelayerRemoved) - if err := _BeefyClientWrapper.contract.UnpackLog(event, "RelayerRemoved", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -// BeefyClientWrapperSubmissionRefundedIterator is returned from FilterSubmissionRefunded and is used to iterate over the raw logs and unpacked data for SubmissionRefunded events raised by the BeefyClientWrapper contract. -type BeefyClientWrapperSubmissionRefundedIterator struct { - Event *BeefyClientWrapperSubmissionRefunded // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration -} - -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *BeefyClientWrapperSubmissionRefundedIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(BeefyClientWrapperSubmissionRefunded) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(BeefyClientWrapperSubmissionRefunded) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -// Error returns any retrieval or parsing error occurred during filtering. -func (it *BeefyClientWrapperSubmissionRefundedIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *BeefyClientWrapperSubmissionRefundedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// BeefyClientWrapperSubmissionRefunded represents a SubmissionRefunded event raised by the BeefyClientWrapper contract. -type BeefyClientWrapperSubmissionRefunded struct { - Relayer common.Address - Amount *big.Int - TotalGasUsed *big.Int - Raw types.Log // Blockchain specific contextual infos -} - -// FilterSubmissionRefunded is a free log retrieval operation binding the contract event 0x103cb711554967fbeea0c6394a6dfedc44d0e729191e719d0976438783912f52. -// -// Solidity: event SubmissionRefunded(address indexed relayer, uint256 amount, uint256 totalGasUsed) -func (_BeefyClientWrapper *BeefyClientWrapperFilterer) FilterSubmissionRefunded(opts *bind.FilterOpts, relayer []common.Address) (*BeefyClientWrapperSubmissionRefundedIterator, error) { - - var relayerRule []interface{} - for _, relayerItem := range relayer { - relayerRule = append(relayerRule, relayerItem) - } - - logs, sub, err := _BeefyClientWrapper.contract.FilterLogs(opts, "SubmissionRefunded", relayerRule) - if err != nil { - return nil, err - } - return &BeefyClientWrapperSubmissionRefundedIterator{contract: _BeefyClientWrapper.contract, event: "SubmissionRefunded", logs: logs, sub: sub}, nil -} - -// WatchSubmissionRefunded is a free log subscription operation binding the contract event 0x103cb711554967fbeea0c6394a6dfedc44d0e729191e719d0976438783912f52. -// -// Solidity: event SubmissionRefunded(address indexed relayer, uint256 amount, uint256 totalGasUsed) -func (_BeefyClientWrapper *BeefyClientWrapperFilterer) WatchSubmissionRefunded(opts *bind.WatchOpts, sink chan<- *BeefyClientWrapperSubmissionRefunded, relayer []common.Address) (event.Subscription, error) { - - var relayerRule []interface{} - for _, relayerItem := range relayer { - relayerRule = append(relayerRule, relayerItem) - } - - logs, sub, err := _BeefyClientWrapper.contract.WatchLogs(opts, "SubmissionRefunded", relayerRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(BeefyClientWrapperSubmissionRefunded) - if err := _BeefyClientWrapper.contract.UnpackLog(event, "SubmissionRefunded", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -// ParseSubmissionRefunded is a log parse operation binding the contract event 0x103cb711554967fbeea0c6394a6dfedc44d0e729191e719d0976438783912f52. -// -// Solidity: event SubmissionRefunded(address indexed relayer, uint256 amount, uint256 totalGasUsed) +// Solidity: event SubmissionRefunded(address indexed relayer, uint256 progress, uint256 refundAmount, uint256 totalGasUsed) func (_BeefyClientWrapper *BeefyClientWrapperFilterer) ParseSubmissionRefunded(log types.Log) (*BeefyClientWrapperSubmissionRefunded, error) { event := new(BeefyClientWrapperSubmissionRefunded) if err := _BeefyClientWrapper.contract.UnpackLog(event, "SubmissionRefunded", log); err != nil { @@ -2333,599 +1486,3 @@ func (_BeefyClientWrapper *BeefyClientWrapperFilterer) ParseSubmissionRefunded(l event.Raw = log return event, nil } - -// BeefyClientWrapperTipAddedIterator is returned from FilterTipAdded and is used to iterate over the raw logs and unpacked data for TipAdded events raised by the BeefyClientWrapper contract. -type BeefyClientWrapperTipAddedIterator struct { - Event *BeefyClientWrapperTipAdded // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration -} - -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *BeefyClientWrapperTipAddedIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(BeefyClientWrapperTipAdded) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(BeefyClientWrapperTipAdded) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -// Error returns any retrieval or parsing error occurred during filtering. -func (it *BeefyClientWrapperTipAddedIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *BeefyClientWrapperTipAddedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// BeefyClientWrapperTipAdded represents a TipAdded event raised by the BeefyClientWrapper contract. -type BeefyClientWrapperTipAdded struct { - Tipper common.Address - BeefyBlockNumber uint32 - Amount *big.Int - Raw types.Log // Blockchain specific contextual infos -} - -// FilterTipAdded is a free log retrieval operation binding the contract event 0x534f476b78e1964cad3783848d29e18156e2e9a2a3cfe8f93735b141d8c1285a. -// -// Solidity: event TipAdded(address indexed tipper, uint32 indexed beefyBlockNumber, uint256 amount) -func (_BeefyClientWrapper *BeefyClientWrapperFilterer) FilterTipAdded(opts *bind.FilterOpts, tipper []common.Address, beefyBlockNumber []uint32) (*BeefyClientWrapperTipAddedIterator, error) { - - var tipperRule []interface{} - for _, tipperItem := range tipper { - tipperRule = append(tipperRule, tipperItem) - } - var beefyBlockNumberRule []interface{} - for _, beefyBlockNumberItem := range beefyBlockNumber { - beefyBlockNumberRule = append(beefyBlockNumberRule, beefyBlockNumberItem) - } - - logs, sub, err := _BeefyClientWrapper.contract.FilterLogs(opts, "TipAdded", tipperRule, beefyBlockNumberRule) - if err != nil { - return nil, err - } - return &BeefyClientWrapperTipAddedIterator{contract: _BeefyClientWrapper.contract, event: "TipAdded", logs: logs, sub: sub}, nil -} - -// WatchTipAdded is a free log subscription operation binding the contract event 0x534f476b78e1964cad3783848d29e18156e2e9a2a3cfe8f93735b141d8c1285a. -// -// Solidity: event TipAdded(address indexed tipper, uint32 indexed beefyBlockNumber, uint256 amount) -func (_BeefyClientWrapper *BeefyClientWrapperFilterer) WatchTipAdded(opts *bind.WatchOpts, sink chan<- *BeefyClientWrapperTipAdded, tipper []common.Address, beefyBlockNumber []uint32) (event.Subscription, error) { - - var tipperRule []interface{} - for _, tipperItem := range tipper { - tipperRule = append(tipperRule, tipperItem) - } - var beefyBlockNumberRule []interface{} - for _, beefyBlockNumberItem := range beefyBlockNumber { - beefyBlockNumberRule = append(beefyBlockNumberRule, beefyBlockNumberItem) - } - - logs, sub, err := _BeefyClientWrapper.contract.WatchLogs(opts, "TipAdded", tipperRule, beefyBlockNumberRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(BeefyClientWrapperTipAdded) - if err := _BeefyClientWrapper.contract.UnpackLog(event, "TipAdded", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -// ParseTipAdded is a log parse operation binding the contract event 0x534f476b78e1964cad3783848d29e18156e2e9a2a3cfe8f93735b141d8c1285a. -// -// Solidity: event TipAdded(address indexed tipper, uint32 indexed beefyBlockNumber, uint256 amount) -func (_BeefyClientWrapper *BeefyClientWrapperFilterer) ParseTipAdded(log types.Log) (*BeefyClientWrapperTipAdded, error) { - event := new(BeefyClientWrapperTipAdded) - if err := _BeefyClientWrapper.contract.UnpackLog(event, "TipAdded", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -// BeefyClientWrapperTipsClaimedIterator is returned from FilterTipsClaimed and is used to iterate over the raw logs and unpacked data for TipsClaimed events raised by the BeefyClientWrapper contract. -type BeefyClientWrapperTipsClaimedIterator struct { - Event *BeefyClientWrapperTipsClaimed // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration -} - -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *BeefyClientWrapperTipsClaimedIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(BeefyClientWrapperTipsClaimed) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(BeefyClientWrapperTipsClaimed) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -// Error returns any retrieval or parsing error occurred during filtering. -func (it *BeefyClientWrapperTipsClaimedIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *BeefyClientWrapperTipsClaimedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// BeefyClientWrapperTipsClaimed represents a TipsClaimed event raised by the BeefyClientWrapper contract. -type BeefyClientWrapperTipsClaimed struct { - Relayer common.Address - TotalAmount *big.Int - Raw types.Log // Blockchain specific contextual infos -} - -// FilterTipsClaimed is a free log retrieval operation binding the contract event 0xf5e7a62133aaed5c8783583a823343c7c0c0f51f0e2e8c76ec50feffc002b1f3. -// -// Solidity: event TipsClaimed(address indexed relayer, uint256 totalAmount) -func (_BeefyClientWrapper *BeefyClientWrapperFilterer) FilterTipsClaimed(opts *bind.FilterOpts, relayer []common.Address) (*BeefyClientWrapperTipsClaimedIterator, error) { - - var relayerRule []interface{} - for _, relayerItem := range relayer { - relayerRule = append(relayerRule, relayerItem) - } - - logs, sub, err := _BeefyClientWrapper.contract.FilterLogs(opts, "TipsClaimed", relayerRule) - if err != nil { - return nil, err - } - return &BeefyClientWrapperTipsClaimedIterator{contract: _BeefyClientWrapper.contract, event: "TipsClaimed", logs: logs, sub: sub}, nil -} - -// WatchTipsClaimed is a free log subscription operation binding the contract event 0xf5e7a62133aaed5c8783583a823343c7c0c0f51f0e2e8c76ec50feffc002b1f3. -// -// Solidity: event TipsClaimed(address indexed relayer, uint256 totalAmount) -func (_BeefyClientWrapper *BeefyClientWrapperFilterer) WatchTipsClaimed(opts *bind.WatchOpts, sink chan<- *BeefyClientWrapperTipsClaimed, relayer []common.Address) (event.Subscription, error) { - - var relayerRule []interface{} - for _, relayerItem := range relayer { - relayerRule = append(relayerRule, relayerItem) - } - - logs, sub, err := _BeefyClientWrapper.contract.WatchLogs(opts, "TipsClaimed", relayerRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(BeefyClientWrapperTipsClaimed) - if err := _BeefyClientWrapper.contract.UnpackLog(event, "TipsClaimed", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -// ParseTipsClaimed is a log parse operation binding the contract event 0xf5e7a62133aaed5c8783583a823343c7c0c0f51f0e2e8c76ec50feffc002b1f3. -// -// Solidity: event TipsClaimed(address indexed relayer, uint256 totalAmount) -func (_BeefyClientWrapper *BeefyClientWrapperFilterer) ParseTipsClaimed(log types.Log) (*BeefyClientWrapperTipsClaimed, error) { - event := new(BeefyClientWrapperTipsClaimed) - if err := _BeefyClientWrapper.contract.UnpackLog(event, "TipsClaimed", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -// BeefyClientWrapperTurnAdvancedIterator is returned from FilterTurnAdvanced and is used to iterate over the raw logs and unpacked data for TurnAdvanced events raised by the BeefyClientWrapper contract. -type BeefyClientWrapperTurnAdvancedIterator struct { - Event *BeefyClientWrapperTurnAdvanced // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration -} - -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *BeefyClientWrapperTurnAdvancedIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(BeefyClientWrapperTurnAdvanced) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(BeefyClientWrapperTurnAdvanced) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -// Error returns any retrieval or parsing error occurred during filtering. -func (it *BeefyClientWrapperTurnAdvancedIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *BeefyClientWrapperTurnAdvancedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// BeefyClientWrapperTurnAdvanced represents a TurnAdvanced event raised by the BeefyClientWrapper contract. -type BeefyClientWrapperTurnAdvanced struct { - NewTurnIndex *big.Int - NextRelayer common.Address - Raw types.Log // Blockchain specific contextual infos -} - -// FilterTurnAdvanced is a free log retrieval operation binding the contract event 0xa1fbd218639d21bc371d11c5d99434f6b493f6b7c3740271906c91b62a215434. -// -// Solidity: event TurnAdvanced(uint256 indexed newTurnIndex, address indexed nextRelayer) -func (_BeefyClientWrapper *BeefyClientWrapperFilterer) FilterTurnAdvanced(opts *bind.FilterOpts, newTurnIndex []*big.Int, nextRelayer []common.Address) (*BeefyClientWrapperTurnAdvancedIterator, error) { - - var newTurnIndexRule []interface{} - for _, newTurnIndexItem := range newTurnIndex { - newTurnIndexRule = append(newTurnIndexRule, newTurnIndexItem) - } - var nextRelayerRule []interface{} - for _, nextRelayerItem := range nextRelayer { - nextRelayerRule = append(nextRelayerRule, nextRelayerItem) - } - - logs, sub, err := _BeefyClientWrapper.contract.FilterLogs(opts, "TurnAdvanced", newTurnIndexRule, nextRelayerRule) - if err != nil { - return nil, err - } - return &BeefyClientWrapperTurnAdvancedIterator{contract: _BeefyClientWrapper.contract, event: "TurnAdvanced", logs: logs, sub: sub}, nil -} - -// WatchTurnAdvanced is a free log subscription operation binding the contract event 0xa1fbd218639d21bc371d11c5d99434f6b493f6b7c3740271906c91b62a215434. -// -// Solidity: event TurnAdvanced(uint256 indexed newTurnIndex, address indexed nextRelayer) -func (_BeefyClientWrapper *BeefyClientWrapperFilterer) WatchTurnAdvanced(opts *bind.WatchOpts, sink chan<- *BeefyClientWrapperTurnAdvanced, newTurnIndex []*big.Int, nextRelayer []common.Address) (event.Subscription, error) { - - var newTurnIndexRule []interface{} - for _, newTurnIndexItem := range newTurnIndex { - newTurnIndexRule = append(newTurnIndexRule, newTurnIndexItem) - } - var nextRelayerRule []interface{} - for _, nextRelayerItem := range nextRelayer { - nextRelayerRule = append(nextRelayerRule, nextRelayerItem) - } - - logs, sub, err := _BeefyClientWrapper.contract.WatchLogs(opts, "TurnAdvanced", newTurnIndexRule, nextRelayerRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(BeefyClientWrapperTurnAdvanced) - if err := _BeefyClientWrapper.contract.UnpackLog(event, "TurnAdvanced", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -// ParseTurnAdvanced is a log parse operation binding the contract event 0xa1fbd218639d21bc371d11c5d99434f6b493f6b7c3740271906c91b62a215434. -// -// Solidity: event TurnAdvanced(uint256 indexed newTurnIndex, address indexed nextRelayer) -func (_BeefyClientWrapper *BeefyClientWrapperFilterer) ParseTurnAdvanced(log types.Log) (*BeefyClientWrapperTurnAdvanced, error) { - event := new(BeefyClientWrapperTurnAdvanced) - if err := _BeefyClientWrapper.contract.UnpackLog(event, "TurnAdvanced", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -// BeefyClientWrapperUpgradedIterator is returned from FilterUpgraded and is used to iterate over the raw logs and unpacked data for Upgraded events raised by the BeefyClientWrapper contract. -type BeefyClientWrapperUpgradedIterator struct { - Event *BeefyClientWrapperUpgraded // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration -} - -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *BeefyClientWrapperUpgradedIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(BeefyClientWrapperUpgraded) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(BeefyClientWrapperUpgraded) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -// Error returns any retrieval or parsing error occurred during filtering. -func (it *BeefyClientWrapperUpgradedIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *BeefyClientWrapperUpgradedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// BeefyClientWrapperUpgraded represents a Upgraded event raised by the BeefyClientWrapper contract. -type BeefyClientWrapperUpgraded struct { - Implementation common.Address - Raw types.Log // Blockchain specific contextual infos -} - -// FilterUpgraded is a free log retrieval operation binding the contract event 0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b. -// -// Solidity: event Upgraded(address indexed implementation) -func (_BeefyClientWrapper *BeefyClientWrapperFilterer) FilterUpgraded(opts *bind.FilterOpts, implementation []common.Address) (*BeefyClientWrapperUpgradedIterator, error) { - - var implementationRule []interface{} - for _, implementationItem := range implementation { - implementationRule = append(implementationRule, implementationItem) - } - - logs, sub, err := _BeefyClientWrapper.contract.FilterLogs(opts, "Upgraded", implementationRule) - if err != nil { - return nil, err - } - return &BeefyClientWrapperUpgradedIterator{contract: _BeefyClientWrapper.contract, event: "Upgraded", logs: logs, sub: sub}, nil -} - -// WatchUpgraded is a free log subscription operation binding the contract event 0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b. -// -// Solidity: event Upgraded(address indexed implementation) -func (_BeefyClientWrapper *BeefyClientWrapperFilterer) WatchUpgraded(opts *bind.WatchOpts, sink chan<- *BeefyClientWrapperUpgraded, implementation []common.Address) (event.Subscription, error) { - - var implementationRule []interface{} - for _, implementationItem := range implementation { - implementationRule = append(implementationRule, implementationItem) - } - - logs, sub, err := _BeefyClientWrapper.contract.WatchLogs(opts, "Upgraded", implementationRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(BeefyClientWrapperUpgraded) - if err := _BeefyClientWrapper.contract.UnpackLog(event, "Upgraded", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -// ParseUpgraded is a log parse operation binding the contract event 0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b. -// -// Solidity: event Upgraded(address indexed implementation) -func (_BeefyClientWrapper *BeefyClientWrapperFilterer) ParseUpgraded(log types.Log) (*BeefyClientWrapperUpgraded, error) { - event := new(BeefyClientWrapperUpgraded) - if err := _BeefyClientWrapper.contract.UnpackLog(event, "Upgraded", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} diff --git a/relayer/relays/beefy/config.go b/relayer/relays/beefy/config.go index 1018826a8..d8a0686c0 100644 --- a/relayer/relays/beefy/config.go +++ b/relayer/relays/beefy/config.go @@ -18,9 +18,8 @@ type SourceConfig struct { } type SinkConfig struct { - Ethereum config.EthereumConfig `mapstructure:"ethereum"` - Contracts ContractsConfig `mapstructure:"contracts"` - EnableFiatShamir bool `mapstructure:"enable-fiat-shamir"` + Ethereum config.EthereumConfig `mapstructure:"ethereum"` + Contracts ContractsConfig `mapstructure:"contracts"` } type ContractsConfig struct { diff --git a/relayer/relays/beefy/ethereum-writer.go b/relayer/relays/beefy/ethereum-writer.go index cb364124a..eafc5fd3b 100644 --- a/relayer/relays/beefy/ethereum-writer.go +++ b/relayer/relays/beefy/ethereum-writer.go @@ -6,7 +6,6 @@ import ( "fmt" "math/big" "math/rand" - "time" "golang.org/x/sync/errgroup" @@ -65,21 +64,11 @@ func (wr *EthereumWriter) Start(ctx context.Context, eg *errgroup.Group, request continue } - // Wait until we're eligible to submit (turn-based scheduling) - err = wr.waitForTurnEligibility(ctx) - if err != nil { - return fmt.Errorf("wait for turn eligibility: %w", err) - } - // Mandatory commitments are always signed by the next validator set recorded in // the beefy light client task.ValidatorsRoot = state.NextValidatorSetRoot - if wr.config.EnableFiatShamir { - err = wr.submitFiatShamir(ctx, &task) - } else { - err = wr.submit(ctx, &task) - } + err = wr.submit(ctx, &task) if err != nil { return fmt.Errorf("submit request: %w", err) } @@ -319,7 +308,6 @@ func (wr *EthereumWriter) doSubmitFinal(ctx context.Context, commitmentHash [32] params.Leaf, params.LeafProof, params.LeafProofOrder, - []uint32{}, // claimTipBlocks - empty for now, can be populated to claim tips ) if err != nil { return nil, fmt.Errorf("final submission: %w", err) @@ -332,70 +320,6 @@ func (wr *EthereumWriter) doSubmitFinal(ctx context.Context, commitmentHash [32] return tx, nil } -func (wr *EthereumWriter) waitForTurnEligibility(ctx context.Context) error { - for { - eligible, err := wr.checkTurnEligibility(ctx) - if err != nil { - return err - } - if eligible { - return nil - } - - // Wait before checking again - log.Debug("Not eligible yet, waiting 12 seconds before rechecking...") - select { - case <-ctx.Done(): - return ctx.Err() - case <-time.After(12 * time.Second): - // Check again - } - } -} - -func (wr *EthereumWriter) checkTurnEligibility(ctx context.Context) (bool, error) { - callOpts := bind.CallOpts{ - Context: ctx, - } - - myAddress := wr.conn.Keypair().CommonAddress() - - currentTurnRelayer, err := wr.contract.GetCurrentTurnRelayer(&callOpts) - if err != nil { - return false, fmt.Errorf("get current turn relayer: %w", err) - } - - if currentTurnRelayer == myAddress { - log.WithFields(logrus.Fields{ - "currentTurnRelayer": currentTurnRelayer.Hex(), - "myAddress": myAddress.Hex(), - }).Debug("It's our turn to submit") - return true, nil - } - - gracePeriodActive, err := wr.contract.IsGracePeriodActive(&callOpts) - if err != nil { - return false, fmt.Errorf("check grace period: %w", err) - } - - if gracePeriodActive { - log.WithFields(logrus.Fields{ - "currentTurnRelayer": currentTurnRelayer.Hex(), - "myAddress": myAddress.Hex(), - "gracePeriodActive": true, - }).Debug("Not our turn, but grace period is active - proceeding") - return true, nil - } - - log.WithFields(logrus.Fields{ - "currentTurnRelayer": currentTurnRelayer.Hex(), - "myAddress": myAddress.Hex(), - "gracePeriodActive": false, - }).Info("Not our turn and grace period not active - waiting") - - return false, nil -} - func (wr *EthereumWriter) initialize(ctx context.Context) error { address := common.HexToAddress(wr.config.Contracts.BeefyClient) @@ -418,93 +342,6 @@ func (wr *EthereumWriter) initialize(ctx context.Context) error { return nil } -func (wr *EthereumWriter) submitFiatShamir(ctx context.Context, task *Request) error { - signedValidators := []*big.Int{} - for i, signature := range task.SignedCommitment.Signatures { - if signature.IsSome() { - signedValidators = append(signedValidators, big.NewInt(int64(i))) - } - } - validatorCount := big.NewInt(int64(len(task.SignedCommitment.Signatures))) - - // Pick a random validator who signs beefy commitment - chosenValidator := signedValidators[rand.Intn(len(signedValidators))].Int64() - - log.WithFields(logrus.Fields{ - "validatorCount": validatorCount, - "signedValidators": signedValidators, - "signedValidatorCount": len(signedValidators), - "chosenValidator": chosenValidator, - }).Info("Creating initial bitfield") - - initialBitfield, err := wr.contract.CreateInitialBitfield( - &bind.CallOpts{ - Pending: true, - From: wr.conn.Keypair().CommonAddress(), - }, - signedValidators, validatorCount, - ) - if err != nil { - return fmt.Errorf("create initial bitfield: %w", err) - } - - commitment := toBeefyClientCommitment(&task.SignedCommitment.Commitment) - - finalBitfield, err := wr.contract.CreateFiatShamirFinalBitfield( - &bind.CallOpts{ - Pending: true, - From: wr.conn.Keypair().CommonAddress(), - }, - *commitment, - initialBitfield, - ) - - if err != nil { - return fmt.Errorf("create validator final bitfield: %w", err) - } - - validatorIndices := bitfield.New(finalBitfield).Members() - - params, err := task.MakeSubmitFinalParams(validatorIndices, initialBitfield) - if err != nil { - return fmt.Errorf("make submit final params: %w", err) - } - - logFields, err := wr.makeSubmitFinalLogFields(task, params) - if err != nil { - return fmt.Errorf("logging params: %w", err) - } - - tx, err := wr.contract.SubmitFiatShamir( - wr.conn.MakeTxOpts(ctx), - params.Commitment, - params.Bitfield, - params.Proofs, - params.Leaf, - params.LeafProof, - params.LeafProofOrder, - ) - if err != nil { - return fmt.Errorf("SubmitFiatShamir: %w", err) - } - - log.WithField("txHash", tx.Hash().Hex()). - WithFields(logFields). - Info("Sent SubmitFiatShamir transaction") - - _, err = wr.conn.WatchTransaction(ctx, tx, 0) - if err != nil { - return fmt.Errorf("Wait receipt for SubmitFiatShamir: %w", err) - } - - log.WithFields(logrus.Fields{ - "tx": tx.Hash().Hex(), - "blockNumber": task.SignedCommitment.Commitment.BlockNumber, - }).Debug("Transaction submitFiatShamir succeeded") - - return nil -} - func (wr *EthereumWriter) isTaskOutdated(ctx context.Context, task *Request) (bool, error) { state, err := wr.queryBeefyClientState(ctx) if err != nil { diff --git a/relayer/relays/beefy/on-demand-sync.go b/relayer/relays/beefy/on-demand-sync.go index 83c35fce7..b925d978e 100644 --- a/relayer/relays/beefy/on-demand-sync.go +++ b/relayer/relays/beefy/on-demand-sync.go @@ -260,11 +260,7 @@ func (relay *OnDemandRelay) syncBeefyUpdate(ctx context.Context, task *Request) } else { task.ValidatorsRoot = state.NextValidatorSetRoot } - if relay.ethereumWriter.config.EnableFiatShamir { - err = relay.ethereumWriter.submitFiatShamir(ctx, task) - } else { - err = relay.ethereumWriter.submit(ctx, task) - } + err = relay.ethereumWriter.submit(ctx, task) if err != nil { return fmt.Errorf("fail to submit beefy update: %w", err) } From 7c94d0982edaae090a845c97595bbdc785cbb3df Mon Sep 17 00:00:00 2001 From: claravanstaden Date: Wed, 4 Feb 2026 16:03:20 +0200 Subject: [PATCH 09/17] cleanup --- .../scripts/DeployBeefyClientWrapper.sol | 2 +- contracts/src/BeefyClient.sol | 8 ++ contracts/src/BeefyClientWrapper.sol | 80 +++++++++---------- contracts/src/interfaces/IBeefyClient.sol | 2 + contracts/test/BeefyClientWrapper.t.sol | 39 +++++---- relayer/contracts/beefy_client.go | 33 +++++++- relayer/contracts/beefy_client_wrapper.go | 64 ++++++++++++++- relayer/relays/beefy/ethereum-writer.go | 75 +++++++++++++++++ 8 files changed, 236 insertions(+), 67 deletions(-) diff --git a/contracts/scripts/DeployBeefyClientWrapper.sol b/contracts/scripts/DeployBeefyClientWrapper.sol index 5e3bb549b..e9546cda3 100644 --- a/contracts/scripts/DeployBeefyClientWrapper.sol +++ b/contracts/scripts/DeployBeefyClientWrapper.sol @@ -21,7 +21,7 @@ contract DeployBeefyClientWrapper is Script { owner: vm.envAddress("REFUND_PROXY_OWNER"), maxGasPrice: vm.envOr("MAX_GAS_PRICE", uint256(100 gwei)), maxRefundAmount: vm.envOr("MAX_REFUND_AMOUNT", uint256(0.05 ether)), - refundTarget: vm.envOr("REFUND_TARGET", uint256(300)) // ~30 min for 100% refund + refundTarget: vm.envOr("REFUND_TARGET", uint256(350)) // ~35 min for 100% refund }); } diff --git a/contracts/src/BeefyClient.sol b/contracts/src/BeefyClient.sol index 4f28c85a0..1843c97fe 100644 --- a/contracts/src/BeefyClient.sol +++ b/contracts/src/BeefyClient.sol @@ -465,6 +465,14 @@ contract BeefyClient { return Bitfield.createBitfield(bitsToSet, length); } + /** + * @dev Compute the hash of a commitment + * @param commitment the commitment to hash + */ + function computeCommitmentHash(Commitment calldata commitment) external pure returns (bytes32) { + return keccak256(encodeCommitment(commitment)); + } + /** * @dev Helper to create a final bitfield, with subsampled validator selections * @param commitmentHash contains the commitmentHash signed by the validators diff --git a/contracts/src/BeefyClientWrapper.sol b/contracts/src/BeefyClientWrapper.sol index 34df42f80..fa48360a3 100644 --- a/contracts/src/BeefyClientWrapper.sol +++ b/contracts/src/BeefyClientWrapper.sol @@ -3,7 +3,6 @@ pragma solidity 0.8.33; import {IBeefyClient} from "./interfaces/IBeefyClient.sol"; -import {ScaleCodec} from "./utils/ScaleCodec.sol"; /** * @title BeefyClientWrapper @@ -34,7 +33,11 @@ contract BeefyClientWrapper { uint256 public maxRefundAmount; // Progress-based refund target - uint256 public refundTarget; // Blocks of progress for 100% gas refund (e.g., 300 = ~30 min) + uint256 public refundTarget; // Blocks of progress for 100% gas refund (e.g., 350 = ~35 min) + + // Highest commitment block number currently in progress (helps relayers avoid duplicate work) + uint256 public highestPendingBlock; + uint256 public highestPendingBlockTimestamp; constructor( address _beefyClient, @@ -65,9 +68,15 @@ contract BeefyClientWrapper { beefyClient.submitInitial(commitment, bitfield, proof); - bytes32 commitmentHash = keccak256(_encodeCommitment(commitment)); + bytes32 commitmentHash = beefyClient.computeCommitmentHash(commitment); ticketOwner[commitmentHash] = msg.sender; + // Track highest pending block so other relayers can check before starting + if (commitment.blockNumber > highestPendingBlock) { + highestPendingBlock = commitment.blockNumber; + highestPendingBlockTimestamp = block.timestamp; + } + _creditGas(startGas, commitmentHash); } @@ -96,7 +105,7 @@ contract BeefyClientWrapper { // Capture previous state for progress calculation uint64 previousBeefyBlock = beefyClient.latestBeefyBlock(); - bytes32 commitmentHash = keccak256(_encodeCommitment(commitment)); + bytes32 commitmentHash = beefyClient.computeCommitmentHash(commitment); if (ticketOwner[commitmentHash] != msg.sender) { revert NotTicketOwner(); } @@ -106,6 +115,12 @@ contract BeefyClientWrapper { // Calculate progress uint256 progress = commitment.blockNumber - previousBeefyBlock; + // Clear highest pending block if light client has caught up + if (beefyClient.latestBeefyBlock() >= highestPendingBlock) { + highestPendingBlock = 0; + highestPendingBlockTimestamp = 0; + } + uint256 previousGas = creditedGas[commitmentHash]; delete creditedGas[commitmentHash]; delete ticketOwner[commitmentHash]; @@ -173,30 +188,24 @@ contract BeefyClientWrapper { } /** - * @dev Calculate and send refund based on progress made. + * @dev Calculate and send refund if progress meets threshold. * - * Refund: Scales from 0% to 100% as progress goes from 0 to refundTarget. - * - * Example with refundTarget=300: - * - 150 blocks progress: 50% gas refund - * - 300 blocks progress: 100% gas refund - * - 600 blocks progress: 100% gas refund (capped) + * Refund if progress >= refundTarget. */ function _refundWithProgress(uint256 startGas, uint256 previousGas, uint256 progress) internal { + if (progress < refundTarget) { + return; + } + uint256 currentGas = startGas - gasleft() + 21000; uint256 totalGasUsed = currentGas + previousGas; uint256 effectiveGasPrice = tx.gasprice < maxGasPrice ? tx.gasprice : maxGasPrice; - uint256 baseRefund = totalGasUsed * effectiveGasPrice; + uint256 refundAmount = totalGasUsed * effectiveGasPrice; - // Cap base refund - if (baseRefund > maxRefundAmount) { - baseRefund = maxRefundAmount; + if (refundAmount > maxRefundAmount) { + refundAmount = maxRefundAmount; } - // Calculate refund ratio (0-100%) - uint256 refundRatio = progress >= refundTarget ? 100 : (progress * 100) / refundTarget; - uint256 refundAmount = (baseRefund * refundRatio) / 100; - if (refundAmount > 0 && address(this).balance >= refundAmount) { (bool success,) = payable(msg.sender).call{value: refundAmount}(""); if (success) { @@ -205,24 +214,6 @@ contract BeefyClientWrapper { } } - function _encodeCommitment(IBeefyClient.Commitment calldata commitment) internal pure returns (bytes memory) { - return bytes.concat( - _encodeCommitmentPayload(commitment.payload), - ScaleCodec.encodeU32(commitment.blockNumber), - ScaleCodec.encodeU64(commitment.validatorSetID) - ); - } - - function _encodeCommitmentPayload(IBeefyClient.PayloadItem[] calldata items) internal pure returns (bytes memory) { - bytes memory payload = ScaleCodec.checkedEncodeCompactU32(items.length); - for (uint256 i = 0; i < items.length; i++) { - payload = bytes.concat( - payload, items[i].payloadID, ScaleCodec.checkedEncodeCompactU32(items[i].data.length), items[i].data - ); - } - return payload; - } - /* Admin Functions */ function setMaxGasPrice(uint256 _maxGasPrice) external { @@ -273,18 +264,19 @@ contract BeefyClientWrapper { view returns (uint256 refundAmount) { + if (progress < refundTarget) { + return 0; + } + uint256 effectiveGasPrice = gasPrice < maxGasPrice ? gasPrice : maxGasPrice; - uint256 baseRefund = gasUsed * effectiveGasPrice; + refundAmount = gasUsed * effectiveGasPrice; - if (baseRefund > maxRefundAmount) { - baseRefund = maxRefundAmount; + if (refundAmount > maxRefundAmount) { + refundAmount = maxRefundAmount; } - - uint256 refundRatio = progress >= refundTarget ? 100 : (progress * 100) / refundTarget; - refundAmount = (baseRefund * refundRatio) / 100; } receive() external payable { emit FundsDeposited(msg.sender, msg.value); } -} \ No newline at end of file +} diff --git a/contracts/src/interfaces/IBeefyClient.sol b/contracts/src/interfaces/IBeefyClient.sol index 5410d88d5..db5d2b75f 100644 --- a/contracts/src/interfaces/IBeefyClient.sol +++ b/contracts/src/interfaces/IBeefyClient.sol @@ -66,6 +66,8 @@ interface IBeefyClient { pure returns (uint256[] memory); + function computeCommitmentHash(Commitment calldata commitment) external pure returns (bytes32); + function randaoCommitDelay() external view returns (uint256); function currentValidatorSet() diff --git a/contracts/test/BeefyClientWrapper.t.sol b/contracts/test/BeefyClientWrapper.t.sol index f8d6305ca..bf3152411 100644 --- a/contracts/test/BeefyClientWrapper.t.sol +++ b/contracts/test/BeefyClientWrapper.t.sol @@ -84,6 +84,10 @@ contract MockBeefyClient { return (2, 100, bytes32(0)); } + function computeCommitmentHash(IBeefyClient.Commitment calldata commitment) external pure returns (bytes32) { + return keccak256(_encodeCommitment(commitment)); + } + function setLatestBeefyBlock(uint64 _block) external { latestBeefyBlock = _block; } @@ -129,7 +133,7 @@ contract BeefyClientWrapperTest is Test { uint256 constant MAX_GAS_PRICE = 100 gwei; uint256 constant MAX_REFUND_AMOUNT = 0.05 ether; - uint256 constant REFUND_TARGET = 300; // 300 blocks for 100% refund + uint256 constant REFUND_TARGET = 350; // ~35 min for 100% refund uint256 constant INITIAL_BEEFY_BLOCK = 1000; function setUp() public { @@ -393,9 +397,9 @@ contract BeefyClientWrapperTest is Test { assertEq(wrapper.creditedGas(commitmentHash), 0); } - function test_partialRefundForLowProgress() public { - // 50% of refund target = 50% refund - uint32 progress = uint32(REFUND_TARGET / 2); // 150 blocks + function test_noRefundForLowProgress() public { + // Below refund target = no refund + uint32 progress = uint32(REFUND_TARGET / 2); // 150 blocks (below 300 threshold) uint32 newBlockNumber = uint32(INITIAL_BEEFY_BLOCK + progress); IBeefyClient.Commitment memory commitment = createCommitment(newBlockNumber); uint256[] memory bitfield = new uint256[](1); @@ -405,7 +409,6 @@ contract BeefyClientWrapperTest is Test { bytes32[] memory leafProof = new bytes32[](0); uint256 relayerBalanceBefore = relayer1.balance; - uint256 wrapperBalanceBefore = address(wrapper).balance; vm.startPrank(relayer1); vm.txGasPrice(50 gwei); @@ -415,12 +418,8 @@ contract BeefyClientWrapperTest is Test { wrapper.submitFinal(commitment, bitfield, proofs, leaf, leafProof, 0); vm.stopPrank(); - uint256 refundAmount = relayer1.balance - relayerBalanceBefore; - uint256 wrapperSpent = wrapperBalanceBefore - address(wrapper).balance; - - // Verify refund was paid - assertGt(refundAmount, 0); - assertEq(refundAmount, wrapperSpent); + // Verify no refund was paid (progress below threshold) + assertEq(relayer1.balance, relayerBalanceBefore); } function test_fullRefundAt100PercentProgress() public { @@ -534,17 +533,17 @@ contract BeefyClientWrapperTest is Test { uint256 gasUsed = 500000; uint256 gasPrice = 50 gwei; - // Test 50% progress (50% refund) - uint256 refund50 = wrapper.estimatePayout(gasUsed, gasPrice, REFUND_TARGET / 2); - assertEq(refund50, (gasUsed * gasPrice * 50) / 100); + // Test below threshold (no refund) + uint256 refundBelow = wrapper.estimatePayout(gasUsed, gasPrice, REFUND_TARGET / 2); + assertEq(refundBelow, 0); - // Test 100% refund progress (100% refund) - uint256 refund100 = wrapper.estimatePayout(gasUsed, gasPrice, REFUND_TARGET); - assertEq(refund100, gasUsed * gasPrice); + // Test at threshold (full refund) + uint256 refundAt = wrapper.estimatePayout(gasUsed, gasPrice, REFUND_TARGET); + assertEq(refundAt, gasUsed * gasPrice); - // Test > 100% progress (still capped at 100% refund) - uint256 refund200 = wrapper.estimatePayout(gasUsed, gasPrice, REFUND_TARGET * 2); - assertEq(refund200, gasUsed * gasPrice); + // Test above threshold (full refund) + uint256 refundAbove = wrapper.estimatePayout(gasUsed, gasPrice, REFUND_TARGET * 2); + assertEq(refundAbove, gasUsed * gasPrice); } /* Admin Function Tests */ diff --git a/relayer/contracts/beefy_client.go b/relayer/contracts/beefy_client.go index 759b93a79..94f8b909a 100644 --- a/relayer/contracts/beefy_client.go +++ b/relayer/contracts/beefy_client.go @@ -78,7 +78,7 @@ type Uint16Array struct { // BeefyClientMetaData contains all meta data concerning the BeefyClient contract. var BeefyClientMetaData = &bind.MetaData{ - ABI: "[{\"type\":\"constructor\",\"inputs\":[{\"name\":\"_randaoCommitDelay\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_randaoCommitExpiration\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_minNumRequiredSignatures\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_fiatShamirRequiredSignatures\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_initialBeefyBlock\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"_initialValidatorSet\",\"type\":\"tuple\",\"internalType\":\"structBeefyClient.ValidatorSet\",\"components\":[{\"name\":\"id\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"length\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"root\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"name\":\"_nextValidatorSet\",\"type\":\"tuple\",\"internalType\":\"structBeefyClient.ValidatorSet\",\"components\":[{\"name\":\"id\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"length\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"root\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"FIAT_SHAMIR_DOMAIN_ID\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"MMR_ROOT_ID\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bytes2\",\"internalType\":\"bytes2\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"commitPrevRandao\",\"inputs\":[{\"name\":\"commitmentHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"createFiatShamirFinalBitfield\",\"inputs\":[{\"name\":\"commitment\",\"type\":\"tuple\",\"internalType\":\"structBeefyClient.Commitment\",\"components\":[{\"name\":\"blockNumber\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"validatorSetID\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"payload\",\"type\":\"tuple[]\",\"internalType\":\"structBeefyClient.PayloadItem[]\",\"components\":[{\"name\":\"payloadID\",\"type\":\"bytes2\",\"internalType\":\"bytes2\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]},{\"name\":\"bitfield\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"createFinalBitfield\",\"inputs\":[{\"name\":\"commitmentHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"bitfield\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"createInitialBitfield\",\"inputs\":[{\"name\":\"bitsToSet\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"},{\"name\":\"length\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"}],\"stateMutability\":\"pure\"},{\"type\":\"function\",\"name\":\"currentValidatorSet\",\"inputs\":[],\"outputs\":[{\"name\":\"id\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"length\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"root\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"usageCounters\",\"type\":\"tuple\",\"internalType\":\"structUint16Array\",\"components\":[{\"name\":\"data\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"},{\"name\":\"length\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"fiatShamirRequiredSignatures\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"latestBeefyBlock\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"latestMMRRoot\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"minNumRequiredSignatures\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"nextValidatorSet\",\"inputs\":[],\"outputs\":[{\"name\":\"id\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"length\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"root\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"usageCounters\",\"type\":\"tuple\",\"internalType\":\"structUint16Array\",\"components\":[{\"name\":\"data\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"},{\"name\":\"length\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"randaoCommitDelay\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"randaoCommitExpiration\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"submitFiatShamir\",\"inputs\":[{\"name\":\"commitment\",\"type\":\"tuple\",\"internalType\":\"structBeefyClient.Commitment\",\"components\":[{\"name\":\"blockNumber\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"validatorSetID\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"payload\",\"type\":\"tuple[]\",\"internalType\":\"structBeefyClient.PayloadItem[]\",\"components\":[{\"name\":\"payloadID\",\"type\":\"bytes2\",\"internalType\":\"bytes2\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]},{\"name\":\"bitfield\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"},{\"name\":\"proofs\",\"type\":\"tuple[]\",\"internalType\":\"structBeefyClient.ValidatorProof[]\",\"components\":[{\"name\":\"v\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"r\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"s\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"index\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"proof\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"}]},{\"name\":\"leaf\",\"type\":\"tuple\",\"internalType\":\"structBeefyClient.MMRLeaf\",\"components\":[{\"name\":\"version\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"parentNumber\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"parentHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"nextAuthoritySetID\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"nextAuthoritySetLen\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"nextAuthoritySetRoot\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"parachainHeadsRoot\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"name\":\"leafProof\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"},{\"name\":\"leafProofOrder\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"submitFinal\",\"inputs\":[{\"name\":\"commitment\",\"type\":\"tuple\",\"internalType\":\"structBeefyClient.Commitment\",\"components\":[{\"name\":\"blockNumber\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"validatorSetID\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"payload\",\"type\":\"tuple[]\",\"internalType\":\"structBeefyClient.PayloadItem[]\",\"components\":[{\"name\":\"payloadID\",\"type\":\"bytes2\",\"internalType\":\"bytes2\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]},{\"name\":\"bitfield\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"},{\"name\":\"proofs\",\"type\":\"tuple[]\",\"internalType\":\"structBeefyClient.ValidatorProof[]\",\"components\":[{\"name\":\"v\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"r\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"s\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"index\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"proof\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"}]},{\"name\":\"leaf\",\"type\":\"tuple\",\"internalType\":\"structBeefyClient.MMRLeaf\",\"components\":[{\"name\":\"version\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"parentNumber\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"parentHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"nextAuthoritySetID\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"nextAuthoritySetLen\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"nextAuthoritySetRoot\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"parachainHeadsRoot\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"name\":\"leafProof\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"},{\"name\":\"leafProofOrder\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"submitInitial\",\"inputs\":[{\"name\":\"commitment\",\"type\":\"tuple\",\"internalType\":\"structBeefyClient.Commitment\",\"components\":[{\"name\":\"blockNumber\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"validatorSetID\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"payload\",\"type\":\"tuple[]\",\"internalType\":\"structBeefyClient.PayloadItem[]\",\"components\":[{\"name\":\"payloadID\",\"type\":\"bytes2\",\"internalType\":\"bytes2\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]},{\"name\":\"bitfield\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"},{\"name\":\"proof\",\"type\":\"tuple\",\"internalType\":\"structBeefyClient.ValidatorProof\",\"components\":[{\"name\":\"v\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"r\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"s\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"index\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"proof\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"tickets\",\"inputs\":[{\"name\":\"ticketID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"blockNumber\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"validatorSetLen\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"numRequiredSignatures\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"prevRandao\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"bitfieldHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"verifyMMRLeafProof\",\"inputs\":[{\"name\":\"leafHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"proof\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"},{\"name\":\"proofOrder\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"event\",\"name\":\"NewMMRRoot\",\"inputs\":[{\"name\":\"mmrRoot\",\"type\":\"bytes32\",\"indexed\":false,\"internalType\":\"bytes32\"},{\"name\":\"blockNumber\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"NewTicket\",\"inputs\":[{\"name\":\"relayer\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"},{\"name\":\"blockNumber\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"TicketExpired\",\"inputs\":[],\"anonymous\":false},{\"type\":\"error\",\"name\":\"CommitmentNotRelevant\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"ECDSAInvalidSignature\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"ECDSAInvalidSignatureLength\",\"inputs\":[{\"name\":\"length\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"ECDSAInvalidSignatureS\",\"inputs\":[{\"name\":\"s\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"type\":\"error\",\"name\":\"IndexOutOfBounds\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidBitfield\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidBitfieldLength\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidBitfieldPadding\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidCommitment\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidMMRLeaf\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidMMRLeafProof\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidMMRRootLength\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidSamplingParams\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidSignature\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidTicket\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidValidatorProof\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidValidatorProofLength\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"PrevRandaoAlreadyCaptured\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"PrevRandaoNotCaptured\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"ProofSizeExceeded\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"StaleCommitment\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"UnsupportedCompactEncoding\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"WaitPeriodNotOver\",\"inputs\":[]}]", + ABI: "[{\"type\":\"constructor\",\"inputs\":[{\"name\":\"_randaoCommitDelay\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_randaoCommitExpiration\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_minNumRequiredSignatures\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_fiatShamirRequiredSignatures\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_initialBeefyBlock\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"_initialValidatorSet\",\"type\":\"tuple\",\"internalType\":\"structBeefyClient.ValidatorSet\",\"components\":[{\"name\":\"id\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"length\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"root\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"name\":\"_nextValidatorSet\",\"type\":\"tuple\",\"internalType\":\"structBeefyClient.ValidatorSet\",\"components\":[{\"name\":\"id\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"length\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"root\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"FIAT_SHAMIR_DOMAIN_ID\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"MMR_ROOT_ID\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bytes2\",\"internalType\":\"bytes2\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"commitPrevRandao\",\"inputs\":[{\"name\":\"commitmentHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"computeCommitmentHash\",\"inputs\":[{\"name\":\"commitment\",\"type\":\"tuple\",\"internalType\":\"structBeefyClient.Commitment\",\"components\":[{\"name\":\"blockNumber\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"validatorSetID\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"payload\",\"type\":\"tuple[]\",\"internalType\":\"structBeefyClient.PayloadItem[]\",\"components\":[{\"name\":\"payloadID\",\"type\":\"bytes2\",\"internalType\":\"bytes2\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"pure\"},{\"type\":\"function\",\"name\":\"createFiatShamirFinalBitfield\",\"inputs\":[{\"name\":\"commitment\",\"type\":\"tuple\",\"internalType\":\"structBeefyClient.Commitment\",\"components\":[{\"name\":\"blockNumber\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"validatorSetID\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"payload\",\"type\":\"tuple[]\",\"internalType\":\"structBeefyClient.PayloadItem[]\",\"components\":[{\"name\":\"payloadID\",\"type\":\"bytes2\",\"internalType\":\"bytes2\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]},{\"name\":\"bitfield\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"createFinalBitfield\",\"inputs\":[{\"name\":\"commitmentHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"bitfield\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"createInitialBitfield\",\"inputs\":[{\"name\":\"bitsToSet\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"},{\"name\":\"length\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"}],\"stateMutability\":\"pure\"},{\"type\":\"function\",\"name\":\"currentValidatorSet\",\"inputs\":[],\"outputs\":[{\"name\":\"id\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"length\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"root\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"usageCounters\",\"type\":\"tuple\",\"internalType\":\"structUint16Array\",\"components\":[{\"name\":\"data\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"},{\"name\":\"length\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"fiatShamirRequiredSignatures\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"latestBeefyBlock\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"latestMMRRoot\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"minNumRequiredSignatures\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"nextValidatorSet\",\"inputs\":[],\"outputs\":[{\"name\":\"id\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"length\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"root\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"usageCounters\",\"type\":\"tuple\",\"internalType\":\"structUint16Array\",\"components\":[{\"name\":\"data\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"},{\"name\":\"length\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"randaoCommitDelay\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"randaoCommitExpiration\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"submitFiatShamir\",\"inputs\":[{\"name\":\"commitment\",\"type\":\"tuple\",\"internalType\":\"structBeefyClient.Commitment\",\"components\":[{\"name\":\"blockNumber\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"validatorSetID\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"payload\",\"type\":\"tuple[]\",\"internalType\":\"structBeefyClient.PayloadItem[]\",\"components\":[{\"name\":\"payloadID\",\"type\":\"bytes2\",\"internalType\":\"bytes2\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]},{\"name\":\"bitfield\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"},{\"name\":\"proofs\",\"type\":\"tuple[]\",\"internalType\":\"structBeefyClient.ValidatorProof[]\",\"components\":[{\"name\":\"v\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"r\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"s\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"index\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"proof\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"}]},{\"name\":\"leaf\",\"type\":\"tuple\",\"internalType\":\"structBeefyClient.MMRLeaf\",\"components\":[{\"name\":\"version\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"parentNumber\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"parentHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"nextAuthoritySetID\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"nextAuthoritySetLen\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"nextAuthoritySetRoot\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"parachainHeadsRoot\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"name\":\"leafProof\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"},{\"name\":\"leafProofOrder\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"submitFinal\",\"inputs\":[{\"name\":\"commitment\",\"type\":\"tuple\",\"internalType\":\"structBeefyClient.Commitment\",\"components\":[{\"name\":\"blockNumber\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"validatorSetID\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"payload\",\"type\":\"tuple[]\",\"internalType\":\"structBeefyClient.PayloadItem[]\",\"components\":[{\"name\":\"payloadID\",\"type\":\"bytes2\",\"internalType\":\"bytes2\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]},{\"name\":\"bitfield\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"},{\"name\":\"proofs\",\"type\":\"tuple[]\",\"internalType\":\"structBeefyClient.ValidatorProof[]\",\"components\":[{\"name\":\"v\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"r\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"s\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"index\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"proof\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"}]},{\"name\":\"leaf\",\"type\":\"tuple\",\"internalType\":\"structBeefyClient.MMRLeaf\",\"components\":[{\"name\":\"version\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"parentNumber\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"parentHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"nextAuthoritySetID\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"nextAuthoritySetLen\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"nextAuthoritySetRoot\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"parachainHeadsRoot\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"name\":\"leafProof\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"},{\"name\":\"leafProofOrder\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"submitInitial\",\"inputs\":[{\"name\":\"commitment\",\"type\":\"tuple\",\"internalType\":\"structBeefyClient.Commitment\",\"components\":[{\"name\":\"blockNumber\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"validatorSetID\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"payload\",\"type\":\"tuple[]\",\"internalType\":\"structBeefyClient.PayloadItem[]\",\"components\":[{\"name\":\"payloadID\",\"type\":\"bytes2\",\"internalType\":\"bytes2\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]},{\"name\":\"bitfield\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"},{\"name\":\"proof\",\"type\":\"tuple\",\"internalType\":\"structBeefyClient.ValidatorProof\",\"components\":[{\"name\":\"v\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"r\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"s\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"index\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"proof\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"tickets\",\"inputs\":[{\"name\":\"ticketID\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"blockNumber\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"validatorSetLen\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"numRequiredSignatures\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"prevRandao\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"bitfieldHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"verifyMMRLeafProof\",\"inputs\":[{\"name\":\"leafHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"proof\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"},{\"name\":\"proofOrder\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"event\",\"name\":\"NewMMRRoot\",\"inputs\":[{\"name\":\"mmrRoot\",\"type\":\"bytes32\",\"indexed\":false,\"internalType\":\"bytes32\"},{\"name\":\"blockNumber\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"NewTicket\",\"inputs\":[{\"name\":\"relayer\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"},{\"name\":\"blockNumber\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"TicketExpired\",\"inputs\":[],\"anonymous\":false},{\"type\":\"error\",\"name\":\"CommitmentNotRelevant\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"ECDSAInvalidSignature\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"ECDSAInvalidSignatureLength\",\"inputs\":[{\"name\":\"length\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]},{\"type\":\"error\",\"name\":\"ECDSAInvalidSignatureS\",\"inputs\":[{\"name\":\"s\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"type\":\"error\",\"name\":\"IndexOutOfBounds\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidBitfield\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidBitfieldLength\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidBitfieldPadding\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidCommitment\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidMMRLeaf\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidMMRLeafProof\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidMMRRootLength\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidSamplingParams\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidSignature\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidTicket\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidValidatorProof\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"InvalidValidatorProofLength\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"PrevRandaoAlreadyCaptured\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"PrevRandaoNotCaptured\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"ProofSizeExceeded\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"StaleCommitment\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"UnsupportedCompactEncoding\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"WaitPeriodNotOver\",\"inputs\":[]}]", } // BeefyClientABI is the input ABI used to generate the binding from. @@ -289,6 +289,37 @@ func (_BeefyClient *BeefyClientCallerSession) MMRROOTID() ([2]byte, error) { return _BeefyClient.Contract.MMRROOTID(&_BeefyClient.CallOpts) } +// ComputeCommitmentHash is a free data retrieval call binding the contract method 0xc6405f31. +// +// Solidity: function computeCommitmentHash((uint32,uint64,(bytes2,bytes)[]) commitment) pure returns(bytes32) +func (_BeefyClient *BeefyClientCaller) ComputeCommitmentHash(opts *bind.CallOpts, commitment BeefyClientCommitment) ([32]byte, error) { + var out []interface{} + err := _BeefyClient.contract.Call(opts, &out, "computeCommitmentHash", commitment) + + if err != nil { + return *new([32]byte), err + } + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + +} + +// ComputeCommitmentHash is a free data retrieval call binding the contract method 0xc6405f31. +// +// Solidity: function computeCommitmentHash((uint32,uint64,(bytes2,bytes)[]) commitment) pure returns(bytes32) +func (_BeefyClient *BeefyClientSession) ComputeCommitmentHash(commitment BeefyClientCommitment) ([32]byte, error) { + return _BeefyClient.Contract.ComputeCommitmentHash(&_BeefyClient.CallOpts, commitment) +} + +// ComputeCommitmentHash is a free data retrieval call binding the contract method 0xc6405f31. +// +// Solidity: function computeCommitmentHash((uint32,uint64,(bytes2,bytes)[]) commitment) pure returns(bytes32) +func (_BeefyClient *BeefyClientCallerSession) ComputeCommitmentHash(commitment BeefyClientCommitment) ([32]byte, error) { + return _BeefyClient.Contract.ComputeCommitmentHash(&_BeefyClient.CallOpts, commitment) +} + // CreateFiatShamirFinalBitfield is a free data retrieval call binding the contract method 0x4b4cfb28. // // Solidity: function createFiatShamirFinalBitfield((uint32,uint64,(bytes2,bytes)[]) commitment, uint256[] bitfield) view returns(uint256[]) diff --git a/relayer/contracts/beefy_client_wrapper.go b/relayer/contracts/beefy_client_wrapper.go index 43dd3dc77..6f325eb99 100644 --- a/relayer/contracts/beefy_client_wrapper.go +++ b/relayer/contracts/beefy_client_wrapper.go @@ -65,7 +65,7 @@ type IBeefyClientValidatorProof struct { // BeefyClientWrapperMetaData contains all meta data concerning the BeefyClientWrapper contract. var BeefyClientWrapperMetaData = &bind.MetaData{ - ABI: "[{\"type\":\"constructor\",\"inputs\":[{\"name\":\"_beefyClient\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"_owner\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"_maxGasPrice\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_maxRefundAmount\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_refundTarget\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"receive\",\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"beefyClient\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"contractIBeefyClient\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"clearTicket\",\"inputs\":[{\"name\":\"commitmentHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"commitPrevRandao\",\"inputs\":[{\"name\":\"commitmentHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"createFinalBitfield\",\"inputs\":[{\"name\":\"commitmentHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"bitfield\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"createInitialBitfield\",\"inputs\":[{\"name\":\"bitsToSet\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"},{\"name\":\"length\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"creditedGas\",\"inputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"currentValidatorSet\",\"inputs\":[],\"outputs\":[{\"name\":\"id\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"length\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"root\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"estimatePayout\",\"inputs\":[{\"name\":\"gasUsed\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"gasPrice\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"progress\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"refundAmount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"latestBeefyBlock\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"maxGasPrice\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"maxRefundAmount\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"nextValidatorSet\",\"inputs\":[],\"outputs\":[{\"name\":\"id\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"length\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"root\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"owner\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"randaoCommitDelay\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"refundTarget\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"setMaxGasPrice\",\"inputs\":[{\"name\":\"_maxGasPrice\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setMaxRefundAmount\",\"inputs\":[{\"name\":\"_maxRefundAmount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setRefundTarget\",\"inputs\":[{\"name\":\"_refundTarget\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"submitFinal\",\"inputs\":[{\"name\":\"commitment\",\"type\":\"tuple\",\"internalType\":\"structIBeefyClient.Commitment\",\"components\":[{\"name\":\"blockNumber\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"validatorSetID\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"payload\",\"type\":\"tuple[]\",\"internalType\":\"structIBeefyClient.PayloadItem[]\",\"components\":[{\"name\":\"payloadID\",\"type\":\"bytes2\",\"internalType\":\"bytes2\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]},{\"name\":\"bitfield\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"},{\"name\":\"proofs\",\"type\":\"tuple[]\",\"internalType\":\"structIBeefyClient.ValidatorProof[]\",\"components\":[{\"name\":\"v\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"r\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"s\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"index\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"proof\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"}]},{\"name\":\"leaf\",\"type\":\"tuple\",\"internalType\":\"structIBeefyClient.MMRLeaf\",\"components\":[{\"name\":\"version\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"parentNumber\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"parentHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"nextAuthoritySetID\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"nextAuthoritySetLen\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"nextAuthoritySetRoot\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"parachainHeadsRoot\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"name\":\"leafProof\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"},{\"name\":\"leafProofOrder\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"submitInitial\",\"inputs\":[{\"name\":\"commitment\",\"type\":\"tuple\",\"internalType\":\"structIBeefyClient.Commitment\",\"components\":[{\"name\":\"blockNumber\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"validatorSetID\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"payload\",\"type\":\"tuple[]\",\"internalType\":\"structIBeefyClient.PayloadItem[]\",\"components\":[{\"name\":\"payloadID\",\"type\":\"bytes2\",\"internalType\":\"bytes2\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]},{\"name\":\"bitfield\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"},{\"name\":\"proof\",\"type\":\"tuple\",\"internalType\":\"structIBeefyClient.ValidatorProof\",\"components\":[{\"name\":\"v\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"r\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"s\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"index\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"proof\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"ticketOwner\",\"inputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"transferOwnership\",\"inputs\":[{\"name\":\"newOwner\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"withdrawFunds\",\"inputs\":[{\"name\":\"recipient\",\"type\":\"address\",\"internalType\":\"addresspayable\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"event\",\"name\":\"FundsDeposited\",\"inputs\":[{\"name\":\"depositor\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"FundsWithdrawn\",\"inputs\":[{\"name\":\"recipient\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"GasCredited\",\"inputs\":[{\"name\":\"relayer\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"commitmentHash\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"gasUsed\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"SubmissionRefunded\",\"inputs\":[{\"name\":\"relayer\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"progress\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"},{\"name\":\"refundAmount\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"},{\"name\":\"totalGasUsed\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"error\",\"name\":\"InvalidAddress\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"NotTicketOwner\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"TransferFailed\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"Unauthorized\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"UnsupportedCompactEncoding\",\"inputs\":[]}]", + ABI: "[{\"type\":\"constructor\",\"inputs\":[{\"name\":\"_beefyClient\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"_owner\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"_maxGasPrice\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_maxRefundAmount\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_refundTarget\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"receive\",\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"beefyClient\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"contractIBeefyClient\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"clearTicket\",\"inputs\":[{\"name\":\"commitmentHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"commitPrevRandao\",\"inputs\":[{\"name\":\"commitmentHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"createFinalBitfield\",\"inputs\":[{\"name\":\"commitmentHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"bitfield\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"createInitialBitfield\",\"inputs\":[{\"name\":\"bitsToSet\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"},{\"name\":\"length\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"creditedGas\",\"inputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"currentValidatorSet\",\"inputs\":[],\"outputs\":[{\"name\":\"id\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"length\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"root\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"estimatePayout\",\"inputs\":[{\"name\":\"gasUsed\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"gasPrice\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"progress\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"refundAmount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"highestPendingBlock\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"highestPendingBlockTimestamp\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"latestBeefyBlock\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"maxGasPrice\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"maxRefundAmount\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"nextValidatorSet\",\"inputs\":[],\"outputs\":[{\"name\":\"id\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"length\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"root\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"owner\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"randaoCommitDelay\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"refundTarget\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"setMaxGasPrice\",\"inputs\":[{\"name\":\"_maxGasPrice\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setMaxRefundAmount\",\"inputs\":[{\"name\":\"_maxRefundAmount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setRefundTarget\",\"inputs\":[{\"name\":\"_refundTarget\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"submitFinal\",\"inputs\":[{\"name\":\"commitment\",\"type\":\"tuple\",\"internalType\":\"structIBeefyClient.Commitment\",\"components\":[{\"name\":\"blockNumber\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"validatorSetID\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"payload\",\"type\":\"tuple[]\",\"internalType\":\"structIBeefyClient.PayloadItem[]\",\"components\":[{\"name\":\"payloadID\",\"type\":\"bytes2\",\"internalType\":\"bytes2\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]},{\"name\":\"bitfield\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"},{\"name\":\"proofs\",\"type\":\"tuple[]\",\"internalType\":\"structIBeefyClient.ValidatorProof[]\",\"components\":[{\"name\":\"v\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"r\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"s\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"index\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"proof\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"}]},{\"name\":\"leaf\",\"type\":\"tuple\",\"internalType\":\"structIBeefyClient.MMRLeaf\",\"components\":[{\"name\":\"version\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"parentNumber\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"parentHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"nextAuthoritySetID\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"nextAuthoritySetLen\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"nextAuthoritySetRoot\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"parachainHeadsRoot\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"name\":\"leafProof\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"},{\"name\":\"leafProofOrder\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"submitInitial\",\"inputs\":[{\"name\":\"commitment\",\"type\":\"tuple\",\"internalType\":\"structIBeefyClient.Commitment\",\"components\":[{\"name\":\"blockNumber\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"validatorSetID\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"payload\",\"type\":\"tuple[]\",\"internalType\":\"structIBeefyClient.PayloadItem[]\",\"components\":[{\"name\":\"payloadID\",\"type\":\"bytes2\",\"internalType\":\"bytes2\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]},{\"name\":\"bitfield\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"},{\"name\":\"proof\",\"type\":\"tuple\",\"internalType\":\"structIBeefyClient.ValidatorProof\",\"components\":[{\"name\":\"v\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"r\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"s\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"index\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"proof\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"ticketOwner\",\"inputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"transferOwnership\",\"inputs\":[{\"name\":\"newOwner\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"withdrawFunds\",\"inputs\":[{\"name\":\"recipient\",\"type\":\"address\",\"internalType\":\"addresspayable\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"event\",\"name\":\"FundsDeposited\",\"inputs\":[{\"name\":\"depositor\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"FundsWithdrawn\",\"inputs\":[{\"name\":\"recipient\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"GasCredited\",\"inputs\":[{\"name\":\"relayer\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"commitmentHash\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"gasUsed\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"SubmissionRefunded\",\"inputs\":[{\"name\":\"relayer\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"progress\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"},{\"name\":\"refundAmount\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"},{\"name\":\"totalGasUsed\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"error\",\"name\":\"InvalidAddress\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"NotTicketOwner\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"TransferFailed\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"Unauthorized\",\"inputs\":[]}]", } // BeefyClientWrapperABI is the input ABI used to generate the binding from. @@ -419,6 +419,68 @@ func (_BeefyClientWrapper *BeefyClientWrapperCallerSession) EstimatePayout(gasUs return _BeefyClientWrapper.Contract.EstimatePayout(&_BeefyClientWrapper.CallOpts, gasUsed, gasPrice, progress) } +// HighestPendingBlock is a free data retrieval call binding the contract method 0x0dc2be13. +// +// Solidity: function highestPendingBlock() view returns(uint256) +func (_BeefyClientWrapper *BeefyClientWrapperCaller) HighestPendingBlock(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _BeefyClientWrapper.contract.Call(opts, &out, "highestPendingBlock") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// HighestPendingBlock is a free data retrieval call binding the contract method 0x0dc2be13. +// +// Solidity: function highestPendingBlock() view returns(uint256) +func (_BeefyClientWrapper *BeefyClientWrapperSession) HighestPendingBlock() (*big.Int, error) { + return _BeefyClientWrapper.Contract.HighestPendingBlock(&_BeefyClientWrapper.CallOpts) +} + +// HighestPendingBlock is a free data retrieval call binding the contract method 0x0dc2be13. +// +// Solidity: function highestPendingBlock() view returns(uint256) +func (_BeefyClientWrapper *BeefyClientWrapperCallerSession) HighestPendingBlock() (*big.Int, error) { + return _BeefyClientWrapper.Contract.HighestPendingBlock(&_BeefyClientWrapper.CallOpts) +} + +// HighestPendingBlockTimestamp is a free data retrieval call binding the contract method 0x33e2c682. +// +// Solidity: function highestPendingBlockTimestamp() view returns(uint256) +func (_BeefyClientWrapper *BeefyClientWrapperCaller) HighestPendingBlockTimestamp(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _BeefyClientWrapper.contract.Call(opts, &out, "highestPendingBlockTimestamp") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// HighestPendingBlockTimestamp is a free data retrieval call binding the contract method 0x33e2c682. +// +// Solidity: function highestPendingBlockTimestamp() view returns(uint256) +func (_BeefyClientWrapper *BeefyClientWrapperSession) HighestPendingBlockTimestamp() (*big.Int, error) { + return _BeefyClientWrapper.Contract.HighestPendingBlockTimestamp(&_BeefyClientWrapper.CallOpts) +} + +// HighestPendingBlockTimestamp is a free data retrieval call binding the contract method 0x33e2c682. +// +// Solidity: function highestPendingBlockTimestamp() view returns(uint256) +func (_BeefyClientWrapper *BeefyClientWrapperCallerSession) HighestPendingBlockTimestamp() (*big.Int, error) { + return _BeefyClientWrapper.Contract.HighestPendingBlockTimestamp(&_BeefyClientWrapper.CallOpts) +} + // LatestBeefyBlock is a free data retrieval call binding the contract method 0x66ae69a0. // // Solidity: function latestBeefyBlock() view returns(uint64) diff --git a/relayer/relays/beefy/ethereum-writer.go b/relayer/relays/beefy/ethereum-writer.go index eafc5fd3b..7e42a02a3 100644 --- a/relayer/relays/beefy/ethereum-writer.go +++ b/relayer/relays/beefy/ethereum-writer.go @@ -6,6 +6,7 @@ import ( "fmt" "math/big" "math/rand" + "time" "golang.org/x/sync/errgroup" @@ -22,6 +23,9 @@ import ( log "github.com/sirupsen/logrus" ) +// SessionTimeout is the duration after which a pending session is considered expired +const SessionTimeout = 40 * time.Minute + type EthereumWriter struct { config *SinkConfig conn *ethereum.Connection @@ -116,6 +120,18 @@ func (wr *EthereumWriter) queryBeefyClientState(ctx context.Context) (*BeefyClie } func (wr *EthereumWriter) submit(ctx context.Context, task *Request) error { + // Check if another relayer already has a session in progress + shouldSkip, err := wr.shouldSkipDueToPendingSession(ctx, task) + if err != nil { + return fmt.Errorf("check pending session: %w", err) + } + if shouldSkip { + log.WithFields(logrus.Fields{ + "beefyBlock": task.SignedCommitment.Commitment.BlockNumber, + }).Info("Skipping submission: another session already in progress with sufficient progress") + return nil + } + // Initial submission tx, initialBitfield, err := wr.doSubmitInitial(ctx, task) if err != nil { @@ -353,3 +369,62 @@ func (wr *EthereumWriter) isTaskOutdated(ctx context.Context, task *Request) (bo } return false, nil } + +// shouldSkipDueToPendingSession checks if another relayer already has a session in progress +// that would advance the light client sufficiently. Returns true if we should skip. +func (wr *EthereumWriter) shouldSkipDueToPendingSession(ctx context.Context, task *Request) (bool, error) { + callOpts := bind.CallOpts{ + Context: ctx, + } + + highestPendingBlock, err := wr.contract.HighestPendingBlock(&callOpts) + if err != nil { + return false, fmt.Errorf("get highest pending block: %w", err) + } + + // No pending session + if highestPendingBlock.Uint64() == 0 { + return false, nil + } + + latestBeefyBlock, err := wr.contract.LatestBeefyBlock(&callOpts) + if err != nil { + return false, fmt.Errorf("get latest beefy block: %w", err) + } + + refundTarget, err := wr.contract.RefundTarget(&callOpts) + if err != nil { + return false, fmt.Errorf("get refund target: %w", err) + } + + // Check if the pending session would give sufficient progress + pendingProgress := highestPendingBlock.Uint64() - latestBeefyBlock + if pendingProgress < refundTarget.Uint64() { + // Pending session wouldn't give good progress, ok to proceed + return false, nil + } + + // Check if the session has expired (> 40 minutes old) + pendingTimestamp, err := wr.contract.HighestPendingBlockTimestamp(&callOpts) + if err != nil { + return false, fmt.Errorf("get highest pending block timestamp: %w", err) + } + + sessionAge := time.Now().Unix() - pendingTimestamp.Int64() + if sessionAge > int64(SessionTimeout.Seconds()) { + log.WithFields(logrus.Fields{ + "highestPendingBlock": highestPendingBlock.Uint64(), + "sessionAgeMinutes": sessionAge / 60, + }).Info("Pending session has expired, proceeding with new submission") + return false, nil + } + + log.WithFields(logrus.Fields{ + "highestPendingBlock": highestPendingBlock.Uint64(), + "latestBeefyBlock": latestBeefyBlock, + "pendingProgress": pendingProgress, + "sessionAgeMinutes": sessionAge / 60, + }).Debug("Active session in progress with sufficient progress") + + return true, nil +} From 9b8fd882efe1217dfedb9abdaa18e032c0b33715 Mon Sep 17 00:00:00 2001 From: claravanstaden Date: Wed, 4 Feb 2026 16:19:51 +0200 Subject: [PATCH 10/17] remove proxy --- .../scripts/DeployBeefyClientWrapper.sol | 2 +- contracts/src/BeefyClientWrapperProxy.sol | 42 ------------------- 2 files changed, 1 insertion(+), 43 deletions(-) delete mode 100644 contracts/src/BeefyClientWrapperProxy.sol diff --git a/contracts/scripts/DeployBeefyClientWrapper.sol b/contracts/scripts/DeployBeefyClientWrapper.sol index e9546cda3..3fbaacee2 100644 --- a/contracts/scripts/DeployBeefyClientWrapper.sol +++ b/contracts/scripts/DeployBeefyClientWrapper.sol @@ -18,7 +18,7 @@ contract DeployBeefyClientWrapper is Script { function readConfig() internal returns (Config memory config) { config = Config({ beefyClient: vm.envAddress("BEEFY_CLIENT_ADDRESS"), - owner: vm.envAddress("REFUND_PROXY_OWNER"), + owner: vm.envAddress("WRAPPER_OWNER"), maxGasPrice: vm.envOr("MAX_GAS_PRICE", uint256(100 gwei)), maxRefundAmount: vm.envOr("MAX_REFUND_AMOUNT", uint256(0.05 ether)), refundTarget: vm.envOr("REFUND_TARGET", uint256(350)) // ~35 min for 100% refund diff --git a/contracts/src/BeefyClientWrapperProxy.sol b/contracts/src/BeefyClientWrapperProxy.sol deleted file mode 100644 index c618cd0cf..000000000 --- a/contracts/src/BeefyClientWrapperProxy.sol +++ /dev/null @@ -1,42 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// SPDX-FileCopyrightText: 2023 Snowfork -pragma solidity 0.8.33; - -import {ERC1967} from "./utils/ERC1967.sol"; -import {Call} from "./utils/Call.sol"; -import {IInitializable} from "./interfaces/IInitializable.sol"; - -contract BeefyClientWrapperProxy is IInitializable { - error Unauthorized(); - - constructor(address implementation, bytes memory params) { - // Store the address of the implementation contract - ERC1967.store(implementation); - // Initialize storage by calling the implementation's `initialize(bytes)` function - // using `delegatecall`. - (bool success, bytes memory returndata) = - implementation.delegatecall(abi.encodeCall(IInitializable.initialize, params)); - Call.verifyResult(success, returndata); - } - - // Prevent fallback() from calling `IInitializable.initialize(bytes)` on the implementation - // contract - function initialize(bytes calldata) external pure { - revert Unauthorized(); - } - - fallback() external payable { - address implementation = ERC1967.load(); - assembly { - calldatacopy(0, 0, calldatasize()) - let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0) - returndatacopy(0, 0, returndatasize()) - switch result - case 0 { revert(0, returndatasize()) } - default { return(0, returndatasize()) } - } - } - - // Note: No receive() needed - fallback() handles plain ETH transfers - // by delegating to the implementation's receive() function -} From d1f0576362c54841e9371f6b3acf903d6c98f3b5 Mon Sep 17 00:00:00 2001 From: claravanstaden Date: Wed, 4 Feb 2026 16:39:18 +0200 Subject: [PATCH 11/17] add fiat shamir back --- relayer/relays/beefy/config.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/relayer/relays/beefy/config.go b/relayer/relays/beefy/config.go index d8a0686c0..1018826a8 100644 --- a/relayer/relays/beefy/config.go +++ b/relayer/relays/beefy/config.go @@ -18,8 +18,9 @@ type SourceConfig struct { } type SinkConfig struct { - Ethereum config.EthereumConfig `mapstructure:"ethereum"` - Contracts ContractsConfig `mapstructure:"contracts"` + Ethereum config.EthereumConfig `mapstructure:"ethereum"` + Contracts ContractsConfig `mapstructure:"contracts"` + EnableFiatShamir bool `mapstructure:"enable-fiat-shamir"` } type ContractsConfig struct { From 6228a56c00236eea3b6f57a2e0ea0bf39c219e89 Mon Sep 17 00:00:00 2001 From: claravanstaden Date: Wed, 4 Feb 2026 16:54:53 +0200 Subject: [PATCH 12/17] revert fiat shamir --- contracts/src/BeefyClientWrapper.sol | 27 +++++++ contracts/src/interfaces/IBeefyClient.sol | 14 ++++ relayer/contracts/beefy_client_wrapper.go | 54 ++++++++++++- relayer/relays/beefy/ethereum-writer.go | 93 ++++++++++++++++++++++- 4 files changed, 186 insertions(+), 2 deletions(-) diff --git a/contracts/src/BeefyClientWrapper.sol b/contracts/src/BeefyClientWrapper.sol index fa48360a3..2030a9f16 100644 --- a/contracts/src/BeefyClientWrapper.sol +++ b/contracts/src/BeefyClientWrapper.sol @@ -160,6 +160,33 @@ contract BeefyClientWrapper { return beefyClient.nextValidatorSet(); } + /* Fiat-Shamir Proxy Functions */ + + function createFiatShamirFinalBitfield(IBeefyClient.Commitment calldata commitment, uint256[] calldata bitfield) + external + view + returns (uint256[] memory) + { + return beefyClient.createFiatShamirFinalBitfield(commitment, bitfield); + } + + function submitFiatShamir( + IBeefyClient.Commitment calldata commitment, + uint256[] calldata bitfield, + IBeefyClient.ValidatorProof[] calldata proofs, + IBeefyClient.MMRLeaf calldata leaf, + bytes32[] calldata leafProof, + uint256 leafProofOrder + ) external { + beefyClient.submitFiatShamir(commitment, bitfield, proofs, leaf, leafProof, leafProofOrder); + + // Clear highest pending block if light client has caught up + if (beefyClient.latestBeefyBlock() >= highestPendingBlock) { + highestPendingBlock = 0; + highestPendingBlockTimestamp = 0; + } + } + /** * @dev Abandon a ticket. Useful if another relayer is competing for the same commitment. * Credited gas is forfeited when clearing a ticket. diff --git a/contracts/src/interfaces/IBeefyClient.sol b/contracts/src/interfaces/IBeefyClient.sol index db5d2b75f..76d99f0be 100644 --- a/contracts/src/interfaces/IBeefyClient.sol +++ b/contracts/src/interfaces/IBeefyClient.sol @@ -79,4 +79,18 @@ interface IBeefyClient { external view returns (uint128 id, uint128 length, bytes32 root); + + function createFiatShamirFinalBitfield(Commitment calldata commitment, uint256[] calldata bitfield) + external + view + returns (uint256[] memory); + + function submitFiatShamir( + Commitment calldata commitment, + uint256[] calldata bitfield, + ValidatorProof[] calldata proofs, + MMRLeaf calldata leaf, + bytes32[] calldata leafProof, + uint256 leafProofOrder + ) external; } diff --git a/relayer/contracts/beefy_client_wrapper.go b/relayer/contracts/beefy_client_wrapper.go index 6f325eb99..d7342f2d3 100644 --- a/relayer/contracts/beefy_client_wrapper.go +++ b/relayer/contracts/beefy_client_wrapper.go @@ -65,7 +65,7 @@ type IBeefyClientValidatorProof struct { // BeefyClientWrapperMetaData contains all meta data concerning the BeefyClientWrapper contract. var BeefyClientWrapperMetaData = &bind.MetaData{ - ABI: "[{\"type\":\"constructor\",\"inputs\":[{\"name\":\"_beefyClient\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"_owner\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"_maxGasPrice\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_maxRefundAmount\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_refundTarget\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"receive\",\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"beefyClient\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"contractIBeefyClient\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"clearTicket\",\"inputs\":[{\"name\":\"commitmentHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"commitPrevRandao\",\"inputs\":[{\"name\":\"commitmentHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"createFinalBitfield\",\"inputs\":[{\"name\":\"commitmentHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"bitfield\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"createInitialBitfield\",\"inputs\":[{\"name\":\"bitsToSet\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"},{\"name\":\"length\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"creditedGas\",\"inputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"currentValidatorSet\",\"inputs\":[],\"outputs\":[{\"name\":\"id\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"length\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"root\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"estimatePayout\",\"inputs\":[{\"name\":\"gasUsed\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"gasPrice\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"progress\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"refundAmount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"highestPendingBlock\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"highestPendingBlockTimestamp\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"latestBeefyBlock\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"maxGasPrice\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"maxRefundAmount\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"nextValidatorSet\",\"inputs\":[],\"outputs\":[{\"name\":\"id\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"length\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"root\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"owner\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"randaoCommitDelay\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"refundTarget\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"setMaxGasPrice\",\"inputs\":[{\"name\":\"_maxGasPrice\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setMaxRefundAmount\",\"inputs\":[{\"name\":\"_maxRefundAmount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setRefundTarget\",\"inputs\":[{\"name\":\"_refundTarget\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"submitFinal\",\"inputs\":[{\"name\":\"commitment\",\"type\":\"tuple\",\"internalType\":\"structIBeefyClient.Commitment\",\"components\":[{\"name\":\"blockNumber\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"validatorSetID\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"payload\",\"type\":\"tuple[]\",\"internalType\":\"structIBeefyClient.PayloadItem[]\",\"components\":[{\"name\":\"payloadID\",\"type\":\"bytes2\",\"internalType\":\"bytes2\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]},{\"name\":\"bitfield\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"},{\"name\":\"proofs\",\"type\":\"tuple[]\",\"internalType\":\"structIBeefyClient.ValidatorProof[]\",\"components\":[{\"name\":\"v\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"r\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"s\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"index\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"proof\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"}]},{\"name\":\"leaf\",\"type\":\"tuple\",\"internalType\":\"structIBeefyClient.MMRLeaf\",\"components\":[{\"name\":\"version\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"parentNumber\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"parentHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"nextAuthoritySetID\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"nextAuthoritySetLen\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"nextAuthoritySetRoot\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"parachainHeadsRoot\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"name\":\"leafProof\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"},{\"name\":\"leafProofOrder\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"submitInitial\",\"inputs\":[{\"name\":\"commitment\",\"type\":\"tuple\",\"internalType\":\"structIBeefyClient.Commitment\",\"components\":[{\"name\":\"blockNumber\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"validatorSetID\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"payload\",\"type\":\"tuple[]\",\"internalType\":\"structIBeefyClient.PayloadItem[]\",\"components\":[{\"name\":\"payloadID\",\"type\":\"bytes2\",\"internalType\":\"bytes2\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]},{\"name\":\"bitfield\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"},{\"name\":\"proof\",\"type\":\"tuple\",\"internalType\":\"structIBeefyClient.ValidatorProof\",\"components\":[{\"name\":\"v\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"r\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"s\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"index\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"proof\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"ticketOwner\",\"inputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"transferOwnership\",\"inputs\":[{\"name\":\"newOwner\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"withdrawFunds\",\"inputs\":[{\"name\":\"recipient\",\"type\":\"address\",\"internalType\":\"addresspayable\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"event\",\"name\":\"FundsDeposited\",\"inputs\":[{\"name\":\"depositor\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"FundsWithdrawn\",\"inputs\":[{\"name\":\"recipient\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"GasCredited\",\"inputs\":[{\"name\":\"relayer\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"commitmentHash\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"gasUsed\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"SubmissionRefunded\",\"inputs\":[{\"name\":\"relayer\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"progress\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"},{\"name\":\"refundAmount\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"},{\"name\":\"totalGasUsed\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"error\",\"name\":\"InvalidAddress\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"NotTicketOwner\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"TransferFailed\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"Unauthorized\",\"inputs\":[]}]", + ABI: "[{\"type\":\"constructor\",\"inputs\":[{\"name\":\"_beefyClient\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"_owner\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"_maxGasPrice\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_maxRefundAmount\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_refundTarget\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"receive\",\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"beefyClient\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"contractIBeefyClient\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"clearTicket\",\"inputs\":[{\"name\":\"commitmentHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"commitPrevRandao\",\"inputs\":[{\"name\":\"commitmentHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"createFiatShamirFinalBitfield\",\"inputs\":[{\"name\":\"commitment\",\"type\":\"tuple\",\"internalType\":\"structIBeefyClient.Commitment\",\"components\":[{\"name\":\"blockNumber\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"validatorSetID\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"payload\",\"type\":\"tuple[]\",\"internalType\":\"structIBeefyClient.PayloadItem[]\",\"components\":[{\"name\":\"payloadID\",\"type\":\"bytes2\",\"internalType\":\"bytes2\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]},{\"name\":\"bitfield\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"createFinalBitfield\",\"inputs\":[{\"name\":\"commitmentHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"bitfield\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"createInitialBitfield\",\"inputs\":[{\"name\":\"bitsToSet\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"},{\"name\":\"length\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"creditedGas\",\"inputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"currentValidatorSet\",\"inputs\":[],\"outputs\":[{\"name\":\"id\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"length\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"root\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"estimatePayout\",\"inputs\":[{\"name\":\"gasUsed\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"gasPrice\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"progress\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"refundAmount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"highestPendingBlock\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"highestPendingBlockTimestamp\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"latestBeefyBlock\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"maxGasPrice\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"maxRefundAmount\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"nextValidatorSet\",\"inputs\":[],\"outputs\":[{\"name\":\"id\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"length\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"root\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"owner\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"randaoCommitDelay\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"refundTarget\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"setMaxGasPrice\",\"inputs\":[{\"name\":\"_maxGasPrice\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setMaxRefundAmount\",\"inputs\":[{\"name\":\"_maxRefundAmount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setRefundTarget\",\"inputs\":[{\"name\":\"_refundTarget\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"submitFiatShamir\",\"inputs\":[{\"name\":\"commitment\",\"type\":\"tuple\",\"internalType\":\"structIBeefyClient.Commitment\",\"components\":[{\"name\":\"blockNumber\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"validatorSetID\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"payload\",\"type\":\"tuple[]\",\"internalType\":\"structIBeefyClient.PayloadItem[]\",\"components\":[{\"name\":\"payloadID\",\"type\":\"bytes2\",\"internalType\":\"bytes2\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]},{\"name\":\"bitfield\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"},{\"name\":\"proofs\",\"type\":\"tuple[]\",\"internalType\":\"structIBeefyClient.ValidatorProof[]\",\"components\":[{\"name\":\"v\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"r\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"s\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"index\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"proof\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"}]},{\"name\":\"leaf\",\"type\":\"tuple\",\"internalType\":\"structIBeefyClient.MMRLeaf\",\"components\":[{\"name\":\"version\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"parentNumber\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"parentHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"nextAuthoritySetID\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"nextAuthoritySetLen\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"nextAuthoritySetRoot\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"parachainHeadsRoot\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"name\":\"leafProof\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"},{\"name\":\"leafProofOrder\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"submitFinal\",\"inputs\":[{\"name\":\"commitment\",\"type\":\"tuple\",\"internalType\":\"structIBeefyClient.Commitment\",\"components\":[{\"name\":\"blockNumber\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"validatorSetID\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"payload\",\"type\":\"tuple[]\",\"internalType\":\"structIBeefyClient.PayloadItem[]\",\"components\":[{\"name\":\"payloadID\",\"type\":\"bytes2\",\"internalType\":\"bytes2\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]},{\"name\":\"bitfield\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"},{\"name\":\"proofs\",\"type\":\"tuple[]\",\"internalType\":\"structIBeefyClient.ValidatorProof[]\",\"components\":[{\"name\":\"v\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"r\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"s\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"index\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"proof\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"}]},{\"name\":\"leaf\",\"type\":\"tuple\",\"internalType\":\"structIBeefyClient.MMRLeaf\",\"components\":[{\"name\":\"version\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"parentNumber\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"parentHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"nextAuthoritySetID\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"nextAuthoritySetLen\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"nextAuthoritySetRoot\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"parachainHeadsRoot\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"name\":\"leafProof\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"},{\"name\":\"leafProofOrder\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"submitInitial\",\"inputs\":[{\"name\":\"commitment\",\"type\":\"tuple\",\"internalType\":\"structIBeefyClient.Commitment\",\"components\":[{\"name\":\"blockNumber\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"validatorSetID\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"payload\",\"type\":\"tuple[]\",\"internalType\":\"structIBeefyClient.PayloadItem[]\",\"components\":[{\"name\":\"payloadID\",\"type\":\"bytes2\",\"internalType\":\"bytes2\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]},{\"name\":\"bitfield\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"},{\"name\":\"proof\",\"type\":\"tuple\",\"internalType\":\"structIBeefyClient.ValidatorProof\",\"components\":[{\"name\":\"v\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"r\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"s\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"index\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"proof\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"ticketOwner\",\"inputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"transferOwnership\",\"inputs\":[{\"name\":\"newOwner\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"withdrawFunds\",\"inputs\":[{\"name\":\"recipient\",\"type\":\"address\",\"internalType\":\"addresspayable\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"event\",\"name\":\"FundsDeposited\",\"inputs\":[{\"name\":\"depositor\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"FundsWithdrawn\",\"inputs\":[{\"name\":\"recipient\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"GasCredited\",\"inputs\":[{\"name\":\"relayer\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"commitmentHash\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"gasUsed\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"SubmissionRefunded\",\"inputs\":[{\"name\":\"relayer\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"progress\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"},{\"name\":\"refundAmount\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"},{\"name\":\"totalGasUsed\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"error\",\"name\":\"InvalidAddress\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"NotTicketOwner\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"TransferFailed\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"Unauthorized\",\"inputs\":[]}]", } // BeefyClientWrapperABI is the input ABI used to generate the binding from. @@ -245,6 +245,37 @@ func (_BeefyClientWrapper *BeefyClientWrapperCallerSession) BeefyClient() (commo return _BeefyClientWrapper.Contract.BeefyClient(&_BeefyClientWrapper.CallOpts) } +// CreateFiatShamirFinalBitfield is a free data retrieval call binding the contract method 0x4b4cfb28. +// +// Solidity: function createFiatShamirFinalBitfield((uint32,uint64,(bytes2,bytes)[]) commitment, uint256[] bitfield) view returns(uint256[]) +func (_BeefyClientWrapper *BeefyClientWrapperCaller) CreateFiatShamirFinalBitfield(opts *bind.CallOpts, commitment IBeefyClientCommitment, bitfield []*big.Int) ([]*big.Int, error) { + var out []interface{} + err := _BeefyClientWrapper.contract.Call(opts, &out, "createFiatShamirFinalBitfield", commitment, bitfield) + + if err != nil { + return *new([]*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new([]*big.Int)).(*[]*big.Int) + + return out0, err + +} + +// CreateFiatShamirFinalBitfield is a free data retrieval call binding the contract method 0x4b4cfb28. +// +// Solidity: function createFiatShamirFinalBitfield((uint32,uint64,(bytes2,bytes)[]) commitment, uint256[] bitfield) view returns(uint256[]) +func (_BeefyClientWrapper *BeefyClientWrapperSession) CreateFiatShamirFinalBitfield(commitment IBeefyClientCommitment, bitfield []*big.Int) ([]*big.Int, error) { + return _BeefyClientWrapper.Contract.CreateFiatShamirFinalBitfield(&_BeefyClientWrapper.CallOpts, commitment, bitfield) +} + +// CreateFiatShamirFinalBitfield is a free data retrieval call binding the contract method 0x4b4cfb28. +// +// Solidity: function createFiatShamirFinalBitfield((uint32,uint64,(bytes2,bytes)[]) commitment, uint256[] bitfield) view returns(uint256[]) +func (_BeefyClientWrapper *BeefyClientWrapperCallerSession) CreateFiatShamirFinalBitfield(commitment IBeefyClientCommitment, bitfield []*big.Int) ([]*big.Int, error) { + return _BeefyClientWrapper.Contract.CreateFiatShamirFinalBitfield(&_BeefyClientWrapper.CallOpts, commitment, bitfield) +} + // CreateFinalBitfield is a free data retrieval call binding the contract method 0x8ab81d13. // // Solidity: function createFinalBitfield(bytes32 commitmentHash, uint256[] bitfield) view returns(uint256[]) @@ -853,6 +884,27 @@ func (_BeefyClientWrapper *BeefyClientWrapperTransactorSession) SetRefundTarget( return _BeefyClientWrapper.Contract.SetRefundTarget(&_BeefyClientWrapper.TransactOpts, _refundTarget) } +// SubmitFiatShamir is a paid mutator transaction binding the contract method 0xc7d6e93d. +// +// Solidity: function submitFiatShamir((uint32,uint64,(bytes2,bytes)[]) commitment, uint256[] bitfield, (uint8,bytes32,bytes32,uint256,address,bytes32[])[] proofs, (uint8,uint32,bytes32,uint64,uint32,bytes32,bytes32) leaf, bytes32[] leafProof, uint256 leafProofOrder) returns() +func (_BeefyClientWrapper *BeefyClientWrapperTransactor) SubmitFiatShamir(opts *bind.TransactOpts, commitment IBeefyClientCommitment, bitfield []*big.Int, proofs []IBeefyClientValidatorProof, leaf IBeefyClientMMRLeaf, leafProof [][32]byte, leafProofOrder *big.Int) (*types.Transaction, error) { + return _BeefyClientWrapper.contract.Transact(opts, "submitFiatShamir", commitment, bitfield, proofs, leaf, leafProof, leafProofOrder) +} + +// SubmitFiatShamir is a paid mutator transaction binding the contract method 0xc7d6e93d. +// +// Solidity: function submitFiatShamir((uint32,uint64,(bytes2,bytes)[]) commitment, uint256[] bitfield, (uint8,bytes32,bytes32,uint256,address,bytes32[])[] proofs, (uint8,uint32,bytes32,uint64,uint32,bytes32,bytes32) leaf, bytes32[] leafProof, uint256 leafProofOrder) returns() +func (_BeefyClientWrapper *BeefyClientWrapperSession) SubmitFiatShamir(commitment IBeefyClientCommitment, bitfield []*big.Int, proofs []IBeefyClientValidatorProof, leaf IBeefyClientMMRLeaf, leafProof [][32]byte, leafProofOrder *big.Int) (*types.Transaction, error) { + return _BeefyClientWrapper.Contract.SubmitFiatShamir(&_BeefyClientWrapper.TransactOpts, commitment, bitfield, proofs, leaf, leafProof, leafProofOrder) +} + +// SubmitFiatShamir is a paid mutator transaction binding the contract method 0xc7d6e93d. +// +// Solidity: function submitFiatShamir((uint32,uint64,(bytes2,bytes)[]) commitment, uint256[] bitfield, (uint8,bytes32,bytes32,uint256,address,bytes32[])[] proofs, (uint8,uint32,bytes32,uint64,uint32,bytes32,bytes32) leaf, bytes32[] leafProof, uint256 leafProofOrder) returns() +func (_BeefyClientWrapper *BeefyClientWrapperTransactorSession) SubmitFiatShamir(commitment IBeefyClientCommitment, bitfield []*big.Int, proofs []IBeefyClientValidatorProof, leaf IBeefyClientMMRLeaf, leafProof [][32]byte, leafProofOrder *big.Int) (*types.Transaction, error) { + return _BeefyClientWrapper.Contract.SubmitFiatShamir(&_BeefyClientWrapper.TransactOpts, commitment, bitfield, proofs, leaf, leafProof, leafProofOrder) +} + // SubmitFinal is a paid mutator transaction binding the contract method 0x623b223d. // // Solidity: function submitFinal((uint32,uint64,(bytes2,bytes)[]) commitment, uint256[] bitfield, (uint8,bytes32,bytes32,uint256,address,bytes32[])[] proofs, (uint8,uint32,bytes32,uint64,uint32,bytes32,bytes32) leaf, bytes32[] leafProof, uint256 leafProofOrder) returns() diff --git a/relayer/relays/beefy/ethereum-writer.go b/relayer/relays/beefy/ethereum-writer.go index 7e42a02a3..d3e12fd87 100644 --- a/relayer/relays/beefy/ethereum-writer.go +++ b/relayer/relays/beefy/ethereum-writer.go @@ -72,7 +72,11 @@ func (wr *EthereumWriter) Start(ctx context.Context, eg *errgroup.Group, request // the beefy light client task.ValidatorsRoot = state.NextValidatorSetRoot - err = wr.submit(ctx, &task) + if wr.config.EnableFiatShamir { + err = wr.submitFiatShamir(ctx, &task) + } else { + err = wr.submit(ctx, &task) + } if err != nil { return fmt.Errorf("submit request: %w", err) } @@ -370,6 +374,93 @@ func (wr *EthereumWriter) isTaskOutdated(ctx context.Context, task *Request) (bo return false, nil } +func (wr *EthereumWriter) submitFiatShamir(ctx context.Context, task *Request) error { + signedValidators := []*big.Int{} + for i, signature := range task.SignedCommitment.Signatures { + if signature.IsSome() { + signedValidators = append(signedValidators, big.NewInt(int64(i))) + } + } + validatorCount := big.NewInt(int64(len(task.SignedCommitment.Signatures))) + + // Pick a random validator who signs beefy commitment + chosenValidator := signedValidators[rand.Intn(len(signedValidators))].Int64() + + log.WithFields(logrus.Fields{ + "validatorCount": validatorCount, + "signedValidators": signedValidators, + "signedValidatorCount": len(signedValidators), + "chosenValidator": chosenValidator, + }).Info("Creating initial bitfield") + + initialBitfield, err := wr.contract.CreateInitialBitfield( + &bind.CallOpts{ + Pending: true, + From: wr.conn.Keypair().CommonAddress(), + }, + signedValidators, validatorCount, + ) + if err != nil { + return fmt.Errorf("create initial bitfield: %w", err) + } + + commitment := toBeefyClientCommitment(&task.SignedCommitment.Commitment) + + finalBitfield, err := wr.contract.CreateFiatShamirFinalBitfield( + &bind.CallOpts{ + Pending: true, + From: wr.conn.Keypair().CommonAddress(), + }, + *commitment, + initialBitfield, + ) + + if err != nil { + return fmt.Errorf("create validator final bitfield: %w", err) + } + + validatorIndices := bitfield.New(finalBitfield).Members() + + params, err := task.MakeSubmitFinalParams(validatorIndices, initialBitfield) + if err != nil { + return fmt.Errorf("make submit final params: %w", err) + } + + logFields, err := wr.makeSubmitFinalLogFields(task, params) + if err != nil { + return fmt.Errorf("logging params: %w", err) + } + + tx, err := wr.contract.SubmitFiatShamir( + wr.conn.MakeTxOpts(ctx), + params.Commitment, + params.Bitfield, + params.Proofs, + params.Leaf, + params.LeafProof, + params.LeafProofOrder, + ) + if err != nil { + return fmt.Errorf("SubmitFiatShamir: %w", err) + } + + log.WithField("txHash", tx.Hash().Hex()). + WithFields(logFields). + Info("Sent SubmitFiatShamir transaction") + + _, err = wr.conn.WatchTransaction(ctx, tx, 0) + if err != nil { + return fmt.Errorf("Wait receipt for SubmitFiatShamir: %w", err) + } + + log.WithFields(logrus.Fields{ + "tx": tx.Hash().Hex(), + "blockNumber": task.SignedCommitment.Commitment.BlockNumber, + }).Debug("Transaction submitFiatShamir succeeded") + + return nil +} + // shouldSkipDueToPendingSession checks if another relayer already has a session in progress // that would advance the light client sufficiently. Returns true if we should skip. func (wr *EthereumWriter) shouldSkipDueToPendingSession(ctx context.Context, task *Request) (bool, error) { From f9b49234aef55673ac1fe30e12d0d8e0256556a4 Mon Sep 17 00:00:00 2001 From: claravanstaden Date: Wed, 4 Feb 2026 19:57:35 +0200 Subject: [PATCH 13/17] relayer tweaks --- relayer/relays/beefy/config.go | 5 +- relayer/relays/beefy/ethereum-writer.go | 316 +++++++++++++++++------- relayer/relays/beefy/parameters.go | 47 ++++ 3 files changed, 274 insertions(+), 94 deletions(-) diff --git a/relayer/relays/beefy/config.go b/relayer/relays/beefy/config.go index 1018826a8..d0b9b0099 100644 --- a/relayer/relays/beefy/config.go +++ b/relayer/relays/beefy/config.go @@ -24,8 +24,9 @@ type SinkConfig struct { } type ContractsConfig struct { - BeefyClient string `mapstructure:"BeefyClient"` - Gateway string `mapstructure:"Gateway"` + BeefyClient string `mapstructure:"BeefyClient"` + BeefyClientWrapper string `mapstructure:"BeefyClientWrapper"` // Optional: if set, use wrapper for gas refunds + Gateway string `mapstructure:"Gateway"` } type OnDemandSyncConfig struct { diff --git a/relayer/relays/beefy/ethereum-writer.go b/relayer/relays/beefy/ethereum-writer.go index d3e12fd87..704254ffe 100644 --- a/relayer/relays/beefy/ethereum-writer.go +++ b/relayer/relays/beefy/ethereum-writer.go @@ -29,7 +29,9 @@ const SessionTimeout = 40 * time.Minute type EthereumWriter struct { config *SinkConfig conn *ethereum.Connection - contract *contracts.BeefyClientWrapper + useWrapper bool + wrapperContract *contracts.BeefyClientWrapper + directContract *contracts.BeefyClient blockWaitPeriod uint64 } @@ -100,16 +102,17 @@ func (wr *EthereumWriter) queryBeefyClientState(ctx context.Context) (*BeefyClie Context: ctx, } - latestBeefyBlock, err := wr.contract.LatestBeefyBlock(&callOpts) + latestBeefyBlock, err := wr.getLatestBeefyBlock(&callOpts) if err != nil { return nil, err } - currentValidatorSet, err := wr.contract.CurrentValidatorSet(&callOpts) + currentValidatorSet, err := wr.getCurrentValidatorSet(&callOpts) if err != nil { return nil, err } - nextValidatorSet, err := wr.contract.NextValidatorSet(&callOpts) + + nextValidatorSet, err := wr.getNextValidatorSet(&callOpts) if err != nil { return nil, err } @@ -124,16 +127,18 @@ func (wr *EthereumWriter) queryBeefyClientState(ctx context.Context) (*BeefyClie } func (wr *EthereumWriter) submit(ctx context.Context, task *Request) error { - // Check if another relayer already has a session in progress - shouldSkip, err := wr.shouldSkipDueToPendingSession(ctx, task) - if err != nil { - return fmt.Errorf("check pending session: %w", err) - } - if shouldSkip { - log.WithFields(logrus.Fields{ - "beefyBlock": task.SignedCommitment.Commitment.BlockNumber, - }).Info("Skipping submission: another session already in progress with sufficient progress") - return nil + // Check if another relayer already has a session in progress (wrapper only) + if wr.useWrapper { + shouldSkip, err := wr.shouldSkipDueToPendingSession(ctx, task) + if err != nil { + return fmt.Errorf("check pending session: %w", err) + } + if shouldSkip { + log.WithFields(logrus.Fields{ + "beefyBlock": task.SignedCommitment.Commitment.BlockNumber, + }).Info("Skipping submission: another session already in progress with sufficient progress") + return nil + } } // Initial submission @@ -181,12 +186,10 @@ func (wr *EthereumWriter) submit(ctx context.Context, task *Request) error { }).Info("Commitment already synced") return nil } + // Commit PrevRandao which will be used as seed to randomly select subset of validators // https://github.com/Snowfork/snowbridge/blob/75a475cbf8fc8e13577ad6b773ac452b2bf82fbb/contracts/contracts/BeefyClient.sol#L446-L447 - tx, err = wr.contract.CommitPrevRandao( - wr.conn.MakeTxOpts(ctx), - *commitmentHash, - ) + tx, err = wr.doCommitPrevRandao(ctx, *commitmentHash) if err != nil { return fmt.Errorf("Failed to call CommitPrevRandao: %w", err) } @@ -212,6 +215,7 @@ func (wr *EthereumWriter) submit(ctx context.Context, task *Request) error { }).Info("Commitment already synced") return nil } + // Final submission tx, err = wr.doSubmitFinal(ctx, *commitmentHash, initialBitfield, task) if err != nil { @@ -229,7 +233,6 @@ func (wr *EthereumWriter) submit(ctx context.Context, task *Request) error { }).Debug("Transaction SubmitFinal succeeded") return nil - } func (wr *EthereumWriter) doSubmitInitial(ctx context.Context, task *Request) (*types.Transaction, []*big.Int, error) { @@ -251,13 +254,7 @@ func (wr *EthereumWriter) doSubmitInitial(ctx context.Context, task *Request) (* "chosenValidator": chosenValidator, }).Info("Creating initial bitfield") - initialBitfield, err := wr.contract.CreateInitialBitfield( - &bind.CallOpts{ - Pending: true, - From: wr.conn.Keypair().CommonAddress(), - }, - signedValidators, validatorCount, - ) + initialBitfield, err := wr.createInitialBitfield(signedValidators, validatorCount) if err != nil { return nil, nil, fmt.Errorf("create initial bitfield: %w", err) } @@ -267,13 +264,7 @@ func (wr *EthereumWriter) doSubmitInitial(ctx context.Context, task *Request) (* return nil, nil, err } - var tx *types.Transaction - tx, err = wr.contract.SubmitInitial( - wr.conn.MakeTxOpts(ctx), - msg.Commitment, - msg.Bitfield, - msg.Proof, - ) + tx, err := wr.submitInitial(ctx, msg) if err != nil { return nil, nil, fmt.Errorf("initial submit: %w", err) } @@ -295,15 +286,7 @@ func (wr *EthereumWriter) doSubmitInitial(ctx context.Context, task *Request) (* // doSubmitFinal sends a SubmitFinal tx to the BeefyClient contract func (wr *EthereumWriter) doSubmitFinal(ctx context.Context, commitmentHash [32]byte, initialBitfield []*big.Int, task *Request) (*types.Transaction, error) { - finalBitfield, err := wr.contract.CreateFinalBitfield( - &bind.CallOpts{ - Pending: true, - From: wr.conn.Keypair().CommonAddress(), - }, - commitmentHash, - initialBitfield, - ) - + finalBitfield, err := wr.createFinalBitfield(commitmentHash, initialBitfield) if err != nil { return nil, fmt.Errorf("create validator bitfield: %w", err) } @@ -320,15 +303,7 @@ func (wr *EthereumWriter) doSubmitFinal(ctx context.Context, commitmentHash [32] return nil, fmt.Errorf("logging params: %w", err) } - tx, err := wr.contract.SubmitFinal( - wr.conn.MakeTxOpts(ctx), - params.Commitment, - params.Bitfield, - params.Proofs, - params.Leaf, - params.LeafProof, - params.LeafProofOrder, - ) + tx, err := wr.submitFinal(ctx, params) if err != nil { return nil, fmt.Errorf("final submission: %w", err) } @@ -341,22 +316,53 @@ func (wr *EthereumWriter) doSubmitFinal(ctx context.Context, commitmentHash [32] } func (wr *EthereumWriter) initialize(ctx context.Context) error { - address := common.HexToAddress(wr.config.Contracts.BeefyClient) - - contract, err := contracts.NewBeefyClientWrapper(address, wr.conn.Client()) - if err != nil { - return fmt.Errorf("create beefy client wrapper: %w", err) - } - wr.contract = contract - callOpts := bind.CallOpts{ Context: ctx, } - blockWaitPeriod, err := wr.contract.RandaoCommitDelay(&callOpts) - if err != nil { - return fmt.Errorf("get randao commit delay: %w", err) + + // Check if wrapper is configured + if wr.config.Contracts.BeefyClientWrapper != "" { + wr.useWrapper = true + address := common.HexToAddress(wr.config.Contracts.BeefyClientWrapper) + + contract, err := contracts.NewBeefyClientWrapper(address, wr.conn.Client()) + if err != nil { + return fmt.Errorf("create beefy client wrapper: %w", err) + } + wr.wrapperContract = contract + + blockWaitPeriod, err := wr.wrapperContract.RandaoCommitDelay(&callOpts) + if err != nil { + return fmt.Errorf("get randao commit delay: %w", err) + } + wr.blockWaitPeriod = blockWaitPeriod.Uint64() + + log.WithFields(logrus.Fields{ + "address": address.Hex(), + "randaoCommitDelay": wr.blockWaitPeriod, + }).Info("Using BeefyClientWrapper for gas refunds") + } else { + wr.useWrapper = false + address := common.HexToAddress(wr.config.Contracts.BeefyClient) + + contract, err := contracts.NewBeefyClient(address, wr.conn.Client()) + if err != nil { + return fmt.Errorf("create beefy client: %w", err) + } + wr.directContract = contract + + blockWaitPeriod, err := wr.directContract.RandaoCommitDelay(&callOpts) + if err != nil { + return fmt.Errorf("get randao commit delay: %w", err) + } + wr.blockWaitPeriod = blockWaitPeriod.Uint64() + + log.WithFields(logrus.Fields{ + "address": address.Hex(), + "randaoCommitDelay": wr.blockWaitPeriod, + }).Info("Using BeefyClient directly (no gas refunds)") } - wr.blockWaitPeriod = blockWaitPeriod.Uint64() + log.WithField("randaoCommitDelay", wr.blockWaitPeriod).Trace("Fetched randaoCommitDelay") return nil @@ -393,28 +399,14 @@ func (wr *EthereumWriter) submitFiatShamir(ctx context.Context, task *Request) e "chosenValidator": chosenValidator, }).Info("Creating initial bitfield") - initialBitfield, err := wr.contract.CreateInitialBitfield( - &bind.CallOpts{ - Pending: true, - From: wr.conn.Keypair().CommonAddress(), - }, - signedValidators, validatorCount, - ) + initialBitfield, err := wr.createInitialBitfield(signedValidators, validatorCount) if err != nil { return fmt.Errorf("create initial bitfield: %w", err) } commitment := toBeefyClientCommitment(&task.SignedCommitment.Commitment) - finalBitfield, err := wr.contract.CreateFiatShamirFinalBitfield( - &bind.CallOpts{ - Pending: true, - From: wr.conn.Keypair().CommonAddress(), - }, - *commitment, - initialBitfield, - ) - + finalBitfield, err := wr.createFiatShamirFinalBitfield(commitment, initialBitfield) if err != nil { return fmt.Errorf("create validator final bitfield: %w", err) } @@ -431,15 +423,7 @@ func (wr *EthereumWriter) submitFiatShamir(ctx context.Context, task *Request) e return fmt.Errorf("logging params: %w", err) } - tx, err := wr.contract.SubmitFiatShamir( - wr.conn.MakeTxOpts(ctx), - params.Commitment, - params.Bitfield, - params.Proofs, - params.Leaf, - params.LeafProof, - params.LeafProofOrder, - ) + tx, err := wr.doSubmitFiatShamir(ctx, params) if err != nil { return fmt.Errorf("SubmitFiatShamir: %w", err) } @@ -463,12 +447,13 @@ func (wr *EthereumWriter) submitFiatShamir(ctx context.Context, task *Request) e // shouldSkipDueToPendingSession checks if another relayer already has a session in progress // that would advance the light client sufficiently. Returns true if we should skip. +// Note: This is only available when using the wrapper contract. func (wr *EthereumWriter) shouldSkipDueToPendingSession(ctx context.Context, task *Request) (bool, error) { callOpts := bind.CallOpts{ Context: ctx, } - highestPendingBlock, err := wr.contract.HighestPendingBlock(&callOpts) + highestPendingBlock, err := wr.wrapperContract.HighestPendingBlock(&callOpts) if err != nil { return false, fmt.Errorf("get highest pending block: %w", err) } @@ -478,12 +463,12 @@ func (wr *EthereumWriter) shouldSkipDueToPendingSession(ctx context.Context, tas return false, nil } - latestBeefyBlock, err := wr.contract.LatestBeefyBlock(&callOpts) + latestBeefyBlock, err := wr.wrapperContract.LatestBeefyBlock(&callOpts) if err != nil { return false, fmt.Errorf("get latest beefy block: %w", err) } - refundTarget, err := wr.contract.RefundTarget(&callOpts) + refundTarget, err := wr.wrapperContract.RefundTarget(&callOpts) if err != nil { return false, fmt.Errorf("get refund target: %w", err) } @@ -496,7 +481,7 @@ func (wr *EthereumWriter) shouldSkipDueToPendingSession(ctx context.Context, tas } // Check if the session has expired (> 40 minutes old) - pendingTimestamp, err := wr.contract.HighestPendingBlockTimestamp(&callOpts) + pendingTimestamp, err := wr.wrapperContract.HighestPendingBlockTimestamp(&callOpts) if err != nil { return false, fmt.Errorf("get highest pending block timestamp: %w", err) } @@ -519,3 +504,150 @@ func (wr *EthereumWriter) shouldSkipDueToPendingSession(ctx context.Context, tas return true, nil } + +// Contract abstraction helpers - these methods handle the contract selection and type conversions + +type validatorSetResult struct { + Id *big.Int + Root [32]byte +} + +func (wr *EthereumWriter) getLatestBeefyBlock(callOpts *bind.CallOpts) (uint64, error) { + if wr.useWrapper { + return wr.wrapperContract.LatestBeefyBlock(callOpts) + } + return wr.directContract.LatestBeefyBlock(callOpts) +} + +func (wr *EthereumWriter) getCurrentValidatorSet(callOpts *bind.CallOpts) (*validatorSetResult, error) { + if wr.useWrapper { + result, err := wr.wrapperContract.CurrentValidatorSet(callOpts) + if err != nil { + return nil, err + } + return &validatorSetResult{Id: result.Id, Root: result.Root}, nil + } + result, err := wr.directContract.CurrentValidatorSet(callOpts) + if err != nil { + return nil, err + } + return &validatorSetResult{Id: result.Id, Root: result.Root}, nil +} + +func (wr *EthereumWriter) getNextValidatorSet(callOpts *bind.CallOpts) (*validatorSetResult, error) { + if wr.useWrapper { + result, err := wr.wrapperContract.NextValidatorSet(callOpts) + if err != nil { + return nil, err + } + return &validatorSetResult{Id: result.Id, Root: result.Root}, nil + } + result, err := wr.directContract.NextValidatorSet(callOpts) + if err != nil { + return nil, err + } + return &validatorSetResult{Id: result.Id, Root: result.Root}, nil +} + +func (wr *EthereumWriter) createInitialBitfield(signedValidators []*big.Int, validatorCount *big.Int) ([]*big.Int, error) { + callOpts := &bind.CallOpts{ + Pending: true, + From: wr.conn.Keypair().CommonAddress(), + } + if wr.useWrapper { + return wr.wrapperContract.CreateInitialBitfield(callOpts, signedValidators, validatorCount) + } + return wr.directContract.CreateInitialBitfield(callOpts, signedValidators, validatorCount) +} + +func (wr *EthereumWriter) createFinalBitfield(commitmentHash [32]byte, initialBitfield []*big.Int) ([]*big.Int, error) { + callOpts := &bind.CallOpts{ + Pending: true, + From: wr.conn.Keypair().CommonAddress(), + } + if wr.useWrapper { + return wr.wrapperContract.CreateFinalBitfield(callOpts, commitmentHash, initialBitfield) + } + return wr.directContract.CreateFinalBitfield(callOpts, commitmentHash, initialBitfield) +} + +func (wr *EthereumWriter) createFiatShamirFinalBitfield(commitment *contracts.IBeefyClientCommitment, initialBitfield []*big.Int) ([]*big.Int, error) { + callOpts := &bind.CallOpts{ + Pending: true, + From: wr.conn.Keypair().CommonAddress(), + } + if wr.useWrapper { + return wr.wrapperContract.CreateFiatShamirFinalBitfield(callOpts, *commitment, initialBitfield) + } + return wr.directContract.CreateFiatShamirFinalBitfield(callOpts, ToBeefyClientCommitment(commitment), initialBitfield) +} + +func (wr *EthereumWriter) submitInitial(ctx context.Context, msg *InitialRequestParams) (*types.Transaction, error) { + if wr.useWrapper { + return wr.wrapperContract.SubmitInitial( + wr.conn.MakeTxOpts(ctx), + msg.Commitment, + msg.Bitfield, + msg.Proof, + ) + } + return wr.directContract.SubmitInitial( + wr.conn.MakeTxOpts(ctx), + ToBeefyClientCommitment(&msg.Commitment), + msg.Bitfield, + ToBeefyClientValidatorProof(&msg.Proof), + ) +} + +func (wr *EthereumWriter) doCommitPrevRandao(ctx context.Context, commitmentHash [32]byte) (*types.Transaction, error) { + if wr.useWrapper { + return wr.wrapperContract.CommitPrevRandao(wr.conn.MakeTxOpts(ctx), commitmentHash) + } + return wr.directContract.CommitPrevRandao(wr.conn.MakeTxOpts(ctx), commitmentHash) +} + +func (wr *EthereumWriter) submitFinal(ctx context.Context, params *FinalRequestParams) (*types.Transaction, error) { + if wr.useWrapper { + return wr.wrapperContract.SubmitFinal( + wr.conn.MakeTxOpts(ctx), + params.Commitment, + params.Bitfield, + params.Proofs, + params.Leaf, + params.LeafProof, + params.LeafProofOrder, + ) + } + return wr.directContract.SubmitFinal( + wr.conn.MakeTxOpts(ctx), + ToBeefyClientCommitment(¶ms.Commitment), + params.Bitfield, + ToBeefyClientValidatorProofs(params.Proofs), + ToBeefyClientMMRLeaf(¶ms.Leaf), + params.LeafProof, + params.LeafProofOrder, + ) +} + +func (wr *EthereumWriter) doSubmitFiatShamir(ctx context.Context, params *FinalRequestParams) (*types.Transaction, error) { + if wr.useWrapper { + return wr.wrapperContract.SubmitFiatShamir( + wr.conn.MakeTxOpts(ctx), + params.Commitment, + params.Bitfield, + params.Proofs, + params.Leaf, + params.LeafProof, + params.LeafProofOrder, + ) + } + return wr.directContract.SubmitFiatShamir( + wr.conn.MakeTxOpts(ctx), + ToBeefyClientCommitment(¶ms.Commitment), + params.Bitfield, + ToBeefyClientValidatorProofs(params.Proofs), + ToBeefyClientMMRLeaf(¶ms.Leaf), + params.LeafProof, + params.LeafProofOrder, + ) +} diff --git a/relayer/relays/beefy/parameters.go b/relayer/relays/beefy/parameters.go index d1a006364..8badf9804 100644 --- a/relayer/relays/beefy/parameters.go +++ b/relayer/relays/beefy/parameters.go @@ -279,3 +279,50 @@ func proofToLog(proof contracts.IBeefyClientValidatorProof) logrus.Fields { "Proof": hexProof, } } + +// Converter functions for direct BeefyClient contract (without wrapper) +func ToBeefyClientCommitment(c *contracts.IBeefyClientCommitment) contracts.BeefyClientCommitment { + payload := make([]contracts.BeefyClientPayloadItem, len(c.Payload)) + for i, item := range c.Payload { + payload[i] = contracts.BeefyClientPayloadItem{ + PayloadID: item.PayloadID, + Data: item.Data, + } + } + return contracts.BeefyClientCommitment{ + BlockNumber: c.BlockNumber, + ValidatorSetID: c.ValidatorSetID, + Payload: payload, + } +} + +func ToBeefyClientValidatorProof(p *contracts.IBeefyClientValidatorProof) contracts.BeefyClientValidatorProof { + return contracts.BeefyClientValidatorProof{ + V: p.V, + R: p.R, + S: p.S, + Index: p.Index, + Account: p.Account, + Proof: p.Proof, + } +} + +func ToBeefyClientValidatorProofs(proofs []contracts.IBeefyClientValidatorProof) []contracts.BeefyClientValidatorProof { + result := make([]contracts.BeefyClientValidatorProof, len(proofs)) + for i, p := range proofs { + result[i] = ToBeefyClientValidatorProof(&p) + } + return result +} + +func ToBeefyClientMMRLeaf(leaf *contracts.IBeefyClientMMRLeaf) contracts.BeefyClientMMRLeaf { + return contracts.BeefyClientMMRLeaf{ + Version: leaf.Version, + ParentNumber: leaf.ParentNumber, + ParentHash: leaf.ParentHash, + ParachainHeadsRoot: leaf.ParachainHeadsRoot, + NextAuthoritySetID: leaf.NextAuthoritySetID, + NextAuthoritySetLen: leaf.NextAuthoritySetLen, + NextAuthoritySetRoot: leaf.NextAuthoritySetRoot, + } +} From e919c32874996c8892295289ef637b5ffc0db696 Mon Sep 17 00:00:00 2001 From: claravanstaden Date: Thu, 5 Feb 2026 11:28:55 +0200 Subject: [PATCH 14/17] use beefy client directly --- contracts/src/BeefyClientWrapper.sol | 42 ---- contracts/test/BeefyClientWrapper.t.sol | 43 ---- relayer/contracts/beefy_client_wrapper.go | 257 +--------------------- relayer/relays/beefy/ethereum-writer.go | 102 +++------ 4 files changed, 36 insertions(+), 408 deletions(-) diff --git a/contracts/src/BeefyClientWrapper.sol b/contracts/src/BeefyClientWrapper.sol index 2030a9f16..b81bcd851 100644 --- a/contracts/src/BeefyClientWrapper.sol +++ b/contracts/src/BeefyClientWrapper.sol @@ -128,48 +128,6 @@ contract BeefyClientWrapper { _refundWithProgress(startGas, previousGas, progress); } - function createFinalBitfield(bytes32 commitmentHash, uint256[] calldata bitfield) - external - view - returns (uint256[] memory) - { - return beefyClient.createFinalBitfield(commitmentHash, bitfield); - } - - function latestBeefyBlock() external view returns (uint64) { - return beefyClient.latestBeefyBlock(); - } - - function createInitialBitfield(uint256[] calldata bitsToSet, uint256 length) - external - view - returns (uint256[] memory) - { - return beefyClient.createInitialBitfield(bitsToSet, length); - } - - function randaoCommitDelay() external view returns (uint256) { - return beefyClient.randaoCommitDelay(); - } - - function currentValidatorSet() external view returns (uint128 id, uint128 length, bytes32 root) { - return beefyClient.currentValidatorSet(); - } - - function nextValidatorSet() external view returns (uint128 id, uint128 length, bytes32 root) { - return beefyClient.nextValidatorSet(); - } - - /* Fiat-Shamir Proxy Functions */ - - function createFiatShamirFinalBitfield(IBeefyClient.Commitment calldata commitment, uint256[] calldata bitfield) - external - view - returns (uint256[] memory) - { - return beefyClient.createFiatShamirFinalBitfield(commitment, bitfield); - } - function submitFiatShamir( IBeefyClient.Commitment calldata commitment, uint256[] calldata bitfield, diff --git a/contracts/test/BeefyClientWrapper.t.sol b/contracts/test/BeefyClientWrapper.t.sol index bf3152411..f42f6522e 100644 --- a/contracts/test/BeefyClientWrapper.t.sol +++ b/contracts/test/BeefyClientWrapper.t.sol @@ -620,47 +620,4 @@ contract BeefyClientWrapperTest is Test { assertTrue(success); assertEq(address(wrapper).balance, balanceBefore + 1 ether); } - - /* View Function Tests */ - - function test_latestBeefyBlock() public { - assertEq(wrapper.latestBeefyBlock(), INITIAL_BEEFY_BLOCK); - } - - /* Proxy View Function Tests */ - - function test_createFinalBitfield() public { - bytes32 commitmentHash = bytes32(uint256(1)); - uint256[] memory bitfield = new uint256[](1); - bitfield[0] = 123; - - uint256[] memory result = wrapper.createFinalBitfield(commitmentHash, bitfield); - assertEq(result[0], 123); - } - - function test_createInitialBitfield() public { - uint256[] memory bitsToSet = new uint256[](1); - bitsToSet[0] = 5; - - uint256[] memory result = wrapper.createInitialBitfield(bitsToSet, 100); - assertEq(result.length, 1); - } - - function test_randaoCommitDelay() public { - assertEq(wrapper.randaoCommitDelay(), 4); - } - - function test_currentValidatorSet() public { - (uint128 id, uint128 length, bytes32 root) = wrapper.currentValidatorSet(); - assertEq(id, 1); - assertEq(length, 100); - assertEq(root, bytes32(0)); - } - - function test_nextValidatorSet() public { - (uint128 id, uint128 length, bytes32 root) = wrapper.nextValidatorSet(); - assertEq(id, 2); - assertEq(length, 100); - assertEq(root, bytes32(0)); - } } diff --git a/relayer/contracts/beefy_client_wrapper.go b/relayer/contracts/beefy_client_wrapper.go index d7342f2d3..8b86478ba 100644 --- a/relayer/contracts/beefy_client_wrapper.go +++ b/relayer/contracts/beefy_client_wrapper.go @@ -65,7 +65,7 @@ type IBeefyClientValidatorProof struct { // BeefyClientWrapperMetaData contains all meta data concerning the BeefyClientWrapper contract. var BeefyClientWrapperMetaData = &bind.MetaData{ - ABI: "[{\"type\":\"constructor\",\"inputs\":[{\"name\":\"_beefyClient\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"_owner\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"_maxGasPrice\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_maxRefundAmount\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_refundTarget\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"receive\",\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"beefyClient\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"contractIBeefyClient\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"clearTicket\",\"inputs\":[{\"name\":\"commitmentHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"commitPrevRandao\",\"inputs\":[{\"name\":\"commitmentHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"createFiatShamirFinalBitfield\",\"inputs\":[{\"name\":\"commitment\",\"type\":\"tuple\",\"internalType\":\"structIBeefyClient.Commitment\",\"components\":[{\"name\":\"blockNumber\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"validatorSetID\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"payload\",\"type\":\"tuple[]\",\"internalType\":\"structIBeefyClient.PayloadItem[]\",\"components\":[{\"name\":\"payloadID\",\"type\":\"bytes2\",\"internalType\":\"bytes2\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]},{\"name\":\"bitfield\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"createFinalBitfield\",\"inputs\":[{\"name\":\"commitmentHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"bitfield\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"createInitialBitfield\",\"inputs\":[{\"name\":\"bitsToSet\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"},{\"name\":\"length\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"creditedGas\",\"inputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"currentValidatorSet\",\"inputs\":[],\"outputs\":[{\"name\":\"id\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"length\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"root\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"estimatePayout\",\"inputs\":[{\"name\":\"gasUsed\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"gasPrice\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"progress\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"refundAmount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"highestPendingBlock\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"highestPendingBlockTimestamp\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"latestBeefyBlock\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint64\",\"internalType\":\"uint64\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"maxGasPrice\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"maxRefundAmount\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"nextValidatorSet\",\"inputs\":[],\"outputs\":[{\"name\":\"id\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"length\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"root\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"owner\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"randaoCommitDelay\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"refundTarget\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"setMaxGasPrice\",\"inputs\":[{\"name\":\"_maxGasPrice\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setMaxRefundAmount\",\"inputs\":[{\"name\":\"_maxRefundAmount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setRefundTarget\",\"inputs\":[{\"name\":\"_refundTarget\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"submitFiatShamir\",\"inputs\":[{\"name\":\"commitment\",\"type\":\"tuple\",\"internalType\":\"structIBeefyClient.Commitment\",\"components\":[{\"name\":\"blockNumber\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"validatorSetID\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"payload\",\"type\":\"tuple[]\",\"internalType\":\"structIBeefyClient.PayloadItem[]\",\"components\":[{\"name\":\"payloadID\",\"type\":\"bytes2\",\"internalType\":\"bytes2\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]},{\"name\":\"bitfield\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"},{\"name\":\"proofs\",\"type\":\"tuple[]\",\"internalType\":\"structIBeefyClient.ValidatorProof[]\",\"components\":[{\"name\":\"v\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"r\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"s\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"index\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"proof\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"}]},{\"name\":\"leaf\",\"type\":\"tuple\",\"internalType\":\"structIBeefyClient.MMRLeaf\",\"components\":[{\"name\":\"version\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"parentNumber\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"parentHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"nextAuthoritySetID\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"nextAuthoritySetLen\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"nextAuthoritySetRoot\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"parachainHeadsRoot\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"name\":\"leafProof\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"},{\"name\":\"leafProofOrder\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"submitFinal\",\"inputs\":[{\"name\":\"commitment\",\"type\":\"tuple\",\"internalType\":\"structIBeefyClient.Commitment\",\"components\":[{\"name\":\"blockNumber\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"validatorSetID\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"payload\",\"type\":\"tuple[]\",\"internalType\":\"structIBeefyClient.PayloadItem[]\",\"components\":[{\"name\":\"payloadID\",\"type\":\"bytes2\",\"internalType\":\"bytes2\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]},{\"name\":\"bitfield\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"},{\"name\":\"proofs\",\"type\":\"tuple[]\",\"internalType\":\"structIBeefyClient.ValidatorProof[]\",\"components\":[{\"name\":\"v\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"r\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"s\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"index\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"proof\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"}]},{\"name\":\"leaf\",\"type\":\"tuple\",\"internalType\":\"structIBeefyClient.MMRLeaf\",\"components\":[{\"name\":\"version\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"parentNumber\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"parentHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"nextAuthoritySetID\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"nextAuthoritySetLen\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"nextAuthoritySetRoot\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"parachainHeadsRoot\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"name\":\"leafProof\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"},{\"name\":\"leafProofOrder\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"submitInitial\",\"inputs\":[{\"name\":\"commitment\",\"type\":\"tuple\",\"internalType\":\"structIBeefyClient.Commitment\",\"components\":[{\"name\":\"blockNumber\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"validatorSetID\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"payload\",\"type\":\"tuple[]\",\"internalType\":\"structIBeefyClient.PayloadItem[]\",\"components\":[{\"name\":\"payloadID\",\"type\":\"bytes2\",\"internalType\":\"bytes2\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]},{\"name\":\"bitfield\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"},{\"name\":\"proof\",\"type\":\"tuple\",\"internalType\":\"structIBeefyClient.ValidatorProof\",\"components\":[{\"name\":\"v\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"r\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"s\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"index\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"proof\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"ticketOwner\",\"inputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"transferOwnership\",\"inputs\":[{\"name\":\"newOwner\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"withdrawFunds\",\"inputs\":[{\"name\":\"recipient\",\"type\":\"address\",\"internalType\":\"addresspayable\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"event\",\"name\":\"FundsDeposited\",\"inputs\":[{\"name\":\"depositor\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"FundsWithdrawn\",\"inputs\":[{\"name\":\"recipient\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"GasCredited\",\"inputs\":[{\"name\":\"relayer\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"commitmentHash\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"gasUsed\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"SubmissionRefunded\",\"inputs\":[{\"name\":\"relayer\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"progress\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"},{\"name\":\"refundAmount\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"},{\"name\":\"totalGasUsed\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"error\",\"name\":\"InvalidAddress\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"NotTicketOwner\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"TransferFailed\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"Unauthorized\",\"inputs\":[]}]", + ABI: "[{\"type\":\"constructor\",\"inputs\":[{\"name\":\"_beefyClient\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"_owner\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"_maxGasPrice\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_maxRefundAmount\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_refundTarget\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"receive\",\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"beefyClient\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"contractIBeefyClient\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"clearTicket\",\"inputs\":[{\"name\":\"commitmentHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"commitPrevRandao\",\"inputs\":[{\"name\":\"commitmentHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"creditedGas\",\"inputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"estimatePayout\",\"inputs\":[{\"name\":\"gasUsed\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"gasPrice\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"progress\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"refundAmount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"highestPendingBlock\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"highestPendingBlockTimestamp\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"maxGasPrice\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"maxRefundAmount\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"owner\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"refundTarget\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"setMaxGasPrice\",\"inputs\":[{\"name\":\"_maxGasPrice\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setMaxRefundAmount\",\"inputs\":[{\"name\":\"_maxRefundAmount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setRefundTarget\",\"inputs\":[{\"name\":\"_refundTarget\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"submitFiatShamir\",\"inputs\":[{\"name\":\"commitment\",\"type\":\"tuple\",\"internalType\":\"structIBeefyClient.Commitment\",\"components\":[{\"name\":\"blockNumber\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"validatorSetID\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"payload\",\"type\":\"tuple[]\",\"internalType\":\"structIBeefyClient.PayloadItem[]\",\"components\":[{\"name\":\"payloadID\",\"type\":\"bytes2\",\"internalType\":\"bytes2\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]},{\"name\":\"bitfield\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"},{\"name\":\"proofs\",\"type\":\"tuple[]\",\"internalType\":\"structIBeefyClient.ValidatorProof[]\",\"components\":[{\"name\":\"v\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"r\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"s\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"index\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"proof\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"}]},{\"name\":\"leaf\",\"type\":\"tuple\",\"internalType\":\"structIBeefyClient.MMRLeaf\",\"components\":[{\"name\":\"version\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"parentNumber\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"parentHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"nextAuthoritySetID\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"nextAuthoritySetLen\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"nextAuthoritySetRoot\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"parachainHeadsRoot\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"name\":\"leafProof\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"},{\"name\":\"leafProofOrder\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"submitFinal\",\"inputs\":[{\"name\":\"commitment\",\"type\":\"tuple\",\"internalType\":\"structIBeefyClient.Commitment\",\"components\":[{\"name\":\"blockNumber\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"validatorSetID\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"payload\",\"type\":\"tuple[]\",\"internalType\":\"structIBeefyClient.PayloadItem[]\",\"components\":[{\"name\":\"payloadID\",\"type\":\"bytes2\",\"internalType\":\"bytes2\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]},{\"name\":\"bitfield\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"},{\"name\":\"proofs\",\"type\":\"tuple[]\",\"internalType\":\"structIBeefyClient.ValidatorProof[]\",\"components\":[{\"name\":\"v\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"r\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"s\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"index\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"proof\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"}]},{\"name\":\"leaf\",\"type\":\"tuple\",\"internalType\":\"structIBeefyClient.MMRLeaf\",\"components\":[{\"name\":\"version\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"parentNumber\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"parentHash\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"nextAuthoritySetID\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"nextAuthoritySetLen\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"nextAuthoritySetRoot\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"parachainHeadsRoot\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}]},{\"name\":\"leafProof\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"},{\"name\":\"leafProofOrder\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"submitInitial\",\"inputs\":[{\"name\":\"commitment\",\"type\":\"tuple\",\"internalType\":\"structIBeefyClient.Commitment\",\"components\":[{\"name\":\"blockNumber\",\"type\":\"uint32\",\"internalType\":\"uint32\"},{\"name\":\"validatorSetID\",\"type\":\"uint64\",\"internalType\":\"uint64\"},{\"name\":\"payload\",\"type\":\"tuple[]\",\"internalType\":\"structIBeefyClient.PayloadItem[]\",\"components\":[{\"name\":\"payloadID\",\"type\":\"bytes2\",\"internalType\":\"bytes2\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"}]}]},{\"name\":\"bitfield\",\"type\":\"uint256[]\",\"internalType\":\"uint256[]\"},{\"name\":\"proof\",\"type\":\"tuple\",\"internalType\":\"structIBeefyClient.ValidatorProof\",\"components\":[{\"name\":\"v\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"r\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"s\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"index\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"account\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"proof\",\"type\":\"bytes32[]\",\"internalType\":\"bytes32[]\"}]}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"ticketOwner\",\"inputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"transferOwnership\",\"inputs\":[{\"name\":\"newOwner\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"withdrawFunds\",\"inputs\":[{\"name\":\"recipient\",\"type\":\"address\",\"internalType\":\"addresspayable\"},{\"name\":\"amount\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"event\",\"name\":\"FundsDeposited\",\"inputs\":[{\"name\":\"depositor\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"FundsWithdrawn\",\"inputs\":[{\"name\":\"recipient\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"amount\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"GasCredited\",\"inputs\":[{\"name\":\"relayer\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"commitmentHash\",\"type\":\"bytes32\",\"indexed\":true,\"internalType\":\"bytes32\"},{\"name\":\"gasUsed\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"SubmissionRefunded\",\"inputs\":[{\"name\":\"relayer\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"progress\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"},{\"name\":\"refundAmount\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"},{\"name\":\"totalGasUsed\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"error\",\"name\":\"InvalidAddress\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"NotTicketOwner\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"TransferFailed\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"Unauthorized\",\"inputs\":[]}]", } // BeefyClientWrapperABI is the input ABI used to generate the binding from. @@ -245,99 +245,6 @@ func (_BeefyClientWrapper *BeefyClientWrapperCallerSession) BeefyClient() (commo return _BeefyClientWrapper.Contract.BeefyClient(&_BeefyClientWrapper.CallOpts) } -// CreateFiatShamirFinalBitfield is a free data retrieval call binding the contract method 0x4b4cfb28. -// -// Solidity: function createFiatShamirFinalBitfield((uint32,uint64,(bytes2,bytes)[]) commitment, uint256[] bitfield) view returns(uint256[]) -func (_BeefyClientWrapper *BeefyClientWrapperCaller) CreateFiatShamirFinalBitfield(opts *bind.CallOpts, commitment IBeefyClientCommitment, bitfield []*big.Int) ([]*big.Int, error) { - var out []interface{} - err := _BeefyClientWrapper.contract.Call(opts, &out, "createFiatShamirFinalBitfield", commitment, bitfield) - - if err != nil { - return *new([]*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new([]*big.Int)).(*[]*big.Int) - - return out0, err - -} - -// CreateFiatShamirFinalBitfield is a free data retrieval call binding the contract method 0x4b4cfb28. -// -// Solidity: function createFiatShamirFinalBitfield((uint32,uint64,(bytes2,bytes)[]) commitment, uint256[] bitfield) view returns(uint256[]) -func (_BeefyClientWrapper *BeefyClientWrapperSession) CreateFiatShamirFinalBitfield(commitment IBeefyClientCommitment, bitfield []*big.Int) ([]*big.Int, error) { - return _BeefyClientWrapper.Contract.CreateFiatShamirFinalBitfield(&_BeefyClientWrapper.CallOpts, commitment, bitfield) -} - -// CreateFiatShamirFinalBitfield is a free data retrieval call binding the contract method 0x4b4cfb28. -// -// Solidity: function createFiatShamirFinalBitfield((uint32,uint64,(bytes2,bytes)[]) commitment, uint256[] bitfield) view returns(uint256[]) -func (_BeefyClientWrapper *BeefyClientWrapperCallerSession) CreateFiatShamirFinalBitfield(commitment IBeefyClientCommitment, bitfield []*big.Int) ([]*big.Int, error) { - return _BeefyClientWrapper.Contract.CreateFiatShamirFinalBitfield(&_BeefyClientWrapper.CallOpts, commitment, bitfield) -} - -// CreateFinalBitfield is a free data retrieval call binding the contract method 0x8ab81d13. -// -// Solidity: function createFinalBitfield(bytes32 commitmentHash, uint256[] bitfield) view returns(uint256[]) -func (_BeefyClientWrapper *BeefyClientWrapperCaller) CreateFinalBitfield(opts *bind.CallOpts, commitmentHash [32]byte, bitfield []*big.Int) ([]*big.Int, error) { - var out []interface{} - err := _BeefyClientWrapper.contract.Call(opts, &out, "createFinalBitfield", commitmentHash, bitfield) - - if err != nil { - return *new([]*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new([]*big.Int)).(*[]*big.Int) - - return out0, err - -} - -// CreateFinalBitfield is a free data retrieval call binding the contract method 0x8ab81d13. -// -// Solidity: function createFinalBitfield(bytes32 commitmentHash, uint256[] bitfield) view returns(uint256[]) -func (_BeefyClientWrapper *BeefyClientWrapperSession) CreateFinalBitfield(commitmentHash [32]byte, bitfield []*big.Int) ([]*big.Int, error) { - return _BeefyClientWrapper.Contract.CreateFinalBitfield(&_BeefyClientWrapper.CallOpts, commitmentHash, bitfield) -} - -// CreateFinalBitfield is a free data retrieval call binding the contract method 0x8ab81d13. -// -// Solidity: function createFinalBitfield(bytes32 commitmentHash, uint256[] bitfield) view returns(uint256[]) -func (_BeefyClientWrapper *BeefyClientWrapperCallerSession) CreateFinalBitfield(commitmentHash [32]byte, bitfield []*big.Int) ([]*big.Int, error) { - return _BeefyClientWrapper.Contract.CreateFinalBitfield(&_BeefyClientWrapper.CallOpts, commitmentHash, bitfield) -} - -// CreateInitialBitfield is a free data retrieval call binding the contract method 0x5da57fe9. -// -// Solidity: function createInitialBitfield(uint256[] bitsToSet, uint256 length) view returns(uint256[]) -func (_BeefyClientWrapper *BeefyClientWrapperCaller) CreateInitialBitfield(opts *bind.CallOpts, bitsToSet []*big.Int, length *big.Int) ([]*big.Int, error) { - var out []interface{} - err := _BeefyClientWrapper.contract.Call(opts, &out, "createInitialBitfield", bitsToSet, length) - - if err != nil { - return *new([]*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new([]*big.Int)).(*[]*big.Int) - - return out0, err - -} - -// CreateInitialBitfield is a free data retrieval call binding the contract method 0x5da57fe9. -// -// Solidity: function createInitialBitfield(uint256[] bitsToSet, uint256 length) view returns(uint256[]) -func (_BeefyClientWrapper *BeefyClientWrapperSession) CreateInitialBitfield(bitsToSet []*big.Int, length *big.Int) ([]*big.Int, error) { - return _BeefyClientWrapper.Contract.CreateInitialBitfield(&_BeefyClientWrapper.CallOpts, bitsToSet, length) -} - -// CreateInitialBitfield is a free data retrieval call binding the contract method 0x5da57fe9. -// -// Solidity: function createInitialBitfield(uint256[] bitsToSet, uint256 length) view returns(uint256[]) -func (_BeefyClientWrapper *BeefyClientWrapperCallerSession) CreateInitialBitfield(bitsToSet []*big.Int, length *big.Int) ([]*big.Int, error) { - return _BeefyClientWrapper.Contract.CreateInitialBitfield(&_BeefyClientWrapper.CallOpts, bitsToSet, length) -} - // CreditedGas is a free data retrieval call binding the contract method 0x660b2928. // // Solidity: function creditedGas(bytes32 ) view returns(uint256) @@ -369,56 +276,6 @@ func (_BeefyClientWrapper *BeefyClientWrapperCallerSession) CreditedGas(arg0 [32 return _BeefyClientWrapper.Contract.CreditedGas(&_BeefyClientWrapper.CallOpts, arg0) } -// CurrentValidatorSet is a free data retrieval call binding the contract method 0x2cdea717. -// -// Solidity: function currentValidatorSet() view returns(uint128 id, uint128 length, bytes32 root) -func (_BeefyClientWrapper *BeefyClientWrapperCaller) CurrentValidatorSet(opts *bind.CallOpts) (struct { - Id *big.Int - Length *big.Int - Root [32]byte -}, error) { - var out []interface{} - err := _BeefyClientWrapper.contract.Call(opts, &out, "currentValidatorSet") - - outstruct := new(struct { - Id *big.Int - Length *big.Int - Root [32]byte - }) - if err != nil { - return *outstruct, err - } - - outstruct.Id = *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - outstruct.Length = *abi.ConvertType(out[1], new(*big.Int)).(**big.Int) - outstruct.Root = *abi.ConvertType(out[2], new([32]byte)).(*[32]byte) - - return *outstruct, err - -} - -// CurrentValidatorSet is a free data retrieval call binding the contract method 0x2cdea717. -// -// Solidity: function currentValidatorSet() view returns(uint128 id, uint128 length, bytes32 root) -func (_BeefyClientWrapper *BeefyClientWrapperSession) CurrentValidatorSet() (struct { - Id *big.Int - Length *big.Int - Root [32]byte -}, error) { - return _BeefyClientWrapper.Contract.CurrentValidatorSet(&_BeefyClientWrapper.CallOpts) -} - -// CurrentValidatorSet is a free data retrieval call binding the contract method 0x2cdea717. -// -// Solidity: function currentValidatorSet() view returns(uint128 id, uint128 length, bytes32 root) -func (_BeefyClientWrapper *BeefyClientWrapperCallerSession) CurrentValidatorSet() (struct { - Id *big.Int - Length *big.Int - Root [32]byte -}, error) { - return _BeefyClientWrapper.Contract.CurrentValidatorSet(&_BeefyClientWrapper.CallOpts) -} - // EstimatePayout is a free data retrieval call binding the contract method 0x83d29b40. // // Solidity: function estimatePayout(uint256 gasUsed, uint256 gasPrice, uint256 progress) view returns(uint256 refundAmount) @@ -512,37 +369,6 @@ func (_BeefyClientWrapper *BeefyClientWrapperCallerSession) HighestPendingBlockT return _BeefyClientWrapper.Contract.HighestPendingBlockTimestamp(&_BeefyClientWrapper.CallOpts) } -// LatestBeefyBlock is a free data retrieval call binding the contract method 0x66ae69a0. -// -// Solidity: function latestBeefyBlock() view returns(uint64) -func (_BeefyClientWrapper *BeefyClientWrapperCaller) LatestBeefyBlock(opts *bind.CallOpts) (uint64, error) { - var out []interface{} - err := _BeefyClientWrapper.contract.Call(opts, &out, "latestBeefyBlock") - - if err != nil { - return *new(uint64), err - } - - out0 := *abi.ConvertType(out[0], new(uint64)).(*uint64) - - return out0, err - -} - -// LatestBeefyBlock is a free data retrieval call binding the contract method 0x66ae69a0. -// -// Solidity: function latestBeefyBlock() view returns(uint64) -func (_BeefyClientWrapper *BeefyClientWrapperSession) LatestBeefyBlock() (uint64, error) { - return _BeefyClientWrapper.Contract.LatestBeefyBlock(&_BeefyClientWrapper.CallOpts) -} - -// LatestBeefyBlock is a free data retrieval call binding the contract method 0x66ae69a0. -// -// Solidity: function latestBeefyBlock() view returns(uint64) -func (_BeefyClientWrapper *BeefyClientWrapperCallerSession) LatestBeefyBlock() (uint64, error) { - return _BeefyClientWrapper.Contract.LatestBeefyBlock(&_BeefyClientWrapper.CallOpts) -} - // MaxGasPrice is a free data retrieval call binding the contract method 0x3de39c11. // // Solidity: function maxGasPrice() view returns(uint256) @@ -605,56 +431,6 @@ func (_BeefyClientWrapper *BeefyClientWrapperCallerSession) MaxRefundAmount() (* return _BeefyClientWrapper.Contract.MaxRefundAmount(&_BeefyClientWrapper.CallOpts) } -// NextValidatorSet is a free data retrieval call binding the contract method 0x36667513. -// -// Solidity: function nextValidatorSet() view returns(uint128 id, uint128 length, bytes32 root) -func (_BeefyClientWrapper *BeefyClientWrapperCaller) NextValidatorSet(opts *bind.CallOpts) (struct { - Id *big.Int - Length *big.Int - Root [32]byte -}, error) { - var out []interface{} - err := _BeefyClientWrapper.contract.Call(opts, &out, "nextValidatorSet") - - outstruct := new(struct { - Id *big.Int - Length *big.Int - Root [32]byte - }) - if err != nil { - return *outstruct, err - } - - outstruct.Id = *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - outstruct.Length = *abi.ConvertType(out[1], new(*big.Int)).(**big.Int) - outstruct.Root = *abi.ConvertType(out[2], new([32]byte)).(*[32]byte) - - return *outstruct, err - -} - -// NextValidatorSet is a free data retrieval call binding the contract method 0x36667513. -// -// Solidity: function nextValidatorSet() view returns(uint128 id, uint128 length, bytes32 root) -func (_BeefyClientWrapper *BeefyClientWrapperSession) NextValidatorSet() (struct { - Id *big.Int - Length *big.Int - Root [32]byte -}, error) { - return _BeefyClientWrapper.Contract.NextValidatorSet(&_BeefyClientWrapper.CallOpts) -} - -// NextValidatorSet is a free data retrieval call binding the contract method 0x36667513. -// -// Solidity: function nextValidatorSet() view returns(uint128 id, uint128 length, bytes32 root) -func (_BeefyClientWrapper *BeefyClientWrapperCallerSession) NextValidatorSet() (struct { - Id *big.Int - Length *big.Int - Root [32]byte -}, error) { - return _BeefyClientWrapper.Contract.NextValidatorSet(&_BeefyClientWrapper.CallOpts) -} - // Owner is a free data retrieval call binding the contract method 0x8da5cb5b. // // Solidity: function owner() view returns(address) @@ -686,37 +462,6 @@ func (_BeefyClientWrapper *BeefyClientWrapperCallerSession) Owner() (common.Addr return _BeefyClientWrapper.Contract.Owner(&_BeefyClientWrapper.CallOpts) } -// RandaoCommitDelay is a free data retrieval call binding the contract method 0x591d99ee. -// -// Solidity: function randaoCommitDelay() view returns(uint256) -func (_BeefyClientWrapper *BeefyClientWrapperCaller) RandaoCommitDelay(opts *bind.CallOpts) (*big.Int, error) { - var out []interface{} - err := _BeefyClientWrapper.contract.Call(opts, &out, "randaoCommitDelay") - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -// RandaoCommitDelay is a free data retrieval call binding the contract method 0x591d99ee. -// -// Solidity: function randaoCommitDelay() view returns(uint256) -func (_BeefyClientWrapper *BeefyClientWrapperSession) RandaoCommitDelay() (*big.Int, error) { - return _BeefyClientWrapper.Contract.RandaoCommitDelay(&_BeefyClientWrapper.CallOpts) -} - -// RandaoCommitDelay is a free data retrieval call binding the contract method 0x591d99ee. -// -// Solidity: function randaoCommitDelay() view returns(uint256) -func (_BeefyClientWrapper *BeefyClientWrapperCallerSession) RandaoCommitDelay() (*big.Int, error) { - return _BeefyClientWrapper.Contract.RandaoCommitDelay(&_BeefyClientWrapper.CallOpts) -} - // RefundTarget is a free data retrieval call binding the contract method 0xd679e02a. // // Solidity: function refundTarget() view returns(uint256) diff --git a/relayer/relays/beefy/ethereum-writer.go b/relayer/relays/beefy/ethereum-writer.go index 704254ffe..bb864b1d5 100644 --- a/relayer/relays/beefy/ethereum-writer.go +++ b/relayer/relays/beefy/ethereum-writer.go @@ -31,7 +31,7 @@ type EthereumWriter struct { conn *ethereum.Connection useWrapper bool wrapperContract *contracts.BeefyClientWrapper - directContract *contracts.BeefyClient + beefyClient *contracts.BeefyClient blockWaitPeriod uint64 } @@ -320,51 +320,43 @@ func (wr *EthereumWriter) initialize(ctx context.Context) error { Context: ctx, } - // Check if wrapper is configured + beefyClientAddress := common.HexToAddress(wr.config.Contracts.BeefyClient) + beefyClient, err := contracts.NewBeefyClient(beefyClientAddress, wr.conn.Client()) + if err != nil { + return fmt.Errorf("create beefy client: %w", err) + } + wr.beefyClient = beefyClient + + blockWaitPeriod, err := wr.beefyClient.RandaoCommitDelay(&callOpts) + if err != nil { + return fmt.Errorf("get randao commit delay: %w", err) + } + wr.blockWaitPeriod = blockWaitPeriod.Uint64() + + // Optionally initialize wrapper for state-changing functions with gas refunds if wr.config.Contracts.BeefyClientWrapper != "" { wr.useWrapper = true - address := common.HexToAddress(wr.config.Contracts.BeefyClientWrapper) + wrapperAddress := common.HexToAddress(wr.config.Contracts.BeefyClientWrapper) - contract, err := contracts.NewBeefyClientWrapper(address, wr.conn.Client()) + wrapperContract, err := contracts.NewBeefyClientWrapper(wrapperAddress, wr.conn.Client()) if err != nil { return fmt.Errorf("create beefy client wrapper: %w", err) } - wr.wrapperContract = contract - - blockWaitPeriod, err := wr.wrapperContract.RandaoCommitDelay(&callOpts) - if err != nil { - return fmt.Errorf("get randao commit delay: %w", err) - } - wr.blockWaitPeriod = blockWaitPeriod.Uint64() + wr.wrapperContract = wrapperContract log.WithFields(logrus.Fields{ - "address": address.Hex(), + "beefyClient": beefyClientAddress.Hex(), + "wrapper": wrapperAddress.Hex(), "randaoCommitDelay": wr.blockWaitPeriod, }).Info("Using BeefyClientWrapper for gas refunds") } else { wr.useWrapper = false - address := common.HexToAddress(wr.config.Contracts.BeefyClient) - - contract, err := contracts.NewBeefyClient(address, wr.conn.Client()) - if err != nil { - return fmt.Errorf("create beefy client: %w", err) - } - wr.directContract = contract - - blockWaitPeriod, err := wr.directContract.RandaoCommitDelay(&callOpts) - if err != nil { - return fmt.Errorf("get randao commit delay: %w", err) - } - wr.blockWaitPeriod = blockWaitPeriod.Uint64() - log.WithFields(logrus.Fields{ - "address": address.Hex(), + "beefyClient": beefyClientAddress.Hex(), "randaoCommitDelay": wr.blockWaitPeriod, }).Info("Using BeefyClient directly (no gas refunds)") } - log.WithField("randaoCommitDelay", wr.blockWaitPeriod).Trace("Fetched randaoCommitDelay") - return nil } @@ -463,7 +455,7 @@ func (wr *EthereumWriter) shouldSkipDueToPendingSession(ctx context.Context, tas return false, nil } - latestBeefyBlock, err := wr.wrapperContract.LatestBeefyBlock(&callOpts) + latestBeefyBlock, err := wr.beefyClient.LatestBeefyBlock(&callOpts) if err != nil { return false, fmt.Errorf("get latest beefy block: %w", err) } @@ -505,7 +497,9 @@ func (wr *EthereumWriter) shouldSkipDueToPendingSession(ctx context.Context, tas return true, nil } -// Contract abstraction helpers - these methods handle the contract selection and type conversions +// Contract abstraction helpers +// View functions always use beefyClient directly +// State-changing functions use wrapper (if configured) or beefyClient type validatorSetResult struct { Id *big.Int @@ -513,21 +507,11 @@ type validatorSetResult struct { } func (wr *EthereumWriter) getLatestBeefyBlock(callOpts *bind.CallOpts) (uint64, error) { - if wr.useWrapper { - return wr.wrapperContract.LatestBeefyBlock(callOpts) - } - return wr.directContract.LatestBeefyBlock(callOpts) + return wr.beefyClient.LatestBeefyBlock(callOpts) } func (wr *EthereumWriter) getCurrentValidatorSet(callOpts *bind.CallOpts) (*validatorSetResult, error) { - if wr.useWrapper { - result, err := wr.wrapperContract.CurrentValidatorSet(callOpts) - if err != nil { - return nil, err - } - return &validatorSetResult{Id: result.Id, Root: result.Root}, nil - } - result, err := wr.directContract.CurrentValidatorSet(callOpts) + result, err := wr.beefyClient.CurrentValidatorSet(callOpts) if err != nil { return nil, err } @@ -535,14 +519,7 @@ func (wr *EthereumWriter) getCurrentValidatorSet(callOpts *bind.CallOpts) (*vali } func (wr *EthereumWriter) getNextValidatorSet(callOpts *bind.CallOpts) (*validatorSetResult, error) { - if wr.useWrapper { - result, err := wr.wrapperContract.NextValidatorSet(callOpts) - if err != nil { - return nil, err - } - return &validatorSetResult{Id: result.Id, Root: result.Root}, nil - } - result, err := wr.directContract.NextValidatorSet(callOpts) + result, err := wr.beefyClient.NextValidatorSet(callOpts) if err != nil { return nil, err } @@ -554,10 +531,7 @@ func (wr *EthereumWriter) createInitialBitfield(signedValidators []*big.Int, val Pending: true, From: wr.conn.Keypair().CommonAddress(), } - if wr.useWrapper { - return wr.wrapperContract.CreateInitialBitfield(callOpts, signedValidators, validatorCount) - } - return wr.directContract.CreateInitialBitfield(callOpts, signedValidators, validatorCount) + return wr.beefyClient.CreateInitialBitfield(callOpts, signedValidators, validatorCount) } func (wr *EthereumWriter) createFinalBitfield(commitmentHash [32]byte, initialBitfield []*big.Int) ([]*big.Int, error) { @@ -565,10 +539,7 @@ func (wr *EthereumWriter) createFinalBitfield(commitmentHash [32]byte, initialBi Pending: true, From: wr.conn.Keypair().CommonAddress(), } - if wr.useWrapper { - return wr.wrapperContract.CreateFinalBitfield(callOpts, commitmentHash, initialBitfield) - } - return wr.directContract.CreateFinalBitfield(callOpts, commitmentHash, initialBitfield) + return wr.beefyClient.CreateFinalBitfield(callOpts, commitmentHash, initialBitfield) } func (wr *EthereumWriter) createFiatShamirFinalBitfield(commitment *contracts.IBeefyClientCommitment, initialBitfield []*big.Int) ([]*big.Int, error) { @@ -576,10 +547,7 @@ func (wr *EthereumWriter) createFiatShamirFinalBitfield(commitment *contracts.IB Pending: true, From: wr.conn.Keypair().CommonAddress(), } - if wr.useWrapper { - return wr.wrapperContract.CreateFiatShamirFinalBitfield(callOpts, *commitment, initialBitfield) - } - return wr.directContract.CreateFiatShamirFinalBitfield(callOpts, ToBeefyClientCommitment(commitment), initialBitfield) + return wr.beefyClient.CreateFiatShamirFinalBitfield(callOpts, ToBeefyClientCommitment(commitment), initialBitfield) } func (wr *EthereumWriter) submitInitial(ctx context.Context, msg *InitialRequestParams) (*types.Transaction, error) { @@ -591,7 +559,7 @@ func (wr *EthereumWriter) submitInitial(ctx context.Context, msg *InitialRequest msg.Proof, ) } - return wr.directContract.SubmitInitial( + return wr.beefyClient.SubmitInitial( wr.conn.MakeTxOpts(ctx), ToBeefyClientCommitment(&msg.Commitment), msg.Bitfield, @@ -603,7 +571,7 @@ func (wr *EthereumWriter) doCommitPrevRandao(ctx context.Context, commitmentHash if wr.useWrapper { return wr.wrapperContract.CommitPrevRandao(wr.conn.MakeTxOpts(ctx), commitmentHash) } - return wr.directContract.CommitPrevRandao(wr.conn.MakeTxOpts(ctx), commitmentHash) + return wr.beefyClient.CommitPrevRandao(wr.conn.MakeTxOpts(ctx), commitmentHash) } func (wr *EthereumWriter) submitFinal(ctx context.Context, params *FinalRequestParams) (*types.Transaction, error) { @@ -618,7 +586,7 @@ func (wr *EthereumWriter) submitFinal(ctx context.Context, params *FinalRequestP params.LeafProofOrder, ) } - return wr.directContract.SubmitFinal( + return wr.beefyClient.SubmitFinal( wr.conn.MakeTxOpts(ctx), ToBeefyClientCommitment(¶ms.Commitment), params.Bitfield, @@ -641,7 +609,7 @@ func (wr *EthereumWriter) doSubmitFiatShamir(ctx context.Context, params *FinalR params.LeafProofOrder, ) } - return wr.directContract.SubmitFiatShamir( + return wr.beefyClient.SubmitFiatShamir( wr.conn.MakeTxOpts(ctx), ToBeefyClientCommitment(¶ms.Commitment), params.Bitfield, From 70ac4b0d9510dbfd0142ac4c8398d3b81438d898 Mon Sep 17 00:00:00 2001 From: claravanstaden Date: Thu, 5 Feb 2026 11:41:11 +0200 Subject: [PATCH 15/17] more tests --- contracts/test/BeefyClient.t.sol | 7 ++ contracts/test/BeefyClientWrapper.t.sol | 154 ++++++++++++++++++++++++ 2 files changed, 161 insertions(+) diff --git a/contracts/test/BeefyClient.t.sol b/contracts/test/BeefyClient.t.sol index a02cdbda9..a154be9b8 100644 --- a/contracts/test/BeefyClient.t.sol +++ b/contracts/test/BeefyClient.t.sol @@ -879,4 +879,11 @@ contract BeefyClientTest is Test { commitment, bitfield, fiatShamirValidatorProofs, mmrLeaf, mmrLeafProofs, leafProofOrder ); } + + function testComputeCommitmentHash() public { + BeefyClient.Commitment memory commitment = initialize(setId); + bytes32 computedHash = beefyClient.computeCommitmentHash(commitment); + // commitHash is loaded from the test data file and should match + assertEq(computedHash, commitHash); + } } diff --git a/contracts/test/BeefyClientWrapper.t.sol b/contracts/test/BeefyClientWrapper.t.sol index f42f6522e..876def7a5 100644 --- a/contracts/test/BeefyClientWrapper.t.sol +++ b/contracts/test/BeefyClientWrapper.t.sol @@ -92,6 +92,20 @@ contract MockBeefyClient { latestBeefyBlock = _block; } + uint256 public submitFiatShamirCount; + + function submitFiatShamir( + IBeefyClient.Commitment calldata commitment, + uint256[] calldata, + IBeefyClient.ValidatorProof[] calldata, + IBeefyClient.MMRLeaf calldata, + bytes32[] calldata, + uint256 + ) external { + submitFiatShamirCount++; + latestBeefyBlock = commitment.blockNumber; + } + function _encodeCommitment(IBeefyClient.Commitment calldata commitment) internal pure @@ -620,4 +634,144 @@ contract BeefyClientWrapperTest is Test { assertTrue(success); assertEq(address(wrapper).balance, balanceBefore + 1 ether); } + + /* Fiat Shamir Tests */ + + function test_submitFiatShamir() public { + uint32 newBlockNumber = uint32(INITIAL_BEEFY_BLOCK + 500); + IBeefyClient.Commitment memory commitment = createCommitment(newBlockNumber); + uint256[] memory bitfield = new uint256[](1); + IBeefyClient.ValidatorProof[] memory proofs = createValidatorProofs(1); + IBeefyClient.MMRLeaf memory leaf = createMMRLeaf(); + bytes32[] memory leafProof = new bytes32[](0); + + vm.prank(relayer1); + wrapper.submitFiatShamir(commitment, bitfield, proofs, leaf, leafProof, 0); + + assertEq(mockBeefyClient.submitFiatShamirCount(), 1); + } + + function test_submitFiatShamir_clearsHighestPendingBlock() public { + // First create a pending session + uint32 pendingBlockNumber = uint32(INITIAL_BEEFY_BLOCK + 100); + IBeefyClient.Commitment memory pendingCommitment = createCommitment(pendingBlockNumber); + uint256[] memory bitfield = new uint256[](1); + IBeefyClient.ValidatorProof memory proof = createValidatorProof(); + + vm.prank(relayer1); + wrapper.submitInitial(pendingCommitment, bitfield, proof); + assertEq(wrapper.highestPendingBlock(), pendingBlockNumber); + + // Submit Fiat Shamir with higher block number + uint32 fiatShamirBlockNumber = uint32(INITIAL_BEEFY_BLOCK + 200); + IBeefyClient.Commitment memory fiatShamirCommitment = createCommitment(fiatShamirBlockNumber); + IBeefyClient.ValidatorProof[] memory proofs = createValidatorProofs(1); + IBeefyClient.MMRLeaf memory leaf = createMMRLeaf(); + bytes32[] memory leafProof = new bytes32[](0); + + vm.prank(relayer2); + wrapper.submitFiatShamir(fiatShamirCommitment, bitfield, proofs, leaf, leafProof, 0); + + // highestPendingBlock should be cleared since latestBeefyBlock >= highestPendingBlock + assertEq(wrapper.highestPendingBlock(), 0); + assertEq(wrapper.highestPendingBlockTimestamp(), 0); + } + + /* Additional Admin Function Tests */ + + function test_withdrawFunds_invalidRecipient() public { + vm.prank(owner); + vm.expectRevert(BeefyClientWrapper.InvalidAddress.selector); + wrapper.withdrawFunds(payable(address(0)), 1 ether); + } + + function test_transferOwnership_invalidAddress() public { + vm.prank(owner); + vm.expectRevert(BeefyClientWrapper.InvalidAddress.selector); + wrapper.transferOwnership(address(0)); + } + + /* Highest Pending Block Tests */ + + function test_submitInitial_doesNotUpdateHighestPendingBlock_whenLower() public { + // First submission sets highestPendingBlock + uint32 higherBlockNumber = uint32(INITIAL_BEEFY_BLOCK + 500); + IBeefyClient.Commitment memory commitment1 = createCommitment(higherBlockNumber); + uint256[] memory bitfield = new uint256[](1); + IBeefyClient.ValidatorProof memory proof = createValidatorProof(); + + vm.prank(relayer1); + wrapper.submitInitial(commitment1, bitfield, proof); + assertEq(wrapper.highestPendingBlock(), higherBlockNumber); + uint256 timestamp1 = wrapper.highestPendingBlockTimestamp(); + + // Second submission with lower block number should NOT update + uint32 lowerBlockNumber = uint32(INITIAL_BEEFY_BLOCK + 200); + IBeefyClient.Commitment memory commitment2 = createCommitment(lowerBlockNumber); + + vm.prank(relayer2); + wrapper.submitInitial(commitment2, bitfield, proof); + + // Should still be the higher block number + assertEq(wrapper.highestPendingBlock(), higherBlockNumber); + assertEq(wrapper.highestPendingBlockTimestamp(), timestamp1); + } + + /* Additional EstimatePayout Tests */ + + function test_estimatePayout_capsGasPrice() public { + uint256 gasUsed = 500000; + uint256 highGasPrice = 200 gwei; // Higher than MAX_GAS_PRICE (100 gwei) + + uint256 refund = wrapper.estimatePayout(gasUsed, highGasPrice, REFUND_TARGET); + + // Should use maxGasPrice (100 gwei), not the provided highGasPrice + assertEq(refund, gasUsed * MAX_GAS_PRICE); + } + + function test_estimatePayout_capsRefundAmount() public { + uint256 gasUsed = 1000000000; // Very high gas to exceed max refund + uint256 gasPrice = 100 gwei; + + uint256 refund = wrapper.estimatePayout(gasUsed, gasPrice, REFUND_TARGET); + + // Should be capped at maxRefundAmount + assertEq(refund, MAX_REFUND_AMOUNT); + } +} + +/** + * @dev Contract that rejects ETH transfers for testing TransferFailed + */ +contract RejectingRecipient { + receive() external payable { + revert("No ETH accepted"); + } +} + +contract BeefyClientWrapperTransferFailedTest is Test { + BeefyClientWrapper wrapper; + MockBeefyClient mockBeefyClient; + RejectingRecipient rejectingRecipient; + + address owner = address(0x1); + + function setUp() public { + mockBeefyClient = new MockBeefyClient(1000); + wrapper = new BeefyClientWrapper( + address(mockBeefyClient), + owner, + 100 gwei, + 0.05 ether, + 350 + ); + vm.deal(address(wrapper), 100 ether); + rejectingRecipient = new RejectingRecipient(); + } + + function test_withdrawFunds_transferFailed() public { + vm.prank(owner); + vm.expectRevert(BeefyClientWrapper.TransferFailed.selector); + wrapper.withdrawFunds(payable(address(rejectingRecipient)), 1 ether); + } } From e3112a211c07307783dfd7a1e21f62731c6defa9 Mon Sep 17 00:00:00 2001 From: claravanstaden Date: Thu, 5 Feb 2026 11:49:19 +0200 Subject: [PATCH 16/17] more tests and update outdated comment --- contracts/src/BeefyClientWrapper.sol | 4 +- contracts/test/BeefyClientWrapper.t.sol | 83 ++++++++++++++++++++++++- 2 files changed, 83 insertions(+), 4 deletions(-) diff --git a/contracts/src/BeefyClientWrapper.sol b/contracts/src/BeefyClientWrapper.sol index b81bcd851..bc1ae69b6 100644 --- a/contracts/src/BeefyClientWrapper.sol +++ b/contracts/src/BeefyClientWrapper.sol @@ -7,8 +7,8 @@ import {IBeefyClient} from "./interfaces/IBeefyClient.sol"; /** * @title BeefyClientWrapper * @dev Forwards BeefyClient submissions and refunds gas costs to relayers. - * Anyone can relay. Uses progress-based refunds: the more blocks a relayer - * advances the light client, the higher percentage of gas refund they receive. + * Anyone can relay. Refunds are only paid when the relayer advances the light + * client by at least `refundTarget` blocks, ensuring meaningful progress. */ contract BeefyClientWrapper { event GasCredited(address indexed relayer, bytes32 indexed commitmentHash, uint256 gasUsed); diff --git a/contracts/test/BeefyClientWrapper.t.sol b/contracts/test/BeefyClientWrapper.t.sol index 876def7a5..a740fb5e0 100644 --- a/contracts/test/BeefyClientWrapper.t.sol +++ b/contracts/test/BeefyClientWrapper.t.sol @@ -749,21 +749,62 @@ contract RejectingRecipient { } } +/** + * @dev Contract relayer that rejects ETH refunds for testing failed refund transfers + */ +contract RejectingRelayer { + BeefyClientWrapper public wrapper; + + constructor(BeefyClientWrapper _wrapper) { + wrapper = _wrapper; + } + + function submitInitial( + IBeefyClient.Commitment calldata commitment, + uint256[] calldata bitfield, + IBeefyClient.ValidatorProof calldata proof + ) external { + wrapper.submitInitial(commitment, bitfield, proof); + } + + function commitPrevRandao(bytes32 commitmentHash) external { + wrapper.commitPrevRandao(commitmentHash); + } + + function submitFinal( + IBeefyClient.Commitment calldata commitment, + uint256[] calldata bitfield, + IBeefyClient.ValidatorProof[] calldata proofs, + IBeefyClient.MMRLeaf calldata leaf, + bytes32[] calldata leafProof, + uint256 leafProofOrder + ) external { + wrapper.submitFinal(commitment, bitfield, proofs, leaf, leafProof, leafProofOrder); + } + + // Reject ETH transfers + receive() external payable { + revert("No refunds accepted"); + } +} + contract BeefyClientWrapperTransferFailedTest is Test { BeefyClientWrapper wrapper; MockBeefyClient mockBeefyClient; RejectingRecipient rejectingRecipient; address owner = address(0x1); + uint256 constant INITIAL_BEEFY_BLOCK = 1000; + uint256 constant REFUND_TARGET = 350; function setUp() public { - mockBeefyClient = new MockBeefyClient(1000); + mockBeefyClient = new MockBeefyClient(uint64(INITIAL_BEEFY_BLOCK)); wrapper = new BeefyClientWrapper( address(mockBeefyClient), owner, 100 gwei, 0.05 ether, - 350 + REFUND_TARGET ); vm.deal(address(wrapper), 100 ether); rejectingRecipient = new RejectingRecipient(); @@ -774,4 +815,42 @@ contract BeefyClientWrapperTransferFailedTest is Test { vm.expectRevert(BeefyClientWrapper.TransferFailed.selector); wrapper.withdrawFunds(payable(address(rejectingRecipient)), 1 ether); } + + function test_refundFailsWhenRelayerRejectsETH() public { + // Create a relayer contract that rejects ETH + RejectingRelayer rejectingRelayer = new RejectingRelayer(wrapper); + + // Create commitment with enough progress for refund + uint32 newBlockNumber = uint32(INITIAL_BEEFY_BLOCK + REFUND_TARGET); + IBeefyClient.PayloadItem[] memory payload = new IBeefyClient.PayloadItem[](1); + payload[0] = IBeefyClient.PayloadItem(bytes2("mh"), abi.encodePacked(bytes32(0))); + IBeefyClient.Commitment memory commitment = IBeefyClient.Commitment(newBlockNumber, 1, payload); + + uint256[] memory bitfield = new uint256[](1); + bytes32[] memory proof = new bytes32[](0); + IBeefyClient.ValidatorProof memory validatorProof = IBeefyClient.ValidatorProof(27, bytes32(0), bytes32(0), 0, address(0), proof); + IBeefyClient.ValidatorProof[] memory proofs = new IBeefyClient.ValidatorProof[](1); + proofs[0] = validatorProof; + IBeefyClient.MMRLeaf memory leaf = IBeefyClient.MMRLeaf(1, 0, bytes32(0), 1, 100, bytes32(0), bytes32(0)); + bytes32[] memory leafProof = new bytes32[](0); + + uint256 wrapperBalanceBefore = address(wrapper).balance; + + // Submit through the rejecting relayer + vm.txGasPrice(50 gwei); + rejectingRelayer.submitInitial(commitment, bitfield, validatorProof); + + bytes32 commitmentHash = mockBeefyClient.computeCommitmentHash(commitment); + rejectingRelayer.commitPrevRandao(commitmentHash); + + // submitFinal should succeed even though refund transfer fails + rejectingRelayer.submitFinal(commitment, bitfield, proofs, leaf, leafProof, 0); + + // Verify submission succeeded + assertEq(mockBeefyClient.submitFinalCount(), 1); + assertEq(mockBeefyClient.latestBeefyBlock(), newBlockNumber); + + // Verify no refund was sent (wrapper balance unchanged) + assertEq(address(wrapper).balance, wrapperBalanceBefore); + } } From f086bcf732cb8e05e7604ea1572f1a0a38a9a59f Mon Sep 17 00:00:00 2001 From: claravanstaden Date: Thu, 5 Feb 2026 12:07:33 +0200 Subject: [PATCH 17/17] add removed fiat shamir back --- relayer/relays/beefy/on-demand-sync.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/relayer/relays/beefy/on-demand-sync.go b/relayer/relays/beefy/on-demand-sync.go index b925d978e..83c35fce7 100644 --- a/relayer/relays/beefy/on-demand-sync.go +++ b/relayer/relays/beefy/on-demand-sync.go @@ -260,7 +260,11 @@ func (relay *OnDemandRelay) syncBeefyUpdate(ctx context.Context, task *Request) } else { task.ValidatorsRoot = state.NextValidatorSetRoot } - err = relay.ethereumWriter.submit(ctx, task) + if relay.ethereumWriter.config.EnableFiatShamir { + err = relay.ethereumWriter.submitFiatShamir(ctx, task) + } else { + err = relay.ethereumWriter.submit(ctx, task) + } if err != nil { return fmt.Errorf("fail to submit beefy update: %w", err) }