From 91cce3275d4862d945377c6d58d21c80edc84832 Mon Sep 17 00:00:00 2001 From: k4m4 Date: Thu, 24 Jul 2025 20:19:25 +0300 Subject: [PATCH 01/64] feat(registry): make {add,remove}Validator external --- solidity-sdk/src/verifier/PodRegistry.sol | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/solidity-sdk/src/verifier/PodRegistry.sol b/solidity-sdk/src/verifier/PodRegistry.sol index af4cf3ea..8002c5e8 100644 --- a/solidity-sdk/src/verifier/PodRegistry.sol +++ b/solidity-sdk/src/verifier/PodRegistry.sol @@ -21,11 +21,15 @@ contract PodRegistry is IPodRegistry, Ownable { constructor(address[] memory initialValidators) Ownable(msg.sender) { for (uint8 i = 0; i < initialValidators.length; i++) { - addValidator(initialValidators[i]); + _addValidator(initialValidators[i]); } } - function addValidator(address validator) public onlyOwner { + function addValidator(address validator) external onlyOwner { + _addValidator(validator); + } + + function _addValidator(address validator) internal { require(validator != address(0), "pod: validator is the zero address"); require(validatorIndex[validator] == 0, "pod: validator already exists"); require(nextValidatorIndex < MAX_VALIDATOR_COUNT, "pod: max validator count reached"); @@ -34,7 +38,11 @@ contract PodRegistry is IPodRegistry, Ownable { emit ValidatorAdded(validator); } - function removeValidator(address validator) public onlyOwner { + function removeValidator(address validator) external onlyOwner { + _removeValidator(validator); + } + + function _removeValidator(address validator) internal { require(validatorIndex[validator] != 0, "pod: validator does not exist"); delete validatorIndex[validator]; validatorCount--; From 163e5dddf330778fc4a4dd06eeff5327cea7edab Mon Sep 17 00:00:00 2001 From: k4m4 Date: Thu, 24 Jul 2025 20:23:48 +0300 Subject: [PATCH 02/64] feat(registry): maintain bitmap w/ validator set --- solidity-sdk/src/verifier/PodRegistry.sol | 9 +++++++-- solidity-sdk/test/PodRegistry.t.sol | 14 ++++++++++++++ 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/solidity-sdk/src/verifier/PodRegistry.sol b/solidity-sdk/src/verifier/PodRegistry.sol index 8002c5e8..cac40e37 100644 --- a/solidity-sdk/src/verifier/PodRegistry.sol +++ b/solidity-sdk/src/verifier/PodRegistry.sol @@ -13,6 +13,7 @@ contract PodRegistry is IPodRegistry, Ownable { mapping(address => uint8) public validatorIndex; + uint256 public validatorBitmap; uint8 public validatorCount; uint8 public nextValidatorIndex; @@ -33,7 +34,9 @@ contract PodRegistry is IPodRegistry, Ownable { require(validator != address(0), "pod: validator is the zero address"); require(validatorIndex[validator] == 0, "pod: validator already exists"); require(nextValidatorIndex < MAX_VALIDATOR_COUNT, "pod: max validator count reached"); - validatorIndex[validator] = ++nextValidatorIndex; + uint8 index = ++nextValidatorIndex; + validatorIndex[validator] = index; + validatorBitmap |= (1 << (index - 1)); validatorCount++; emit ValidatorAdded(validator); } @@ -43,7 +46,9 @@ contract PodRegistry is IPodRegistry, Ownable { } function _removeValidator(address validator) internal { - require(validatorIndex[validator] != 0, "pod: validator does not exist"); + uint8 index = validatorIndex[validator]; + require(index != 0, "pod: validator does not exist"); + validatorBitmap &= ~(1 << (index - 1)); delete validatorIndex[validator]; validatorCount--; emit ValidatorRemoved(validator); diff --git a/solidity-sdk/test/PodRegistry.t.sol b/solidity-sdk/test/PodRegistry.t.sol index 6c38866a..2cff3a12 100644 --- a/solidity-sdk/test/PodRegistry.t.sol +++ b/solidity-sdk/test/PodRegistry.t.sol @@ -118,4 +118,18 @@ contract PodRegistryTest is Test { assertEq(registry.validatorCount(), 255); } + + function test_ValidatorBitmapAfterAddRemove() public { + vm.startPrank(owner); + + registry.addValidator(validator3); + + uint256 bitmapAfterAdd = registry.validatorBitmap(); + assertEq(bitmapAfterAdd & (1 << (3 - 1)), (1 << (3 - 1))); + + registry.removeValidator(validator3); + + uint256 bitmapAfterRemove = registry.validatorBitmap(); + assertEq(bitmapAfterRemove & (1 << (3 - 1)), 0); + } } From 5f6abc7f143a2776fbdf65303493562d543c0085 Mon Sep 17 00:00:00 2001 From: k4m4 Date: Thu, 24 Jul 2025 20:25:54 +0300 Subject: [PATCH 03/64] feat(registry): enable validator {de,re}activation --- solidity-sdk/src/verifier/PodRegistry.sol | 22 ++++++- solidity-sdk/test/PodRegistry.t.sol | 71 +++++++++++++++++++++++ 2 files changed, 92 insertions(+), 1 deletion(-) diff --git a/solidity-sdk/src/verifier/PodRegistry.sol b/solidity-sdk/src/verifier/PodRegistry.sol index cac40e37..960c3feb 100644 --- a/solidity-sdk/src/verifier/PodRegistry.sol +++ b/solidity-sdk/src/verifier/PodRegistry.sol @@ -19,6 +19,8 @@ contract PodRegistry is IPodRegistry, Ownable { event ValidatorAdded(address indexed validator); event ValidatorRemoved(address indexed validator); + event ValidatorDeactivated(address indexed validator); + event ValidatorReactivated(address indexed validator); constructor(address[] memory initialValidators) Ownable(msg.sender) { for (uint8 i = 0; i < initialValidators.length; i++) { @@ -54,6 +56,24 @@ contract PodRegistry is IPodRegistry, Ownable { emit ValidatorRemoved(validator); } + function deactivate() external { + uint8 index = validatorIndex[msg.sender]; + require(index != 0, "pod: caller is not a validator"); + uint256 mask = 1 << (index - 1); + require((validatorBitmap & mask) != 0, "pod: caller is already inactive"); + validatorBitmap &= ~mask; + emit ValidatorDeactivated(msg.sender); + } + + function reactivate() external { + uint8 index = validatorIndex[msg.sender]; + require(index != 0, "pod: caller is not a validator"); + uint256 mask = 1 << (index - 1); + require((validatorBitmap & mask) == 0, "pod: caller is already active"); + validatorBitmap |= mask; + emit ValidatorReactivated(msg.sender); + } + function computeWeight(address[] memory subset) public view returns (uint256 weight) { uint256 counted = 0; for (uint8 i = 0; i < subset.length; i++) { @@ -64,7 +84,7 @@ contract PodRegistry is IPodRegistry, Ownable { } uint256 mask = 1 << (index - 1); - if ((counted & mask) == 0) { + if ((validatorBitmap & mask) != 0 && (counted & mask) == 0) { counted |= mask; weight++; } diff --git a/solidity-sdk/test/PodRegistry.t.sol b/solidity-sdk/test/PodRegistry.t.sol index 2cff3a12..89c540d4 100644 --- a/solidity-sdk/test/PodRegistry.t.sol +++ b/solidity-sdk/test/PodRegistry.t.sol @@ -132,4 +132,75 @@ contract PodRegistryTest is Test { uint256 bitmapAfterRemove = registry.validatorBitmap(); assertEq(bitmapAfterRemove & (1 << (3 - 1)), 0); } + + function test_DeactivateAndReactivate() public { + vm.startPrank(validator1); + + registry.deactivate(); + assertEq((registry.validatorBitmap() & (1 << (1 - 1))), 0); + + registry.reactivate(); + assertEq((registry.validatorBitmap() & (1 << (1 - 1))), (1 << (1 - 1))); + } + + function test_Deactivate_RevertIfAlreadyInactive() public { + vm.startPrank(validator1); + registry.deactivate(); + + vm.expectRevert("pod: caller is already inactive"); + registry.deactivate(); + } + + function test_Reactivate_RevertIfAlreadyActive() public { + vm.startPrank(validator1); + vm.expectRevert("pod: caller is already active"); + registry.reactivate(); + } + + function test_Deactivate_RevertIfNotValidator() public { + vm.startPrank(address(1337)); + vm.expectRevert("pod: caller is not a validator"); + registry.deactivate(); + } + + function test_Reactivate_RevertIfNotValidator() public { + vm.startPrank(address(1337)); + vm.expectRevert("pod: caller is not a validator"); + registry.reactivate(); + } + + function test_ComputeWeight_IgnoresInactiveValidators() public { + vm.startPrank(validator1); + registry.deactivate(); + vm.stopPrank(); + + address[] memory subset = new address[](2); + subset[0] = validator1; + subset[1] = validator2; + + uint256 weight = registry.computeWeight(subset); + assertEq(weight, 1); + } + + function test_RemoveValidator_AfterDeactivation() public { + vm.prank(validator1); + registry.deactivate(); + + vm.prank(owner); + registry.removeValidator(validator1); + + assertEq(registry.validatorIndex(validator1), 0); + assertEq((registry.validatorBitmap() & (1 << (1 - 1))), 0); + } + + function test_ValidatorCount_UnchangedOnDeactivateReactivate() public { + uint8 before = registry.validatorCount(); + + vm.startPrank(validator1); + registry.deactivate(); + registry.reactivate(); + vm.stopPrank(); + + assertEq(registry.validatorCount(), before); + } } From 9024c00c27dc653da762ee6d5a92aa9251eac721 Mon Sep 17 00:00:00 2001 From: k4m4 Date: Thu, 24 Jul 2025 23:49:02 +0300 Subject: [PATCH 04/64] feat(registry): computeWeight for historical validator sets --- solidity-sdk/src/verifier/PodRegistry.sol | 132 ++++++- solidity-sdk/test/PodRegistry.t.sol | 459 ++++++++++++++++++---- 2 files changed, 502 insertions(+), 89 deletions(-) diff --git a/solidity-sdk/src/verifier/PodRegistry.sol b/solidity-sdk/src/verifier/PodRegistry.sol index 960c3feb..2b22c157 100644 --- a/solidity-sdk/src/verifier/PodRegistry.sol +++ b/solidity-sdk/src/verifier/PodRegistry.sol @@ -4,32 +4,58 @@ pragma solidity ^0.8.20; import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; interface IPodRegistry { + struct Snapshot { + uint256 effectiveAsOfBlockNumber; + uint256 bitmap; + } + + function validatorIndex(address validator) external view returns (uint8 index); + function activeValidatorBitmap() external view returns (uint256 bitmap); + function activeValidatorCount() external view returns (uint8 count); + function computeWeight(address[] memory subset) external view returns (uint256 weight); + function computeWeight(address[] memory subset, uint256 blockNumber, uint256 snapshotIndex) + external + view + returns (uint256 weight); + function getFaultTolerance() external view returns (uint8); + function getSnapshot(uint256 index) external view returns (uint256 effectiveAsOfBlockNumber, uint256 bitmap); + function getHistoryLength() external view returns (uint256); } contract PodRegistry is IPodRegistry, Ownable { uint256 constant MAX_VALIDATOR_COUNT = 255; + Snapshot[] public history; + mapping(address => uint8) public validatorIndex; + mapping(address => bool) public bannedValidators; - uint256 public validatorBitmap; uint8 public validatorCount; uint8 public nextValidatorIndex; + uint8 public activeValidatorCount; + uint256 public activeValidatorBitmap; + event ValidatorAdded(address indexed validator); - event ValidatorRemoved(address indexed validator); + event ValidatorBanned(address indexed validator); + event ValidatorUnbanned(address indexed validator); event ValidatorDeactivated(address indexed validator); event ValidatorReactivated(address indexed validator); + event SnapshotCreated(uint256 indexed effectiveAsOfBlockNumber, uint256 bitmap); constructor(address[] memory initialValidators) Ownable(msg.sender) { for (uint8 i = 0; i < initialValidators.length; i++) { _addValidator(initialValidators[i]); } + + _createSnapshot(); } function addValidator(address validator) external onlyOwner { _addValidator(validator); + _createSnapshot(); } function _addValidator(address validator) internal { @@ -38,44 +64,93 @@ contract PodRegistry is IPodRegistry, Ownable { require(nextValidatorIndex < MAX_VALIDATOR_COUNT, "pod: max validator count reached"); uint8 index = ++nextValidatorIndex; validatorIndex[validator] = index; - validatorBitmap |= (1 << (index - 1)); + activeValidatorBitmap |= (1 << (index - 1)); validatorCount++; + activeValidatorCount++; emit ValidatorAdded(validator); } - function removeValidator(address validator) external onlyOwner { - _removeValidator(validator); + function banValidator(address validator) external onlyOwner { + _banValidator(validator); + _createSnapshot(); } - function _removeValidator(address validator) internal { + function _banValidator(address validator) internal { uint8 index = validatorIndex[validator]; require(index != 0, "pod: validator does not exist"); - validatorBitmap &= ~(1 << (index - 1)); - delete validatorIndex[validator]; + require(!bannedValidators[validator], "pod: validator is already banned"); + + uint256 mask = 1 << (index - 1); + if ((activeValidatorBitmap & mask) != 0) { + activeValidatorBitmap &= ~mask; + activeValidatorCount--; + } + + bannedValidators[validator] = true; validatorCount--; - emit ValidatorRemoved(validator); + emit ValidatorBanned(validator); + } + + function unbanValidator(address validator) external onlyOwner { + require(validatorIndex[validator] != 0, "pod: validator does not exist"); + require(bannedValidators[validator], "pod: validator is not banned"); + bannedValidators[validator] = false; + validatorCount++; + emit ValidatorUnbanned(validator); } function deactivate() external { uint8 index = validatorIndex[msg.sender]; require(index != 0, "pod: caller is not a validator"); uint256 mask = 1 << (index - 1); - require((validatorBitmap & mask) != 0, "pod: caller is already inactive"); - validatorBitmap &= ~mask; + require((activeValidatorBitmap & mask) != 0, "pod: caller is already inactive"); + activeValidatorBitmap &= ~mask; + activeValidatorCount--; emit ValidatorDeactivated(msg.sender); + _createSnapshot(); } function reactivate() external { uint8 index = validatorIndex[msg.sender]; require(index != 0, "pod: caller is not a validator"); + require(!bannedValidators[msg.sender], "pod: caller has been banned"); uint256 mask = 1 << (index - 1); - require((validatorBitmap & mask) == 0, "pod: caller is already active"); - validatorBitmap |= mask; + require((activeValidatorBitmap & mask) == 0, "pod: caller is already active"); + activeValidatorBitmap |= mask; + activeValidatorCount++; emit ValidatorReactivated(msg.sender); + _createSnapshot(); + } + + function _createSnapshot() internal { + history.push(Snapshot({effectiveAsOfBlockNumber: block.number, bitmap: activeValidatorBitmap})); + emit SnapshotCreated(block.number, activeValidatorBitmap); } function computeWeight(address[] memory subset) public view returns (uint256 weight) { + if (history.length == 0) { + return 0; + } + + return computeWeight(subset, block.number, history.length - 1); + } + + function computeWeight(address[] memory subset, uint256 blockNumber, uint256 snapshotIndex) + public + view + returns (uint256 weight) + { + require(snapshotIndex < history.length, "pod: invalid snapshot index"); + Snapshot memory snapshot = history[snapshotIndex]; + require(snapshot.effectiveAsOfBlockNumber <= blockNumber, "pod: snapshot too new"); + require( + snapshotIndex == history.length - 1 || history[snapshotIndex + 1].effectiveAsOfBlockNumber > blockNumber, + "pod: snapshot too old" + ); + + uint256 bitmap = snapshot.bitmap; uint256 counted = 0; + for (uint8 i = 0; i < subset.length; i++) { uint8 index = validatorIndex[subset[i]]; @@ -84,14 +159,41 @@ contract PodRegistry is IPodRegistry, Ownable { } uint256 mask = 1 << (index - 1); - if ((validatorBitmap & mask) != 0 && (counted & mask) == 0) { + if ((bitmap & mask) != 0 && (counted & mask) == 0) { counted |= mask; weight++; } } } + function findSnapshotIndex(uint256 blockNumber) external view returns (uint256 index) { + require(history.length > 0, "pod: no historical snapshots"); + + uint256 low = 0; + uint256 high = history.length - 1; + + while (low < high) { + uint256 mid = (low + high + 1) / 2; + if (history[mid].effectiveAsOfBlockNumber <= blockNumber) { + low = mid; + } else { + high = mid - 1; + } + } + + return low; + } + function getFaultTolerance() external view returns (uint8) { - return validatorCount / 3; + return activeValidatorCount / 3; + } + + function getSnapshot(uint256 index) external view returns (uint256 effectiveAsOfBlockNumber, uint256 bitmap) { + Snapshot memory s = history[index]; + return (s.effectiveAsOfBlockNumber, s.bitmap); + } + + function getHistoryLength() external view returns (uint256) { + return history.length; } } diff --git a/solidity-sdk/test/PodRegistry.t.sol b/solidity-sdk/test/PodRegistry.t.sol index 89c540d4..be676f94 100644 --- a/solidity-sdk/test/PodRegistry.t.sol +++ b/solidity-sdk/test/PodRegistry.t.sol @@ -13,26 +13,33 @@ contract PodRegistryTest is Test { address public validator4 = address(5); function setUp() public { - vm.startPrank(owner); address[] memory initialValidators = new address[](2); initialValidators[0] = validator1; initialValidators[1] = validator2; + vm.prank(owner); registry = new PodRegistry(initialValidators); - vm.stopPrank(); } function test_Initialization() public view { assertEq(registry.validatorCount(), 2); + assertEq(registry.activeValidatorCount(), 2); assertEq(registry.validatorIndex(validator1), 1); assertEq(registry.validatorIndex(validator2), 2); + assertEq(registry.getHistoryLength(), 1); } function test_AddValidator() public { - vm.startPrank(owner); + uint256 beforeHistory = registry.getHistoryLength(); + + vm.prank(owner); + vm.expectEmit(true, false, false, true); + emit PodRegistry.ValidatorAdded(validator3); registry.addValidator(validator3); assertEq(registry.validatorCount(), 3); + assertEq(registry.activeValidatorCount(), 3); assertEq(registry.validatorIndex(validator3), 3); + assertEq(registry.getHistoryLength(), beforeHistory + 1); } function test_AddValidator_RevertIfNotOwner() public { @@ -41,166 +48,470 @@ contract PodRegistryTest is Test { } function test_AddValidator_RevertIfZeroAddress() public { - vm.startPrank(owner); + vm.prank(owner); vm.expectRevert("pod: validator is the zero address"); registry.addValidator(address(0)); } function test_AddValidator_RevertIfAlreadyExists() public { - vm.startPrank(owner); + vm.prank(owner); vm.expectRevert("pod: validator already exists"); registry.addValidator(validator1); } - function test_RemoveValidator() public { + function test_AddValidator_RevertIfMaxCountReached() public { vm.startPrank(owner); - registry.removeValidator(validator1); + for (uint8 i = 0; i < 253; i++) { + address newValidator = address(uint160(1000 + i)); + registry.addValidator(newValidator); + } + vm.expectRevert("pod: max validator count reached"); + registry.addValidator(address(9999)); + vm.stopPrank(); + + assertEq(registry.validatorCount(), 255); + } + + function test_BanValidator() public { + uint256 beforeHistory = registry.getHistoryLength(); + + vm.prank(owner); + vm.expectEmit(true, false, false, true); + emit PodRegistry.ValidatorBanned(validator1); + registry.banValidator(validator1); + + assertEq(registry.activeValidatorCount(), 1); assertEq(registry.validatorCount(), 1); - assertEq(registry.validatorIndex(validator1), 0); + // index does not change after banning + assertEq(registry.validatorIndex(validator1), 1); + assertEq(registry.getHistoryLength(), beforeHistory + 1); } - function test_RemoveValidator_RevertIfNotOwner() public { + function test_BanValidator_RevertIfNotOwner() public { vm.expectRevert(abi.encodeWithSignature("OwnableUnauthorizedAccount(address)", address(this))); - registry.removeValidator(validator1); + registry.banValidator(validator1); } - function test_RemoveValidator_RevertIfNotExists() public { - vm.startPrank(owner); + function test_BanValidator_RevertIfNotExists() public { + vm.prank(owner); vm.expectRevert("pod: validator does not exist"); - registry.removeValidator(validator3); + registry.banValidator(validator3); } - function test_ComputeWeight() public view { - address[] memory subset = new address[](3); - subset[0] = validator1; - subset[1] = validator2; - subset[2] = validator3; // Not in registry + function test_BanValidatorTwiceReverts() public { + vm.prank(owner); + registry.banValidator(validator1); - uint256 weight = registry.computeWeight(subset); - assertEq(weight, 2); + vm.prank(owner); + vm.expectRevert("pod: validator is already banned"); + registry.banValidator(validator1); } - function test_ComputeWeight_WithDuplicates() public view { - address[] memory subset = new address[](4); - subset[0] = validator1; - subset[1] = validator1; // Duplicate - subset[2] = validator2; - subset[3] = validator2; // Duplicate - - uint256 weight = registry.computeWeight(subset); - assertEq(weight, 2); - } + function test_UnbanValidator() public { + vm.prank(owner); + registry.banValidator(validator1); + assertTrue(registry.bannedValidators(validator1)); - function test_GetFaultTolerance() public view { - assertEq(registry.getFaultTolerance(), 0); // 2/3 = 0 + vm.prank(owner); + vm.expectEmit(true, false, false, true); + emit PodRegistry.ValidatorUnbanned(validator1); + registry.unbanValidator(validator1); + assertFalse(registry.bannedValidators(validator1)); + assertEq(registry.validatorCount(), 2); // count restored } - function test_GetFaultTolerance_WithMoreValidators() public { - vm.startPrank(owner); - registry.addValidator(validator3); - registry.addValidator(validator4); - vm.stopPrank(); + function test_UnbanValidator_DoesNotCreateSnapshot() public { + vm.prank(owner); + registry.banValidator(validator1); - assertEq(registry.getFaultTolerance(), 1); // 4/3 = 1 + uint256 before = registry.getHistoryLength(); + vm.prank(owner); + registry.unbanValidator(validator1); + assertEq(registry.getHistoryLength(), before); } - function test_AddValidator_RevertIfMaxCountReached() public { - vm.startPrank(owner); + function test_UnbanValidatorAndReactivate() public { + vm.prank(owner); + registry.banValidator(validator1); - for (uint8 i = 0; i < 253; i++) { - address newValidator = address(uint160(1000 + i)); - registry.addValidator(newValidator); - } + vm.prank(validator1); + vm.expectRevert("pod: caller has been banned"); + registry.reactivate(); - vm.expectRevert("pod: max validator count reached"); - registry.addValidator(address(9999)); + vm.prank(owner); + registry.unbanValidator(validator1); - assertEq(registry.validatorCount(), 255); + vm.prank(validator1); + registry.reactivate(); + assertTrue((registry.activeValidatorBitmap() & (1 << (1 - 1))) != 0); } - function test_ValidatorBitmapAfterAddRemove() public { - vm.startPrank(owner); - + function test_ActiveValidatorBitmap_AfterAddBan() public { + vm.prank(owner); registry.addValidator(validator3); - uint256 bitmapAfterAdd = registry.validatorBitmap(); + uint256 bitmapAfterAdd = registry.activeValidatorBitmap(); assertEq(bitmapAfterAdd & (1 << (3 - 1)), (1 << (3 - 1))); - registry.removeValidator(validator3); + vm.prank(owner); + registry.banValidator(validator3); - uint256 bitmapAfterRemove = registry.validatorBitmap(); - assertEq(bitmapAfterRemove & (1 << (3 - 1)), 0); + uint256 bitmapAfterBan = registry.activeValidatorBitmap(); + assertEq(bitmapAfterBan & (1 << (3 - 1)), 0); } function test_DeactivateAndReactivate() public { - vm.startPrank(validator1); + uint256 beforeHistory = registry.getHistoryLength(); + vm.prank(validator1); + vm.expectEmit(true, false, false, true); + emit PodRegistry.ValidatorDeactivated(validator1); registry.deactivate(); - assertEq((registry.validatorBitmap() & (1 << (1 - 1))), 0); + assertEq((registry.activeValidatorBitmap() & (1 << (1 - 1))), 0); + assertEq(registry.getHistoryLength(), beforeHistory + 1); + vm.prank(validator1); + vm.expectEmit(true, false, false, true); + emit PodRegistry.ValidatorReactivated(validator1); registry.reactivate(); - assertEq((registry.validatorBitmap() & (1 << (1 - 1))), (1 << (1 - 1))); + assertEq((registry.activeValidatorBitmap() & (1 << (1 - 1))), (1 << (1 - 1))); + assertEq(registry.getHistoryLength(), beforeHistory + 2); } function test_Deactivate_RevertIfAlreadyInactive() public { - vm.startPrank(validator1); + vm.prank(validator1); registry.deactivate(); + vm.prank(validator1); vm.expectRevert("pod: caller is already inactive"); registry.deactivate(); } function test_Reactivate_RevertIfAlreadyActive() public { - vm.startPrank(validator1); + vm.prank(validator1); vm.expectRevert("pod: caller is already active"); registry.reactivate(); } + function test_Reactivate_RevertIfBanned() public { + vm.prank(owner); + registry.banValidator(validator1); + + vm.prank(validator1); + vm.expectRevert("pod: caller has been banned"); + registry.reactivate(); + } + + function test_Reactivate_RevertsIfBanned() public { + vm.prank(owner); + registry.banValidator(validator1); + + vm.prank(validator1); + vm.expectRevert("pod: caller has been banned"); + registry.reactivate(); + } + function test_Deactivate_RevertIfNotValidator() public { - vm.startPrank(address(1337)); + vm.prank(address(1337)); vm.expectRevert("pod: caller is not a validator"); registry.deactivate(); } function test_Reactivate_RevertIfNotValidator() public { - vm.startPrank(address(1337)); + vm.prank(address(1337)); vm.expectRevert("pod: caller is not a validator"); registry.reactivate(); } - function test_ComputeWeight_IgnoresInactiveValidators() public { + function test_BanValidator_AfterDeactivation() public { + vm.prank(validator1); + registry.deactivate(); + + vm.prank(owner); + registry.banValidator(validator1); + + assertEq((registry.activeValidatorBitmap() & (1 << (1 - 1))), 0); + // index does not change after banning + assertEq(registry.validatorIndex(validator1), 1); + } + + function test_ValidatorCount_UnchangedOnDeactivateReactivate() public { + uint8 before = registry.validatorCount(); + vm.startPrank(validator1); registry.deactivate(); + registry.reactivate(); vm.stopPrank(); - address[] memory subset = new address[](2); + assertEq(registry.validatorCount(), before); + } + + function test_SnapshotCreatedOnAddBanDeactivateReactivate() public { + uint256 initialHistory = registry.getHistoryLength(); + + vm.prank(owner); + vm.expectEmit(true, false, false, true); + emit PodRegistry.SnapshotCreated(block.number, (1 << (1 - 1)) | (1 << (2 - 1)) | (1 << (3 - 1))); + registry.addValidator(validator3); + assertEq(registry.getHistoryLength(), initialHistory + 1); + + vm.prank(owner); + vm.expectEmit(true, false, false, true); + emit PodRegistry.SnapshotCreated(block.number, (1 << (1 - 1)) | (1 << (2 - 1))); + registry.banValidator(validator3); + assertEq(registry.getHistoryLength(), initialHistory + 2); + + vm.prank(validator1); + vm.expectEmit(true, false, false, true); + emit PodRegistry.SnapshotCreated(block.number, (1 << (2 - 1))); + registry.deactivate(); + assertEq(registry.getHistoryLength(), initialHistory + 3); + + vm.prank(validator1); + vm.expectEmit(true, false, false, true); + emit PodRegistry.SnapshotCreated(block.number, (1 << (1 - 1)) | (1 << (2 - 1))); + registry.reactivate(); + assertEq(registry.getHistoryLength(), initialHistory + 4); + } + + function test_ComputeWeight() public view { + address[] memory subset = new address[](3); subset[0] = validator1; subset[1] = validator2; + subset[2] = validator3; // not in registry uint256 weight = registry.computeWeight(subset); - assertEq(weight, 1); + assertEq(weight, 2); + } + + function test_ComputeWeight_WithDuplicates() public view { + address[] memory subset = new address[](4); + subset[0] = validator1; + subset[1] = validator1; // duplicate + subset[2] = validator2; + subset[3] = validator2; // duplicate + + uint256 weight = registry.computeWeight(subset); + assertEq(weight, 2); } - function test_RemoveValidator_AfterDeactivation() public { + function test_ComputeWeight_IgnoresInactiveValidators() public { vm.prank(validator1); registry.deactivate(); + address[] memory subset = new address[](2); + subset[0] = validator1; + subset[1] = validator2; + + uint256 weight = registry.computeWeight(subset); + assertEq(weight, 1); + } + + function test_ComputeWeight_HistoricalAndSnapshotValidation() public { vm.prank(owner); - registry.removeValidator(validator1); + registry.addValidator(validator3); // snapshot - assertEq(registry.validatorIndex(validator1), 0); - assertEq((registry.validatorBitmap() & (1 << (1 - 1))), 0); + vm.roll(block.number + 5); + vm.prank(owner); + registry.banValidator(validator1); // another snapshot + + uint256 oldBlock = block.number - 3; + uint256 snapshotIndex = registry.findSnapshotIndex(oldBlock); + + address[] memory subset = new address[](3); + subset[0] = validator1; + subset[1] = validator2; + subset[2] = validator3; + + uint256 weight = registry.computeWeight(subset, oldBlock, snapshotIndex); + assertEq(weight, 3); } - function test_ValidatorCount_UnchangedOnDeactivateReactivate() public { - uint8 before = registry.validatorCount(); + function test_ComputeWeight_ExactSnapshotBlock() public { + vm.prank(owner); + registry.addValidator(validator3); + uint256 snapshotIndex = registry.getHistoryLength() - 1; + uint256 snapshotBlock; + (snapshotBlock,) = registry.getSnapshot(snapshotIndex); - vm.startPrank(validator1); - registry.deactivate(); - registry.reactivate(); + address[] memory subset = new address[](3); + subset[0] = validator1; + subset[1] = validator2; + subset[2] = validator3; + + uint256 weight = registry.computeWeight(subset, snapshotBlock, snapshotIndex); + assertEq(weight, 3); + } + + function test_ComputeWeight_RevertIfSnapshotTooOld() public { + vm.prank(owner); + registry.addValidator(validator3); // snapshot at index 1 + + vm.prank(owner); + vm.roll(block.number + 5); + registry.banValidator(validator1); // snapshot at index 2 + + // Use snapshot 0 for current block (too old) + uint256 latestBlock = block.number; + + address[] memory subset = new address[](2); + subset[0] = validator1; + subset[1] = validator2; + + vm.expectRevert("pod: snapshot too old"); + registry.computeWeight(subset, latestBlock, 0); + } + + function test_ComputeWeight_RevertIfSnapshotTooNew() public { + vm.prank(owner); + registry.addValidator(validator3); // snapshot at index 1 + uint256 blockAtAdd = block.number; + + vm.roll(block.number + 5); + vm.prank(owner); + registry.banValidator(validator1); // snapshot at index 2 + + // Use snapshot 2 for blockAtAdd (too new) + address[] memory subset = new address[](2); + subset[0] = validator1; + subset[1] = validator3; + + vm.expectRevert("pod: snapshot too new"); + registry.computeWeight(subset, blockAtAdd, 2); + } + + function test_ComputeWeight_RevertIfSnapshotIndexOutOfBounds() public { + address[] memory subset = new address[](1); + subset[0] = validator1; + + vm.expectRevert("pod: invalid snapshot index"); + registry.computeWeight(subset, block.number, 999); + } + + function test_ComputeWeight_NoHistoryReturnsZero() public { + PodRegistry emptyRegistry = new PodRegistry(new address[](0)); + address[] memory subset = new address[](1); + subset[0] = validator1; + assertEq(emptyRegistry.computeWeight(subset), 0); + } + + function test_ComputeWeight_EmptySubsetReturnsZero() public view { + address[] memory emptySubset = new address[](0); + uint256 weight = registry.computeWeight(emptySubset); + assertEq(weight, 0); + } + + function test_FindSnapshotIndex() public { + vm.roll(101); + // Initial snapshot from constructor + uint256 initialIndex = registry.findSnapshotIndex(block.number); + assertEq(initialIndex, 0); + + // Roll blocks and add a new validator (creates snapshot) + vm.roll(block.number + 5); + vm.prank(owner); + registry.addValidator(validator3); + uint256 blockAtAdd = block.number; + + // Roll blocks and ban validator1 (creates another snapshot) + vm.roll(block.number + 10); + vm.prank(owner); + registry.banValidator(validator1); + uint256 blockAtBan = block.number; + + // History should now have 3 snapshots: + // index 0 -> constructor snapshot + // index 1 -> after adding validator3 + // index 2 -> after banning validator1 + assertEq(registry.getHistoryLength(), 3); + + // Case 1: Block way before first snapshot → index 0 + uint256 indexBeforeFirst = registry.findSnapshotIndex(blockAtAdd - 100); + assertEq(indexBeforeFirst, 0); + + // Case 2: Block exactly at first add snapshot → index 1 + uint256 indexAtAdd = registry.findSnapshotIndex(blockAtAdd); + assertEq(indexAtAdd, 1); + + // Case 3: Block between add and ban → index 1 + uint256 midBlock = blockAtAdd + 5; + uint256 indexMid = registry.findSnapshotIndex(midBlock); + assertEq(indexMid, 1); + + // Case 4: Block after last snapshot → index 2 + uint256 indexAfterLast = registry.findSnapshotIndex(block.number + 50); + assertEq(indexAfterLast, 2); + + // Validate that returned snapshots are correct + (uint256 blockNum1, uint256 bitmap1) = registry.getSnapshot(indexAtAdd); + assertEq(blockNum1, blockAtAdd); + assertTrue(bitmap1 & (1 << (3 - 1)) != 0); // validator3 should be active here + + (uint256 blockNum2, uint256 bitmap2) = registry.getSnapshot(indexAfterLast); + assertEq(blockNum2, blockAtBan); + assertTrue(bitmap2 & (1 << (3 - 1)) != 0); // validator3 still active + assertFalse(bitmap2 & (1 << (1 - 1)) != 0); // validator1 banned + } + + function test_FindSnapshotIndex_BeforeFirstSnapshot() public { + vm.roll(101); + uint256 index = registry.findSnapshotIndex(block.number - 100); // way before + assertEq(index, 0); + } + + function test_FindSnapshotIndex_AfterLastSnapshot() public { + vm.prank(owner); + registry.addValidator(validator3); + + vm.roll(block.number + 10); + vm.prank(owner); + registry.banValidator(validator1); + + uint256 index = registry.findSnapshotIndex(block.number + 50); // after last + assertEq(index, registry.getHistoryLength() - 1); + } + + function test_FindSnapshotIndex_SingleSnapshot() public view { + uint256 index = registry.findSnapshotIndex(block.number); + assertEq(index, 0); + } + + function test_FindSnapshotIndex_ExactMatchLastSnapshot() public { + vm.roll(block.number + 10); + vm.prank(owner); + registry.addValidator(validator3); + uint256 latestSnapshotBlock = block.number; + uint256 index = registry.findSnapshotIndex(latestSnapshotBlock); + assertEq(index, registry.getHistoryLength() - 1); + } + + function test_GetSnapshot() public { + vm.prank(owner); + registry.addValidator(validator3); + uint256 index = registry.getHistoryLength() - 1; + (uint256 blockNumber, uint256 bitmap) = registry.getSnapshot(index); + assertGt(blockNumber, 0); + assertTrue(bitmap & (1 << (3 - 1)) != 0); + } + + function test_GetHistory() public { + uint256 before = registry.getHistoryLength(); + vm.prank(owner); + registry.addValidator(validator3); + assertEq(registry.getHistoryLength(), before + 1); + } + + function test_GetFaultTolerance() public view { + assertEq(registry.getFaultTolerance(), 0); // 2/3 = 0 + } + + function test_GetFaultTolerance_WithMoreValidators() public { + vm.startPrank(owner); + registry.addValidator(validator3); + registry.addValidator(validator4); vm.stopPrank(); - assertEq(registry.validatorCount(), before); + assertEq(registry.getFaultTolerance(), 1); // 4/3 = 1 } } From 13a0a01c76929ff7fbcfcb2a24a71659bdbf8995 Mon Sep 17 00:00:00 2001 From: k4m4 Date: Fri, 25 Jul 2025 00:16:37 +0300 Subject: [PATCH 05/64] feat(registry): remove validator count state vars --- solidity-sdk/src/verifier/PodRegistry.sol | 23 +++++++++++------------ solidity-sdk/test/PodRegistry.t.sol | 22 ++-------------------- 2 files changed, 13 insertions(+), 32 deletions(-) diff --git a/solidity-sdk/src/verifier/PodRegistry.sol b/solidity-sdk/src/verifier/PodRegistry.sol index 2b22c157..7f44a212 100644 --- a/solidity-sdk/src/verifier/PodRegistry.sol +++ b/solidity-sdk/src/verifier/PodRegistry.sol @@ -11,7 +11,6 @@ interface IPodRegistry { function validatorIndex(address validator) external view returns (uint8 index); function activeValidatorBitmap() external view returns (uint256 bitmap); - function activeValidatorCount() external view returns (uint8 count); function computeWeight(address[] memory subset) external view returns (uint256 weight); function computeWeight(address[] memory subset, uint256 blockNumber, uint256 snapshotIndex) @@ -19,6 +18,7 @@ interface IPodRegistry { view returns (uint256 weight); + function getActiveValidatorCount() external view returns (uint8 count); function getFaultTolerance() external view returns (uint8); function getSnapshot(uint256 index) external view returns (uint256 effectiveAsOfBlockNumber, uint256 bitmap); function getHistoryLength() external view returns (uint256); @@ -32,10 +32,7 @@ contract PodRegistry is IPodRegistry, Ownable { mapping(address => uint8) public validatorIndex; mapping(address => bool) public bannedValidators; - uint8 public validatorCount; uint8 public nextValidatorIndex; - - uint8 public activeValidatorCount; uint256 public activeValidatorBitmap; event ValidatorAdded(address indexed validator); @@ -65,8 +62,6 @@ contract PodRegistry is IPodRegistry, Ownable { uint8 index = ++nextValidatorIndex; validatorIndex[validator] = index; activeValidatorBitmap |= (1 << (index - 1)); - validatorCount++; - activeValidatorCount++; emit ValidatorAdded(validator); } @@ -83,11 +78,9 @@ contract PodRegistry is IPodRegistry, Ownable { uint256 mask = 1 << (index - 1); if ((activeValidatorBitmap & mask) != 0) { activeValidatorBitmap &= ~mask; - activeValidatorCount--; } bannedValidators[validator] = true; - validatorCount--; emit ValidatorBanned(validator); } @@ -95,7 +88,6 @@ contract PodRegistry is IPodRegistry, Ownable { require(validatorIndex[validator] != 0, "pod: validator does not exist"); require(bannedValidators[validator], "pod: validator is not banned"); bannedValidators[validator] = false; - validatorCount++; emit ValidatorUnbanned(validator); } @@ -105,7 +97,6 @@ contract PodRegistry is IPodRegistry, Ownable { uint256 mask = 1 << (index - 1); require((activeValidatorBitmap & mask) != 0, "pod: caller is already inactive"); activeValidatorBitmap &= ~mask; - activeValidatorCount--; emit ValidatorDeactivated(msg.sender); _createSnapshot(); } @@ -117,7 +108,6 @@ contract PodRegistry is IPodRegistry, Ownable { uint256 mask = 1 << (index - 1); require((activeValidatorBitmap & mask) == 0, "pod: caller is already active"); activeValidatorBitmap |= mask; - activeValidatorCount++; emit ValidatorReactivated(msg.sender); _createSnapshot(); } @@ -184,8 +174,17 @@ contract PodRegistry is IPodRegistry, Ownable { return low; } + function getActiveValidatorCount() public view returns (uint8 count) { + count = 0; + uint256 bitmap = activeValidatorBitmap; + while (bitmap != 0) { + count++; + bitmap &= bitmap - 1; + } + } + function getFaultTolerance() external view returns (uint8) { - return activeValidatorCount / 3; + return getActiveValidatorCount() / 3; } function getSnapshot(uint256 index) external view returns (uint256 effectiveAsOfBlockNumber, uint256 bitmap) { diff --git a/solidity-sdk/test/PodRegistry.t.sol b/solidity-sdk/test/PodRegistry.t.sol index be676f94..7df9fc99 100644 --- a/solidity-sdk/test/PodRegistry.t.sol +++ b/solidity-sdk/test/PodRegistry.t.sol @@ -21,8 +21,6 @@ contract PodRegistryTest is Test { } function test_Initialization() public view { - assertEq(registry.validatorCount(), 2); - assertEq(registry.activeValidatorCount(), 2); assertEq(registry.validatorIndex(validator1), 1); assertEq(registry.validatorIndex(validator2), 2); assertEq(registry.getHistoryLength(), 1); @@ -36,8 +34,7 @@ contract PodRegistryTest is Test { emit PodRegistry.ValidatorAdded(validator3); registry.addValidator(validator3); - assertEq(registry.validatorCount(), 3); - assertEq(registry.activeValidatorCount(), 3); + assertEq(registry.getActiveValidatorCount(), 3); assertEq(registry.validatorIndex(validator3), 3); assertEq(registry.getHistoryLength(), beforeHistory + 1); } @@ -69,8 +66,6 @@ contract PodRegistryTest is Test { vm.expectRevert("pod: max validator count reached"); registry.addValidator(address(9999)); vm.stopPrank(); - - assertEq(registry.validatorCount(), 255); } function test_BanValidator() public { @@ -81,8 +76,7 @@ contract PodRegistryTest is Test { emit PodRegistry.ValidatorBanned(validator1); registry.banValidator(validator1); - assertEq(registry.activeValidatorCount(), 1); - assertEq(registry.validatorCount(), 1); + assertEq(registry.getActiveValidatorCount(), 1); // index does not change after banning assertEq(registry.validatorIndex(validator1), 1); assertEq(registry.getHistoryLength(), beforeHistory + 1); @@ -118,7 +112,6 @@ contract PodRegistryTest is Test { emit PodRegistry.ValidatorUnbanned(validator1); registry.unbanValidator(validator1); assertFalse(registry.bannedValidators(validator1)); - assertEq(registry.validatorCount(), 2); // count restored } function test_UnbanValidator_DoesNotCreateSnapshot() public { @@ -236,17 +229,6 @@ contract PodRegistryTest is Test { assertEq(registry.validatorIndex(validator1), 1); } - function test_ValidatorCount_UnchangedOnDeactivateReactivate() public { - uint8 before = registry.validatorCount(); - - vm.startPrank(validator1); - registry.deactivate(); - registry.reactivate(); - vm.stopPrank(); - - assertEq(registry.validatorCount(), before); - } - function test_SnapshotCreatedOnAddBanDeactivateReactivate() public { uint256 initialHistory = registry.getHistoryLength(); From f9beeb4c03a1b36dcabd379290d4418dffafd58e Mon Sep 17 00:00:00 2001 From: k4m4 Date: Fri, 25 Jul 2025 00:37:27 +0300 Subject: [PATCH 06/64] refactor(registry): move events to interface --- solidity-sdk/src/verifier/PodRegistry.sol | 14 +++++++------- solidity-sdk/test/PodRegistry.t.sol | 18 +++++++++--------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/solidity-sdk/src/verifier/PodRegistry.sol b/solidity-sdk/src/verifier/PodRegistry.sol index 7f44a212..d4deb651 100644 --- a/solidity-sdk/src/verifier/PodRegistry.sol +++ b/solidity-sdk/src/verifier/PodRegistry.sol @@ -9,6 +9,13 @@ interface IPodRegistry { uint256 bitmap; } + event ValidatorAdded(address indexed validator); + event ValidatorBanned(address indexed validator); + event ValidatorUnbanned(address indexed validator); + event ValidatorDeactivated(address indexed validator); + event ValidatorReactivated(address indexed validator); + event SnapshotCreated(uint256 indexed effectiveAsOfBlockNumber, uint256 bitmap); + function validatorIndex(address validator) external view returns (uint8 index); function activeValidatorBitmap() external view returns (uint256 bitmap); @@ -35,13 +42,6 @@ contract PodRegistry is IPodRegistry, Ownable { uint8 public nextValidatorIndex; uint256 public activeValidatorBitmap; - event ValidatorAdded(address indexed validator); - event ValidatorBanned(address indexed validator); - event ValidatorUnbanned(address indexed validator); - event ValidatorDeactivated(address indexed validator); - event ValidatorReactivated(address indexed validator); - event SnapshotCreated(uint256 indexed effectiveAsOfBlockNumber, uint256 bitmap); - constructor(address[] memory initialValidators) Ownable(msg.sender) { for (uint8 i = 0; i < initialValidators.length; i++) { _addValidator(initialValidators[i]); diff --git a/solidity-sdk/test/PodRegistry.t.sol b/solidity-sdk/test/PodRegistry.t.sol index 7df9fc99..0e32ce23 100644 --- a/solidity-sdk/test/PodRegistry.t.sol +++ b/solidity-sdk/test/PodRegistry.t.sol @@ -31,7 +31,7 @@ contract PodRegistryTest is Test { vm.prank(owner); vm.expectEmit(true, false, false, true); - emit PodRegistry.ValidatorAdded(validator3); + emit IPodRegistry.ValidatorAdded(validator3); registry.addValidator(validator3); assertEq(registry.getActiveValidatorCount(), 3); @@ -73,7 +73,7 @@ contract PodRegistryTest is Test { vm.prank(owner); vm.expectEmit(true, false, false, true); - emit PodRegistry.ValidatorBanned(validator1); + emit IPodRegistry.ValidatorBanned(validator1); registry.banValidator(validator1); assertEq(registry.getActiveValidatorCount(), 1); @@ -109,7 +109,7 @@ contract PodRegistryTest is Test { vm.prank(owner); vm.expectEmit(true, false, false, true); - emit PodRegistry.ValidatorUnbanned(validator1); + emit IPodRegistry.ValidatorUnbanned(validator1); registry.unbanValidator(validator1); assertFalse(registry.bannedValidators(validator1)); } @@ -159,14 +159,14 @@ contract PodRegistryTest is Test { vm.prank(validator1); vm.expectEmit(true, false, false, true); - emit PodRegistry.ValidatorDeactivated(validator1); + emit IPodRegistry.ValidatorDeactivated(validator1); registry.deactivate(); assertEq((registry.activeValidatorBitmap() & (1 << (1 - 1))), 0); assertEq(registry.getHistoryLength(), beforeHistory + 1); vm.prank(validator1); vm.expectEmit(true, false, false, true); - emit PodRegistry.ValidatorReactivated(validator1); + emit IPodRegistry.ValidatorReactivated(validator1); registry.reactivate(); assertEq((registry.activeValidatorBitmap() & (1 << (1 - 1))), (1 << (1 - 1))); assertEq(registry.getHistoryLength(), beforeHistory + 2); @@ -234,25 +234,25 @@ contract PodRegistryTest is Test { vm.prank(owner); vm.expectEmit(true, false, false, true); - emit PodRegistry.SnapshotCreated(block.number, (1 << (1 - 1)) | (1 << (2 - 1)) | (1 << (3 - 1))); + emit IPodRegistry.SnapshotCreated(block.number, (1 << (1 - 1)) | (1 << (2 - 1)) | (1 << (3 - 1))); registry.addValidator(validator3); assertEq(registry.getHistoryLength(), initialHistory + 1); vm.prank(owner); vm.expectEmit(true, false, false, true); - emit PodRegistry.SnapshotCreated(block.number, (1 << (1 - 1)) | (1 << (2 - 1))); + emit IPodRegistry.SnapshotCreated(block.number, (1 << (1 - 1)) | (1 << (2 - 1))); registry.banValidator(validator3); assertEq(registry.getHistoryLength(), initialHistory + 2); vm.prank(validator1); vm.expectEmit(true, false, false, true); - emit PodRegistry.SnapshotCreated(block.number, (1 << (2 - 1))); + emit IPodRegistry.SnapshotCreated(block.number, (1 << (2 - 1))); registry.deactivate(); assertEq(registry.getHistoryLength(), initialHistory + 3); vm.prank(validator1); vm.expectEmit(true, false, false, true); - emit PodRegistry.SnapshotCreated(block.number, (1 << (1 - 1)) | (1 << (2 - 1))); + emit IPodRegistry.SnapshotCreated(block.number, (1 << (1 - 1)) | (1 << (2 - 1))); registry.reactivate(); assertEq(registry.getHistoryLength(), initialHistory + 4); } From 10908999af11eee2c06ca4b1c617f00a0227a140 Mon Sep 17 00:00:00 2001 From: k4m4 Date: Fri, 25 Jul 2025 00:38:04 +0300 Subject: [PATCH 07/64] feat(registry): add missing functions to interface --- solidity-sdk/src/verifier/PodRegistry.sol | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/solidity-sdk/src/verifier/PodRegistry.sol b/solidity-sdk/src/verifier/PodRegistry.sol index d4deb651..f7cfe7b4 100644 --- a/solidity-sdk/src/verifier/PodRegistry.sol +++ b/solidity-sdk/src/verifier/PodRegistry.sol @@ -17,14 +17,25 @@ interface IPodRegistry { event SnapshotCreated(uint256 indexed effectiveAsOfBlockNumber, uint256 bitmap); function validatorIndex(address validator) external view returns (uint8 index); + function bannedValidators(address validator) external view returns (bool isBanned); + + function nextValidatorIndex() external view returns (uint8 index); function activeValidatorBitmap() external view returns (uint256 bitmap); + function addValidator(address validator) external; + function banValidator(address validator) external; + function unbanValidator(address validator) external; + function deactivate() external; + function reactivate() external; + function computeWeight(address[] memory subset) external view returns (uint256 weight); function computeWeight(address[] memory subset, uint256 blockNumber, uint256 snapshotIndex) external view returns (uint256 weight); + function findSnapshotIndex(uint256 blockNumber) external view returns (uint256 index); + function getActiveValidatorCount() external view returns (uint8 count); function getFaultTolerance() external view returns (uint8); function getSnapshot(uint256 index) external view returns (uint256 effectiveAsOfBlockNumber, uint256 bitmap); From d171ddcbf35aef4af4fce130e1c647eaf0e1c845 Mon Sep 17 00:00:00 2001 From: k4m4 Date: Fri, 25 Jul 2025 00:41:18 +0300 Subject: [PATCH 08/64] refactor(registry): {effective -> active}AsOfBlockNumber --- solidity-sdk/src/verifier/PodRegistry.sol | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/solidity-sdk/src/verifier/PodRegistry.sol b/solidity-sdk/src/verifier/PodRegistry.sol index f7cfe7b4..afe61e17 100644 --- a/solidity-sdk/src/verifier/PodRegistry.sol +++ b/solidity-sdk/src/verifier/PodRegistry.sol @@ -5,7 +5,7 @@ import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; interface IPodRegistry { struct Snapshot { - uint256 effectiveAsOfBlockNumber; + uint256 activeAsOfBlockNumber; uint256 bitmap; } @@ -14,7 +14,7 @@ interface IPodRegistry { event ValidatorUnbanned(address indexed validator); event ValidatorDeactivated(address indexed validator); event ValidatorReactivated(address indexed validator); - event SnapshotCreated(uint256 indexed effectiveAsOfBlockNumber, uint256 bitmap); + event SnapshotCreated(uint256 indexed activeAsOfBlockNumber, uint256 bitmap); function validatorIndex(address validator) external view returns (uint8 index); function bannedValidators(address validator) external view returns (bool isBanned); @@ -38,7 +38,7 @@ interface IPodRegistry { function getActiveValidatorCount() external view returns (uint8 count); function getFaultTolerance() external view returns (uint8); - function getSnapshot(uint256 index) external view returns (uint256 effectiveAsOfBlockNumber, uint256 bitmap); + function getSnapshot(uint256 index) external view returns (uint256 activeAsOfBlockNumber, uint256 bitmap); function getHistoryLength() external view returns (uint256); } @@ -124,7 +124,7 @@ contract PodRegistry is IPodRegistry, Ownable { } function _createSnapshot() internal { - history.push(Snapshot({effectiveAsOfBlockNumber: block.number, bitmap: activeValidatorBitmap})); + history.push(Snapshot({activeAsOfBlockNumber: block.number, bitmap: activeValidatorBitmap})); emit SnapshotCreated(block.number, activeValidatorBitmap); } @@ -143,9 +143,9 @@ contract PodRegistry is IPodRegistry, Ownable { { require(snapshotIndex < history.length, "pod: invalid snapshot index"); Snapshot memory snapshot = history[snapshotIndex]; - require(snapshot.effectiveAsOfBlockNumber <= blockNumber, "pod: snapshot too new"); + require(snapshot.activeAsOfBlockNumber <= blockNumber, "pod: snapshot too new"); require( - snapshotIndex == history.length - 1 || history[snapshotIndex + 1].effectiveAsOfBlockNumber > blockNumber, + snapshotIndex == history.length - 1 || history[snapshotIndex + 1].activeAsOfBlockNumber > blockNumber, "pod: snapshot too old" ); @@ -175,7 +175,7 @@ contract PodRegistry is IPodRegistry, Ownable { while (low < high) { uint256 mid = (low + high + 1) / 2; - if (history[mid].effectiveAsOfBlockNumber <= blockNumber) { + if (history[mid].activeAsOfBlockNumber <= blockNumber) { low = mid; } else { high = mid - 1; @@ -198,9 +198,9 @@ contract PodRegistry is IPodRegistry, Ownable { return getActiveValidatorCount() / 3; } - function getSnapshot(uint256 index) external view returns (uint256 effectiveAsOfBlockNumber, uint256 bitmap) { + function getSnapshot(uint256 index) external view returns (uint256 activeAsOfBlockNumber, uint256 bitmap) { Snapshot memory s = history[index]; - return (s.effectiveAsOfBlockNumber, s.bitmap); + return (s.activeAsOfBlockNumber, s.bitmap); } function getHistoryLength() external view returns (uint256) { From 5276a770de3c558a5e88431aa9771736c1b45be3 Mon Sep 17 00:00:00 2001 From: Jakov Mitrovski Date: Fri, 8 Aug 2025 14:36:06 +0200 Subject: [PATCH 09/64] refactor(registry): address PR comments, minor fixes --- solidity-sdk/src/verifier/PodRegistry.sol | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/solidity-sdk/src/verifier/PodRegistry.sol b/solidity-sdk/src/verifier/PodRegistry.sol index afe61e17..aeb9b5e8 100644 --- a/solidity-sdk/src/verifier/PodRegistry.sol +++ b/solidity-sdk/src/verifier/PodRegistry.sol @@ -50,10 +50,12 @@ contract PodRegistry is IPodRegistry, Ownable { mapping(address => uint8) public validatorIndex; mapping(address => bool) public bannedValidators; - uint8 public nextValidatorIndex; uint256 public activeValidatorBitmap; + uint8 public nextValidatorIndex; constructor(address[] memory initialValidators) Ownable(msg.sender) { + require(initialValidators.length <= MAX_VALIDATOR_COUNT, "pod: validator count exceeds max allowed"); + for (uint8 i = 0; i < initialValidators.length; i++) { _addValidator(initialValidators[i]); } @@ -72,7 +74,8 @@ contract PodRegistry is IPodRegistry, Ownable { require(nextValidatorIndex < MAX_VALIDATOR_COUNT, "pod: max validator count reached"); uint8 index = ++nextValidatorIndex; validatorIndex[validator] = index; - activeValidatorBitmap |= (1 << (index - 1)); + uint256 mask = 1 << (index - 1); + activeValidatorBitmap |= mask; emit ValidatorAdded(validator); } @@ -87,9 +90,7 @@ contract PodRegistry is IPodRegistry, Ownable { require(!bannedValidators[validator], "pod: validator is already banned"); uint256 mask = 1 << (index - 1); - if ((activeValidatorBitmap & mask) != 0) { - activeValidatorBitmap &= ~mask; - } + activeValidatorBitmap &= ~mask; bannedValidators[validator] = true; emit ValidatorBanned(validator); @@ -149,10 +150,9 @@ contract PodRegistry is IPodRegistry, Ownable { "pod: snapshot too old" ); - uint256 bitmap = snapshot.bitmap; uint256 counted = 0; - for (uint8 i = 0; i < subset.length; i++) { + for (uint256 i = 0; i < subset.length; i++) { uint8 index = validatorIndex[subset[i]]; if (index == 0) { @@ -160,7 +160,7 @@ contract PodRegistry is IPodRegistry, Ownable { } uint256 mask = 1 << (index - 1); - if ((bitmap & mask) != 0 && (counted & mask) == 0) { + if ((snapshot.bitmap & mask) != 0 && (counted & mask) == 0) { counted |= mask; weight++; } From 31926778d264137972521aaa3e11b950cda2b839 Mon Sep 17 00:00:00 2001 From: Jakov Mitrovski Date: Wed, 13 Aug 2025 10:37:51 +0200 Subject: [PATCH 10/64] feat(registry): address PR comments --- solidity-sdk/src/verifier/PodRegistry.sol | 133 +++++++++++++++------- 1 file changed, 91 insertions(+), 42 deletions(-) diff --git a/solidity-sdk/src/verifier/PodRegistry.sol b/solidity-sdk/src/verifier/PodRegistry.sol index aeb9b5e8..7bf6ec2e 100644 --- a/solidity-sdk/src/verifier/PodRegistry.sol +++ b/solidity-sdk/src/verifier/PodRegistry.sol @@ -14,12 +14,19 @@ interface IPodRegistry { event ValidatorUnbanned(address indexed validator); event ValidatorDeactivated(address indexed validator); event ValidatorReactivated(address indexed validator); - event SnapshotCreated(uint256 indexed activeAsOfBlockNumber, uint256 bitmap); - - function validatorIndex(address validator) external view returns (uint8 index); - function bannedValidators(address validator) external view returns (bool isBanned); - - function nextValidatorIndex() external view returns (uint8 index); + event SnapshotCreated( + uint256 indexed activeAsOfBlockNumber, + uint256 bitmap + ); + + function validatorIndex( + address validator + ) external view returns (uint8 index); + function bannedValidators( + address validator + ) external view returns (bool isBanned); + + function validatorCount() external view returns (uint8 index); function activeValidatorBitmap() external view returns (uint256 bitmap); function addValidator(address validator) external; @@ -28,17 +35,24 @@ interface IPodRegistry { function deactivate() external; function reactivate() external; - function computeWeight(address[] memory subset) external view returns (uint256 weight); - function computeWeight(address[] memory subset, uint256 blockNumber, uint256 snapshotIndex) - external - view - returns (uint256 weight); + function computeWeight( + address[] memory subset + ) external view returns (uint256 weight); + function computeWeight( + address[] memory subset, + uint256 blockNumber, + uint256 snapshotIndex + ) external view returns (uint256 weight); - function findSnapshotIndex(uint256 blockNumber) external view returns (uint256 index); + function findSnapshotIndex( + uint256 blockNumber + ) external view returns (uint256 index); function getActiveValidatorCount() external view returns (uint8 count); function getFaultTolerance() external view returns (uint8); - function getSnapshot(uint256 index) external view returns (uint256 activeAsOfBlockNumber, uint256 bitmap); + function getSnapshot( + uint256 index + ) external view returns (uint256 activeAsOfBlockNumber, uint256 bitmap); function getHistoryLength() external view returns (uint256); } @@ -51,11 +65,9 @@ contract PodRegistry is IPodRegistry, Ownable { mapping(address => bool) public bannedValidators; uint256 public activeValidatorBitmap; - uint8 public nextValidatorIndex; + uint8 public validatorCount; constructor(address[] memory initialValidators) Ownable(msg.sender) { - require(initialValidators.length <= MAX_VALIDATOR_COUNT, "pod: validator count exceeds max allowed"); - for (uint8 i = 0; i < initialValidators.length; i++) { _addValidator(initialValidators[i]); } @@ -70,12 +82,17 @@ contract PodRegistry is IPodRegistry, Ownable { function _addValidator(address validator) internal { require(validator != address(0), "pod: validator is the zero address"); - require(validatorIndex[validator] == 0, "pod: validator already exists"); - require(nextValidatorIndex < MAX_VALIDATOR_COUNT, "pod: max validator count reached"); - uint8 index = ++nextValidatorIndex; + require( + validatorIndex[validator] == 0, + "pod: validator already exists" + ); + require( + validatorCount < MAX_VALIDATOR_COUNT, + "pod: max validator count reached" + ); + uint8 index = ++validatorCount; validatorIndex[validator] = index; - uint256 mask = 1 << (index - 1); - activeValidatorBitmap |= mask; + _activateValidator(index); emit ValidatorAdded(validator); } @@ -87,17 +104,24 @@ contract PodRegistry is IPodRegistry, Ownable { function _banValidator(address validator) internal { uint8 index = validatorIndex[validator]; require(index != 0, "pod: validator does not exist"); - require(!bannedValidators[validator], "pod: validator is already banned"); + require( + !bannedValidators[validator], + "pod: validator is already banned" + ); - uint256 mask = 1 << (index - 1); - activeValidatorBitmap &= ~mask; + if (_isValidatorActive(index)) { + _deactivateValidator(index); + } bannedValidators[validator] = true; emit ValidatorBanned(validator); } function unbanValidator(address validator) external onlyOwner { - require(validatorIndex[validator] != 0, "pod: validator does not exist"); + require( + validatorIndex[validator] != 0, + "pod: validator does not exist" + ); require(bannedValidators[validator], "pod: validator is not banned"); bannedValidators[validator] = false; emit ValidatorUnbanned(validator); @@ -106,9 +130,8 @@ contract PodRegistry is IPodRegistry, Ownable { function deactivate() external { uint8 index = validatorIndex[msg.sender]; require(index != 0, "pod: caller is not a validator"); - uint256 mask = 1 << (index - 1); - require((activeValidatorBitmap & mask) != 0, "pod: caller is already inactive"); - activeValidatorBitmap &= ~mask; + require(_isValidatorActive(index), "pod: caller is already inactive"); + _deactivateValidator(index); emit ValidatorDeactivated(msg.sender); _createSnapshot(); } @@ -117,19 +140,25 @@ contract PodRegistry is IPodRegistry, Ownable { uint8 index = validatorIndex[msg.sender]; require(index != 0, "pod: caller is not a validator"); require(!bannedValidators[msg.sender], "pod: caller has been banned"); - uint256 mask = 1 << (index - 1); - require((activeValidatorBitmap & mask) == 0, "pod: caller is already active"); - activeValidatorBitmap |= mask; + require(!_isValidatorActive(index), "pod: caller is already active"); + _activateValidator(index); emit ValidatorReactivated(msg.sender); _createSnapshot(); } function _createSnapshot() internal { - history.push(Snapshot({activeAsOfBlockNumber: block.number, bitmap: activeValidatorBitmap})); + history.push( + Snapshot({ + activeAsOfBlockNumber: block.number, + bitmap: activeValidatorBitmap + }) + ); emit SnapshotCreated(block.number, activeValidatorBitmap); } - function computeWeight(address[] memory subset) public view returns (uint256 weight) { + function computeWeight( + address[] memory subset + ) public view returns (uint256 weight) { if (history.length == 0) { return 0; } @@ -137,16 +166,20 @@ contract PodRegistry is IPodRegistry, Ownable { return computeWeight(subset, block.number, history.length - 1); } - function computeWeight(address[] memory subset, uint256 blockNumber, uint256 snapshotIndex) - public - view - returns (uint256 weight) - { + function computeWeight( + address[] memory subset, + uint256 blockNumber, + uint256 snapshotIndex + ) public view returns (uint256 weight) { require(snapshotIndex < history.length, "pod: invalid snapshot index"); Snapshot memory snapshot = history[snapshotIndex]; - require(snapshot.activeAsOfBlockNumber <= blockNumber, "pod: snapshot too new"); require( - snapshotIndex == history.length - 1 || history[snapshotIndex + 1].activeAsOfBlockNumber > blockNumber, + snapshot.activeAsOfBlockNumber <= blockNumber, + "pod: snapshot too new" + ); + require( + snapshotIndex == history.length - 1 || + history[snapshotIndex + 1].activeAsOfBlockNumber > blockNumber, "pod: snapshot too old" ); @@ -167,7 +200,9 @@ contract PodRegistry is IPodRegistry, Ownable { } } - function findSnapshotIndex(uint256 blockNumber) external view returns (uint256 index) { + function findSnapshotIndex( + uint256 blockNumber + ) external view returns (uint256 index) { require(history.length > 0, "pod: no historical snapshots"); uint256 low = 0; @@ -198,7 +233,9 @@ contract PodRegistry is IPodRegistry, Ownable { return getActiveValidatorCount() / 3; } - function getSnapshot(uint256 index) external view returns (uint256 activeAsOfBlockNumber, uint256 bitmap) { + function getSnapshot( + uint256 index + ) external view returns (uint256 activeAsOfBlockNumber, uint256 bitmap) { Snapshot memory s = history[index]; return (s.activeAsOfBlockNumber, s.bitmap); } @@ -206,4 +243,16 @@ contract PodRegistry is IPodRegistry, Ownable { function getHistoryLength() external view returns (uint256) { return history.length; } + + function _activateValidator(uint8 index) internal { + activeValidatorBitmap |= (1 << (index - 1)); + } + + function _deactivateValidator(uint8 index) internal { + activeValidatorBitmap &= ~(1 << (index - 1)); + } + + function _isValidatorActive(uint8 index) internal view returns (bool) { + return (activeValidatorBitmap & (1 << (index - 1))) != 0; + } } From 8b0563b6b8782cc8d0cf9d7f646972dedc502174 Mon Sep 17 00:00:00 2001 From: Jakov Mitrovski Date: Wed, 13 Aug 2025 14:26:29 +0200 Subject: [PATCH 11/64] refactor(registry): refactor snapshotting logic and add tests - Add functions for activating / deactivating validators - Add a function for initializing a validator - Refactor methods to use the functions - Rename nextValidatorIndex to validatorCount and derive index from it - Add tests compute weight when subset is larger than 255 and test ban not creating a snapshot when the banned validator is inactive --- solidity-sdk/src/verifier/PodRegistry.sol | 29 +++++++++++++---------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/solidity-sdk/src/verifier/PodRegistry.sol b/solidity-sdk/src/verifier/PodRegistry.sol index 7bf6ec2e..ea6ffcbc 100644 --- a/solidity-sdk/src/verifier/PodRegistry.sol +++ b/solidity-sdk/src/verifier/PodRegistry.sol @@ -68,19 +68,25 @@ contract PodRegistry is IPodRegistry, Ownable { uint8 public validatorCount; constructor(address[] memory initialValidators) Ownable(msg.sender) { + require( + initialValidators.length < MAX_VALIDATOR_COUNT, + "pod: too many initial validators" + ); + validatorCount = uint8(initialValidators.length); + for (uint8 i = 0; i < initialValidators.length; i++) { - _addValidator(initialValidators[i]); + _addValidatorOnInit(initialValidators[i], i); } _createSnapshot(); } - function addValidator(address validator) external onlyOwner { - _addValidator(validator); - _createSnapshot(); + function _addValidatorOnInit(address validator, uint8 index) internal { + validatorIndex[validator] = index + 1; + activeValidatorBitmap |= (1 << index); } - function _addValidator(address validator) internal { + function addValidator(address validator) external onlyOwner { require(validator != address(0), "pod: validator is the zero address"); require( validatorIndex[validator] == 0, @@ -92,16 +98,13 @@ contract PodRegistry is IPodRegistry, Ownable { ); uint8 index = ++validatorCount; validatorIndex[validator] = index; - _activateValidator(index); + if (!_isValidatorActive(index)) { + _activateValidator(index); + } emit ValidatorAdded(validator); } function banValidator(address validator) external onlyOwner { - _banValidator(validator); - _createSnapshot(); - } - - function _banValidator(address validator) internal { uint8 index = validatorIndex[validator]; require(index != 0, "pod: validator does not exist"); require( @@ -133,7 +136,6 @@ contract PodRegistry is IPodRegistry, Ownable { require(_isValidatorActive(index), "pod: caller is already inactive"); _deactivateValidator(index); emit ValidatorDeactivated(msg.sender); - _createSnapshot(); } function reactivate() external { @@ -143,7 +145,6 @@ contract PodRegistry is IPodRegistry, Ownable { require(!_isValidatorActive(index), "pod: caller is already active"); _activateValidator(index); emit ValidatorReactivated(msg.sender); - _createSnapshot(); } function _createSnapshot() internal { @@ -246,10 +247,12 @@ contract PodRegistry is IPodRegistry, Ownable { function _activateValidator(uint8 index) internal { activeValidatorBitmap |= (1 << (index - 1)); + _createSnapshot(); } function _deactivateValidator(uint8 index) internal { activeValidatorBitmap &= ~(1 << (index - 1)); + _createSnapshot(); } function _isValidatorActive(uint8 index) internal view returns (bool) { From c096cbc5248bf73ffbfecf0bf9bea20a2b501361 Mon Sep 17 00:00:00 2001 From: Jakov Mitrovski Date: Wed, 13 Aug 2025 14:44:41 +0200 Subject: [PATCH 12/64] refactor(registry): replace requires with error reverts --- solidity-sdk/src/verifier/PodRegistry.sol | 171 +++++++++++----------- 1 file changed, 87 insertions(+), 84 deletions(-) diff --git a/solidity-sdk/src/verifier/PodRegistry.sol b/solidity-sdk/src/verifier/PodRegistry.sol index ea6ffcbc..cfde88e6 100644 --- a/solidity-sdk/src/verifier/PodRegistry.sol +++ b/solidity-sdk/src/verifier/PodRegistry.sol @@ -9,22 +9,31 @@ interface IPodRegistry { uint256 bitmap; } + error TooManyInitialValidators(); + error ValidatorIsZeroAddress(); + error ValidatorAlreadyExists(); + error MaxValidatorCountReached(); + error ValidatorDoesNotExist(); + error ValidatorAlreadyBanned(); + error ValidatorNotBanned(); + error CallerNotValidator(); + error CallerAlreadyInactive(); + error CallerHasBeenBanned(); + error CallerAlreadyActive(); + error InvalidSnapshotIndex(); + error SnapshotTooNew(); + error SnapshotTooOld(); + error NoHistoricalSnapshots(); + event ValidatorAdded(address indexed validator); event ValidatorBanned(address indexed validator); event ValidatorUnbanned(address indexed validator); event ValidatorDeactivated(address indexed validator); event ValidatorReactivated(address indexed validator); - event SnapshotCreated( - uint256 indexed activeAsOfBlockNumber, - uint256 bitmap - ); - - function validatorIndex( - address validator - ) external view returns (uint8 index); - function bannedValidators( - address validator - ) external view returns (bool isBanned); + event SnapshotCreated(uint256 indexed activeAsOfBlockNumber, uint256 bitmap); + + function validatorIndex(address validator) external view returns (uint8 index); + function bannedValidators(address validator) external view returns (bool isBanned); function validatorCount() external view returns (uint8 index); function activeValidatorBitmap() external view returns (uint256 bitmap); @@ -35,24 +44,17 @@ interface IPodRegistry { function deactivate() external; function reactivate() external; - function computeWeight( - address[] memory subset - ) external view returns (uint256 weight); - function computeWeight( - address[] memory subset, - uint256 blockNumber, - uint256 snapshotIndex - ) external view returns (uint256 weight); + function computeWeight(address[] memory subset) external view returns (uint256 weight); + function computeWeight(address[] memory subset, uint256 blockNumber, uint256 snapshotIndex) + external + view + returns (uint256 weight); - function findSnapshotIndex( - uint256 blockNumber - ) external view returns (uint256 index); + function findSnapshotIndex(uint256 blockNumber) external view returns (uint256 index); function getActiveValidatorCount() external view returns (uint8 count); function getFaultTolerance() external view returns (uint8); - function getSnapshot( - uint256 index - ) external view returns (uint256 activeAsOfBlockNumber, uint256 bitmap); + function getSnapshot(uint256 index) external view returns (uint256 activeAsOfBlockNumber, uint256 bitmap); function getHistoryLength() external view returns (uint256); } @@ -68,10 +70,9 @@ contract PodRegistry is IPodRegistry, Ownable { uint8 public validatorCount; constructor(address[] memory initialValidators) Ownable(msg.sender) { - require( - initialValidators.length < MAX_VALIDATOR_COUNT, - "pod: too many initial validators" - ); + if (initialValidators.length >= MAX_VALIDATOR_COUNT) { + revert TooManyInitialValidators(); + } validatorCount = uint8(initialValidators.length); for (uint8 i = 0; i < initialValidators.length; i++) { @@ -87,15 +88,15 @@ contract PodRegistry is IPodRegistry, Ownable { } function addValidator(address validator) external onlyOwner { - require(validator != address(0), "pod: validator is the zero address"); - require( - validatorIndex[validator] == 0, - "pod: validator already exists" - ); - require( - validatorCount < MAX_VALIDATOR_COUNT, - "pod: max validator count reached" - ); + if (validator == address(0)) { + revert ValidatorIsZeroAddress(); + } + if (validatorIndex[validator] != 0) { + revert ValidatorAlreadyExists(); + } + if (validatorCount >= MAX_VALIDATOR_COUNT) { + revert MaxValidatorCountReached(); + } uint8 index = ++validatorCount; validatorIndex[validator] = index; if (!_isValidatorActive(index)) { @@ -106,11 +107,12 @@ contract PodRegistry is IPodRegistry, Ownable { function banValidator(address validator) external onlyOwner { uint8 index = validatorIndex[validator]; - require(index != 0, "pod: validator does not exist"); - require( - !bannedValidators[validator], - "pod: validator is already banned" - ); + if (index == 0) { + revert ValidatorDoesNotExist(); + } + if (bannedValidators[validator]) { + revert ValidatorAlreadyBanned(); + } if (_isValidatorActive(index)) { _deactivateValidator(index); @@ -121,45 +123,49 @@ contract PodRegistry is IPodRegistry, Ownable { } function unbanValidator(address validator) external onlyOwner { - require( - validatorIndex[validator] != 0, - "pod: validator does not exist" - ); - require(bannedValidators[validator], "pod: validator is not banned"); + if (validatorIndex[validator] == 0) { + revert ValidatorDoesNotExist(); + } + if (!bannedValidators[validator]) { + revert ValidatorNotBanned(); + } bannedValidators[validator] = false; emit ValidatorUnbanned(validator); } function deactivate() external { uint8 index = validatorIndex[msg.sender]; - require(index != 0, "pod: caller is not a validator"); - require(_isValidatorActive(index), "pod: caller is already inactive"); + if (index == 0) { + revert CallerNotValidator(); + } + if (!_isValidatorActive(index)) { + revert CallerAlreadyInactive(); + } _deactivateValidator(index); emit ValidatorDeactivated(msg.sender); } function reactivate() external { uint8 index = validatorIndex[msg.sender]; - require(index != 0, "pod: caller is not a validator"); - require(!bannedValidators[msg.sender], "pod: caller has been banned"); - require(!_isValidatorActive(index), "pod: caller is already active"); + if (index == 0) { + revert CallerNotValidator(); + } + if (bannedValidators[msg.sender]) { + revert CallerHasBeenBanned(); + } + if (_isValidatorActive(index)) { + revert CallerAlreadyActive(); + } _activateValidator(index); emit ValidatorReactivated(msg.sender); } function _createSnapshot() internal { - history.push( - Snapshot({ - activeAsOfBlockNumber: block.number, - bitmap: activeValidatorBitmap - }) - ); + history.push(Snapshot({activeAsOfBlockNumber: block.number, bitmap: activeValidatorBitmap})); emit SnapshotCreated(block.number, activeValidatorBitmap); } - function computeWeight( - address[] memory subset - ) public view returns (uint256 weight) { + function computeWeight(address[] memory subset) public view returns (uint256 weight) { if (history.length == 0) { return 0; } @@ -167,22 +173,21 @@ contract PodRegistry is IPodRegistry, Ownable { return computeWeight(subset, block.number, history.length - 1); } - function computeWeight( - address[] memory subset, - uint256 blockNumber, - uint256 snapshotIndex - ) public view returns (uint256 weight) { - require(snapshotIndex < history.length, "pod: invalid snapshot index"); + function computeWeight(address[] memory subset, uint256 blockNumber, uint256 snapshotIndex) + public + view + returns (uint256 weight) + { + if (snapshotIndex >= history.length) { + revert InvalidSnapshotIndex(); + } Snapshot memory snapshot = history[snapshotIndex]; - require( - snapshot.activeAsOfBlockNumber <= blockNumber, - "pod: snapshot too new" - ); - require( - snapshotIndex == history.length - 1 || - history[snapshotIndex + 1].activeAsOfBlockNumber > blockNumber, - "pod: snapshot too old" - ); + if (snapshot.activeAsOfBlockNumber > blockNumber) { + revert SnapshotTooNew(); + } + if (snapshotIndex != history.length - 1 && history[snapshotIndex + 1].activeAsOfBlockNumber <= blockNumber) { + revert SnapshotTooOld(); + } uint256 counted = 0; @@ -201,10 +206,10 @@ contract PodRegistry is IPodRegistry, Ownable { } } - function findSnapshotIndex( - uint256 blockNumber - ) external view returns (uint256 index) { - require(history.length > 0, "pod: no historical snapshots"); + function findSnapshotIndex(uint256 blockNumber) external view returns (uint256 index) { + if (history.length == 0) { + revert NoHistoricalSnapshots(); + } uint256 low = 0; uint256 high = history.length - 1; @@ -234,9 +239,7 @@ contract PodRegistry is IPodRegistry, Ownable { return getActiveValidatorCount() / 3; } - function getSnapshot( - uint256 index - ) external view returns (uint256 activeAsOfBlockNumber, uint256 bitmap) { + function getSnapshot(uint256 index) external view returns (uint256 activeAsOfBlockNumber, uint256 bitmap) { Snapshot memory s = history[index]; return (s.activeAsOfBlockNumber, s.bitmap); } From 55c4043b8fa76548d129569b210c0d2ea0967d5e Mon Sep 17 00:00:00 2001 From: Jakov Mitrovski Date: Wed, 13 Aug 2025 14:46:30 +0200 Subject: [PATCH 13/64] refactor(registry): replace requires with error reverts --- solidity-sdk/test/PodRegistry.t.sol | 58 +++++++++++++++++++++-------- 1 file changed, 43 insertions(+), 15 deletions(-) diff --git a/solidity-sdk/test/PodRegistry.t.sol b/solidity-sdk/test/PodRegistry.t.sol index 0e32ce23..8e015703 100644 --- a/solidity-sdk/test/PodRegistry.t.sol +++ b/solidity-sdk/test/PodRegistry.t.sol @@ -46,16 +46,25 @@ contract PodRegistryTest is Test { function test_AddValidator_RevertIfZeroAddress() public { vm.prank(owner); - vm.expectRevert("pod: validator is the zero address"); + vm.expectRevert(abi.encodeWithSignature("ValidatorIsZeroAddress()")); registry.addValidator(address(0)); } function test_AddValidator_RevertIfAlreadyExists() public { vm.prank(owner); - vm.expectRevert("pod: validator already exists"); + vm.expectRevert(abi.encodeWithSignature("ValidatorAlreadyExists()")); registry.addValidator(validator1); } + function test_Initialize_RevertIfTooManyValidators() public { + address[] memory initialValidators = new address[](255); + for (uint8 i = 0; i < 255; i++) { + initialValidators[i] = address(uint160(1000 + i)); + } + vm.expectRevert(abi.encodeWithSignature("TooManyInitialValidators()")); + new PodRegistry(initialValidators); + } + function test_AddValidator_RevertIfMaxCountReached() public { vm.startPrank(owner); for (uint8 i = 0; i < 253; i++) { @@ -63,7 +72,7 @@ contract PodRegistryTest is Test { registry.addValidator(newValidator); } - vm.expectRevert("pod: max validator count reached"); + vm.expectRevert(abi.encodeWithSignature("MaxValidatorCountReached()")); registry.addValidator(address(9999)); vm.stopPrank(); } @@ -82,6 +91,16 @@ contract PodRegistryTest is Test { assertEq(registry.getHistoryLength(), beforeHistory + 1); } + function test_BanValidator_DoesNotCreateSnapshotWhenValidatorIsInactive() public { + vm.prank(validator1); + registry.deactivate(); + + uint256 beforeHistory = registry.getHistoryLength(); + vm.prank(owner); + registry.banValidator(validator1); + assertEq(registry.getHistoryLength(), beforeHistory); + } + function test_BanValidator_RevertIfNotOwner() public { vm.expectRevert(abi.encodeWithSignature("OwnableUnauthorizedAccount(address)", address(this))); registry.banValidator(validator1); @@ -89,7 +108,7 @@ contract PodRegistryTest is Test { function test_BanValidator_RevertIfNotExists() public { vm.prank(owner); - vm.expectRevert("pod: validator does not exist"); + vm.expectRevert(abi.encodeWithSignature("ValidatorDoesNotExist()")); registry.banValidator(validator3); } @@ -98,7 +117,7 @@ contract PodRegistryTest is Test { registry.banValidator(validator1); vm.prank(owner); - vm.expectRevert("pod: validator is already banned"); + vm.expectRevert(abi.encodeWithSignature("ValidatorAlreadyBanned()")); registry.banValidator(validator1); } @@ -129,7 +148,7 @@ contract PodRegistryTest is Test { registry.banValidator(validator1); vm.prank(validator1); - vm.expectRevert("pod: caller has been banned"); + vm.expectRevert(abi.encodeWithSignature("CallerHasBeenBanned()")); registry.reactivate(); vm.prank(owner); @@ -177,13 +196,13 @@ contract PodRegistryTest is Test { registry.deactivate(); vm.prank(validator1); - vm.expectRevert("pod: caller is already inactive"); + vm.expectRevert(abi.encodeWithSignature("CallerAlreadyInactive()")); registry.deactivate(); } function test_Reactivate_RevertIfAlreadyActive() public { vm.prank(validator1); - vm.expectRevert("pod: caller is already active"); + vm.expectRevert(abi.encodeWithSignature("CallerAlreadyActive()")); registry.reactivate(); } @@ -192,7 +211,7 @@ contract PodRegistryTest is Test { registry.banValidator(validator1); vm.prank(validator1); - vm.expectRevert("pod: caller has been banned"); + vm.expectRevert(abi.encodeWithSignature("CallerHasBeenBanned()")); registry.reactivate(); } @@ -201,19 +220,19 @@ contract PodRegistryTest is Test { registry.banValidator(validator1); vm.prank(validator1); - vm.expectRevert("pod: caller has been banned"); + vm.expectRevert(abi.encodeWithSignature("CallerHasBeenBanned()")); registry.reactivate(); } function test_Deactivate_RevertIfNotValidator() public { vm.prank(address(1337)); - vm.expectRevert("pod: caller is not a validator"); + vm.expectRevert(abi.encodeWithSignature("CallerNotValidator()")); registry.deactivate(); } function test_Reactivate_RevertIfNotValidator() public { vm.prank(address(1337)); - vm.expectRevert("pod: caller is not a validator"); + vm.expectRevert(abi.encodeWithSignature("CallerNotValidator()")); registry.reactivate(); } @@ -278,6 +297,15 @@ contract PodRegistryTest is Test { assertEq(weight, 2); } + function test_ComputeWeight_WithSubsetLargerThan255() public view { + address[] memory subset = new address[](256); + for (uint16 i = 0; i < 256; i++) { + subset[i] = validator1; + } + uint256 weight = registry.computeWeight(subset); + assertEq(weight, 1); + } + function test_ComputeWeight_IgnoresInactiveValidators() public { vm.prank(validator1); registry.deactivate(); @@ -341,7 +369,7 @@ contract PodRegistryTest is Test { subset[0] = validator1; subset[1] = validator2; - vm.expectRevert("pod: snapshot too old"); + vm.expectRevert(abi.encodeWithSignature("SnapshotTooOld()")); registry.computeWeight(subset, latestBlock, 0); } @@ -359,7 +387,7 @@ contract PodRegistryTest is Test { subset[0] = validator1; subset[1] = validator3; - vm.expectRevert("pod: snapshot too new"); + vm.expectRevert(abi.encodeWithSignature("SnapshotTooNew()")); registry.computeWeight(subset, blockAtAdd, 2); } @@ -367,7 +395,7 @@ contract PodRegistryTest is Test { address[] memory subset = new address[](1); subset[0] = validator1; - vm.expectRevert("pod: invalid snapshot index"); + vm.expectRevert(abi.encodeWithSignature("InvalidSnapshotIndex()")); registry.computeWeight(subset, block.number, 999); } From 2c5ed4a4962fc86651278de6a8882bc9fec5ab15 Mon Sep 17 00:00:00 2001 From: Jakov Mitrovski Date: Wed, 13 Aug 2025 15:01:43 +0200 Subject: [PATCH 14/64] refactor(registry): rename error --- solidity-sdk/src/verifier/PodRegistry.sol | 4 ++-- solidity-sdk/test/PodRegistry.t.sol | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/solidity-sdk/src/verifier/PodRegistry.sol b/solidity-sdk/src/verifier/PodRegistry.sol index cfde88e6..dd2a2acd 100644 --- a/solidity-sdk/src/verifier/PodRegistry.sol +++ b/solidity-sdk/src/verifier/PodRegistry.sol @@ -18,7 +18,7 @@ interface IPodRegistry { error ValidatorNotBanned(); error CallerNotValidator(); error CallerAlreadyInactive(); - error CallerHasBeenBanned(); + error CallerAlreadyBanned(); error CallerAlreadyActive(); error InvalidSnapshotIndex(); error SnapshotTooNew(); @@ -151,7 +151,7 @@ contract PodRegistry is IPodRegistry, Ownable { revert CallerNotValidator(); } if (bannedValidators[msg.sender]) { - revert CallerHasBeenBanned(); + revert CallerAlreadyBanned(); } if (_isValidatorActive(index)) { revert CallerAlreadyActive(); diff --git a/solidity-sdk/test/PodRegistry.t.sol b/solidity-sdk/test/PodRegistry.t.sol index 8e015703..79ad0134 100644 --- a/solidity-sdk/test/PodRegistry.t.sol +++ b/solidity-sdk/test/PodRegistry.t.sol @@ -148,7 +148,7 @@ contract PodRegistryTest is Test { registry.banValidator(validator1); vm.prank(validator1); - vm.expectRevert(abi.encodeWithSignature("CallerHasBeenBanned()")); + vm.expectRevert(abi.encodeWithSignature("CallerAlreadyBanned()")); registry.reactivate(); vm.prank(owner); @@ -211,7 +211,7 @@ contract PodRegistryTest is Test { registry.banValidator(validator1); vm.prank(validator1); - vm.expectRevert(abi.encodeWithSignature("CallerHasBeenBanned()")); + vm.expectRevert(abi.encodeWithSignature("CallerAlreadyBanned()")); registry.reactivate(); } @@ -220,7 +220,7 @@ contract PodRegistryTest is Test { registry.banValidator(validator1); vm.prank(validator1); - vm.expectRevert(abi.encodeWithSignature("CallerHasBeenBanned()")); + vm.expectRevert(abi.encodeWithSignature("CallerAlreadyBanned()")); registry.reactivate(); } From e101bb8848bf1d34f91546ead414ae2f737106cc Mon Sep 17 00:00:00 2001 From: Jakov Mitrovski Date: Thu, 14 Aug 2025 13:19:44 +0200 Subject: [PATCH 15/64] feat(registry): add getActiveValidators and getValidatorsAt functions + tests --- solidity-sdk/src/verifier/PodRegistry.sol | 37 ++++++++++++++++++++--- solidity-sdk/test/PodRegistry.t.sol | 22 ++++++++++++++ 2 files changed, 55 insertions(+), 4 deletions(-) diff --git a/solidity-sdk/src/verifier/PodRegistry.sol b/solidity-sdk/src/verifier/PodRegistry.sol index dd2a2acd..d2540296 100644 --- a/solidity-sdk/src/verifier/PodRegistry.sol +++ b/solidity-sdk/src/verifier/PodRegistry.sol @@ -53,6 +53,8 @@ interface IPodRegistry { function findSnapshotIndex(uint256 blockNumber) external view returns (uint256 index); function getActiveValidatorCount() external view returns (uint8 count); + function getActiveValidators() external view returns (address[] memory); + function getValidatorsAt(uint256 blockNumber) external view returns (address[] memory); function getFaultTolerance() external view returns (uint8); function getSnapshot(uint256 index) external view returns (uint256 activeAsOfBlockNumber, uint256 bitmap); function getHistoryLength() external view returns (uint256); @@ -64,6 +66,7 @@ contract PodRegistry is IPodRegistry, Ownable { Snapshot[] public history; mapping(address => uint8) public validatorIndex; + mapping(uint8 => address) public validatorAddress; mapping(address => bool) public bannedValidators; uint256 public activeValidatorBitmap; @@ -85,6 +88,7 @@ contract PodRegistry is IPodRegistry, Ownable { function _addValidatorOnInit(address validator, uint8 index) internal { validatorIndex[validator] = index + 1; activeValidatorBitmap |= (1 << index); + validatorAddress[index + 1] = validator; } function addValidator(address validator) external onlyOwner { @@ -99,6 +103,7 @@ contract PodRegistry is IPodRegistry, Ownable { } uint8 index = ++validatorCount; validatorIndex[validator] = index; + validatorAddress[index] = validator; if (!_isValidatorActive(index)) { _activateValidator(index); } @@ -206,7 +211,7 @@ contract PodRegistry is IPodRegistry, Ownable { } } - function findSnapshotIndex(uint256 blockNumber) external view returns (uint256 index) { + function findSnapshotIndex(uint256 blockNumber) public view returns (uint256 index) { if (history.length == 0) { revert NoHistoricalSnapshots(); } @@ -227,14 +232,34 @@ contract PodRegistry is IPodRegistry, Ownable { } function getActiveValidatorCount() public view returns (uint8 count) { - count = 0; - uint256 bitmap = activeValidatorBitmap; + return _popCount(activeValidatorBitmap); + } + + function _popCount(uint256 bitmap) internal pure returns (uint8 count) { while (bitmap != 0) { count++; bitmap &= bitmap - 1; } } + function getValidatorsAt(uint256 blockNumber) public view returns (address[] memory) { + uint256 index = findSnapshotIndex(blockNumber); + uint256 bitmap = history[index].bitmap; + uint8 count = _popCount(bitmap); + address[] memory validators = new address[](count); + uint8 j = 0; + for (uint8 i = 0; i < validatorCount; i++) { + if (_isBitSet(bitmap, i)) { + validators[j++] = validatorAddress[i + 1]; + } + } + return validators; + } + + function getActiveValidators() external view returns (address[] memory) { + return getValidatorsAt(block.number); + } + function getFaultTolerance() external view returns (uint8) { return getActiveValidatorCount() / 3; } @@ -259,6 +284,10 @@ contract PodRegistry is IPodRegistry, Ownable { } function _isValidatorActive(uint8 index) internal view returns (bool) { - return (activeValidatorBitmap & (1 << (index - 1))) != 0; + return _isBitSet(activeValidatorBitmap, index - 1); + } + + function _isBitSet(uint256 bitmap, uint8 i) internal pure returns (bool) { + return (bitmap & (1 << i)) != 0; } } diff --git a/solidity-sdk/test/PodRegistry.t.sol b/solidity-sdk/test/PodRegistry.t.sol index 79ad0134..0f5b4408 100644 --- a/solidity-sdk/test/PodRegistry.t.sol +++ b/solidity-sdk/test/PodRegistry.t.sol @@ -3,6 +3,7 @@ pragma solidity ^0.8.20; import "forge-std/Test.sol"; import "../src/verifier/PodRegistry.sol"; +import "forge-std/console.sol"; contract PodRegistryTest is Test { PodRegistry public registry; @@ -524,4 +525,25 @@ contract PodRegistryTest is Test { assertEq(registry.getFaultTolerance(), 1); // 4/3 = 1 } + + function test_GetActiveValidators() public view { + address[] memory validators = registry.getActiveValidators(); + assertEq(validators.length, 2); + assertEq(validators[0], validator1); + assertEq(validators[1], validator2); + } + + function test_GetValidatorsAt() public { + vm.startPrank(owner); + vm.roll(100); + registry.addValidator(validator3); + registry.banValidator(validator1); + vm.roll(block.number + 100); + registry.addValidator(validator4); + vm.stopPrank(); + address[] memory validators = registry.getValidatorsAt(100); + assertEq(validators.length, 2); + assertEq(validators[0], validator2); + assertEq(validators[1], validator3); + } } From 58ff3a707e24f2e0107aeac9d1c144608cf80eed Mon Sep 17 00:00:00 2001 From: Jakov Mitrovski Date: Thu, 14 Aug 2025 13:30:11 +0200 Subject: [PATCH 16/64] refactor(registry): remove fault tolerance, renaming, change blocknum to index in params --- solidity-sdk/src/verifier/PodRegistry.sol | 25 ++++++++++++----------- solidity-sdk/test/PodRegistry.t.sol | 24 ++++++---------------- 2 files changed, 19 insertions(+), 30 deletions(-) diff --git a/solidity-sdk/src/verifier/PodRegistry.sol b/solidity-sdk/src/verifier/PodRegistry.sol index d2540296..00b05966 100644 --- a/solidity-sdk/src/verifier/PodRegistry.sol +++ b/solidity-sdk/src/verifier/PodRegistry.sol @@ -33,9 +33,10 @@ interface IPodRegistry { event SnapshotCreated(uint256 indexed activeAsOfBlockNumber, uint256 bitmap); function validatorIndex(address validator) external view returns (uint8 index); + function validatorAddress(uint8 index) external view returns (address validator); function bannedValidators(address validator) external view returns (bool isBanned); - function validatorCount() external view returns (uint8 index); + function validatorCount() external view returns (uint8 count); function activeValidatorBitmap() external view returns (uint256 bitmap); function addValidator(address validator) external; @@ -53,10 +54,10 @@ interface IPodRegistry { function findSnapshotIndex(uint256 blockNumber) external view returns (uint256 index); function getActiveValidatorCount() external view returns (uint8 count); + function getValidatorCountAt(uint256 index) external view returns (uint8 count); function getActiveValidators() external view returns (address[] memory); - function getValidatorsAt(uint256 blockNumber) external view returns (address[] memory); - function getFaultTolerance() external view returns (uint8); - function getSnapshot(uint256 index) external view returns (uint256 activeAsOfBlockNumber, uint256 bitmap); + function getValidatorsAt(uint256 index) external view returns (address[] memory); + function getSnapshotAt(uint256 index) external view returns (uint256 activeAsOfBlockNumber, uint256 bitmap); function getHistoryLength() external view returns (uint256); } @@ -235,6 +236,11 @@ contract PodRegistry is IPodRegistry, Ownable { return _popCount(activeValidatorBitmap); } + function getValidatorCountAt(uint256 index) public view returns (uint8 count) { + uint256 bitmap = history[index].bitmap; + return _popCount(bitmap); + } + function _popCount(uint256 bitmap) internal pure returns (uint8 count) { while (bitmap != 0) { count++; @@ -242,8 +248,7 @@ contract PodRegistry is IPodRegistry, Ownable { } } - function getValidatorsAt(uint256 blockNumber) public view returns (address[] memory) { - uint256 index = findSnapshotIndex(blockNumber); + function getValidatorsAt(uint256 index) public view returns (address[] memory) { uint256 bitmap = history[index].bitmap; uint8 count = _popCount(bitmap); address[] memory validators = new address[](count); @@ -257,14 +262,10 @@ contract PodRegistry is IPodRegistry, Ownable { } function getActiveValidators() external view returns (address[] memory) { - return getValidatorsAt(block.number); - } - - function getFaultTolerance() external view returns (uint8) { - return getActiveValidatorCount() / 3; + return getValidatorsAt(history.length - 1); } - function getSnapshot(uint256 index) external view returns (uint256 activeAsOfBlockNumber, uint256 bitmap) { + function getSnapshotAt(uint256 index) external view returns (uint256 activeAsOfBlockNumber, uint256 bitmap) { Snapshot memory s = history[index]; return (s.activeAsOfBlockNumber, s.bitmap); } diff --git a/solidity-sdk/test/PodRegistry.t.sol b/solidity-sdk/test/PodRegistry.t.sol index 0f5b4408..76a093ae 100644 --- a/solidity-sdk/test/PodRegistry.t.sol +++ b/solidity-sdk/test/PodRegistry.t.sol @@ -344,7 +344,7 @@ contract PodRegistryTest is Test { registry.addValidator(validator3); uint256 snapshotIndex = registry.getHistoryLength() - 1; uint256 snapshotBlock; - (snapshotBlock,) = registry.getSnapshot(snapshotIndex); + (snapshotBlock,) = registry.getSnapshotAt(snapshotIndex); address[] memory subset = new address[](3); subset[0] = validator1; @@ -455,11 +455,11 @@ contract PodRegistryTest is Test { assertEq(indexAfterLast, 2); // Validate that returned snapshots are correct - (uint256 blockNum1, uint256 bitmap1) = registry.getSnapshot(indexAtAdd); + (uint256 blockNum1, uint256 bitmap1) = registry.getSnapshotAt(indexAtAdd); assertEq(blockNum1, blockAtAdd); assertTrue(bitmap1 & (1 << (3 - 1)) != 0); // validator3 should be active here - (uint256 blockNum2, uint256 bitmap2) = registry.getSnapshot(indexAfterLast); + (uint256 blockNum2, uint256 bitmap2) = registry.getSnapshotAt(indexAfterLast); assertEq(blockNum2, blockAtBan); assertTrue(bitmap2 & (1 << (3 - 1)) != 0); // validator3 still active assertFalse(bitmap2 & (1 << (1 - 1)) != 0); // validator1 banned @@ -501,7 +501,7 @@ contract PodRegistryTest is Test { vm.prank(owner); registry.addValidator(validator3); uint256 index = registry.getHistoryLength() - 1; - (uint256 blockNumber, uint256 bitmap) = registry.getSnapshot(index); + (uint256 blockNumber, uint256 bitmap) = registry.getSnapshotAt(index); assertGt(blockNumber, 0); assertTrue(bitmap & (1 << (3 - 1)) != 0); } @@ -513,19 +513,6 @@ contract PodRegistryTest is Test { assertEq(registry.getHistoryLength(), before + 1); } - function test_GetFaultTolerance() public view { - assertEq(registry.getFaultTolerance(), 0); // 2/3 = 0 - } - - function test_GetFaultTolerance_WithMoreValidators() public { - vm.startPrank(owner); - registry.addValidator(validator3); - registry.addValidator(validator4); - vm.stopPrank(); - - assertEq(registry.getFaultTolerance(), 1); // 4/3 = 1 - } - function test_GetActiveValidators() public view { address[] memory validators = registry.getActiveValidators(); assertEq(validators.length, 2); @@ -541,7 +528,8 @@ contract PodRegistryTest is Test { vm.roll(block.number + 100); registry.addValidator(validator4); vm.stopPrank(); - address[] memory validators = registry.getValidatorsAt(100); + uint256 index = registry.findSnapshotIndex(100); + address[] memory validators = registry.getValidatorsAt(index); assertEq(validators.length, 2); assertEq(validators[0], validator2); assertEq(validators[1], validator3); From d063e9e0a703f6b7b61a9cbdb8de4e057fcd2217 Mon Sep 17 00:00:00 2001 From: Jakov Mitrovski Date: Thu, 14 Aug 2025 14:02:56 +0200 Subject: [PATCH 17/64] feat(registry): replace block numbers with timestamps --- solidity-sdk/src/verifier/PodRegistry.sol | 44 ++++++--- solidity-sdk/test/PodRegistry.t.sol | 106 +++++++++++----------- 2 files changed, 82 insertions(+), 68 deletions(-) diff --git a/solidity-sdk/src/verifier/PodRegistry.sol b/solidity-sdk/src/verifier/PodRegistry.sol index 00b05966..730cd889 100644 --- a/solidity-sdk/src/verifier/PodRegistry.sol +++ b/solidity-sdk/src/verifier/PodRegistry.sol @@ -5,7 +5,7 @@ import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; interface IPodRegistry { struct Snapshot { - uint256 activeAsOfBlockNumber; + uint256 activeAsOfTimestamp; uint256 bitmap; } @@ -30,7 +30,7 @@ interface IPodRegistry { event ValidatorUnbanned(address indexed validator); event ValidatorDeactivated(address indexed validator); event ValidatorReactivated(address indexed validator); - event SnapshotCreated(uint256 indexed activeAsOfBlockNumber, uint256 bitmap); + event SnapshotCreated(uint256 indexed activeAsOfTimestamp, uint256 bitmap); function validatorIndex(address validator) external view returns (uint8 index); function validatorAddress(uint8 index) external view returns (address validator); @@ -46,18 +46,19 @@ interface IPodRegistry { function reactivate() external; function computeWeight(address[] memory subset) external view returns (uint256 weight); - function computeWeight(address[] memory subset, uint256 blockNumber, uint256 snapshotIndex) + function computeWeight(address[] memory subset, uint256 timestamp, uint256 snapshotIndex) external view returns (uint256 weight); - function findSnapshotIndex(uint256 blockNumber) external view returns (uint256 index); + function findSnapshotIndex(uint256 timestamp) external view returns (uint256 index); function getActiveValidatorCount() external view returns (uint8 count); function getValidatorCountAt(uint256 index) external view returns (uint8 count); function getActiveValidators() external view returns (address[] memory); + function getActiveValidators(uint256 timestamp) external view returns (address[] memory); function getValidatorsAt(uint256 index) external view returns (address[] memory); - function getSnapshotAt(uint256 index) external view returns (uint256 activeAsOfBlockNumber, uint256 bitmap); + function getSnapshotAt(uint256 index) external view returns (uint256 activeAsOfTimestamp, uint256 bitmap); function getHistoryLength() external view returns (uint256); } @@ -167,8 +168,8 @@ contract PodRegistry is IPodRegistry, Ownable { } function _createSnapshot() internal { - history.push(Snapshot({activeAsOfBlockNumber: block.number, bitmap: activeValidatorBitmap})); - emit SnapshotCreated(block.number, activeValidatorBitmap); + history.push(Snapshot({activeAsOfTimestamp: block.timestamp, bitmap: activeValidatorBitmap})); + emit SnapshotCreated(block.timestamp, activeValidatorBitmap); } function computeWeight(address[] memory subset) public view returns (uint256 weight) { @@ -176,10 +177,10 @@ contract PodRegistry is IPodRegistry, Ownable { return 0; } - return computeWeight(subset, block.number, history.length - 1); + return computeWeight(subset, block.timestamp, history.length - 1); } - function computeWeight(address[] memory subset, uint256 blockNumber, uint256 snapshotIndex) + function computeWeight(address[] memory subset, uint256 timestamp, uint256 snapshotIndex) public view returns (uint256 weight) @@ -188,10 +189,10 @@ contract PodRegistry is IPodRegistry, Ownable { revert InvalidSnapshotIndex(); } Snapshot memory snapshot = history[snapshotIndex]; - if (snapshot.activeAsOfBlockNumber > blockNumber) { + if (snapshot.activeAsOfTimestamp > timestamp) { revert SnapshotTooNew(); } - if (snapshotIndex != history.length - 1 && history[snapshotIndex + 1].activeAsOfBlockNumber <= blockNumber) { + if (snapshotIndex != history.length - 1 && history[snapshotIndex + 1].activeAsOfTimestamp <= timestamp) { revert SnapshotTooOld(); } @@ -212,7 +213,7 @@ contract PodRegistry is IPodRegistry, Ownable { } } - function findSnapshotIndex(uint256 blockNumber) public view returns (uint256 index) { + function findSnapshotIndex(uint256 timestamp) public view returns (uint256 index) { if (history.length == 0) { revert NoHistoricalSnapshots(); } @@ -222,7 +223,7 @@ contract PodRegistry is IPodRegistry, Ownable { while (low < high) { uint256 mid = (low + high + 1) / 2; - if (history[mid].activeAsOfBlockNumber <= blockNumber) { + if (history[mid].activeAsOfTimestamp <= timestamp) { low = mid; } else { high = mid - 1; @@ -262,12 +263,25 @@ contract PodRegistry is IPodRegistry, Ownable { } function getActiveValidators() external view returns (address[] memory) { + if (history.length == 0) { + return new address[](0); + } + return getValidatorsAt(history.length - 1); } - function getSnapshotAt(uint256 index) external view returns (uint256 activeAsOfBlockNumber, uint256 bitmap) { + function getActiveValidators(uint256 timestamp) external view returns (address[] memory) { + if (history.length == 0) { + return new address[](0); + } + + uint256 snapshotIndex = findSnapshotIndex(timestamp); + return getValidatorsAt(snapshotIndex); + } + + function getSnapshotAt(uint256 index) external view returns (uint256 activeAsOfTimestamp, uint256 bitmap) { Snapshot memory s = history[index]; - return (s.activeAsOfBlockNumber, s.bitmap); + return (s.activeAsOfTimestamp, s.bitmap); } function getHistoryLength() external view returns (uint256) { diff --git a/solidity-sdk/test/PodRegistry.t.sol b/solidity-sdk/test/PodRegistry.t.sol index 76a093ae..204f8ccd 100644 --- a/solidity-sdk/test/PodRegistry.t.sol +++ b/solidity-sdk/test/PodRegistry.t.sol @@ -254,25 +254,25 @@ contract PodRegistryTest is Test { vm.prank(owner); vm.expectEmit(true, false, false, true); - emit IPodRegistry.SnapshotCreated(block.number, (1 << (1 - 1)) | (1 << (2 - 1)) | (1 << (3 - 1))); + emit IPodRegistry.SnapshotCreated(block.timestamp, (1 << (1 - 1)) | (1 << (2 - 1)) | (1 << (3 - 1))); registry.addValidator(validator3); assertEq(registry.getHistoryLength(), initialHistory + 1); vm.prank(owner); vm.expectEmit(true, false, false, true); - emit IPodRegistry.SnapshotCreated(block.number, (1 << (1 - 1)) | (1 << (2 - 1))); + emit IPodRegistry.SnapshotCreated(block.timestamp, (1 << (1 - 1)) | (1 << (2 - 1))); registry.banValidator(validator3); assertEq(registry.getHistoryLength(), initialHistory + 2); vm.prank(validator1); vm.expectEmit(true, false, false, true); - emit IPodRegistry.SnapshotCreated(block.number, (1 << (2 - 1))); + emit IPodRegistry.SnapshotCreated(block.timestamp, (1 << (2 - 1))); registry.deactivate(); assertEq(registry.getHistoryLength(), initialHistory + 3); vm.prank(validator1); vm.expectEmit(true, false, false, true); - emit IPodRegistry.SnapshotCreated(block.number, (1 << (1 - 1)) | (1 << (2 - 1))); + emit IPodRegistry.SnapshotCreated(block.timestamp, (1 << (1 - 1)) | (1 << (2 - 1))); registry.reactivate(); assertEq(registry.getHistoryLength(), initialHistory + 4); } @@ -323,19 +323,19 @@ contract PodRegistryTest is Test { vm.prank(owner); registry.addValidator(validator3); // snapshot - vm.roll(block.number + 5); + vm.warp(block.timestamp + 5); vm.prank(owner); registry.banValidator(validator1); // another snapshot - uint256 oldBlock = block.number - 3; - uint256 snapshotIndex = registry.findSnapshotIndex(oldBlock); + uint256 oldTimestamp = block.timestamp - 3; + uint256 snapshotIndex = registry.findSnapshotIndex(oldTimestamp); address[] memory subset = new address[](3); subset[0] = validator1; subset[1] = validator2; subset[2] = validator3; - uint256 weight = registry.computeWeight(subset, oldBlock, snapshotIndex); + uint256 weight = registry.computeWeight(subset, oldTimestamp, snapshotIndex); assertEq(weight, 3); } @@ -343,15 +343,15 @@ contract PodRegistryTest is Test { vm.prank(owner); registry.addValidator(validator3); uint256 snapshotIndex = registry.getHistoryLength() - 1; - uint256 snapshotBlock; - (snapshotBlock,) = registry.getSnapshotAt(snapshotIndex); + uint256 snapshotTimestamp; + (snapshotTimestamp,) = registry.getSnapshotAt(snapshotIndex); address[] memory subset = new address[](3); subset[0] = validator1; subset[1] = validator2; subset[2] = validator3; - uint256 weight = registry.computeWeight(subset, snapshotBlock, snapshotIndex); + uint256 weight = registry.computeWeight(subset, snapshotTimestamp, snapshotIndex); assertEq(weight, 3); } @@ -360,36 +360,36 @@ contract PodRegistryTest is Test { registry.addValidator(validator3); // snapshot at index 1 vm.prank(owner); - vm.roll(block.number + 5); + vm.warp(block.timestamp + 5); registry.banValidator(validator1); // snapshot at index 2 - // Use snapshot 0 for current block (too old) - uint256 latestBlock = block.number; + // Use snapshot 0 for current timestamp (too old) + uint256 latestTimestamp = block.timestamp; address[] memory subset = new address[](2); subset[0] = validator1; subset[1] = validator2; vm.expectRevert(abi.encodeWithSignature("SnapshotTooOld()")); - registry.computeWeight(subset, latestBlock, 0); + registry.computeWeight(subset, latestTimestamp, 0); } function test_ComputeWeight_RevertIfSnapshotTooNew() public { vm.prank(owner); registry.addValidator(validator3); // snapshot at index 1 - uint256 blockAtAdd = block.number; + uint256 timestampAtAdd = block.timestamp; - vm.roll(block.number + 5); + vm.warp(block.timestamp + 5); vm.prank(owner); registry.banValidator(validator1); // snapshot at index 2 - // Use snapshot 2 for blockAtAdd (too new) + // Use snapshot 2 for timestampAtAdd (too new) address[] memory subset = new address[](2); subset[0] = validator1; subset[1] = validator3; vm.expectRevert(abi.encodeWithSignature("SnapshotTooNew()")); - registry.computeWeight(subset, blockAtAdd, 2); + registry.computeWeight(subset, timestampAtAdd, 2); } function test_ComputeWeight_RevertIfSnapshotIndexOutOfBounds() public { @@ -397,7 +397,7 @@ contract PodRegistryTest is Test { subset[0] = validator1; vm.expectRevert(abi.encodeWithSignature("InvalidSnapshotIndex()")); - registry.computeWeight(subset, block.number, 999); + registry.computeWeight(subset, block.timestamp, 999); } function test_ComputeWeight_NoHistoryReturnsZero() public { @@ -414,22 +414,22 @@ contract PodRegistryTest is Test { } function test_FindSnapshotIndex() public { - vm.roll(101); + vm.warp(101); // Initial snapshot from constructor - uint256 initialIndex = registry.findSnapshotIndex(block.number); + uint256 initialIndex = registry.findSnapshotIndex(block.timestamp); assertEq(initialIndex, 0); - // Roll blocks and add a new validator (creates snapshot) - vm.roll(block.number + 5); + // Warp time and add a new validator (creates snapshot) + vm.warp(block.timestamp + 5); vm.prank(owner); registry.addValidator(validator3); - uint256 blockAtAdd = block.number; + uint256 timestampAtAdd = block.timestamp; - // Roll blocks and ban validator1 (creates another snapshot) - vm.roll(block.number + 10); + // Warp time and ban validator1 (creates another snapshot) + vm.warp(block.timestamp + 10); vm.prank(owner); registry.banValidator(validator1); - uint256 blockAtBan = block.number; + uint256 timestampAtBan = block.timestamp; // History should now have 3 snapshots: // index 0 -> constructor snapshot @@ -437,37 +437,37 @@ contract PodRegistryTest is Test { // index 2 -> after banning validator1 assertEq(registry.getHistoryLength(), 3); - // Case 1: Block way before first snapshot → index 0 - uint256 indexBeforeFirst = registry.findSnapshotIndex(blockAtAdd - 100); + // Case 1: Timestamp way before first snapshot → index 0 + uint256 indexBeforeFirst = registry.findSnapshotIndex(timestampAtAdd - 100); assertEq(indexBeforeFirst, 0); - // Case 2: Block exactly at first add snapshot → index 1 - uint256 indexAtAdd = registry.findSnapshotIndex(blockAtAdd); + // Case 2: Timestamp exactly at first add snapshot → index 1 + uint256 indexAtAdd = registry.findSnapshotIndex(timestampAtAdd); assertEq(indexAtAdd, 1); - // Case 3: Block between add and ban → index 1 - uint256 midBlock = blockAtAdd + 5; - uint256 indexMid = registry.findSnapshotIndex(midBlock); + // Case 3: Timestamp between add and ban → index 1 + uint256 midTimestamp = timestampAtAdd + 5; + uint256 indexMid = registry.findSnapshotIndex(midTimestamp); assertEq(indexMid, 1); - // Case 4: Block after last snapshot → index 2 - uint256 indexAfterLast = registry.findSnapshotIndex(block.number + 50); + // Case 4: Timestamp after last snapshot → index 2 + uint256 indexAfterLast = registry.findSnapshotIndex(block.timestamp + 50); assertEq(indexAfterLast, 2); // Validate that returned snapshots are correct - (uint256 blockNum1, uint256 bitmap1) = registry.getSnapshotAt(indexAtAdd); - assertEq(blockNum1, blockAtAdd); + (uint256 timestamp1, uint256 bitmap1) = registry.getSnapshotAt(indexAtAdd); + assertEq(timestamp1, timestampAtAdd); assertTrue(bitmap1 & (1 << (3 - 1)) != 0); // validator3 should be active here - (uint256 blockNum2, uint256 bitmap2) = registry.getSnapshotAt(indexAfterLast); - assertEq(blockNum2, blockAtBan); + (uint256 timestamp2, uint256 bitmap2) = registry.getSnapshotAt(indexAfterLast); + assertEq(timestamp2, timestampAtBan); assertTrue(bitmap2 & (1 << (3 - 1)) != 0); // validator3 still active assertFalse(bitmap2 & (1 << (1 - 1)) != 0); // validator1 banned } function test_FindSnapshotIndex_BeforeFirstSnapshot() public { - vm.roll(101); - uint256 index = registry.findSnapshotIndex(block.number - 100); // way before + vm.warp(101); + uint256 index = registry.findSnapshotIndex(block.timestamp - 100); // way before assertEq(index, 0); } @@ -475,25 +475,25 @@ contract PodRegistryTest is Test { vm.prank(owner); registry.addValidator(validator3); - vm.roll(block.number + 10); + vm.warp(block.timestamp + 10); vm.prank(owner); registry.banValidator(validator1); - uint256 index = registry.findSnapshotIndex(block.number + 50); // after last + uint256 index = registry.findSnapshotIndex(block.timestamp + 50); // after last assertEq(index, registry.getHistoryLength() - 1); } function test_FindSnapshotIndex_SingleSnapshot() public view { - uint256 index = registry.findSnapshotIndex(block.number); + uint256 index = registry.findSnapshotIndex(block.timestamp); assertEq(index, 0); } function test_FindSnapshotIndex_ExactMatchLastSnapshot() public { - vm.roll(block.number + 10); + vm.warp(block.timestamp + 10); vm.prank(owner); registry.addValidator(validator3); - uint256 latestSnapshotBlock = block.number; - uint256 index = registry.findSnapshotIndex(latestSnapshotBlock); + uint256 latestSnapshotTimestamp = block.timestamp; + uint256 index = registry.findSnapshotIndex(latestSnapshotTimestamp); assertEq(index, registry.getHistoryLength() - 1); } @@ -501,8 +501,8 @@ contract PodRegistryTest is Test { vm.prank(owner); registry.addValidator(validator3); uint256 index = registry.getHistoryLength() - 1; - (uint256 blockNumber, uint256 bitmap) = registry.getSnapshotAt(index); - assertGt(blockNumber, 0); + (uint256 timestamp, uint256 bitmap) = registry.getSnapshotAt(index); + assertGt(timestamp, 0); assertTrue(bitmap & (1 << (3 - 1)) != 0); } @@ -522,10 +522,10 @@ contract PodRegistryTest is Test { function test_GetValidatorsAt() public { vm.startPrank(owner); - vm.roll(100); + vm.warp(100); registry.addValidator(validator3); registry.banValidator(validator1); - vm.roll(block.number + 100); + vm.warp(block.timestamp + 100); registry.addValidator(validator4); vm.stopPrank(); uint256 index = registry.findSnapshotIndex(100); From d0ac49c04fb8a7c0349ec595c1e99d3867db4a94 Mon Sep 17 00:00:00 2001 From: Jakov Mitrovski Date: Fri, 15 Aug 2025 12:59:01 +0200 Subject: [PATCH 18/64] feat(podecdsa): implement old certificate verification --- solidity-sdk/src/verifier/PodECDSA.sol | 49 ++++++++++- solidity-sdk/test/PodECDSA.t.sol | 113 ++++++++++++++++++++++--- 2 files changed, 147 insertions(+), 15 deletions(-) diff --git a/solidity-sdk/src/verifier/PodECDSA.sol b/solidity-sdk/src/verifier/PodECDSA.sol index 061da148..5d0b38e0 100644 --- a/solidity-sdk/src/verifier/PodECDSA.sol +++ b/solidity-sdk/src/verifier/PodECDSA.sol @@ -21,6 +21,8 @@ library PodECDSA { struct CertifiedReceipt { bytes32 receiptRoot; bytes aggregateSignature; + uint256[] attestationTimestamps; + uint256 medianTimestamp; } struct Certificate { @@ -50,9 +52,20 @@ library PodECDSA { view returns (bool) { + uint256 snapshotIndex = podConfig.registry.findSnapshotIndex(certifiedReceipt.medianTimestamp); + return verifyCertifiedReceipt(podConfig, certifiedReceipt, snapshotIndex); + } + + function verifyCertifiedReceipt( + PodConfig calldata podConfig, + CertifiedReceipt calldata certifiedReceipt, + uint256 snapshotIndex + ) public view returns (bool) { address[] memory validators = ECDSA.recoverSigners(certifiedReceipt.receiptRoot, certifiedReceipt.aggregateSignature); - return podConfig.registry.computeWeight(validators) >= podConfig.quorum; + + return podConfig.registry.computeWeight(validators, certifiedReceipt.medianTimestamp, snapshotIndex) + >= podConfig.quorum; } function verifyCertificate(PodConfig calldata podConfig, Certificate calldata certificate) @@ -60,7 +73,16 @@ library PodECDSA { view returns (bool) { - return verifyCertifiedReceipt(podConfig, certificate.certifiedReceipt) + uint256 snapshotIndex = podConfig.registry.findSnapshotIndex(certificate.certifiedReceipt.medianTimestamp); + return verifyCertificate(podConfig, certificate, snapshotIndex); + } + + function verifyCertificate(PodConfig calldata podConfig, Certificate calldata certificate, uint256 snapshotIndex) + public + view + returns (bool) + { + return verifyCertifiedReceipt(podConfig, certificate.certifiedReceipt, snapshotIndex) && MerkleTree.verify(certificate.certifiedReceipt.receiptRoot, certificate.leaf, certificate.proof); } @@ -69,7 +91,16 @@ library PodECDSA { view returns (bool) { - return verifyCertifiedReceipt(podConfig, certificate.certifiedReceipt) + uint256 snapshotIndex = podConfig.registry.findSnapshotIndex(certificate.certifiedReceipt.medianTimestamp); + return verifyMultiCertificate(podConfig, certificate, snapshotIndex); + } + + function verifyMultiCertificate( + PodConfig calldata podConfig, + MultiCertificate calldata certificate, + uint256 snapshotIndex + ) public view returns (bool) { + return verifyCertifiedReceipt(podConfig, certificate.certifiedReceipt, snapshotIndex) && MerkleTree.verifyMulti(certificate.certifiedReceipt.receiptRoot, certificate.leaves, certificate.proof); } @@ -77,6 +108,16 @@ library PodECDSA { public view returns (bool) + { + uint256 snapshotIndex = + podConfig.registry.findSnapshotIndex(certifiedLog.certificate.certifiedReceipt.medianTimestamp); + return verifyCertifiedLog(podConfig, certifiedLog, snapshotIndex); + } + + function verifyCertifiedLog(PodConfig calldata podConfig, CertifiedLog calldata certifiedLog, uint256 snapshotIndex) + public + view + returns (bool) { bytes32 logHash = hashLog(certifiedLog.log); @@ -86,6 +127,6 @@ library PodECDSA { require(leaf == certifiedLog.certificate.leaf, "Invalid certificate"); - return verifyCertificate(podConfig, certifiedLog.certificate); + return verifyCertificate(podConfig, certifiedLog.certificate, snapshotIndex); } } diff --git a/solidity-sdk/test/PodECDSA.t.sol b/solidity-sdk/test/PodECDSA.t.sol index 83b39eb5..b684463f 100644 --- a/solidity-sdk/test/PodECDSA.t.sol +++ b/solidity-sdk/test/PodECDSA.t.sol @@ -15,22 +15,25 @@ contract PodECDSATest is Test { uint256[] public validatorPrivateKeys = new uint256[](128); function setUp() public { - vm.prank(OWNER); - podRegistry = new PodRegistry(new address[](0)); + address[] memory initialValidators = new address[](validatorPrivateKeys.length); for (uint256 i = 0; i < validatorPrivateKeys.length; i++) { validatorPrivateKeys[i] = uint256(i + 1); - vm.prank(OWNER); - podRegistry.addValidator(vm.addr(validatorPrivateKeys[i])); + initialValidators[i] = vm.addr(validatorPrivateKeys[i]); } + + vm.prank(OWNER); + podRegistry = new PodRegistry(initialValidators); } function test_verify() public view { bytes32 receiptRoot = 0x5511dff743741cf4814cb39fa20ec04f304218d45c8c2bd6639a9437af3bf12a; bytes[] memory signatures = new bytes[](validatorPrivateKeys.length); + uint256[] memory attestationTimestamps = new uint256[](validatorPrivateKeys.length); for (uint256 i = 0; i < validatorPrivateKeys.length; i++) { (uint8 v, bytes32 r, bytes32 s) = vm.sign(validatorPrivateKeys[i], receiptRoot); signatures[i] = ECDSA._serialize_signature(v, r, s); + attestationTimestamps[i] = i + 1; } bytes memory aggregateSignature = ECDSA.aggregate_signatures(signatures); @@ -47,20 +50,27 @@ contract PodECDSATest is Test { PodECDSA.Certificate memory certificate = PodECDSA.Certificate({ leaf: leaf, - certifiedReceipt: PodECDSA.CertifiedReceipt({receiptRoot: receiptRoot, aggregateSignature: aggregateSignature}), + certifiedReceipt: PodECDSA.CertifiedReceipt({ + receiptRoot: receiptRoot, + aggregateSignature: aggregateSignature, + attestationTimestamps: attestationTimestamps, + medianTimestamp: attestationTimestamps[attestationTimestamps.length / 2] + }), proof: MerkleTree.Proof({path: path}) }); - PodECDSA.PodConfig memory podConfig = PodECDSA.PodConfig({quorum: 3, registry: podRegistry}); + PodECDSA.PodConfig memory podConfig = PodECDSA.PodConfig({quorum: 86, registry: podRegistry}); assertTrue(PodECDSA.verifyCertificate(podConfig, certificate)); } function test_verifyMulti() public view { bytes32 receiptRoot = 0xa3a78fbdee5849d00cf13b73978d417d1832737562353e7d7448d149c563d411; bytes[] memory signatures = new bytes[](validatorPrivateKeys.length); + uint256[] memory attestationTimestamps = new uint256[](validatorPrivateKeys.length); for (uint256 i = 0; i < validatorPrivateKeys.length; i++) { (uint8 v, bytes32 r, bytes32 s) = vm.sign(validatorPrivateKeys[i], receiptRoot); signatures[i] = ECDSA._serialize_signature(v, r, s); + attestationTimestamps[i] = i + 1; } bytes memory aggregateSignature = ECDSA.aggregate_signatures(signatures); @@ -98,26 +108,37 @@ contract PodECDSATest is Test { PodECDSA.MultiCertificate memory certificate = PodECDSA.MultiCertificate({ leaves: leaves, - certifiedReceipt: PodECDSA.CertifiedReceipt({receiptRoot: receiptRoot, aggregateSignature: aggregateSignature}), + certifiedReceipt: PodECDSA.CertifiedReceipt({ + receiptRoot: receiptRoot, + aggregateSignature: aggregateSignature, + attestationTimestamps: attestationTimestamps, + medianTimestamp: attestationTimestamps[attestationTimestamps.length / 2] + }), proof: MerkleTree.MultiProof({path: path, flags: flags}) }); - PodECDSA.PodConfig memory podConfig = PodECDSA.PodConfig({quorum: 3, registry: podRegistry}); + PodECDSA.PodConfig memory podConfig = PodECDSA.PodConfig({quorum: 86, registry: podRegistry}); assertTrue(PodECDSA.verifyMultiCertificate(podConfig, certificate)); } function test_verifyLog() public view { bytes32 receiptRoot = 0x32bf7ef0c0291bc3b73afd18a62cca74ff8ee51c801b8b619c360e1c1dac9c84; bytes[] memory signatures = new bytes[](validatorPrivateKeys.length); + uint256[] memory attestationTimestamps = new uint256[](validatorPrivateKeys.length); for (uint256 i = 0; i < validatorPrivateKeys.length; i++) { (uint8 v, bytes32 r, bytes32 s) = vm.sign(validatorPrivateKeys[i], receiptRoot); signatures[i] = ECDSA._serialize_signature(v, r, s); + attestationTimestamps[i] = i + 1; } bytes memory aggregateSignature = ECDSA.aggregate_signatures(signatures); - PodECDSA.CertifiedReceipt memory receipt = - PodECDSA.CertifiedReceipt({receiptRoot: receiptRoot, aggregateSignature: aggregateSignature}); + PodECDSA.CertifiedReceipt memory receipt = PodECDSA.CertifiedReceipt({ + receiptRoot: receiptRoot, + aggregateSignature: aggregateSignature, + attestationTimestamps: attestationTimestamps, + medianTimestamp: attestationTimestamps[attestationTimestamps.length / 2] + }); bytes32[] memory topics = new bytes32[](4); topics[0] = 0x71a5674c44b823bc0df08201dfeb2e8bdf698cd684fd2bbaa79adcf2c99fc186; @@ -148,7 +169,7 @@ contract PodECDSATest is Test { certificate: PodECDSA.Certificate({leaf: leaf, certifiedReceipt: receipt, proof: proof}) }); - PodECDSA.PodConfig memory podConfig = PodECDSA.PodConfig({quorum: 3, registry: podRegistry}); + PodECDSA.PodConfig memory podConfig = PodECDSA.PodConfig({quorum: 86, registry: podRegistry}); assertTrue(PodECDSA.verifyCertifiedLog(podConfig, certifiedLog)); } @@ -162,4 +183,74 @@ contract PodECDSATest is Test { assertEq(PodECDSA.hashLog(log), 0x01863af86eec26cec7e83925382f100ecf80cda979aed17146631c6fba129816); } + + function test_verifyRecentWithSnapshotIndex() public { + bytes32 receiptRoot = 0x32bf7ef0c0291bc3b73afd18a62cca74ff8ee51c801b8b619c360e1c1dac9c84; + bytes[] memory signatures = new bytes[](validatorPrivateKeys.length); + uint256[] memory attestationTimestamps = new uint256[](validatorPrivateKeys.length); + for (uint256 i = 0; i < validatorPrivateKeys.length; i++) { + (uint8 v, bytes32 r, bytes32 s) = vm.sign(validatorPrivateKeys[i], receiptRoot); + signatures[i] = ECDSA._serialize_signature(v, r, s); + attestationTimestamps[i] = i + 1; + } + + uint256 medianTimestamp = attestationTimestamps[attestationTimestamps.length / 2]; + + vm.warp(medianTimestamp - 1); + + vm.prank(OWNER); + podRegistry.addValidator(vm.addr(0x123abc)); + + bytes memory aggregateSignature = ECDSA.aggregate_signatures(signatures); + + PodECDSA.CertifiedReceipt memory receipt = PodECDSA.CertifiedReceipt({ + receiptRoot: receiptRoot, + aggregateSignature: aggregateSignature, + attestationTimestamps: attestationTimestamps, + medianTimestamp: medianTimestamp + }); + + PodECDSA.PodConfig memory podConfig = PodECDSA.PodConfig({quorum: 86, registry: podRegistry}); + assertTrue(PodECDSA.verifyCertifiedReceipt(podConfig, receipt, 1)); + assertTrue(podRegistry.getHistoryLength() == 2); + } + + function test_verifyOld() public { + bytes32 receiptRoot = 0x32bf7ef0c0291bc3b73afd18a62cca74ff8ee51c801b8b619c360e1c1dac9c84; + bytes[] memory signatures = new bytes[](validatorPrivateKeys.length); + uint256[] memory attestationTimestamps = new uint256[](validatorPrivateKeys.length); + for (uint256 i = 0; i < validatorPrivateKeys.length; i++) { + (uint8 v, bytes32 r, bytes32 s) = vm.sign(validatorPrivateKeys[i], receiptRoot); + signatures[i] = ECDSA._serialize_signature(v, r, s); + attestationTimestamps[i] = i + 1; + } + + bytes memory aggregateSignature = ECDSA.aggregate_signatures(signatures); + + uint256 medianTimestamp = attestationTimestamps[attestationTimestamps.length / 2]; + + PodECDSA.CertifiedReceipt memory receipt = PodECDSA.CertifiedReceipt({ + receiptRoot: receiptRoot, + aggregateSignature: aggregateSignature, + attestationTimestamps: attestationTimestamps, + medianTimestamp: medianTimestamp + }); + + uint256 snapshotIndex = podRegistry.findSnapshotIndex(medianTimestamp); + + vm.warp(medianTimestamp + 2); + vm.startPrank(OWNER); + podRegistry.addValidator(vm.addr(0x123abcd)); + vm.warp(block.timestamp + medianTimestamp); + podRegistry.addValidator(vm.addr(0x456defa)); + vm.warp(block.timestamp + medianTimestamp); + podRegistry.addValidator(vm.addr(0x789abcd)); + vm.warp(block.timestamp + medianTimestamp); + vm.stopPrank(); + + PodECDSA.PodConfig memory podConfig = PodECDSA.PodConfig({quorum: 86, registry: podRegistry}); + assertTrue(PodECDSA.verifyCertifiedReceipt(podConfig, receipt, snapshotIndex)); + assertTrue(PodECDSA.verifyCertifiedReceipt(podConfig, receipt)); + assertTrue(podRegistry.getHistoryLength() == 4); + } } From a5b9b30e241d745c1efa5d753f8678a906e96b7b Mon Sep 17 00:00:00 2001 From: Jakov Mitrovski Date: Fri, 15 Aug 2025 13:11:01 +0200 Subject: [PATCH 19/64] refactor(podecdsa): remove all timestamps from certified receipt --- solidity-sdk/src/verifier/PodECDSA.sol | 1 - solidity-sdk/test/PodECDSA.t.sol | 5 ----- 2 files changed, 6 deletions(-) diff --git a/solidity-sdk/src/verifier/PodECDSA.sol b/solidity-sdk/src/verifier/PodECDSA.sol index 5d0b38e0..6c9ea6a6 100644 --- a/solidity-sdk/src/verifier/PodECDSA.sol +++ b/solidity-sdk/src/verifier/PodECDSA.sol @@ -21,7 +21,6 @@ library PodECDSA { struct CertifiedReceipt { bytes32 receiptRoot; bytes aggregateSignature; - uint256[] attestationTimestamps; uint256 medianTimestamp; } diff --git a/solidity-sdk/test/PodECDSA.t.sol b/solidity-sdk/test/PodECDSA.t.sol index b684463f..2fd42660 100644 --- a/solidity-sdk/test/PodECDSA.t.sol +++ b/solidity-sdk/test/PodECDSA.t.sol @@ -53,7 +53,6 @@ contract PodECDSATest is Test { certifiedReceipt: PodECDSA.CertifiedReceipt({ receiptRoot: receiptRoot, aggregateSignature: aggregateSignature, - attestationTimestamps: attestationTimestamps, medianTimestamp: attestationTimestamps[attestationTimestamps.length / 2] }), proof: MerkleTree.Proof({path: path}) @@ -111,7 +110,6 @@ contract PodECDSATest is Test { certifiedReceipt: PodECDSA.CertifiedReceipt({ receiptRoot: receiptRoot, aggregateSignature: aggregateSignature, - attestationTimestamps: attestationTimestamps, medianTimestamp: attestationTimestamps[attestationTimestamps.length / 2] }), proof: MerkleTree.MultiProof({path: path, flags: flags}) @@ -136,7 +134,6 @@ contract PodECDSATest is Test { PodECDSA.CertifiedReceipt memory receipt = PodECDSA.CertifiedReceipt({ receiptRoot: receiptRoot, aggregateSignature: aggregateSignature, - attestationTimestamps: attestationTimestamps, medianTimestamp: attestationTimestamps[attestationTimestamps.length / 2] }); @@ -206,7 +203,6 @@ contract PodECDSATest is Test { PodECDSA.CertifiedReceipt memory receipt = PodECDSA.CertifiedReceipt({ receiptRoot: receiptRoot, aggregateSignature: aggregateSignature, - attestationTimestamps: attestationTimestamps, medianTimestamp: medianTimestamp }); @@ -232,7 +228,6 @@ contract PodECDSATest is Test { PodECDSA.CertifiedReceipt memory receipt = PodECDSA.CertifiedReceipt({ receiptRoot: receiptRoot, aggregateSignature: aggregateSignature, - attestationTimestamps: attestationTimestamps, medianTimestamp: medianTimestamp }); From fd63e1417545b17f69b9396058a1554ec5fe1162 Mon Sep 17 00:00:00 2001 From: Jakov Mitrovski Date: Fri, 15 Aug 2025 16:57:59 +0200 Subject: [PATCH 20/64] feat(podecdsa): modify threshold to be a fraction --- solidity-sdk/src/verifier/PodECDSA.sol | 15 ++++-- solidity-sdk/test/PodECDSA.t.sol | 64 ++++++++++++++++++++++++-- 2 files changed, 71 insertions(+), 8 deletions(-) diff --git a/solidity-sdk/src/verifier/PodECDSA.sol b/solidity-sdk/src/verifier/PodECDSA.sol index 6c9ea6a6..a02fd67f 100644 --- a/solidity-sdk/src/verifier/PodECDSA.sol +++ b/solidity-sdk/src/verifier/PodECDSA.sol @@ -5,10 +5,12 @@ import {ECDSA} from "./ECDSA.sol"; import {MerkleTree} from "./MerkleTree.sol"; import {IPodRegistry} from "./PodRegistry.sol"; import {Strings} from "@openzeppelin/contracts/utils/Strings.sol"; +import {Math} from "@openzeppelin/contracts/utils/math/Math.sol"; library PodECDSA { struct PodConfig { - uint256 quorum; + uint256 thresholdNumerator; + uint256 thresholdDenominator; IPodRegistry registry; } @@ -63,8 +65,15 @@ library PodECDSA { address[] memory validators = ECDSA.recoverSigners(certifiedReceipt.receiptRoot, certifiedReceipt.aggregateSignature); - return podConfig.registry.computeWeight(validators, certifiedReceipt.medianTimestamp, snapshotIndex) - >= podConfig.quorum; + uint256 weight = podConfig.registry.computeWeight(validators, certifiedReceipt.medianTimestamp, snapshotIndex); + uint256 threshold = Math.mulDiv( + podConfig.registry.getValidatorCountAt(snapshotIndex), + podConfig.thresholdNumerator, + podConfig.thresholdDenominator, + Math.Rounding.Ceil + ); + + return weight >= threshold; } function verifyCertificate(PodConfig calldata podConfig, Certificate calldata certificate) diff --git a/solidity-sdk/test/PodECDSA.t.sol b/solidity-sdk/test/PodECDSA.t.sol index 2fd42660..ffddbac3 100644 --- a/solidity-sdk/test/PodECDSA.t.sol +++ b/solidity-sdk/test/PodECDSA.t.sol @@ -7,6 +7,7 @@ import {ECDSA} from "../src/verifier/ECDSA.sol"; import {MerkleTree} from "../src/verifier/MerkleTree.sol"; import {PodRegistry} from "../src/verifier/PodRegistry.sol"; import {console} from "forge-std/console.sol"; +import {Math} from "@openzeppelin/contracts/utils/math/Math.sol"; contract PodECDSATest is Test { PodRegistry public podRegistry; @@ -58,7 +59,8 @@ contract PodECDSATest is Test { proof: MerkleTree.Proof({path: path}) }); - PodECDSA.PodConfig memory podConfig = PodECDSA.PodConfig({quorum: 86, registry: podRegistry}); + PodECDSA.PodConfig memory podConfig = + PodECDSA.PodConfig({thresholdNumerator: 2, thresholdDenominator: 3, registry: podRegistry}); assertTrue(PodECDSA.verifyCertificate(podConfig, certificate)); } @@ -115,7 +117,8 @@ contract PodECDSATest is Test { proof: MerkleTree.MultiProof({path: path, flags: flags}) }); - PodECDSA.PodConfig memory podConfig = PodECDSA.PodConfig({quorum: 86, registry: podRegistry}); + PodECDSA.PodConfig memory podConfig = + PodECDSA.PodConfig({thresholdNumerator: 2, thresholdDenominator: 3, registry: podRegistry}); assertTrue(PodECDSA.verifyMultiCertificate(podConfig, certificate)); } @@ -166,7 +169,8 @@ contract PodECDSATest is Test { certificate: PodECDSA.Certificate({leaf: leaf, certifiedReceipt: receipt, proof: proof}) }); - PodECDSA.PodConfig memory podConfig = PodECDSA.PodConfig({quorum: 86, registry: podRegistry}); + PodECDSA.PodConfig memory podConfig = + PodECDSA.PodConfig({thresholdNumerator: 2, thresholdDenominator: 3, registry: podRegistry}); assertTrue(PodECDSA.verifyCertifiedLog(podConfig, certifiedLog)); } @@ -206,7 +210,8 @@ contract PodECDSATest is Test { medianTimestamp: medianTimestamp }); - PodECDSA.PodConfig memory podConfig = PodECDSA.PodConfig({quorum: 86, registry: podRegistry}); + PodECDSA.PodConfig memory podConfig = + PodECDSA.PodConfig({thresholdNumerator: 2, thresholdDenominator: 3, registry: podRegistry}); assertTrue(PodECDSA.verifyCertifiedReceipt(podConfig, receipt, 1)); assertTrue(podRegistry.getHistoryLength() == 2); } @@ -243,9 +248,58 @@ contract PodECDSATest is Test { vm.warp(block.timestamp + medianTimestamp); vm.stopPrank(); - PodECDSA.PodConfig memory podConfig = PodECDSA.PodConfig({quorum: 86, registry: podRegistry}); + PodECDSA.PodConfig memory podConfig = + PodECDSA.PodConfig({thresholdNumerator: 2, thresholdDenominator: 3, registry: podRegistry}); assertTrue(PodECDSA.verifyCertifiedReceipt(podConfig, receipt, snapshotIndex)); assertTrue(PodECDSA.verifyCertifiedReceipt(podConfig, receipt)); assertTrue(podRegistry.getHistoryLength() == 4); } + + function test_verifyBeforeTresholdFails() public view { + bytes32 receiptRoot = 0x32bf7ef0c0291bc3b73afd18a62cca74ff8ee51c801b8b619c360e1c1dac9c84; + uint256 threshold = Math.mulDiv(validatorPrivateKeys.length, 2, 3, Math.Rounding.Ceil); + bytes[] memory signatures = new bytes[](threshold - 1); + uint256[] memory attestationTimestamps = new uint256[](threshold - 1); + for (uint256 i = 0; i < threshold - 1; i++) { + (uint8 v, bytes32 r, bytes32 s) = vm.sign(validatorPrivateKeys[i], receiptRoot); + signatures[i] = ECDSA._serialize_signature(v, r, s); + attestationTimestamps[i] = i + 1; + } + + bytes memory aggregateSignature = ECDSA.aggregate_signatures(signatures); + + PodECDSA.CertifiedReceipt memory receipt = PodECDSA.CertifiedReceipt({ + receiptRoot: receiptRoot, + aggregateSignature: aggregateSignature, + medianTimestamp: attestationTimestamps[attestationTimestamps.length / 2] + }); + + PodECDSA.PodConfig memory podConfig = + PodECDSA.PodConfig({thresholdNumerator: 2, thresholdDenominator: 3, registry: podRegistry}); + assertFalse(PodECDSA.verifyCertifiedReceipt(podConfig, receipt)); + } + + function test_verifyExactlyThresholdPasses() public view { + bytes32 receiptRoot = 0x32bf7ef0c0291bc3b73afd18a62cca74ff8ee51c801b8b619c360e1c1dac9c84; + uint256 threshold = Math.mulDiv(validatorPrivateKeys.length, 4, 5, Math.Rounding.Ceil); + bytes[] memory signatures = new bytes[](threshold); + uint256[] memory attestationTimestamps = new uint256[](threshold); + for (uint256 i = 0; i < threshold; i++) { + (uint8 v, bytes32 r, bytes32 s) = vm.sign(validatorPrivateKeys[i], receiptRoot); + signatures[i] = ECDSA._serialize_signature(v, r, s); + attestationTimestamps[i] = i + 1; + } + + bytes memory aggregateSignature = ECDSA.aggregate_signatures(signatures); + + PodECDSA.CertifiedReceipt memory receipt = PodECDSA.CertifiedReceipt({ + receiptRoot: receiptRoot, + aggregateSignature: aggregateSignature, + medianTimestamp: attestationTimestamps[attestationTimestamps.length / 2] + }); + + PodECDSA.PodConfig memory podConfig = + PodECDSA.PodConfig({thresholdNumerator: 4, thresholdDenominator: 5, registry: podRegistry}); + assertTrue(PodECDSA.verifyCertifiedReceipt(podConfig, receipt)); + } } From 0ebf49bf734ac89d84ce03fe4b1beb5f5e6fbc7b Mon Sep 17 00:00:00 2001 From: Jakov Mitrovski Date: Fri, 15 Aug 2025 18:26:42 +0200 Subject: [PATCH 21/64] docs(registry): add natspec docs --- solidity-sdk/src/verifier/PodRegistry.sol | 304 +++++++++++++++++++++- 1 file changed, 295 insertions(+), 9 deletions(-) diff --git a/solidity-sdk/src/verifier/PodRegistry.sol b/solidity-sdk/src/verifier/PodRegistry.sol index 730cd889..185ee51a 100644 --- a/solidity-sdk/src/verifier/PodRegistry.sol +++ b/solidity-sdk/src/verifier/PodRegistry.sol @@ -3,77 +3,281 @@ pragma solidity ^0.8.20; import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; +/** + * @title IPodRegistry + * @notice Interface for the Pod Registry contract that manages the validator committee and committee rotation. + * @dev This interface defines the core functionality for committee rotation. It is responsible + * for adding, banning, unbanning, activating and deactivating validators. It also provides + * ways to compute the weight of a subset of validators at a specific timestamp. + * In order to allow this, snapshots are created whenever the validator set changes. + */ interface IPodRegistry { + /** + * @notice Represents a snapshot of the validator set at a specific timestamp + * @param activeAsOfTimestamp The timestamp when this snapshot was created + * @param bitmap Bitmap representing which validators were active at this snapshot + */ struct Snapshot { uint256 activeAsOfTimestamp; uint256 bitmap; } + /// @notice Error thrown when too many initial validators are provided error TooManyInitialValidators(); + + /// @notice Error thrown when a validator is a zero address error ValidatorIsZeroAddress(); + + /// @notice Error thrown when a validator already exists error ValidatorAlreadyExists(); + + /// @notice Error thrown when the maximum validator count is reached error MaxValidatorCountReached(); + + /// @notice Error thrown when a validator does not exist error ValidatorDoesNotExist(); + + /// @notice Error thrown when a validator is already banned error ValidatorAlreadyBanned(); + + /// @notice Error thrown when a validator is not banned error ValidatorNotBanned(); + + /// @notice Error thrown when the caller is not a validator error CallerNotValidator(); + + /// @notice Error thrown when the caller is already inactive error CallerAlreadyInactive(); + + /// @notice Error thrown when the caller is already banned error CallerAlreadyBanned(); + + /// @notice Error thrown when the caller is already active error CallerAlreadyActive(); + + /// @notice Error thrown when the snapshot index is invalid error InvalidSnapshotIndex(); + + /// @notice Error thrown when the snapshot is too new error SnapshotTooNew(); + + /// @notice Error thrown when the snapshot is too old error SnapshotTooOld(); + + /// @notice Error thrown when there are no historical snapshots error NoHistoricalSnapshots(); + /// @notice Event emitted when a validator is added event ValidatorAdded(address indexed validator); + + /// @notice Event emitted when a validator is banned event ValidatorBanned(address indexed validator); + + /// @notice Event emitted when a validator is unbanned event ValidatorUnbanned(address indexed validator); + + /// @notice Event emitted when a validator is deactivated event ValidatorDeactivated(address indexed validator); + + /// @notice Event emitted when a validator is reactivated event ValidatorReactivated(address indexed validator); + + /// @notice Event emitted when a snapshot is created event SnapshotCreated(uint256 indexed activeAsOfTimestamp, uint256 bitmap); + /** + * @notice Get the index of a validator in the registry + * @param validator The address of the validator + * @return index The 1-based index of the validator (0 if not found) + */ function validatorIndex(address validator) external view returns (uint8 index); + + /** + * @notice Get the address of a validator by their index + * @param index The 1-based index of the validator + * @return validator The address of the validator at the given index (address(0) if not found) + */ function validatorAddress(uint8 index) external view returns (address validator); + + /** + * @notice Check if a validator is banned + * @param validator The address of the validator + * @return isBanned True if the validator is banned, false otherwise + */ function bannedValidators(address validator) external view returns (bool isBanned); + /** + * @notice Get the total number of validators in the registry. Counts banned and active validators too. + * @return count The total count of validators + */ function validatorCount() external view returns (uint8 count); + + /** + * @notice Get the current bitmap of active validators + * @return bitmap The bitmap representing which validators are currently active + */ function activeValidatorBitmap() external view returns (uint256 bitmap); + /** + * @notice Add a new validator to the registry and activates them. Modifies the current validator set + * therefore creates a new snapshot. + * @param validator The address of the validator to add + * @dev Only callable by the contract owner + */ function addValidator(address validator) external; + + /** + * @notice Ban a validator from the registry + * if they are active, they are deactivated first. Modifies the current validator set + * therefore creates a new snapshot. + * @param validator The address of the validator to ban + * @dev Only callable by the contract owner + */ function banValidator(address validator) external; + + /** + * @notice Unban a previously banned validator. Does not automatically reactivate the validator. + * So it does not modify the current validator set. + * @param validator The address of the validator to unban + * @dev Only callable by the contract owner + */ function unbanValidator(address validator) external; + + /** + * @notice Deactivate the caller's validator status. Modifies the current validator set + * therefore creates a new snapshot. + * @dev Only callable by registered validators + */ function deactivate() external; + + /** + * @notice Reactivate the caller's validator status. Modifies the current validator set + * therefore creates a new snapshot. + * @dev Only callable by registered validators who are not banned + */ function reactivate() external; + /** + * @notice Compute the weight of a subset of validators at the current time + * @param subset Array of validator addresses to compute weight for + * @return weight The computed weight (count of unique active validators in the subset) + * @dev Uses the most recent snapshot for computation + */ function computeWeight(address[] memory subset) external view returns (uint256 weight); + + /** + * @notice Compute the weight of a subset of validators at a specific historical point + * @param subset Array of validator addresses to compute weight for + * @param timestamp The timestamp to compute weight at + * @param snapshotIndex The snapshot index to use for computation + * @return weight The computed weight at the specified historical point + * @dev Validates that the snapshot is appropriate for the given timestamp + */ function computeWeight(address[] memory subset, uint256 timestamp, uint256 snapshotIndex) external view returns (uint256 weight); - function findSnapshotIndex(uint256 timestamp) external view returns (uint256 index); - + /** + * @notice Find the appropriate snapshot index for a given timestamp + * Since this is a view function, it can be called off-chain to compute the correct snapshotIndex + * corresponding to a particular timestamp. + * Then, the function computeWeight can be called on-chain with the correct snapshotIndex. + * @param timestamp The timestamp to find a snapshot for + * @return snapshotIndex The index of the most recent snapshot at or before the timestamp + * @dev Uses binary search for efficient lookup + */ + function findSnapshotIndex(uint256 timestamp) external view returns (uint256 snapshotIndex); + + /** + * @notice Get the count of currently active validators + * @return count The number of active validators + */ function getActiveValidatorCount() external view returns (uint8 count); - function getValidatorCountAt(uint256 index) external view returns (uint8 count); + + /** + * @notice Get the count of validators at a specific snapshot + * @param snapshotIndex The snapshot index to query + * @return count The number of validators at the specified snapshot + */ + function getValidatorCountAt(uint256 snapshotIndex) external view returns (uint8 count); + + /** + * @notice Get all currently active validators + * @return Array of addresses of currently active validators + */ function getActiveValidators() external view returns (address[] memory); + + /** + * @notice Get all validators that were active at a specific timestamp + * @param timestamp The timestamp to query + * @return Array of addresses of validators active at the specified timestamp + */ function getActiveValidators(uint256 timestamp) external view returns (address[] memory); + + /** + * @notice Get all validators at a specific snapshot + * @param index The snapshot index to query + * @return Array of addresses of validators at the specified snapshot + */ function getValidatorsAt(uint256 index) external view returns (address[] memory); + + /** + * @notice Get snapshot details at a specific index + * @param index The snapshot index to query + * @return activeAsOfTimestamp The timestamp when the snapshot was created + * @return bitmap The bitmap of active validators at this snapshot + */ function getSnapshotAt(uint256 index) external view returns (uint256 activeAsOfTimestamp, uint256 bitmap); + + /** + * @notice Get the total number of snapshots in the history + * @return The length of the snapshot history + */ function getHistoryLength() external view returns (uint256); } +/** + * @title PodRegistry + * @notice Manages a dynamic set of validators with historical snapshots for quorum verification + * @dev This contract maintains a bitmap-based validator set with the ability to create + * historical snapshots for quorum verification of certificates signed by previously active committees. + * It supports up to 255 validators + * and uses bitmap operations for validator status tracking. + * + * @custom:security This contract is Ownable and should only be deployed with trusted ownership + */ contract PodRegistry is IPodRegistry, Ownable { + /// @notice Maximum number of validators allowed in the registry uint256 constant MAX_VALIDATOR_COUNT = 255; + /// @notice Array of historical snapshots for time-based verification Snapshot[] public history; + /// @notice Mapping from validator address to their 1-based index mapping(address => uint8) public validatorIndex; + + /// @notice Mapping from validator 1-based index to their address mapping(uint8 => address) public validatorAddress; + + /// @notice Mapping from validator address to banned status mapping(address => bool) public bannedValidators; + /// @notice Bitmap of the currently active validators uint256 public activeValidatorBitmap; + + /** + * @notice Total count of validators in the registry. We also use `validatorCount` to + * track the index of the next validator to add. + */ uint8 public validatorCount; + /** + * @notice Initialize the registry with a set of initial validators. Only creates one snapshot + * after adding all the initial validators. + * @param initialValidators Array of validator addresses to initialize with + * @dev The contract owner will be set to msg.sender + */ constructor(address[] memory initialValidators) Ownable(msg.sender) { if (initialValidators.length >= MAX_VALIDATOR_COUNT) { revert TooManyInitialValidators(); @@ -87,12 +291,21 @@ contract PodRegistry is IPodRegistry, Ownable { _createSnapshot(); } + /** + * @notice Add a validator during contract initialization. Does not create a snapshot. + * @param validator The address of the validator to add + * @param index The 0-based index for the validator + * @dev Internal function used only during construction + */ function _addValidatorOnInit(address validator, uint8 index) internal { validatorIndex[validator] = index + 1; activeValidatorBitmap |= (1 << index); validatorAddress[index + 1] = validator; } + /** + * @inheritdoc IPodRegistry + */ function addValidator(address validator) external onlyOwner { if (validator == address(0)) { revert ValidatorIsZeroAddress(); @@ -112,6 +325,9 @@ contract PodRegistry is IPodRegistry, Ownable { emit ValidatorAdded(validator); } + /** + * @inheritdoc IPodRegistry + */ function banValidator(address validator) external onlyOwner { uint8 index = validatorIndex[validator]; if (index == 0) { @@ -129,6 +345,9 @@ contract PodRegistry is IPodRegistry, Ownable { emit ValidatorBanned(validator); } + /** + * @inheritdoc IPodRegistry + */ function unbanValidator(address validator) external onlyOwner { if (validatorIndex[validator] == 0) { revert ValidatorDoesNotExist(); @@ -140,6 +359,9 @@ contract PodRegistry is IPodRegistry, Ownable { emit ValidatorUnbanned(validator); } + /** + * @inheritdoc IPodRegistry + */ function deactivate() external { uint8 index = validatorIndex[msg.sender]; if (index == 0) { @@ -152,6 +374,9 @@ contract PodRegistry is IPodRegistry, Ownable { emit ValidatorDeactivated(msg.sender); } + /** + * @inheritdoc IPodRegistry + */ function reactivate() external { uint8 index = validatorIndex[msg.sender]; if (index == 0) { @@ -167,11 +392,18 @@ contract PodRegistry is IPodRegistry, Ownable { emit ValidatorReactivated(msg.sender); } + /** + * @notice Create a new snapshot at the current timestamp of the current validator set + * @dev Internal function called whenever the validator set changes + */ function _createSnapshot() internal { history.push(Snapshot({activeAsOfTimestamp: block.timestamp, bitmap: activeValidatorBitmap})); emit SnapshotCreated(block.timestamp, activeValidatorBitmap); } + /** + * @inheritdoc IPodRegistry + */ function computeWeight(address[] memory subset) public view returns (uint256 weight) { if (history.length == 0) { return 0; @@ -180,6 +412,9 @@ contract PodRegistry is IPodRegistry, Ownable { return computeWeight(subset, block.timestamp, history.length - 1); } + /** + * @inheritdoc IPodRegistry + */ function computeWeight(address[] memory subset, uint256 timestamp, uint256 snapshotIndex) public view @@ -213,6 +448,9 @@ contract PodRegistry is IPodRegistry, Ownable { } } + /** + * @inheritdoc IPodRegistry + */ function findSnapshotIndex(uint256 timestamp) public view returns (uint256 index) { if (history.length == 0) { revert NoHistoricalSnapshots(); @@ -233,15 +471,27 @@ contract PodRegistry is IPodRegistry, Ownable { return low; } + /** + * @inheritdoc IPodRegistry + */ function getActiveValidatorCount() public view returns (uint8 count) { return _popCount(activeValidatorBitmap); } - function getValidatorCountAt(uint256 index) public view returns (uint8 count) { - uint256 bitmap = history[index].bitmap; + /** + * @inheritdoc IPodRegistry + */ + function getValidatorCountAt(uint256 snapshotIndex) public view returns (uint8 count) { + uint256 bitmap = history[snapshotIndex].bitmap; return _popCount(bitmap); } + /** + * @notice Count the number of set bits in a bitmap (pop count) + * @param bitmap The bitmap to count set bits in + * @return count The number of set bits + * @dev Efficient implementation using Brian Kernighan's algorithm + */ function _popCount(uint256 bitmap) internal pure returns (uint8 count) { while (bitmap != 0) { count++; @@ -249,8 +499,11 @@ contract PodRegistry is IPodRegistry, Ownable { } } - function getValidatorsAt(uint256 index) public view returns (address[] memory) { - uint256 bitmap = history[index].bitmap; + /** + * @inheritdoc IPodRegistry + */ + function getValidatorsAt(uint256 snapshotIndex) public view returns (address[] memory) { + uint256 bitmap = history[snapshotIndex].bitmap; uint8 count = _popCount(bitmap); address[] memory validators = new address[](count); uint8 j = 0; @@ -262,6 +515,9 @@ contract PodRegistry is IPodRegistry, Ownable { return validators; } + /** + * @inheritdoc IPodRegistry + */ function getActiveValidators() external view returns (address[] memory) { if (history.length == 0) { return new address[](0); @@ -270,6 +526,9 @@ contract PodRegistry is IPodRegistry, Ownable { return getValidatorsAt(history.length - 1); } + /** + * @inheritdoc IPodRegistry + */ function getActiveValidators(uint256 timestamp) external view returns (address[] memory) { if (history.length == 0) { return new address[](0); @@ -279,29 +538,56 @@ contract PodRegistry is IPodRegistry, Ownable { return getValidatorsAt(snapshotIndex); } - function getSnapshotAt(uint256 index) external view returns (uint256 activeAsOfTimestamp, uint256 bitmap) { - Snapshot memory s = history[index]; + /** + * @inheritdoc IPodRegistry + */ + function getSnapshotAt(uint256 snapshotIndex) external view returns (uint256 activeAsOfTimestamp, uint256 bitmap) { + Snapshot memory s = history[snapshotIndex]; return (s.activeAsOfTimestamp, s.bitmap); } + /** + * @inheritdoc IPodRegistry + */ function getHistoryLength() external view returns (uint256) { return history.length; } + /** + * @notice Activate a validator by setting their bit in the active bitmap + * @param index The 1-based index of the validator to activate + * @dev Creates a new snapshot after activation + */ function _activateValidator(uint8 index) internal { activeValidatorBitmap |= (1 << (index - 1)); _createSnapshot(); } + /** + * @notice Deactivate a validator by clearing their bit in the active bitmap + * @param index The 1-based index of the validator to deactivate + * @dev Creates a new snapshot after deactivation + */ function _deactivateValidator(uint8 index) internal { activeValidatorBitmap &= ~(1 << (index - 1)); _createSnapshot(); } + /** + * @notice Check if a validator is currently active + * @param index The 1-based index of the validator to check + * @return True if the validator is active, false otherwise + */ function _isValidatorActive(uint8 index) internal view returns (bool) { return _isBitSet(activeValidatorBitmap, index - 1); } + /** + * @notice Check if a specific bit is set in a bitmap + * @param bitmap The bitmap to check + * @param i The 0-based bit position to check + * @return True if the bit is set, false otherwise + */ function _isBitSet(uint256 bitmap, uint8 i) internal pure returns (bool) { return (bitmap & (1 << i)) != 0; } From 811c22d623e119ded10f7911a2fbd11e29744ef0 Mon Sep 17 00:00:00 2001 From: Jakov Mitrovski Date: Fri, 15 Aug 2025 19:43:51 +0200 Subject: [PATCH 22/64] update optimistic-auction to reflect changes in podecdsa, regen bindings, revert test to Test --- .../bindings/src/pod_auction_consumer.rs | 670 ++++-------------- .../contracts/PodAuctionConsumer.sol | 57 +- .../test/PodAuctionConsumer.t.sol | 145 ++-- 3 files changed, 251 insertions(+), 621 deletions(-) diff --git a/examples/optimistic-auction/bindings/src/pod_auction_consumer.rs b/examples/optimistic-auction/bindings/src/pod_auction_consumer.rs index 79ab1180..e21f4040 100644 --- a/examples/optimistic-auction/bindings/src/pod_auction_consumer.rs +++ b/examples/optimistic-auction/bindings/src/pod_auction_consumer.rs @@ -348,7 +348,7 @@ See the [wrapper's documentation](`MerkleTreeInstance`) for more details.*/ library PodECDSA { struct Certificate { CertifiedReceipt certifiedReceipt; bytes32 leaf; MerkleTree.Proof proof; } struct CertifiedLog { Log log; uint256 logIndex; Certificate certificate; } - struct CertifiedReceipt { bytes32 receiptRoot; bytes aggregateSignature; } + struct CertifiedReceipt { bytes32 receiptRoot; bytes aggregateSignature; uint256 medianTimestamp; } struct Log { address addr; bytes32[] topics; bytes data; } } ```*/ @@ -865,7 +865,7 @@ struct CertifiedLog { Log log; uint256 logIndex; Certificate certificate; } #[derive(serde::Serialize, serde::Deserialize)] #[derive(Default, Debug, PartialEq, Eq, Hash)] /**```solidity -struct CertifiedReceipt { bytes32 receiptRoot; bytes aggregateSignature; } +struct CertifiedReceipt { bytes32 receiptRoot; bytes aggregateSignature; uint256 medianTimestamp; } ```*/ #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] #[derive(Clone)] @@ -874,6 +874,8 @@ struct CertifiedReceipt { bytes32 receiptRoot; bytes aggregateSignature; } pub receiptRoot: alloy::sol_types::private::FixedBytes<32>, #[allow(missing_docs)] pub aggregateSignature: alloy::sol_types::private::Bytes, + #[allow(missing_docs)] + pub medianTimestamp: alloy::sol_types::private::primitives::aliases::U256, } #[allow( non_camel_case_types, @@ -887,11 +889,13 @@ struct CertifiedReceipt { bytes32 receiptRoot; bytes aggregateSignature; } type UnderlyingSolTuple<'a> = ( alloy::sol_types::sol_data::FixedBytes<32>, alloy::sol_types::sol_data::Bytes, + alloy::sol_types::sol_data::Uint<256>, ); #[doc(hidden)] type UnderlyingRustTuple<'a> = ( alloy::sol_types::private::FixedBytes<32>, alloy::sol_types::private::Bytes, + alloy::sol_types::private::primitives::aliases::U256, ); #[cfg(test)] #[allow(dead_code, unreachable_patterns)] @@ -908,7 +912,7 @@ struct CertifiedReceipt { bytes32 receiptRoot; bytes aggregateSignature; } #[doc(hidden)] impl ::core::convert::From for UnderlyingRustTuple<'_> { fn from(value: CertifiedReceipt) -> Self { - (value.receiptRoot, value.aggregateSignature) + (value.receiptRoot, value.aggregateSignature, value.medianTimestamp) } } #[automatically_derived] @@ -918,6 +922,7 @@ struct CertifiedReceipt { bytes32 receiptRoot; bytes aggregateSignature; } Self { receiptRoot: tuple.0, aggregateSignature: tuple.1, + medianTimestamp: tuple.2, } } } @@ -936,6 +941,9 @@ struct CertifiedReceipt { bytes32 receiptRoot; bytes aggregateSignature; } ::tokenize( &self.aggregateSignature, ), + as alloy_sol_types::SolType>::tokenize(&self.medianTimestamp), ) } #[inline] @@ -1010,7 +1018,7 @@ struct CertifiedReceipt { bytes32 receiptRoot; bytes aggregateSignature; } #[inline] fn eip712_root_type() -> alloy_sol_types::private::Cow<'static, str> { alloy_sol_types::private::Cow::Borrowed( - "CertifiedReceipt(bytes32 receiptRoot,bytes aggregateSignature)", + "CertifiedReceipt(bytes32 receiptRoot,bytes aggregateSignature,uint256 medianTimestamp)", ) } #[inline] @@ -1034,6 +1042,12 @@ struct CertifiedReceipt { bytes32 receiptRoot; bytes aggregateSignature; } &self.aggregateSignature, ) .0, + as alloy_sol_types::SolType>::eip712_data_word( + &self.medianTimestamp, + ) + .0, ] .concat() } @@ -1051,6 +1065,11 @@ struct CertifiedReceipt { bytes32 receiptRoot; bytes aggregateSignature; } + ::topic_preimage_length( &rust.aggregateSignature, ) + + as alloy_sol_types::EventTopic>::topic_preimage_length( + &rust.medianTimestamp, + ) } #[inline] fn encode_topic_preimage( @@ -1070,6 +1089,12 @@ struct CertifiedReceipt { bytes32 receiptRoot; bytes aggregateSignature; } &rust.aggregateSignature, out, ); + as alloy_sol_types::EventTopic>::encode_topic_preimage( + &rust.medianTimestamp, + out, + ); } #[inline] fn encode_topic( @@ -1457,283 +1482,6 @@ See the [wrapper's documentation](`PodECDSAInstance`) for more details.*/ } } } -///Module containing a contract's types and functions. -/** - -```solidity -library Time { - type Timestamp is uint64; -} -```*/ -#[allow( - non_camel_case_types, - non_snake_case, - clippy::pub_underscore_fields, - clippy::style, - clippy::empty_structs_with_brackets -)] -pub mod Time { - use super::*; - use alloy::sol_types as alloy_sol_types; - #[derive(serde::Serialize, serde::Deserialize)] - #[derive(Default, Debug, PartialEq, Eq, Hash)] - #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] - #[derive(Clone)] - pub struct Timestamp(u64); - const _: () = { - use alloy::sol_types as alloy_sol_types; - #[automatically_derived] - impl alloy_sol_types::private::SolTypeValue for u64 { - #[inline] - fn stv_to_tokens( - &self, - ) -> as alloy_sol_types::SolType>::Token<'_> { - alloy_sol_types::private::SolTypeValue::< - alloy::sol_types::sol_data::Uint<64>, - >::stv_to_tokens(self) - } - #[inline] - fn stv_eip712_data_word(&self) -> alloy_sol_types::Word { - as alloy_sol_types::SolType>::tokenize(self) - .0 - } - #[inline] - fn stv_abi_encode_packed_to( - &self, - out: &mut alloy_sol_types::private::Vec, - ) { - as alloy_sol_types::SolType>::abi_encode_packed_to(self, out) - } - #[inline] - fn stv_abi_packed_encoded_size(&self) -> usize { - as alloy_sol_types::SolType>::abi_encoded_size(self) - } - } - #[automatically_derived] - impl Timestamp { - /// The Solidity type name. - pub const NAME: &'static str = stringify!(@ name); - /// Convert from the underlying value type. - #[inline] - pub const fn from_underlying(value: u64) -> Self { - Self(value) - } - /// Return the underlying value. - #[inline] - pub const fn into_underlying(self) -> u64 { - self.0 - } - /// Return the single encoding of this value, delegating to the - /// underlying type. - #[inline] - pub fn abi_encode(&self) -> alloy_sol_types::private::Vec { - ::abi_encode(&self.0) - } - /// Return the packed encoding of this value, delegating to the - /// underlying type. - #[inline] - pub fn abi_encode_packed(&self) -> alloy_sol_types::private::Vec { - ::abi_encode_packed(&self.0) - } - } - #[automatically_derived] - impl From for Timestamp { - fn from(value: u64) -> Self { - Self::from_underlying(value) - } - } - #[automatically_derived] - impl From for u64 { - fn from(value: Timestamp) -> Self { - value.into_underlying() - } - } - #[automatically_derived] - impl alloy_sol_types::SolType for Timestamp { - type RustType = u64; - type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; - const SOL_NAME: &'static str = Self::NAME; - const ENCODED_SIZE: Option = as alloy_sol_types::SolType>::ENCODED_SIZE; - const PACKED_ENCODED_SIZE: Option = as alloy_sol_types::SolType>::PACKED_ENCODED_SIZE; - #[inline] - fn valid_token(token: &Self::Token<'_>) -> bool { - Self::type_check(token).is_ok() - } - #[inline] - fn type_check(token: &Self::Token<'_>) -> alloy_sol_types::Result<()> { - as alloy_sol_types::SolType>::type_check(token) - } - #[inline] - fn detokenize(token: Self::Token<'_>) -> Self::RustType { - as alloy_sol_types::SolType>::detokenize(token) - } - } - #[automatically_derived] - impl alloy_sol_types::EventTopic for Timestamp { - #[inline] - fn topic_preimage_length(rust: &Self::RustType) -> usize { - as alloy_sol_types::EventTopic>::topic_preimage_length(rust) - } - #[inline] - fn encode_topic_preimage( - rust: &Self::RustType, - out: &mut alloy_sol_types::private::Vec, - ) { - as alloy_sol_types::EventTopic>::encode_topic_preimage(rust, out) - } - #[inline] - fn encode_topic( - rust: &Self::RustType, - ) -> alloy_sol_types::abi::token::WordToken { - as alloy_sol_types::EventTopic>::encode_topic(rust) - } - } - }; - use alloy::contract as alloy_contract; - /**Creates a new wrapper around an on-chain [`Time`](self) contract instance. - -See the [wrapper's documentation](`TimeInstance`) for more details.*/ - #[inline] - pub const fn new< - P: alloy_contract::private::Provider, - N: alloy_contract::private::Network, - >(address: alloy_sol_types::private::Address, provider: P) -> TimeInstance { - TimeInstance::::new(address, provider) - } - /**A [`Time`](self) instance. - -Contains type-safe methods for interacting with an on-chain instance of the -[`Time`](self) contract located at a given `address`, using a given -provider `P`. - -If the contract bytecode is available (see the [`sol!`](alloy_sol_types::sol!) -documentation on how to provide it), the `deploy` and `deploy_builder` methods can -be used to deploy a new instance of the contract. - -See the [module-level documentation](self) for all the available methods.*/ - #[derive(Clone)] - pub struct TimeInstance { - address: alloy_sol_types::private::Address, - provider: P, - _network: ::core::marker::PhantomData, - } - #[automatically_derived] - impl ::core::fmt::Debug for TimeInstance { - #[inline] - fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { - f.debug_tuple("TimeInstance").field(&self.address).finish() - } - } - /// Instantiation and getters/setters. - #[automatically_derived] - impl< - P: alloy_contract::private::Provider, - N: alloy_contract::private::Network, - > TimeInstance { - /**Creates a new wrapper around an on-chain [`Time`](self) contract instance. - -See the [wrapper's documentation](`TimeInstance`) for more details.*/ - #[inline] - pub const fn new( - address: alloy_sol_types::private::Address, - provider: P, - ) -> Self { - Self { - address, - provider, - _network: ::core::marker::PhantomData, - } - } - /// Returns a reference to the address. - #[inline] - pub const fn address(&self) -> &alloy_sol_types::private::Address { - &self.address - } - /// Sets the address. - #[inline] - pub fn set_address(&mut self, address: alloy_sol_types::private::Address) { - self.address = address; - } - /// Sets the address and returns `self`. - pub fn at(mut self, address: alloy_sol_types::private::Address) -> Self { - self.set_address(address); - self - } - /// Returns a reference to the provider. - #[inline] - pub const fn provider(&self) -> &P { - &self.provider - } - } - impl TimeInstance<&P, N> { - /// Clones the provider and returns a new instance with the cloned provider. - #[inline] - pub fn with_cloned_provider(self) -> TimeInstance { - TimeInstance { - address: self.address, - provider: ::core::clone::Clone::clone(&self.provider), - _network: ::core::marker::PhantomData, - } - } - } - /// Function calls. - #[automatically_derived] - impl< - P: alloy_contract::private::Provider, - N: alloy_contract::private::Network, - > TimeInstance { - /// Creates a new call builder using this contract instance's provider and address. - /// - /// Note that the call can be any function call, not just those defined in this - /// contract. Prefer using the other methods for building type-safe contract calls. - pub fn call_builder( - &self, - call: &C, - ) -> alloy_contract::SolCallBuilder<&P, C, N> { - alloy_contract::SolCallBuilder::new_sol(&self.provider, &self.address, call) - } - } - /// Event filters. - #[automatically_derived] - impl< - P: alloy_contract::private::Provider, - N: alloy_contract::private::Network, - > TimeInstance { - /// Creates a new event filter using this contract instance's provider and address. - /// - /// Note that the type can be any event, not just those defined in this contract. - /// Prefer using the other methods for building type-safe event filters. - pub fn event_filter( - &self, - ) -> alloy_contract::Event<&P, E, N> { - alloy_contract::Event::new_sol(&self.provider, &self.address) - } - } -} /** Generated by the following Solidity interface... @@ -1758,6 +1506,7 @@ library PodECDSA { struct CertifiedReceipt { bytes32 receiptRoot; bytes aggregateSignature; + uint256 medianTimestamp; } struct Log { address addr; @@ -1766,10 +1515,6 @@ library PodECDSA { } } -library Time { - type Timestamp is uint64; -} - interface PodAuctionConsumer { struct Bid { address bidder; @@ -1786,7 +1531,6 @@ interface PodAuctionConsumer { event BidBlamed(bytes32 indexed auctionId, address indexed blamedBidder, uint256 bid); event BidWritten(bytes32 indexed auctionId, address indexed bidder, uint256 bid); event Bonded(address indexed validator); - event Log(string message, Time.Timestamp value); event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); event Slashed(address indexed validator); event Unbonded(address indexed validator); @@ -1794,7 +1538,7 @@ interface PodAuctionConsumer { constructor(address _podRegistry, uint256 _bondAmount); function LOG_TOPIC_0() external view returns (bytes32); - function U() external view returns (uint64); + function U() external view returns (uint256); function blameIllAnnounced(PodECDSA.CertifiedLog memory certifiedLog) external; function blameNoShow(PodECDSA.CertifiedLog memory certifiedLog) external; function bond() external payable; @@ -1802,7 +1546,7 @@ interface PodAuctionConsumer { function isBonded(address) external view returns (bool); function owner() external view returns (address); function podRegistry() external view returns (address); - function read(uint256 auctionId, Time.Timestamp deadline) external view returns (State memory); + function read(uint256 auctionId, uint256 deadline) external view returns (State memory); function renounceOwnership() external; function state(bytes32) external view returns (Bid memory winner, Bid memory blamed); function transferOwnership(address newOwner) external; @@ -1851,8 +1595,8 @@ interface PodAuctionConsumer { "outputs": [ { "name": "", - "type": "uint64", - "internalType": "uint64" + "type": "uint256", + "internalType": "uint256" } ], "stateMutability": "view" @@ -1912,6 +1656,11 @@ interface PodAuctionConsumer { "name": "aggregateSignature", "type": "bytes", "internalType": "bytes" + }, + { + "name": "medianTimestamp", + "type": "uint256", + "internalType": "uint256" } ] }, @@ -1995,6 +1744,11 @@ interface PodAuctionConsumer { "name": "aggregateSignature", "type": "bytes", "internalType": "bytes" + }, + { + "name": "medianTimestamp", + "type": "uint256", + "internalType": "uint256" } ] }, @@ -2099,8 +1853,8 @@ interface PodAuctionConsumer { }, { "name": "deadline", - "type": "uint64", - "internalType": "Time.Timestamp" + "type": "uint256", + "internalType": "uint256" } ], "outputs": [ @@ -2285,6 +2039,11 @@ interface PodAuctionConsumer { "name": "aggregateSignature", "type": "bytes", "internalType": "bytes" + }, + { + "name": "medianTimestamp", + "type": "uint256", + "internalType": "uint256" } ] }, @@ -2376,25 +2135,6 @@ interface PodAuctionConsumer { ], "anonymous": false }, - { - "type": "event", - "name": "Log", - "inputs": [ - { - "name": "message", - "type": "string", - "indexed": false, - "internalType": "string" - }, - { - "name": "value", - "type": "uint64", - "indexed": false, - "internalType": "Time.Timestamp" - } - ], - "anonymous": false - }, { "type": "event", "name": "OwnershipTransferred", @@ -3426,117 +3166,6 @@ event Bonded(address indexed validator); }; #[derive(serde::Serialize, serde::Deserialize)] #[derive(Default, Debug, PartialEq, Eq, Hash)] - /**Event with signature `Log(string,uint64)` and selector `0x9b17d545c0fe66a8ad6062cc7474298f40a7ea4b601267406d79749513311c95`. -```solidity -event Log(string message, Time.Timestamp value); -```*/ - #[allow( - non_camel_case_types, - non_snake_case, - clippy::pub_underscore_fields, - clippy::style - )] - #[derive(Clone)] - pub struct Log { - #[allow(missing_docs)] - pub message: alloy::sol_types::private::String, - #[allow(missing_docs)] - pub value: ::RustType, - } - #[allow( - non_camel_case_types, - non_snake_case, - clippy::pub_underscore_fields, - clippy::style - )] - const _: () = { - use alloy::sol_types as alloy_sol_types; - #[automatically_derived] - impl alloy_sol_types::SolEvent for Log { - type DataTuple<'a> = (alloy::sol_types::sol_data::String, Time::Timestamp); - type DataToken<'a> = as alloy_sol_types::SolType>::Token<'a>; - type TopicList = (alloy_sol_types::sol_data::FixedBytes<32>,); - const SIGNATURE: &'static str = "Log(string,uint64)"; - const SIGNATURE_HASH: alloy_sol_types::private::B256 = alloy_sol_types::private::B256::new([ - 155u8, 23u8, 213u8, 69u8, 192u8, 254u8, 102u8, 168u8, 173u8, 96u8, 98u8, - 204u8, 116u8, 116u8, 41u8, 143u8, 64u8, 167u8, 234u8, 75u8, 96u8, 18u8, - 103u8, 64u8, 109u8, 121u8, 116u8, 149u8, 19u8, 49u8, 28u8, 149u8, - ]); - const ANONYMOUS: bool = false; - #[allow(unused_variables)] - #[inline] - fn new( - topics: ::RustType, - data: as alloy_sol_types::SolType>::RustType, - ) -> Self { - Self { - message: data.0, - value: data.1, - } - } - #[inline] - fn check_signature( - topics: &::RustType, - ) -> alloy_sol_types::Result<()> { - if topics.0 != Self::SIGNATURE_HASH { - return Err( - alloy_sol_types::Error::invalid_event_signature_hash( - Self::SIGNATURE, - topics.0, - Self::SIGNATURE_HASH, - ), - ); - } - Ok(()) - } - #[inline] - fn tokenize_body(&self) -> Self::DataToken<'_> { - ( - ::tokenize( - &self.message, - ), - ::tokenize(&self.value), - ) - } - #[inline] - fn topics(&self) -> ::RustType { - (Self::SIGNATURE_HASH.into(),) - } - #[inline] - fn encode_topics_raw( - &self, - out: &mut [alloy_sol_types::abi::token::WordToken], - ) -> alloy_sol_types::Result<()> { - if out.len() < ::COUNT { - return Err(alloy_sol_types::Error::Overrun); - } - out[0usize] = alloy_sol_types::abi::token::WordToken( - Self::SIGNATURE_HASH, - ); - Ok(()) - } - } - #[automatically_derived] - impl alloy_sol_types::private::IntoLogData for Log { - fn to_log_data(&self) -> alloy_sol_types::private::LogData { - From::from(self) - } - fn into_log_data(self) -> alloy_sol_types::private::LogData { - From::from(&self) - } - } - #[automatically_derived] - impl From<&Log> for alloy_sol_types::private::LogData { - #[inline] - fn from(this: &Log) -> alloy_sol_types::private::LogData { - alloy_sol_types::SolEvent::encode_log_data(this) - } - } - }; - #[derive(serde::Serialize, serde::Deserialize)] - #[derive(Default, Debug, PartialEq, Eq, Hash)] /**Event with signature `OwnershipTransferred(address,address)` and selector `0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0`. ```solidity event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); @@ -4098,7 +3727,7 @@ function LOG_TOPIC_0() external view returns (bytes32); #[derive(Default, Debug, PartialEq, Eq, Hash)] /**Function with signature `U()` and selector `0x2688454a`. ```solidity -function U() external view returns (uint64); +function U() external view returns (uint256); ```*/ #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] #[derive(Clone)] @@ -4110,7 +3739,7 @@ function U() external view returns (uint64); #[derive(Clone)] pub struct UReturn { #[allow(missing_docs)] - pub _0: u64, + pub _0: alloy::sol_types::private::primitives::aliases::U256, } #[allow( non_camel_case_types, @@ -4153,9 +3782,11 @@ function U() external view returns (uint64); } { #[doc(hidden)] - type UnderlyingSolTuple<'a> = (alloy::sol_types::sol_data::Uint<64>,); + type UnderlyingSolTuple<'a> = (alloy::sol_types::sol_data::Uint<256>,); #[doc(hidden)] - type UnderlyingRustTuple<'a> = (u64,); + type UnderlyingRustTuple<'a> = ( + alloy::sol_types::private::primitives::aliases::U256, + ); #[cfg(test)] #[allow(dead_code, unreachable_patterns)] fn _type_assertion( @@ -4188,8 +3819,8 @@ function U() external view returns (uint64); type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; - type Return = u64; - type ReturnTuple<'a> = (alloy::sol_types::sol_data::Uint<64>,); + type Return = alloy::sol_types::private::primitives::aliases::U256; + type ReturnTuple<'a> = (alloy::sol_types::sol_data::Uint<256>,); type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; @@ -4209,7 +3840,7 @@ function U() external view returns (uint64); fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> { ( as alloy_sol_types::SolType>::tokenize(ret), ) } @@ -4239,7 +3870,7 @@ function U() external view returns (uint64); }; #[derive(serde::Serialize, serde::Deserialize)] #[derive()] - /**Function with signature `blameIllAnnounced(((address,bytes32[],bytes),uint256,((bytes32,bytes),bytes32,(bytes32[]))))` and selector `0xf257b5ab`. + /**Function with signature `blameIllAnnounced(((address,bytes32[],bytes),uint256,((bytes32,bytes,uint256),bytes32,(bytes32[]))))` and selector `0x0ecd990e`. ```solidity function blameIllAnnounced(PodECDSA.CertifiedLog memory certifiedLog) external; ```*/ @@ -4249,7 +3880,7 @@ function blameIllAnnounced(PodECDSA.CertifiedLog memory certifiedLog) external; #[allow(missing_docs)] pub certifiedLog: ::RustType, } - ///Container type for the return parameters of the [`blameIllAnnounced(((address,bytes32[],bytes),uint256,((bytes32,bytes),bytes32,(bytes32[]))))`](blameIllAnnouncedCall) function. + ///Container type for the return parameters of the [`blameIllAnnounced(((address,bytes32[],bytes),uint256,((bytes32,bytes,uint256),bytes32,(bytes32[]))))`](blameIllAnnouncedCall) function. #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] #[derive(Clone)] pub struct blameIllAnnouncedReturn {} @@ -4347,8 +3978,8 @@ function blameIllAnnounced(PodECDSA.CertifiedLog memory certifiedLog) external; type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; - const SIGNATURE: &'static str = "blameIllAnnounced(((address,bytes32[],bytes),uint256,((bytes32,bytes),bytes32,(bytes32[]))))"; - const SELECTOR: [u8; 4] = [242u8, 87u8, 181u8, 171u8]; + const SIGNATURE: &'static str = "blameIllAnnounced(((address,bytes32[],bytes),uint256,((bytes32,bytes,uint256),bytes32,(bytes32[]))))"; + const SELECTOR: [u8; 4] = [14u8, 205u8, 153u8, 14u8]; #[inline] fn new<'a>( tuple: as alloy_sol_types::SolType>::RustType, @@ -4387,7 +4018,7 @@ function blameIllAnnounced(PodECDSA.CertifiedLog memory certifiedLog) external; }; #[derive(serde::Serialize, serde::Deserialize)] #[derive()] - /**Function with signature `blameNoShow(((address,bytes32[],bytes),uint256,((bytes32,bytes),bytes32,(bytes32[]))))` and selector `0x80814a88`. + /**Function with signature `blameNoShow(((address,bytes32[],bytes),uint256,((bytes32,bytes,uint256),bytes32,(bytes32[]))))` and selector `0x9a62c2a3`. ```solidity function blameNoShow(PodECDSA.CertifiedLog memory certifiedLog) external; ```*/ @@ -4397,7 +4028,7 @@ function blameNoShow(PodECDSA.CertifiedLog memory certifiedLog) external; #[allow(missing_docs)] pub certifiedLog: ::RustType, } - ///Container type for the return parameters of the [`blameNoShow(((address,bytes32[],bytes),uint256,((bytes32,bytes),bytes32,(bytes32[]))))`](blameNoShowCall) function. + ///Container type for the return parameters of the [`blameNoShow(((address,bytes32[],bytes),uint256,((bytes32,bytes,uint256),bytes32,(bytes32[]))))`](blameNoShowCall) function. #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] #[derive(Clone)] pub struct blameNoShowReturn {} @@ -4491,8 +4122,8 @@ function blameNoShow(PodECDSA.CertifiedLog memory certifiedLog) external; type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; - const SIGNATURE: &'static str = "blameNoShow(((address,bytes32[],bytes),uint256,((bytes32,bytes),bytes32,(bytes32[]))))"; - const SELECTOR: [u8; 4] = [128u8, 129u8, 74u8, 136u8]; + const SIGNATURE: &'static str = "blameNoShow(((address,bytes32[],bytes),uint256,((bytes32,bytes,uint256),bytes32,(bytes32[]))))"; + const SELECTOR: [u8; 4] = [154u8, 98u8, 194u8, 163u8]; #[inline] fn new<'a>( tuple: as alloy_sol_types::SolType>::RustType, @@ -5244,9 +4875,9 @@ function podRegistry() external view returns (address); }; #[derive(serde::Serialize, serde::Deserialize)] #[derive(Default, Debug, PartialEq, Eq, Hash)] - /**Function with signature `read(uint256,uint64)` and selector `0x46336cd3`. + /**Function with signature `read(uint256,uint256)` and selector `0x75080997`. ```solidity -function read(uint256 auctionId, Time.Timestamp deadline) external view returns (State memory); +function read(uint256 auctionId, uint256 deadline) external view returns (State memory); ```*/ #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] #[derive(Clone)] @@ -5254,11 +4885,11 @@ function read(uint256 auctionId, Time.Timestamp deadline) external view returns #[allow(missing_docs)] pub auctionId: alloy::sol_types::private::primitives::aliases::U256, #[allow(missing_docs)] - pub deadline: ::RustType, + pub deadline: alloy::sol_types::private::primitives::aliases::U256, } #[derive(serde::Serialize, serde::Deserialize)] #[derive(Default, Debug, PartialEq, Eq, Hash)] - ///Container type for the return parameters of the [`read(uint256,uint64)`](readCall) function. + ///Container type for the return parameters of the [`read(uint256,uint256)`](readCall) function. #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] #[derive(Clone)] pub struct readReturn { @@ -5277,12 +4908,12 @@ function read(uint256 auctionId, Time.Timestamp deadline) external view returns #[doc(hidden)] type UnderlyingSolTuple<'a> = ( alloy::sol_types::sol_data::Uint<256>, - Time::Timestamp, + alloy::sol_types::sol_data::Uint<256>, ); #[doc(hidden)] type UnderlyingRustTuple<'a> = ( alloy::sol_types::private::primitives::aliases::U256, - ::RustType, + alloy::sol_types::private::primitives::aliases::U256, ); #[cfg(test)] #[allow(dead_code, unreachable_patterns)] @@ -5350,7 +4981,7 @@ function read(uint256 auctionId, Time.Timestamp deadline) external view returns impl alloy_sol_types::SolCall for readCall { type Parameters<'a> = ( alloy::sol_types::sol_data::Uint<256>, - Time::Timestamp, + alloy::sol_types::sol_data::Uint<256>, ); type Token<'a> = = as alloy_sol_types::SolType>::Token<'a>; - const SIGNATURE: &'static str = "read(uint256,uint64)"; - const SELECTOR: [u8; 4] = [70u8, 51u8, 108u8, 211u8]; + const SIGNATURE: &'static str = "read(uint256,uint256)"; + const SELECTOR: [u8; 4] = [117u8, 8u8, 9u8, 151u8]; #[inline] fn new<'a>( tuple: as alloy_sol_types::SolType>::RustType, @@ -5374,9 +5005,9 @@ function read(uint256 auctionId, Time.Timestamp deadline) external view returns as alloy_sol_types::SolType>::tokenize(&self.auctionId), - ::tokenize( - &self.deadline, - ), + as alloy_sol_types::SolType>::tokenize(&self.deadline), ) } #[inline] @@ -6119,7 +5750,7 @@ function withdraw() external; }; #[derive(serde::Serialize, serde::Deserialize)] #[derive()] - /**Function with signature `write(((address,bytes32[],bytes),uint256,((bytes32,bytes),bytes32,(bytes32[]))))` and selector `0x061a70ab`. + /**Function with signature `write(((address,bytes32[],bytes),uint256,((bytes32,bytes,uint256),bytes32,(bytes32[]))))` and selector `0x52070195`. ```solidity function write(PodECDSA.CertifiedLog memory certifiedLog) external; ```*/ @@ -6129,7 +5760,7 @@ function write(PodECDSA.CertifiedLog memory certifiedLog) external; #[allow(missing_docs)] pub certifiedLog: ::RustType, } - ///Container type for the return parameters of the [`write(((address,bytes32[],bytes),uint256,((bytes32,bytes),bytes32,(bytes32[]))))`](writeCall) function. + ///Container type for the return parameters of the [`write(((address,bytes32[],bytes),uint256,((bytes32,bytes,uint256),bytes32,(bytes32[]))))`](writeCall) function. #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] #[derive(Clone)] pub struct writeReturn {} @@ -6223,8 +5854,8 @@ function write(PodECDSA.CertifiedLog memory certifiedLog) external; type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; - const SIGNATURE: &'static str = "write(((address,bytes32[],bytes),uint256,((bytes32,bytes),bytes32,(bytes32[]))))"; - const SELECTOR: [u8; 4] = [6u8, 26u8, 112u8, 171u8]; + const SIGNATURE: &'static str = "write(((address,bytes32[],bytes),uint256,((bytes32,bytes,uint256),bytes32,(bytes32[]))))"; + const SELECTOR: [u8; 4] = [82u8, 7u8, 1u8, 149u8]; #[inline] fn new<'a>( tuple: as alloy_sol_types::SolType>::RustType, @@ -6307,21 +5938,21 @@ function write(PodECDSA.CertifiedLog memory certifiedLog) external; /// /// Prefer using `SolInterface` methods instead. pub const SELECTORS: &'static [[u8; 4usize]] = &[ - [6u8, 26u8, 112u8, 171u8], + [14u8, 205u8, 153u8, 14u8], [38u8, 136u8, 69u8, 74u8], [56u8, 114u8, 51u8, 236u8], [60u8, 207u8, 214u8, 11u8], - [70u8, 51u8, 108u8, 211u8], [74u8, 165u8, 232u8, 133u8], + [82u8, 7u8, 1u8, 149u8], [93u8, 246u8, 166u8, 188u8], [97u8, 213u8, 133u8, 218u8], [100u8, 201u8, 236u8, 111u8], [113u8, 80u8, 24u8, 166u8], - [128u8, 129u8, 74u8, 136u8], + [117u8, 8u8, 9u8, 151u8], [128u8, 243u8, 35u8, 167u8], [141u8, 165u8, 203u8, 91u8], + [154u8, 98u8, 194u8, 163u8], [233u8, 117u8, 27u8, 55u8], - [242u8, 87u8, 181u8, 171u8], [242u8, 253u8, 227u8, 139u8], ]; } @@ -6383,13 +6014,15 @@ function write(PodECDSA.CertifiedLog memory certifiedLog) external; &[u8], ) -> alloy_sol_types::Result] = &[ { - fn write( + fn blameIllAnnounced( data: &[u8], ) -> alloy_sol_types::Result { - ::abi_decode_raw(data) - .map(PodAuctionConsumerCalls::write) + ::abi_decode_raw( + data, + ) + .map(PodAuctionConsumerCalls::blameIllAnnounced) } - write + blameIllAnnounced }, { fn U( @@ -6421,22 +6054,22 @@ function write(PodECDSA.CertifiedLog memory certifiedLog) external; withdraw }, { - fn read( + fn isBonded( data: &[u8], ) -> alloy_sol_types::Result { - ::abi_decode_raw(data) - .map(PodAuctionConsumerCalls::read) + ::abi_decode_raw(data) + .map(PodAuctionConsumerCalls::isBonded) } - read + isBonded }, { - fn isBonded( + fn write( data: &[u8], ) -> alloy_sol_types::Result { - ::abi_decode_raw(data) - .map(PodAuctionConsumerCalls::isBonded) + ::abi_decode_raw(data) + .map(PodAuctionConsumerCalls::write) } - isBonded + write }, { fn unbond( @@ -6477,15 +6110,13 @@ function write(PodECDSA.CertifiedLog memory certifiedLog) external; renounceOwnership }, { - fn blameNoShow( + fn read( data: &[u8], ) -> alloy_sol_types::Result { - ::abi_decode_raw( - data, - ) - .map(PodAuctionConsumerCalls::blameNoShow) + ::abi_decode_raw(data) + .map(PodAuctionConsumerCalls::read) } - blameNoShow + read }, { fn bondAmount( @@ -6508,26 +6139,26 @@ function write(PodECDSA.CertifiedLog memory certifiedLog) external; owner }, { - fn LOG_TOPIC_0( + fn blameNoShow( data: &[u8], ) -> alloy_sol_types::Result { - ::abi_decode_raw( + ::abi_decode_raw( data, ) - .map(PodAuctionConsumerCalls::LOG_TOPIC_0) + .map(PodAuctionConsumerCalls::blameNoShow) } - LOG_TOPIC_0 + blameNoShow }, { - fn blameIllAnnounced( + fn LOG_TOPIC_0( data: &[u8], ) -> alloy_sol_types::Result { - ::abi_decode_raw( + ::abi_decode_raw( data, ) - .map(PodAuctionConsumerCalls::blameIllAnnounced) + .map(PodAuctionConsumerCalls::LOG_TOPIC_0) } - blameIllAnnounced + LOG_TOPIC_0 }, { fn transferOwnership( @@ -6561,15 +6192,15 @@ function write(PodECDSA.CertifiedLog memory certifiedLog) external; &[u8], ) -> alloy_sol_types::Result] = &[ { - fn write( + fn blameIllAnnounced( data: &[u8], ) -> alloy_sol_types::Result { - ::abi_decode_raw_validate( + ::abi_decode_raw_validate( data, ) - .map(PodAuctionConsumerCalls::write) + .map(PodAuctionConsumerCalls::blameIllAnnounced) } - write + blameIllAnnounced }, { fn U( @@ -6605,26 +6236,26 @@ function write(PodECDSA.CertifiedLog memory certifiedLog) external; withdraw }, { - fn read( + fn isBonded( data: &[u8], ) -> alloy_sol_types::Result { - ::abi_decode_raw_validate( + ::abi_decode_raw_validate( data, ) - .map(PodAuctionConsumerCalls::read) + .map(PodAuctionConsumerCalls::isBonded) } - read + isBonded }, { - fn isBonded( + fn write( data: &[u8], ) -> alloy_sol_types::Result { - ::abi_decode_raw_validate( + ::abi_decode_raw_validate( data, ) - .map(PodAuctionConsumerCalls::isBonded) + .map(PodAuctionConsumerCalls::write) } - isBonded + write }, { fn unbond( @@ -6671,15 +6302,15 @@ function write(PodECDSA.CertifiedLog memory certifiedLog) external; renounceOwnership }, { - fn blameNoShow( + fn read( data: &[u8], ) -> alloy_sol_types::Result { - ::abi_decode_raw_validate( + ::abi_decode_raw_validate( data, ) - .map(PodAuctionConsumerCalls::blameNoShow) + .map(PodAuctionConsumerCalls::read) } - blameNoShow + read }, { fn bondAmount( @@ -6704,26 +6335,26 @@ function write(PodECDSA.CertifiedLog memory certifiedLog) external; owner }, { - fn LOG_TOPIC_0( + fn blameNoShow( data: &[u8], ) -> alloy_sol_types::Result { - ::abi_decode_raw_validate( + ::abi_decode_raw_validate( data, ) - .map(PodAuctionConsumerCalls::LOG_TOPIC_0) + .map(PodAuctionConsumerCalls::blameNoShow) } - LOG_TOPIC_0 + blameNoShow }, { - fn blameIllAnnounced( + fn LOG_TOPIC_0( data: &[u8], ) -> alloy_sol_types::Result { - ::abi_decode_raw_validate( + ::abi_decode_raw_validate( data, ) - .map(PodAuctionConsumerCalls::blameIllAnnounced) + .map(PodAuctionConsumerCalls::LOG_TOPIC_0) } - blameIllAnnounced + LOG_TOPIC_0 }, { fn transferOwnership( @@ -7067,8 +6698,6 @@ function write(PodECDSA.CertifiedLog memory certifiedLog) external; #[allow(missing_docs)] Bonded(Bonded), #[allow(missing_docs)] - Log(Log), - #[allow(missing_docs)] OwnershipTransferred(OwnershipTransferred), #[allow(missing_docs)] Slashed(Slashed), @@ -7109,11 +6738,6 @@ function write(PodECDSA.CertifiedLog memory certifiedLog) external; 197u8, 124u8, 99u8, 111u8, 250u8, 86u8, 198u8, 182u8, 103u8, 154u8, 14u8, 47u8, 181u8, 104u8, 155u8, 79u8, 149u8, 230u8, 90u8, 105u8, 70u8, ], - [ - 155u8, 23u8, 213u8, 69u8, 192u8, 254u8, 102u8, 168u8, 173u8, 96u8, 98u8, - 204u8, 116u8, 116u8, 41u8, 143u8, 64u8, 167u8, 234u8, 75u8, 96u8, 18u8, - 103u8, 64u8, 109u8, 121u8, 116u8, 149u8, 19u8, 49u8, 28u8, 149u8, - ], [ 239u8, 75u8, 17u8, 44u8, 221u8, 205u8, 183u8, 59u8, 194u8, 254u8, 103u8, 77u8, 46u8, 43u8, 55u8, 168u8, 126u8, 234u8, 110u8, 146u8, 77u8, 135u8, @@ -7124,7 +6748,7 @@ function write(PodECDSA.CertifiedLog memory certifiedLog) external; #[automatically_derived] impl alloy_sol_types::SolEventInterface for PodAuctionConsumerEvents { const NAME: &'static str = "PodAuctionConsumerEvents"; - const COUNT: usize = 7usize; + const COUNT: usize = 6usize; fn decode_raw_log( topics: &[alloy_sol_types::Word], data: &[u8], @@ -7148,10 +6772,6 @@ function write(PodECDSA.CertifiedLog memory certifiedLog) external; ::decode_raw_log(topics, data) .map(Self::Bonded) } - Some(::SIGNATURE_HASH) => { - ::decode_raw_log(topics, data) - .map(Self::Log) - } Some( ::SIGNATURE_HASH, ) => { @@ -7196,9 +6816,6 @@ function write(PodECDSA.CertifiedLog memory certifiedLog) external; Self::Bonded(inner) => { alloy_sol_types::private::IntoLogData::to_log_data(inner) } - Self::Log(inner) => { - alloy_sol_types::private::IntoLogData::to_log_data(inner) - } Self::OwnershipTransferred(inner) => { alloy_sol_types::private::IntoLogData::to_log_data(inner) } @@ -7221,9 +6838,6 @@ function write(PodECDSA.CertifiedLog memory certifiedLog) external; Self::Bonded(inner) => { alloy_sol_types::private::IntoLogData::into_log_data(inner) } - Self::Log(inner) => { - alloy_sol_types::private::IntoLogData::into_log_data(inner) - } Self::OwnershipTransferred(inner) => { alloy_sol_types::private::IntoLogData::into_log_data(inner) } @@ -7401,7 +7015,7 @@ See the [wrapper's documentation](`PodAuctionConsumerInstance`) for more details pub fn read( &self, auctionId: alloy::sol_types::private::primitives::aliases::U256, - deadline: ::RustType, + deadline: alloy::sol_types::private::primitives::aliases::U256, ) -> alloy_contract::SolCallBuilder<&P, readCall, N> { self.call_builder(&readCall { auctionId, deadline }) } @@ -7468,10 +7082,6 @@ See the [wrapper's documentation](`PodAuctionConsumerInstance`) for more details pub fn Bonded_filter(&self) -> alloy_contract::Event<&P, Bonded, N> { self.event_filter::() } - ///Creates a new event filter for the [`Log`] event. - pub fn Log_filter(&self) -> alloy_contract::Event<&P, Log, N> { - self.event_filter::() - } ///Creates a new event filter for the [`OwnershipTransferred`] event. pub fn OwnershipTransferred_filter( &self, diff --git a/examples/optimistic-auction/contracts/PodAuctionConsumer.sol b/examples/optimistic-auction/contracts/PodAuctionConsumer.sol index 21f5aa77..f01d7af2 100644 --- a/examples/optimistic-auction/contracts/PodAuctionConsumer.sol +++ b/examples/optimistic-auction/contracts/PodAuctionConsumer.sol @@ -5,16 +5,11 @@ import {PodECDSA} from "pod-sdk/verifier/PodECDSA.sol"; import {MerkleTree} from "pod-sdk/verifier/MerkleTree.sol"; import {IPodRegistry} from "pod-sdk/verifier/PodRegistry.sol"; import {AbsBonding} from "./AbsBonding.sol"; -import {requireTimeBefore, requireTimeAtLeast, Time} from "pod-sdk/Time.sol"; contract PodAuctionConsumer is AbsBonding { - using Time for Time.Timestamp; - - uint64 public constant U = 10 minutes; // Waiting period for announcement or blaming + uint256 public constant U = 10 minutes; // Waiting period for announcement or blaming bytes32 public constant LOG_TOPIC_0 = 0xfa9544cad94ab8507946215078af54be3ed0a1f19911d5dab2037baf8e064fb0; - event Log(string message, Time.Timestamp value); - struct Bid { address bidder; uint256 bid; @@ -42,40 +37,40 @@ contract PodAuctionConsumer is AbsBonding { } /** - * @notice deadline in microseconds + * @notice deadline in seconds */ - function getUniqueAuctionId(uint256 auctionId, Time.Timestamp deadline) internal pure returns (bytes32) { + function getUniqueAuctionId(uint256 auctionId, uint256 deadline) internal pure returns (bytes32) { return keccak256(abi.encodePacked(auctionId, deadline)); } /** - * @notice deadline in microseconds + * @notice deadline in seconds */ function decodeBid(PodECDSA.Log calldata log) internal pure - returns (uint256 auctionId, address bidder, Time.Timestamp deadline, uint256 bid) + returns (uint256 auctionId, address bidder, uint256 deadline, uint256 bid) { require(log.topics.length == 4, "Invalid log"); require(log.topics[0] == LOG_TOPIC_0, "Invalid log topic"); auctionId = uint256(log.topics[1]); bidder = address(uint160(uint256(log.topics[2]))); - deadline = Time.fromMicros(uint64(uint256(log.topics[3]))); + deadline = uint256(log.topics[3]); bid = abi.decode(log.data, (uint256)); } function write(PodECDSA.CertifiedLog calldata certifiedLog) external validLog(certifiedLog.log) onlyBonded { - (uint256 auctionId, address bidder, Time.Timestamp deadline, uint256 bid) = decodeBid(certifiedLog.log); + (uint256 auctionId, address bidder, uint256 deadline, uint256 bid) = decodeBid(certifiedLog.log); bytes32 uniqueAuctionId = getUniqueAuctionId(auctionId, deadline); State storage s = state[uniqueAuctionId]; - requireTimeAtLeast(deadline, "Writing period has not started"); - requireTimeBefore(deadline.addSeconds(U), "Writing period ended"); + require(block.timestamp >= deadline, "Writing period has not started"); + require(block.timestamp < deadline + U, "Writing period ended"); require(s.winner.bid == 0, "Bid already exists"); require(msg.sender == bidder, "Invalid caller"); - uint256 f = podRegistry.getFaultTolerance(); - bool verified = - PodECDSA.verifyCertifiedLog(PodECDSA.PodConfig({quorum: 2 * f + 1, registry: podRegistry}), certifiedLog); + bool verified = PodECDSA.verifyCertifiedLog( + PodECDSA.PodConfig({thresholdNumerator: 2, thresholdDenominator: 3, registry: podRegistry}), certifiedLog + ); require(verified, "Invalid proof or quorum not reached"); s.winner.bidder = bidder; @@ -87,9 +82,9 @@ contract PodAuctionConsumer is AbsBonding { /** * @notice deadline in microseconds */ - function read(uint256 auctionId, Time.Timestamp deadline) external view returns (State memory) { + function read(uint256 auctionId, uint256 deadline) external view returns (State memory) { bytes32 uniqueAuctionId = getUniqueAuctionId(auctionId, deadline); - requireTimeAtLeast(deadline.addSeconds(2 * U), "Dispute period NOT ended"); + require(block.timestamp >= deadline + 2 * U, "Dispute period NOT ended"); return state[uniqueAuctionId]; } @@ -98,17 +93,15 @@ contract PodAuctionConsumer is AbsBonding { validLog(certifiedLog.log) onlyBonded { - (uint256 auctionId, address bidder, Time.Timestamp deadline, uint256 bid) = decodeBid(certifiedLog.log); + (uint256 auctionId, address bidder, uint256 deadline, uint256 bid) = decodeBid(certifiedLog.log); bytes32 uniqueAuctionId = getUniqueAuctionId(auctionId, deadline); State storage s = state[uniqueAuctionId]; require(s.winner.bid != 0, "Bid not written"); - emit Log("Contract log deadline", deadline); - emit Log("Contract log deadline + 2U", deadline.addSeconds(2 * U)); - requireTimeBefore(deadline.addSeconds(2 * U), "Dispute period ended"); + require(block.timestamp < deadline + 2 * U, "Dispute period ended"); - uint256 f = podRegistry.getFaultTolerance(); - bool verified = - PodECDSA.verifyCertifiedLog(PodECDSA.PodConfig({quorum: 2 * f + 1, registry: podRegistry}), certifiedLog); + bool verified = PodECDSA.verifyCertifiedLog( + PodECDSA.PodConfig({thresholdNumerator: 2, thresholdDenominator: 3, registry: podRegistry}), certifiedLog + ); require(verified, "Invalid proof or quorum not reached"); s.blamed.bid = s.winner.bid; @@ -122,18 +115,18 @@ contract PodAuctionConsumer is AbsBonding { } function blameNoShow(PodECDSA.CertifiedLog calldata certifiedLog) external validLog(certifiedLog.log) onlyBonded { - (uint256 auctionId, address bidder, Time.Timestamp deadline, uint256 bid) = decodeBid(certifiedLog.log); + (uint256 auctionId, address bidder, uint256 deadline, uint256 bid) = decodeBid(certifiedLog.log); bytes32 uniqueAuctionId = getUniqueAuctionId(auctionId, deadline); State storage s = state[uniqueAuctionId]; require(s.winner.bid == 0, "Bid already exists"); - requireTimeAtLeast(deadline.addSeconds(U), "Still in waiting period"); - requireTimeBefore(deadline.addSeconds(2 * U), "Dispute period ended"); + require(block.timestamp >= deadline + U, "Still in waiting period"); + require(block.timestamp < deadline + 2 * U, "Dispute period ended"); require(s.blamed.bid < bid, "Invalid blamed bid"); - uint256 f = podRegistry.getFaultTolerance(); - bool verified = - PodECDSA.verifyCertifiedLog(PodECDSA.PodConfig({quorum: f + 1, registry: podRegistry}), certifiedLog); + bool verified = PodECDSA.verifyCertifiedLog( + PodECDSA.PodConfig({thresholdNumerator: 1, thresholdDenominator: 3, registry: podRegistry}), certifiedLog + ); require(verified, "Invalid proof or quorum not reached"); s.blamed.bid = bid; diff --git a/examples/optimistic-auction/test/PodAuctionConsumer.t.sol b/examples/optimistic-auction/test/PodAuctionConsumer.t.sol index c80902e2..f16eeeda 100644 --- a/examples/optimistic-auction/test/PodAuctionConsumer.t.sol +++ b/examples/optimistic-auction/test/PodAuctionConsumer.t.sol @@ -1,16 +1,15 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.20; -import {PodTest} from "pod-sdk/test/podTest.sol"; +import {Test} from "forge-std/Test.sol"; import {PodECDSA, ECDSA} from "pod-sdk/verifier/PodECDSA.sol"; import {MerkleTree} from "pod-sdk/verifier/MerkleTree.sol"; import {PodRegistry} from "pod-sdk/verifier/PodRegistry.sol"; import {PodAuctionConsumer} from "../contracts/PodAuctionConsumer.sol"; -import {Time} from "pod-sdk/Time.sol"; - -contract PodAuctionConsumerTest is PodTest { - using Time for Time.Timestamp; +import {console} from "forge-std/console.sol"; +import {Math} from "openzeppelin-contracts/utils/math/Math.sol"; +contract PodAuctionConsumerTest is Test { PodAuctionConsumer consumer; PodRegistry podRegistry; @@ -18,26 +17,34 @@ contract PodAuctionConsumerTest is PodTest { address constant OWNER = address(0x123abc); uint256 constant AUCTION_ID = 1; - uint64 constant DEADLINE = 3485693721; + uint256 constant DEADLINE = 3485693721; address constant SMALLER_BIDDER = 0x13791790Bef192d14712D627f13A55c4ABEe52a4; address constant HIGHER_BIDDER = 0xb8AA43999C2b3Cbb10FbE2092432f98D8F35Dcd7; address constant BONDED_ADDRESS = address(0x123def); - uint64 constant U = 10 minutes * Time.MICROSECONDS_PER_SECOND; + uint256 constant U = 10 minutes; uint256 constant NUMBER_OF_VALIDATORS = 128; - uint256 constant F = NUMBER_OF_VALIDATORS / 3; + + function getRequiredSigs(uint256 thresholdNumerator, uint256 thresholdDenominator, Math.Rounding rounding) + internal + pure + returns (uint256) + { + return Math.mulDiv(thresholdNumerator, NUMBER_OF_VALIDATORS, thresholdDenominator, rounding); + } function setUp() public { - vm.prank(OWNER); - podRegistry = new PodRegistry(new address[](0)); + address[] memory initialValidators = new address[](NUMBER_OF_VALIDATORS); validatorPrivateKeys = new uint256[](NUMBER_OF_VALIDATORS); for (uint256 i = 0; i < NUMBER_OF_VALIDATORS; i++) { validatorPrivateKeys[i] = uint256(i + 1); - vm.prank(OWNER); - podRegistry.addValidator(vm.addr(validatorPrivateKeys[i])); + initialValidators[i] = vm.addr(validatorPrivateKeys[i]); } + vm.prank(OWNER); + podRegistry = new PodRegistry(initialValidators); + consumer = new PodAuctionConsumer(address(podRegistry), 1 ether); vm.deal(SMALLER_BIDDER, 2 ether); vm.deal(HIGHER_BIDDER, 2 ether); @@ -49,36 +56,34 @@ contract PodAuctionConsumerTest is PodTest { vm.prank(BONDED_ADDRESS); consumer.bond{value: 1 ether}(); - podWarp(Time.fromMicros(DEADLINE)); - podMockQuorum(); - } - - function tearDown() public { - vm.clearMockedCalls(); + vm.warp(DEADLINE); } function test_Write_Success() public { - PodECDSA.CertifiedLog memory certifiedLog = createCertifiedLog(2 * F + 1, true); + uint256 requiredSigs = getRequiredSigs(2, 3, Math.Rounding.Ceil); + PodECDSA.CertifiedLog memory certifiedLog = createCertifiedLog(requiredSigs, true); vm.prank(SMALLER_BIDDER); consumer.write(certifiedLog); - podWarp(Time.currentTime().addMicros(2 * U)); + vm.warp(block.timestamp + 2 * U); + PodAuctionConsumer.State memory state = consumer.read(AUCTION_ID, DEADLINE); - PodAuctionConsumer.State memory state = consumer.read(AUCTION_ID, Time.fromMicros(DEADLINE)); assertEq(state.winner.bid, 100); assertEq(state.winner.bidder, SMALLER_BIDDER); } function test_Write_Fail_BidderNotBonded() public { vm.prank(makeAddr("not_bonded")); - PodECDSA.CertifiedLog memory certifiedLog = createCertifiedLog(2 * F + 1, true); + uint256 requiredSigs = getRequiredSigs(2, 3, Math.Rounding.Ceil); + PodECDSA.CertifiedLog memory certifiedLog = createCertifiedLog(requiredSigs, true); vm.expectRevert("Not bonded"); consumer.write(certifiedLog); } function test_Write_Fail_BidderNotWriter() public { - PodECDSA.CertifiedLog memory certifiedLog = createCertifiedLog(2 * F + 1, true); + uint256 requiredSigs = getRequiredSigs(2, 3, Math.Rounding.Ceil); + PodECDSA.CertifiedLog memory certifiedLog = createCertifiedLog(requiredSigs, true); vm.prank(BONDED_ADDRESS); vm.expectRevert("Invalid caller"); @@ -86,12 +91,14 @@ contract PodAuctionConsumerTest is PodTest { } function test_Write_Fail_BidAlreadyWritten() public { - PodECDSA.CertifiedLog memory certifiedLogSmallerBid = createCertifiedLog(2 * F + 1, true); + uint256 requiredSigs = getRequiredSigs(2, 3, Math.Rounding.Ceil); + PodECDSA.CertifiedLog memory certifiedLogSmallerBid = createCertifiedLog(requiredSigs, true); vm.prank(SMALLER_BIDDER); consumer.write(certifiedLogSmallerBid); - PodECDSA.CertifiedLog memory certifiedLogHigherBid = createCertifiedLog(2 * F + 1, false); + requiredSigs = getRequiredSigs(2, 3, Math.Rounding.Ceil); + PodECDSA.CertifiedLog memory certifiedLogHigherBid = createCertifiedLog(requiredSigs, false); vm.prank(HIGHER_BIDDER); vm.expectRevert("Bid already exists"); @@ -99,9 +106,10 @@ contract PodAuctionConsumerTest is PodTest { } function test_Write_Fail_WritingPeriodEnded() public { - PodECDSA.CertifiedLog memory certifiedLog = createCertifiedLog(2 * F + 1, true); + uint256 requiredSigs = getRequiredSigs(2, 3, Math.Rounding.Ceil); + PodECDSA.CertifiedLog memory certifiedLog = createCertifiedLog(requiredSigs, true); - podWarp(Time.currentTime().addMicros(U + 1 seconds * Time.MICROSECONDS_PER_SECOND)); + vm.warp(block.timestamp + U + 1 seconds); vm.prank(SMALLER_BIDDER); vm.expectRevert("Writing period ended"); @@ -109,27 +117,30 @@ contract PodAuctionConsumerTest is PodTest { } function test_Write_Fail_InvalidCommittee() public { - PodECDSA.CertifiedLog memory certifiedLog = createCertifiedLog(2 * F, true); + uint256 requiredSigs = getRequiredSigs(2, 3, Math.Rounding.Floor); + console.log("requiredSigs", requiredSigs); + PodECDSA.CertifiedLog memory certifiedLog = createCertifiedLog(requiredSigs, true); vm.expectRevert("Invalid proof or quorum not reached"); vm.prank(SMALLER_BIDDER); consumer.write(certifiedLog); } function test_BlameIllAnnounced_Success() public { - PodECDSA.CertifiedLog memory certifiedLogSmallerBid = createCertifiedLog(2 * F + 1, true); + uint256 requiredSigs = getRequiredSigs(2, 3, Math.Rounding.Ceil); + PodECDSA.CertifiedLog memory certifiedLogSmallerBid = createCertifiedLog(requiredSigs, true); vm.prank(SMALLER_BIDDER); consumer.write(certifiedLogSmallerBid); - PodECDSA.CertifiedLog memory certifiedLogHigherBid = createCertifiedLog(2 * F + 1, false); + requiredSigs = getRequiredSigs(2, 3, Math.Rounding.Ceil); + PodECDSA.CertifiedLog memory certifiedLogHigherBid = createCertifiedLog(requiredSigs, false); assert(consumer.isBonded(SMALLER_BIDDER)); vm.prank(HIGHER_BIDDER); consumer.blameIllAnnounced(certifiedLogHigherBid); - podWarp(Time.currentTime().addMicros(2 * U)); - - PodAuctionConsumer.State memory state = consumer.read(AUCTION_ID, Time.fromMicros(DEADLINE)); + vm.warp(block.timestamp + 2 * U); + PodAuctionConsumer.State memory state = consumer.read(AUCTION_ID, DEADLINE); assertEq(state.winner.bid, 1000); assertEq(state.winner.bidder, HIGHER_BIDDER); assertEq(state.blamed.bid, 100); @@ -138,7 +149,8 @@ contract PodAuctionConsumerTest is PodTest { } function test_BlameIllAnnounced_Fail_BidNotWritten() public { - PodECDSA.CertifiedLog memory certifiedLog = createCertifiedLog(2 * F + 1, true); + uint256 requiredSigs = getRequiredSigs(2, 3, Math.Rounding.Ceil); + PodECDSA.CertifiedLog memory certifiedLog = createCertifiedLog(requiredSigs, true); vm.prank(BONDED_ADDRESS); vm.expectRevert("Bid not written"); @@ -146,14 +158,16 @@ contract PodAuctionConsumerTest is PodTest { } function test_BlameIllAnnounced_Fail_DisputePeriodEnded() public { - PodECDSA.CertifiedLog memory certifiedLogSmallerBid = createCertifiedLog(2 * F + 1, true); + uint256 requiredSigs = getRequiredSigs(2, 3, Math.Rounding.Ceil); + PodECDSA.CertifiedLog memory certifiedLogSmallerBid = createCertifiedLog(requiredSigs, true); vm.prank(SMALLER_BIDDER); consumer.write(certifiedLogSmallerBid); - podWarp(Time.currentTime().addMicros(2 * U)); + vm.warp(block.timestamp + 2 * U); - PodECDSA.CertifiedLog memory certifiedLogHigherBid = createCertifiedLog(2 * F + 1, false); + requiredSigs = getRequiredSigs(2, 3, Math.Rounding.Ceil); + PodECDSA.CertifiedLog memory certifiedLogHigherBid = createCertifiedLog(requiredSigs, false); vm.prank(BONDED_ADDRESS); vm.expectRevert("Dispute period ended"); @@ -161,12 +175,14 @@ contract PodAuctionConsumerTest is PodTest { } function test_BlameIllAnnounced_Fail_InvalidCommittee() public { - PodECDSA.CertifiedLog memory certifiedLog = createCertifiedLog(2 * F + 1, true); + uint256 requiredSigs = getRequiredSigs(2, 3, Math.Rounding.Ceil); + PodECDSA.CertifiedLog memory certifiedLog = createCertifiedLog(requiredSigs, true); vm.prank(SMALLER_BIDDER); consumer.write(certifiedLog); - PodECDSA.CertifiedLog memory certifiedLogHigherBid = createCertifiedLog(2 * F, false); + requiredSigs = getRequiredSigs(2, 3, Math.Rounding.Floor); + PodECDSA.CertifiedLog memory certifiedLogHigherBid = createCertifiedLog(requiredSigs, false); vm.prank(BONDED_ADDRESS); vm.expectRevert("Invalid proof or quorum not reached"); @@ -174,11 +190,13 @@ contract PodAuctionConsumerTest is PodTest { } function test_BlameNoShow_Success() public { - PodECDSA.CertifiedLog memory certifiedLogSmallerBid = createCertifiedLog(2 * F + 1, true); + uint256 requiredSigs = getRequiredSigs(2, 3, Math.Rounding.Ceil); + PodECDSA.CertifiedLog memory certifiedLogSmallerBid = createCertifiedLog(requiredSigs, true); - PodECDSA.CertifiedLog memory certifiedLogHigherBid = createCertifiedLog(F + 1, false); + requiredSigs = getRequiredSigs(1, 3, Math.Rounding.Ceil); + PodECDSA.CertifiedLog memory certifiedLogHigherBid = createCertifiedLog(requiredSigs, false); - podWarp(Time.currentTime().addMicros(U)); + vm.warp(block.timestamp + U); assert(consumer.isBonded(SMALLER_BIDDER)); @@ -187,9 +205,8 @@ contract PodAuctionConsumerTest is PodTest { vm.prank(BONDED_ADDRESS); consumer.blameNoShow(certifiedLogHigherBid); - podWarp(Time.currentTime().addMicros(2 * U)); - - PodAuctionConsumer.State memory state = consumer.read(AUCTION_ID, Time.fromMicros(DEADLINE)); + vm.warp(block.timestamp + U); + PodAuctionConsumer.State memory state = consumer.read(AUCTION_ID, DEADLINE); assertEq(state.winner.bid, 0); assertEq(state.winner.bidder, address(0)); assertEq(state.blamed.bid, 1000); @@ -198,9 +215,10 @@ contract PodAuctionConsumerTest is PodTest { } function test_BlameNoShow_Fail_InvalidCommittee() public { - PodECDSA.CertifiedLog memory certifiedLog = createCertifiedLog(F, true); + uint256 requiredSigs = getRequiredSigs(1, 3, Math.Rounding.Floor); + PodECDSA.CertifiedLog memory certifiedLog = createCertifiedLog(requiredSigs, true); - podWarp(Time.currentTime().addMicros(U)); + vm.warp(block.timestamp + U); vm.prank(BONDED_ADDRESS); vm.expectRevert("Invalid proof or quorum not reached"); @@ -208,14 +226,16 @@ contract PodAuctionConsumerTest is PodTest { } function test_BlameNoShow_Fail_BidAlreadyExists() public { - PodECDSA.CertifiedLog memory certifiedLogSmallerBid = createCertifiedLog(2 * F + 1, true); + uint256 requiredSigs = getRequiredSigs(2, 3, Math.Rounding.Ceil); + PodECDSA.CertifiedLog memory certifiedLogSmallerBid = createCertifiedLog(requiredSigs, true); vm.prank(SMALLER_BIDDER); consumer.write(certifiedLogSmallerBid); - podWarp(Time.currentTime().addMicros(U)); + vm.warp(block.timestamp + U); - PodECDSA.CertifiedLog memory certifiedLogHigherBid = createCertifiedLog(F + 1, false); + requiredSigs = getRequiredSigs(1, 3, Math.Rounding.Ceil); + PodECDSA.CertifiedLog memory certifiedLogHigherBid = createCertifiedLog(requiredSigs, false); vm.prank(BONDED_ADDRESS); vm.expectRevert("Bid already exists"); @@ -223,11 +243,12 @@ contract PodAuctionConsumerTest is PodTest { } function test_BlameNoShow_Fail_DisputePeriodEnded() public { - podWarp(Time.currentTime().addMicros(2 * U)); + vm.warp(block.timestamp + 2 * U); - PodECDSA.CertifiedLog memory certifiedLogHigherBid = createCertifiedLog(F + 1, false); + uint256 requiredSigs = getRequiredSigs(1, 3, Math.Rounding.Ceil); + PodECDSA.CertifiedLog memory certifiedLogHigherBid = createCertifiedLog(requiredSigs, false); - podWarp(Time.currentTime().addMicros(2 * U)); + vm.warp(block.timestamp + 2 * U); vm.prank(BONDED_ADDRESS); vm.expectRevert("Dispute period ended"); @@ -235,7 +256,8 @@ contract PodAuctionConsumerTest is PodTest { } function test_BlameNoShow_Fail_StillInWaitingPeriod() public { - PodECDSA.CertifiedLog memory certifiedLog = createCertifiedLog(F + 1, false); + uint256 requiredSigs = getRequiredSigs(1, 3, Math.Rounding.Ceil); + PodECDSA.CertifiedLog memory certifiedLog = createCertifiedLog(requiredSigs, false); vm.prank(BONDED_ADDRESS); vm.expectRevert("Still in waiting period"); @@ -243,11 +265,13 @@ contract PodAuctionConsumerTest is PodTest { } function test_BlameNoShow_Fail_InvalidBid() public { - PodECDSA.CertifiedLog memory certifiedLogHigherBid = createCertifiedLog(F + 1, false); + uint256 requiredSigs = getRequiredSigs(1, 3, Math.Rounding.Ceil); + + PodECDSA.CertifiedLog memory certifiedLogHigherBid = createCertifiedLog(requiredSigs, false); - PodECDSA.CertifiedLog memory certifiedLogSmallerBid = createCertifiedLog(F + 1, true); + PodECDSA.CertifiedLog memory certifiedLogSmallerBid = createCertifiedLog(requiredSigs, true); - podWarp(Time.currentTime().addMicros(U)); + vm.warp(block.timestamp + U); vm.prank(BONDED_ADDRESS); consumer.blameNoShow(certifiedLogHigherBid); @@ -277,8 +301,11 @@ contract PodAuctionConsumerTest is PodTest { bytes memory aggregateSignature = ECDSA.aggregate_signatures(signatures); - PodECDSA.CertifiedReceipt memory certifiedReceipt = - PodECDSA.CertifiedReceipt({receiptRoot: receiptRoot, aggregateSignature: aggregateSignature}); + PodECDSA.CertifiedReceipt memory certifiedReceipt = PodECDSA.CertifiedReceipt({ + receiptRoot: receiptRoot, + aggregateSignature: aggregateSignature, + medianTimestamp: 2 + }); PodECDSA.Log memory log = PodECDSA.Log({addr: 0x217F5658c6ecC27D439922263AD9Bb8e992e0373, topics: topics, data: data}); From a1ef89688a7fb2c3d6a32db13fc1401b15b0f381 Mon Sep 17 00:00:00 2001 From: Jakov Mitrovski Date: Fri, 15 Aug 2025 19:50:57 +0200 Subject: [PATCH 23/64] update optimistic-auction client --- examples/optimistic-auction/client/main.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/examples/optimistic-auction/client/main.rs b/examples/optimistic-auction/client/main.rs index dc90f53e..e58b5f5f 100644 --- a/examples/optimistic-auction/client/main.rs +++ b/examples/optimistic-auction/client/main.rs @@ -79,6 +79,7 @@ fn get_certified_log(log: &VerifiableLog) -> Result { certifiedReceipt: CertifiedReceipt { receiptRoot: log.pod_metadata.receipt.hash_custom(), aggregateSignature: log.aggregate_signatures().into(), + medianTimestamp: U256::from(log.inner.block_timestamp.unwrap()), }, leaf, proof: Proof { path: proof.path }, @@ -234,7 +235,7 @@ impl AuctionClient { // Ok(()) // } - pub async fn read_state(&self, auction_id: U256, deadline: u64) -> Result<()> { + pub async fn read_state(&self, auction_id: U256, deadline: U256) -> Result<()> { let state = self .consumer_contract .read(auction_id, deadline) @@ -414,7 +415,9 @@ async fn main() -> Result<()> { ) .await?; - auction_client_1.read_state(auction_id, deadline).await?; + auction_client_1 + .read_state(auction_id, U256::from(deadline)) + .await?; // TODO: uncomment if you wish to use, to use this, we need to comment the write + blame ill announced calls // let _ = auction_client_1.blame_no_show(certified_log1).await; From 55bf2ba268b21b8dfdcd7361b33e1ebd441c7e24 Mon Sep 17 00:00:00 2001 From: Jakov Mitrovski Date: Mon, 18 Aug 2025 14:22:31 +0200 Subject: [PATCH 24/64] refactor(optimistic-auction): rename and update constant usage --- .../contracts/PodAuctionConsumer.sol | 13 ++++++----- .../test/PodAuctionConsumer.t.sol | 23 +++++++++---------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/examples/optimistic-auction/contracts/PodAuctionConsumer.sol b/examples/optimistic-auction/contracts/PodAuctionConsumer.sol index f01d7af2..c4ceabf1 100644 --- a/examples/optimistic-auction/contracts/PodAuctionConsumer.sol +++ b/examples/optimistic-auction/contracts/PodAuctionConsumer.sol @@ -7,7 +7,8 @@ import {IPodRegistry} from "pod-sdk/verifier/PodRegistry.sol"; import {AbsBonding} from "./AbsBonding.sol"; contract PodAuctionConsumer is AbsBonding { - uint256 public constant U = 10 minutes; // Waiting period for announcement or blaming + uint256 public constant DISPUTE_PERIOD = 10 minutes; + uint256 public constant TWO_TIMES_DISPUTE_PERIOD = 2 * DISPUTE_PERIOD; bytes32 public constant LOG_TOPIC_0 = 0xfa9544cad94ab8507946215078af54be3ed0a1f19911d5dab2037baf8e064fb0; struct Bid { @@ -64,7 +65,7 @@ contract PodAuctionConsumer is AbsBonding { bytes32 uniqueAuctionId = getUniqueAuctionId(auctionId, deadline); State storage s = state[uniqueAuctionId]; require(block.timestamp >= deadline, "Writing period has not started"); - require(block.timestamp < deadline + U, "Writing period ended"); + require(block.timestamp < deadline + DISPUTE_PERIOD, "Writing period ended"); require(s.winner.bid == 0, "Bid already exists"); require(msg.sender == bidder, "Invalid caller"); @@ -84,7 +85,7 @@ contract PodAuctionConsumer is AbsBonding { */ function read(uint256 auctionId, uint256 deadline) external view returns (State memory) { bytes32 uniqueAuctionId = getUniqueAuctionId(auctionId, deadline); - require(block.timestamp >= deadline + 2 * U, "Dispute period NOT ended"); + require(block.timestamp >= deadline + TWO_TIMES_DISPUTE_PERIOD, "Dispute period NOT ended"); return state[uniqueAuctionId]; } @@ -97,7 +98,7 @@ contract PodAuctionConsumer is AbsBonding { bytes32 uniqueAuctionId = getUniqueAuctionId(auctionId, deadline); State storage s = state[uniqueAuctionId]; require(s.winner.bid != 0, "Bid not written"); - require(block.timestamp < deadline + 2 * U, "Dispute period ended"); + require(block.timestamp < deadline + TWO_TIMES_DISPUTE_PERIOD, "Dispute period ended"); bool verified = PodECDSA.verifyCertifiedLog( PodECDSA.PodConfig({thresholdNumerator: 2, thresholdDenominator: 3, registry: podRegistry}), certifiedLog @@ -120,8 +121,8 @@ contract PodAuctionConsumer is AbsBonding { State storage s = state[uniqueAuctionId]; require(s.winner.bid == 0, "Bid already exists"); - require(block.timestamp >= deadline + U, "Still in waiting period"); - require(block.timestamp < deadline + 2 * U, "Dispute period ended"); + require(block.timestamp >= deadline + DISPUTE_PERIOD, "Still in waiting period"); + require(block.timestamp < deadline + TWO_TIMES_DISPUTE_PERIOD, "Dispute period ended"); require(s.blamed.bid < bid, "Invalid blamed bid"); bool verified = PodECDSA.verifyCertifiedLog( diff --git a/examples/optimistic-auction/test/PodAuctionConsumer.t.sol b/examples/optimistic-auction/test/PodAuctionConsumer.t.sol index f16eeeda..491ab9c0 100644 --- a/examples/optimistic-auction/test/PodAuctionConsumer.t.sol +++ b/examples/optimistic-auction/test/PodAuctionConsumer.t.sol @@ -21,7 +21,6 @@ contract PodAuctionConsumerTest is Test { address constant SMALLER_BIDDER = 0x13791790Bef192d14712D627f13A55c4ABEe52a4; address constant HIGHER_BIDDER = 0xb8AA43999C2b3Cbb10FbE2092432f98D8F35Dcd7; address constant BONDED_ADDRESS = address(0x123def); - uint256 constant U = 10 minutes; uint256 constant NUMBER_OF_VALIDATORS = 128; function getRequiredSigs(uint256 thresholdNumerator, uint256 thresholdDenominator, Math.Rounding rounding) @@ -66,7 +65,7 @@ contract PodAuctionConsumerTest is Test { vm.prank(SMALLER_BIDDER); consumer.write(certifiedLog); - vm.warp(block.timestamp + 2 * U); + vm.warp(block.timestamp + consumer.TWO_TIMES_DISPUTE_PERIOD()); PodAuctionConsumer.State memory state = consumer.read(AUCTION_ID, DEADLINE); assertEq(state.winner.bid, 100); @@ -109,7 +108,7 @@ contract PodAuctionConsumerTest is Test { uint256 requiredSigs = getRequiredSigs(2, 3, Math.Rounding.Ceil); PodECDSA.CertifiedLog memory certifiedLog = createCertifiedLog(requiredSigs, true); - vm.warp(block.timestamp + U + 1 seconds); + vm.warp(block.timestamp + consumer.DISPUTE_PERIOD() + 1 seconds); vm.prank(SMALLER_BIDDER); vm.expectRevert("Writing period ended"); @@ -139,7 +138,7 @@ contract PodAuctionConsumerTest is Test { vm.prank(HIGHER_BIDDER); consumer.blameIllAnnounced(certifiedLogHigherBid); - vm.warp(block.timestamp + 2 * U); + vm.warp(block.timestamp + consumer.TWO_TIMES_DISPUTE_PERIOD()); PodAuctionConsumer.State memory state = consumer.read(AUCTION_ID, DEADLINE); assertEq(state.winner.bid, 1000); assertEq(state.winner.bidder, HIGHER_BIDDER); @@ -164,7 +163,7 @@ contract PodAuctionConsumerTest is Test { vm.prank(SMALLER_BIDDER); consumer.write(certifiedLogSmallerBid); - vm.warp(block.timestamp + 2 * U); + vm.warp(block.timestamp + consumer.TWO_TIMES_DISPUTE_PERIOD()); requiredSigs = getRequiredSigs(2, 3, Math.Rounding.Ceil); PodECDSA.CertifiedLog memory certifiedLogHigherBid = createCertifiedLog(requiredSigs, false); @@ -196,7 +195,7 @@ contract PodAuctionConsumerTest is Test { requiredSigs = getRequiredSigs(1, 3, Math.Rounding.Ceil); PodECDSA.CertifiedLog memory certifiedLogHigherBid = createCertifiedLog(requiredSigs, false); - vm.warp(block.timestamp + U); + vm.warp(block.timestamp + consumer.DISPUTE_PERIOD()); assert(consumer.isBonded(SMALLER_BIDDER)); @@ -205,7 +204,7 @@ contract PodAuctionConsumerTest is Test { vm.prank(BONDED_ADDRESS); consumer.blameNoShow(certifiedLogHigherBid); - vm.warp(block.timestamp + U); + vm.warp(block.timestamp + consumer.DISPUTE_PERIOD()); PodAuctionConsumer.State memory state = consumer.read(AUCTION_ID, DEADLINE); assertEq(state.winner.bid, 0); assertEq(state.winner.bidder, address(0)); @@ -218,7 +217,7 @@ contract PodAuctionConsumerTest is Test { uint256 requiredSigs = getRequiredSigs(1, 3, Math.Rounding.Floor); PodECDSA.CertifiedLog memory certifiedLog = createCertifiedLog(requiredSigs, true); - vm.warp(block.timestamp + U); + vm.warp(block.timestamp + consumer.DISPUTE_PERIOD()); vm.prank(BONDED_ADDRESS); vm.expectRevert("Invalid proof or quorum not reached"); @@ -232,7 +231,7 @@ contract PodAuctionConsumerTest is Test { vm.prank(SMALLER_BIDDER); consumer.write(certifiedLogSmallerBid); - vm.warp(block.timestamp + U); + vm.warp(block.timestamp + consumer.DISPUTE_PERIOD()); requiredSigs = getRequiredSigs(1, 3, Math.Rounding.Ceil); PodECDSA.CertifiedLog memory certifiedLogHigherBid = createCertifiedLog(requiredSigs, false); @@ -243,12 +242,12 @@ contract PodAuctionConsumerTest is Test { } function test_BlameNoShow_Fail_DisputePeriodEnded() public { - vm.warp(block.timestamp + 2 * U); + vm.warp(block.timestamp + consumer.TWO_TIMES_DISPUTE_PERIOD()); uint256 requiredSigs = getRequiredSigs(1, 3, Math.Rounding.Ceil); PodECDSA.CertifiedLog memory certifiedLogHigherBid = createCertifiedLog(requiredSigs, false); - vm.warp(block.timestamp + 2 * U); + vm.warp(block.timestamp + consumer.TWO_TIMES_DISPUTE_PERIOD()); vm.prank(BONDED_ADDRESS); vm.expectRevert("Dispute period ended"); @@ -271,7 +270,7 @@ contract PodAuctionConsumerTest is Test { PodECDSA.CertifiedLog memory certifiedLogSmallerBid = createCertifiedLog(requiredSigs, true); - vm.warp(block.timestamp + U); + vm.warp(block.timestamp + consumer.DISPUTE_PERIOD()); vm.prank(BONDED_ADDRESS); consumer.blameNoShow(certifiedLogHigherBid); From 419c00d3fedd2fe692f8e208b339270d9bb4b77b Mon Sep 17 00:00:00 2001 From: Jakov Mitrovski Date: Mon, 18 Aug 2025 15:07:44 +0200 Subject: [PATCH 25/64] refacotr(registry): address PR comments --- solidity-sdk/src/verifier/PodECDSA.sol | 2 +- solidity-sdk/src/verifier/PodRegistry.sol | 161 +++++++++++++--------- solidity-sdk/test/PodRegistry.t.sol | 16 +-- 3 files changed, 105 insertions(+), 74 deletions(-) diff --git a/solidity-sdk/src/verifier/PodECDSA.sol b/solidity-sdk/src/verifier/PodECDSA.sol index a02fd67f..e9551d05 100644 --- a/solidity-sdk/src/verifier/PodECDSA.sol +++ b/solidity-sdk/src/verifier/PodECDSA.sol @@ -67,7 +67,7 @@ library PodECDSA { uint256 weight = podConfig.registry.computeWeight(validators, certifiedReceipt.medianTimestamp, snapshotIndex); uint256 threshold = Math.mulDiv( - podConfig.registry.getValidatorCountAt(snapshotIndex), + podConfig.registry.getValidatorCountAtIndex(snapshotIndex), podConfig.thresholdNumerator, podConfig.thresholdDenominator, Math.Rounding.Ceil diff --git a/solidity-sdk/src/verifier/PodRegistry.sol b/solidity-sdk/src/verifier/PodRegistry.sol index 185ee51a..978ca885 100644 --- a/solidity-sdk/src/verifier/PodRegistry.sol +++ b/solidity-sdk/src/verifier/PodRegistry.sol @@ -92,19 +92,12 @@ interface IPodRegistry { */ function validatorIndex(address validator) external view returns (uint8 index); - /** - * @notice Get the address of a validator by their index - * @param index The 1-based index of the validator - * @return validator The address of the validator at the given index (address(0) if not found) - */ - function validatorAddress(uint8 index) external view returns (address validator); - /** * @notice Check if a validator is banned * @param validator The address of the validator * @return isBanned True if the validator is banned, false otherwise */ - function bannedValidators(address validator) external view returns (bool isBanned); + function isValidatorBanned(address validator) external view returns (bool isBanned); /** * @notice Get the total number of validators in the registry. Counts banned and active validators too. @@ -200,7 +193,7 @@ interface IPodRegistry { * @param snapshotIndex The snapshot index to query * @return count The number of validators at the specified snapshot */ - function getValidatorCountAt(uint256 snapshotIndex) external view returns (uint8 count); + function getValidatorCountAtIndex(uint256 snapshotIndex) external view returns (uint8 count); /** * @notice Get all currently active validators @@ -213,22 +206,25 @@ interface IPodRegistry { * @param timestamp The timestamp to query * @return Array of addresses of validators active at the specified timestamp */ - function getActiveValidators(uint256 timestamp) external view returns (address[] memory); + function getActiveValidatorsAtTimestamp(uint256 timestamp) external view returns (address[] memory); /** * @notice Get all validators at a specific snapshot - * @param index The snapshot index to query + * @param snapshotIndex The snapshot index to query * @return Array of addresses of validators at the specified snapshot */ - function getValidatorsAt(uint256 index) external view returns (address[] memory); + function getValidatorsAtIndex(uint256 snapshotIndex) external view returns (address[] memory); /** * @notice Get snapshot details at a specific index - * @param index The snapshot index to query + * @param snapshotIndex The snapshot index to query * @return activeAsOfTimestamp The timestamp when the snapshot was created * @return bitmap The bitmap of active validators at this snapshot */ - function getSnapshotAt(uint256 index) external view returns (uint256 activeAsOfTimestamp, uint256 bitmap); + function getSnapshotAtIndex(uint256 snapshotIndex) + external + view + returns (uint256 activeAsOfTimestamp, uint256 bitmap); /** * @notice Get the total number of snapshots in the history @@ -257,20 +253,17 @@ contract PodRegistry is IPodRegistry, Ownable { /// @notice Mapping from validator address to their 1-based index mapping(address => uint8) public validatorIndex; - /// @notice Mapping from validator 1-based index to their address - mapping(uint8 => address) public validatorAddress; - - /// @notice Mapping from validator address to banned status - mapping(address => bool) public bannedValidators; + /** + * @notice Array of validators in the registry. We also use `validators.length + 1` to track the 1-based + * index of the next validator to add. + */ + address[] public validators; /// @notice Bitmap of the currently active validators uint256 public activeValidatorBitmap; - /** - * @notice Total count of validators in the registry. We also use `validatorCount` to - * track the index of the next validator to add. - */ - uint8 public validatorCount; + /// @notice Bitmap of the currently banned validators + uint256 public bannedValidatorBitmap; /** * @notice Initialize the registry with a set of initial validators. Only creates one snapshot @@ -282,43 +275,42 @@ contract PodRegistry is IPodRegistry, Ownable { if (initialValidators.length >= MAX_VALIDATOR_COUNT) { revert TooManyInitialValidators(); } - validatorCount = uint8(initialValidators.length); for (uint8 i = 0; i < initialValidators.length; i++) { - _addValidatorOnInit(initialValidators[i], i); + _addValidator(initialValidators[i], i + 1); + activeValidatorBitmap |= (1 << i); } _createSnapshot(); } /** - * @notice Add a validator during contract initialization. Does not create a snapshot. + * @notice Add a validator to the registry * @param validator The address of the validator to add - * @param index The 0-based index for the validator - * @dev Internal function used only during construction - */ - function _addValidatorOnInit(address validator, uint8 index) internal { - validatorIndex[validator] = index + 1; - activeValidatorBitmap |= (1 << index); - validatorAddress[index + 1] = validator; - } - - /** - * @inheritdoc IPodRegistry + * @param index The 1-based index of the validator + * @dev Internal function called by addValidator */ - function addValidator(address validator) external onlyOwner { + function _addValidator(address validator, uint8 index) internal { if (validator == address(0)) { revert ValidatorIsZeroAddress(); } if (validatorIndex[validator] != 0) { revert ValidatorAlreadyExists(); } - if (validatorCount >= MAX_VALIDATOR_COUNT) { + + validatorIndex[validator] = index; + validators.push(validator); + } + + /** + * @inheritdoc IPodRegistry + */ + function addValidator(address validator) external onlyOwner { + if (validators.length >= MAX_VALIDATOR_COUNT) { revert MaxValidatorCountReached(); } - uint8 index = ++validatorCount; - validatorIndex[validator] = index; - validatorAddress[index] = validator; + uint8 index = uint8(validators.length + 1); + _addValidator(validator, index); if (!_isValidatorActive(index)) { _activateValidator(index); } @@ -333,7 +325,7 @@ contract PodRegistry is IPodRegistry, Ownable { if (index == 0) { revert ValidatorDoesNotExist(); } - if (bannedValidators[validator]) { + if (_isValidatorBanned(index)) { revert ValidatorAlreadyBanned(); } @@ -341,7 +333,7 @@ contract PodRegistry is IPodRegistry, Ownable { _deactivateValidator(index); } - bannedValidators[validator] = true; + bannedValidatorBitmap = _setBit(bannedValidatorBitmap, index - 1); emit ValidatorBanned(validator); } @@ -349,13 +341,14 @@ contract PodRegistry is IPodRegistry, Ownable { * @inheritdoc IPodRegistry */ function unbanValidator(address validator) external onlyOwner { - if (validatorIndex[validator] == 0) { + uint8 index = validatorIndex[validator]; + if (index == 0) { revert ValidatorDoesNotExist(); } - if (!bannedValidators[validator]) { + if (!_isValidatorBanned(index)) { revert ValidatorNotBanned(); } - bannedValidators[validator] = false; + bannedValidatorBitmap = _clearBit(bannedValidatorBitmap, index - 1); emit ValidatorUnbanned(validator); } @@ -382,7 +375,7 @@ contract PodRegistry is IPodRegistry, Ownable { if (index == 0) { revert CallerNotValidator(); } - if (bannedValidators[msg.sender]) { + if (_isValidatorBanned(index)) { revert CallerAlreadyBanned(); } if (_isValidatorActive(index)) { @@ -440,9 +433,8 @@ contract PodRegistry is IPodRegistry, Ownable { continue; } - uint256 mask = 1 << (index - 1); - if ((snapshot.bitmap & mask) != 0 && (counted & mask) == 0) { - counted |= mask; + if (_isBitSet(snapshot.bitmap, index - 1) && !_isBitSet(counted, index - 1)) { + counted = _setBit(counted, index - 1); weight++; } } @@ -451,7 +443,7 @@ contract PodRegistry is IPodRegistry, Ownable { /** * @inheritdoc IPodRegistry */ - function findSnapshotIndex(uint256 timestamp) public view returns (uint256 index) { + function findSnapshotIndex(uint256 timestamp) public view returns (uint256 snapshotIndex) { if (history.length == 0) { revert NoHistoricalSnapshots(); } @@ -481,7 +473,7 @@ contract PodRegistry is IPodRegistry, Ownable { /** * @inheritdoc IPodRegistry */ - function getValidatorCountAt(uint256 snapshotIndex) public view returns (uint8 count) { + function getValidatorCountAtIndex(uint256 snapshotIndex) public view returns (uint8 count) { uint256 bitmap = history[snapshotIndex].bitmap; return _popCount(bitmap); } @@ -502,17 +494,17 @@ contract PodRegistry is IPodRegistry, Ownable { /** * @inheritdoc IPodRegistry */ - function getValidatorsAt(uint256 snapshotIndex) public view returns (address[] memory) { + function getValidatorsAtIndex(uint256 snapshotIndex) public view returns (address[] memory) { uint256 bitmap = history[snapshotIndex].bitmap; uint8 count = _popCount(bitmap); - address[] memory validators = new address[](count); + address[] memory subset = new address[](count); uint8 j = 0; - for (uint8 i = 0; i < validatorCount; i++) { + for (uint8 i = 0; i < validators.length; i++) { if (_isBitSet(bitmap, i)) { - validators[j++] = validatorAddress[i + 1]; + subset[j++] = validators[i]; } } - return validators; + return subset; } /** @@ -523,29 +515,51 @@ contract PodRegistry is IPodRegistry, Ownable { return new address[](0); } - return getValidatorsAt(history.length - 1); + return getValidatorsAtIndex(history.length - 1); } /** * @inheritdoc IPodRegistry */ - function getActiveValidators(uint256 timestamp) external view returns (address[] memory) { + function getActiveValidatorsAtTimestamp(uint256 timestamp) external view returns (address[] memory) { if (history.length == 0) { return new address[](0); } uint256 snapshotIndex = findSnapshotIndex(timestamp); - return getValidatorsAt(snapshotIndex); + return getValidatorsAtIndex(snapshotIndex); + } + + /** + * @inheritdoc IPodRegistry + */ + function isValidatorBanned(address validator) external view returns (bool isBanned) { + uint8 index = validatorIndex[validator]; + if (index == 0) { + return false; + } + return _isValidatorBanned(index); } /** * @inheritdoc IPodRegistry */ - function getSnapshotAt(uint256 snapshotIndex) external view returns (uint256 activeAsOfTimestamp, uint256 bitmap) { + function getSnapshotAtIndex(uint256 snapshotIndex) + external + view + returns (uint256 activeAsOfTimestamp, uint256 bitmap) + { Snapshot memory s = history[snapshotIndex]; return (s.activeAsOfTimestamp, s.bitmap); } + /** + * @inheritdoc IPodRegistry + */ + function validatorCount() external view returns (uint8 count) { + return uint8(validators.length); + } + /** * @inheritdoc IPodRegistry */ @@ -559,7 +573,7 @@ contract PodRegistry is IPodRegistry, Ownable { * @dev Creates a new snapshot after activation */ function _activateValidator(uint8 index) internal { - activeValidatorBitmap |= (1 << (index - 1)); + activeValidatorBitmap = _setBit(activeValidatorBitmap, index - 1); _createSnapshot(); } @@ -569,7 +583,7 @@ contract PodRegistry is IPodRegistry, Ownable { * @dev Creates a new snapshot after deactivation */ function _deactivateValidator(uint8 index) internal { - activeValidatorBitmap &= ~(1 << (index - 1)); + activeValidatorBitmap = _clearBit(activeValidatorBitmap, index - 1); _createSnapshot(); } @@ -582,6 +596,15 @@ contract PodRegistry is IPodRegistry, Ownable { return _isBitSet(activeValidatorBitmap, index - 1); } + /** + * @notice Check if a validator is currently banned + * @param index The 1-based index of the validator to check + * @return True if the validator is banned, false otherwise + */ + function _isValidatorBanned(uint8 index) internal view returns (bool) { + return _isBitSet(bannedValidatorBitmap, index - 1); + } + /** * @notice Check if a specific bit is set in a bitmap * @param bitmap The bitmap to check @@ -591,4 +614,12 @@ contract PodRegistry is IPodRegistry, Ownable { function _isBitSet(uint256 bitmap, uint8 i) internal pure returns (bool) { return (bitmap & (1 << i)) != 0; } + + function _setBit(uint256 bitmap, uint8 i) internal pure returns (uint256) { + return bitmap | (1 << i); + } + + function _clearBit(uint256 bitmap, uint8 i) internal pure returns (uint256) { + return bitmap & ~(1 << i); + } } diff --git a/solidity-sdk/test/PodRegistry.t.sol b/solidity-sdk/test/PodRegistry.t.sol index 204f8ccd..d0e163da 100644 --- a/solidity-sdk/test/PodRegistry.t.sol +++ b/solidity-sdk/test/PodRegistry.t.sol @@ -125,13 +125,13 @@ contract PodRegistryTest is Test { function test_UnbanValidator() public { vm.prank(owner); registry.banValidator(validator1); - assertTrue(registry.bannedValidators(validator1)); + assertTrue(registry.isValidatorBanned(validator1)); vm.prank(owner); vm.expectEmit(true, false, false, true); emit IPodRegistry.ValidatorUnbanned(validator1); registry.unbanValidator(validator1); - assertFalse(registry.bannedValidators(validator1)); + assertFalse(registry.isValidatorBanned(validator1)); } function test_UnbanValidator_DoesNotCreateSnapshot() public { @@ -344,7 +344,7 @@ contract PodRegistryTest is Test { registry.addValidator(validator3); uint256 snapshotIndex = registry.getHistoryLength() - 1; uint256 snapshotTimestamp; - (snapshotTimestamp,) = registry.getSnapshotAt(snapshotIndex); + (snapshotTimestamp,) = registry.getSnapshotAtIndex(snapshotIndex); address[] memory subset = new address[](3); subset[0] = validator1; @@ -455,11 +455,11 @@ contract PodRegistryTest is Test { assertEq(indexAfterLast, 2); // Validate that returned snapshots are correct - (uint256 timestamp1, uint256 bitmap1) = registry.getSnapshotAt(indexAtAdd); + (uint256 timestamp1, uint256 bitmap1) = registry.getSnapshotAtIndex(indexAtAdd); assertEq(timestamp1, timestampAtAdd); assertTrue(bitmap1 & (1 << (3 - 1)) != 0); // validator3 should be active here - (uint256 timestamp2, uint256 bitmap2) = registry.getSnapshotAt(indexAfterLast); + (uint256 timestamp2, uint256 bitmap2) = registry.getSnapshotAtIndex(indexAfterLast); assertEq(timestamp2, timestampAtBan); assertTrue(bitmap2 & (1 << (3 - 1)) != 0); // validator3 still active assertFalse(bitmap2 & (1 << (1 - 1)) != 0); // validator1 banned @@ -501,7 +501,7 @@ contract PodRegistryTest is Test { vm.prank(owner); registry.addValidator(validator3); uint256 index = registry.getHistoryLength() - 1; - (uint256 timestamp, uint256 bitmap) = registry.getSnapshotAt(index); + (uint256 timestamp, uint256 bitmap) = registry.getSnapshotAtIndex(index); assertGt(timestamp, 0); assertTrue(bitmap & (1 << (3 - 1)) != 0); } @@ -520,7 +520,7 @@ contract PodRegistryTest is Test { assertEq(validators[1], validator2); } - function test_GetValidatorsAt() public { + function test_GetValidatorsAtIndex() public { vm.startPrank(owner); vm.warp(100); registry.addValidator(validator3); @@ -529,7 +529,7 @@ contract PodRegistryTest is Test { registry.addValidator(validator4); vm.stopPrank(); uint256 index = registry.findSnapshotIndex(100); - address[] memory validators = registry.getValidatorsAt(index); + address[] memory validators = registry.getValidatorsAtIndex(index); assertEq(validators.length, 2); assertEq(validators[0], validator2); assertEq(validators[1], validator3); From e6f1f7d71ab6c9ab051dca9063786f2ab2d3c7e3 Mon Sep 17 00:00:00 2001 From: Jakov Mitrovski Date: Mon, 18 Aug 2025 15:10:00 +0200 Subject: [PATCH 26/64] add bindings --- .../bindings/src/pod_auction_consumer.rs | 319 +++++++++++++++--- 1 file changed, 270 insertions(+), 49 deletions(-) diff --git a/examples/optimistic-auction/bindings/src/pod_auction_consumer.rs b/examples/optimistic-auction/bindings/src/pod_auction_consumer.rs index e21f4040..336a4d06 100644 --- a/examples/optimistic-auction/bindings/src/pod_auction_consumer.rs +++ b/examples/optimistic-auction/bindings/src/pod_auction_consumer.rs @@ -1537,8 +1537,9 @@ interface PodAuctionConsumer { constructor(address _podRegistry, uint256 _bondAmount); + function DISPUTE_PERIOD() external view returns (uint256); function LOG_TOPIC_0() external view returns (bytes32); - function U() external view returns (uint256); + function TWO_TIMES_DISPUTE_PERIOD() external view returns (uint256); function blameIllAnnounced(PodECDSA.CertifiedLog memory certifiedLog) external; function blameNoShow(PodECDSA.CertifiedLog memory certifiedLog) external; function bond() external payable; @@ -1575,6 +1576,19 @@ interface PodAuctionConsumer { ], "stateMutability": "nonpayable" }, + { + "type": "function", + "name": "DISPUTE_PERIOD", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, { "type": "function", "name": "LOG_TOPIC_0", @@ -1590,7 +1604,7 @@ interface PodAuctionConsumer { }, { "type": "function", - "name": "U", + "name": "TWO_TIMES_DISPUTE_PERIOD", "inputs": [], "outputs": [ { @@ -3582,6 +3596,153 @@ constructor(address _podRegistry, uint256 _bondAmount); }; #[derive(serde::Serialize, serde::Deserialize)] #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Function with signature `DISPUTE_PERIOD()` and selector `0xa5bbe22b`. +```solidity +function DISPUTE_PERIOD() external view returns (uint256); +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct DISPUTE_PERIODCall; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + ///Container type for the return parameters of the [`DISPUTE_PERIOD()`](DISPUTE_PERIODCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct DISPUTE_PERIODReturn { + #[allow(missing_docs)] + pub _0: alloy::sol_types::private::primitives::aliases::U256, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: DISPUTE_PERIODCall) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for DISPUTE_PERIODCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self + } + } + } + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (alloy::sol_types::sol_data::Uint<256>,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = ( + alloy::sol_types::private::primitives::aliases::U256, + ); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From + for UnderlyingRustTuple<'_> { + fn from(value: DISPUTE_PERIODReturn) -> Self { + (value._0,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> + for DISPUTE_PERIODReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { _0: tuple.0 } + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for DISPUTE_PERIODCall { + type Parameters<'a> = (); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = alloy::sol_types::private::primitives::aliases::U256; + type ReturnTuple<'a> = (alloy::sol_types::sol_data::Uint<256>,); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "DISPUTE_PERIOD()"; + const SELECTOR: [u8; 4] = [165u8, 187u8, 226u8, 43u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + () + } + #[inline] + fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> { + ( + as alloy_sol_types::SolType>::tokenize(ret), + ) + } + #[inline] + fn abi_decode_returns(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data) + .map(|r| { + let r: DISPUTE_PERIODReturn = r.into(); + r._0 + }) + } + #[inline] + fn abi_decode_returns_validate( + data: &[u8], + ) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(|r| { + let r: DISPUTE_PERIODReturn = r.into(); + r._0 + }) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] /**Function with signature `LOG_TOPIC_0()` and selector `0xe9751b37`. ```solidity function LOG_TOPIC_0() external view returns (bytes32); @@ -3725,19 +3886,19 @@ function LOG_TOPIC_0() external view returns (bytes32); }; #[derive(serde::Serialize, serde::Deserialize)] #[derive(Default, Debug, PartialEq, Eq, Hash)] - /**Function with signature `U()` and selector `0x2688454a`. + /**Function with signature `TWO_TIMES_DISPUTE_PERIOD()` and selector `0xc5dcc691`. ```solidity -function U() external view returns (uint256); +function TWO_TIMES_DISPUTE_PERIOD() external view returns (uint256); ```*/ #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] #[derive(Clone)] - pub struct UCall; + pub struct TWO_TIMES_DISPUTE_PERIODCall; #[derive(serde::Serialize, serde::Deserialize)] #[derive(Default, Debug, PartialEq, Eq, Hash)] - ///Container type for the return parameters of the [`U()`](UCall) function. + ///Container type for the return parameters of the [`TWO_TIMES_DISPUTE_PERIOD()`](TWO_TIMES_DISPUTE_PERIODCall) function. #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] #[derive(Clone)] - pub struct UReturn { + pub struct TWO_TIMES_DISPUTE_PERIODReturn { #[allow(missing_docs)] pub _0: alloy::sol_types::private::primitives::aliases::U256, } @@ -3767,14 +3928,16 @@ function U() external view returns (uint256); } #[automatically_derived] #[doc(hidden)] - impl ::core::convert::From for UnderlyingRustTuple<'_> { - fn from(value: UCall) -> Self { + impl ::core::convert::From + for UnderlyingRustTuple<'_> { + fn from(value: TWO_TIMES_DISPUTE_PERIODCall) -> Self { () } } #[automatically_derived] #[doc(hidden)] - impl ::core::convert::From> for UCall { + impl ::core::convert::From> + for TWO_TIMES_DISPUTE_PERIODCall { fn from(tuple: UnderlyingRustTuple<'_>) -> Self { Self } @@ -3800,21 +3963,23 @@ function U() external view returns (uint256); } #[automatically_derived] #[doc(hidden)] - impl ::core::convert::From for UnderlyingRustTuple<'_> { - fn from(value: UReturn) -> Self { + impl ::core::convert::From + for UnderlyingRustTuple<'_> { + fn from(value: TWO_TIMES_DISPUTE_PERIODReturn) -> Self { (value._0,) } } #[automatically_derived] #[doc(hidden)] - impl ::core::convert::From> for UReturn { + impl ::core::convert::From> + for TWO_TIMES_DISPUTE_PERIODReturn { fn from(tuple: UnderlyingRustTuple<'_>) -> Self { Self { _0: tuple.0 } } } } #[automatically_derived] - impl alloy_sol_types::SolCall for UCall { + impl alloy_sol_types::SolCall for TWO_TIMES_DISPUTE_PERIODCall { type Parameters<'a> = (); type Token<'a> = = as alloy_sol_types::SolType>::Token<'a>; - const SIGNATURE: &'static str = "U()"; - const SELECTOR: [u8; 4] = [38u8, 136u8, 69u8, 74u8]; + const SIGNATURE: &'static str = "TWO_TIMES_DISPUTE_PERIOD()"; + const SELECTOR: [u8; 4] = [197u8, 220u8, 198u8, 145u8]; #[inline] fn new<'a>( tuple: as alloy_sol_types::SolType>::RustType, @@ -3850,7 +4015,7 @@ function U() external view returns (uint256); '_, > as alloy_sol_types::SolType>::abi_decode_sequence(data) .map(|r| { - let r: UReturn = r.into(); + let r: TWO_TIMES_DISPUTE_PERIODReturn = r.into(); r._0 }) } @@ -3862,7 +4027,7 @@ function U() external view returns (uint256); '_, > as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) .map(|r| { - let r: UReturn = r.into(); + let r: TWO_TIMES_DISPUTE_PERIODReturn = r.into(); r._0 }) } @@ -5896,10 +6061,12 @@ function write(PodECDSA.CertifiedLog memory certifiedLog) external; #[derive(serde::Serialize, serde::Deserialize)] #[derive()] pub enum PodAuctionConsumerCalls { + #[allow(missing_docs)] + DISPUTE_PERIOD(DISPUTE_PERIODCall), #[allow(missing_docs)] LOG_TOPIC_0(LOG_TOPIC_0Call), #[allow(missing_docs)] - U(UCall), + TWO_TIMES_DISPUTE_PERIOD(TWO_TIMES_DISPUTE_PERIODCall), #[allow(missing_docs)] blameIllAnnounced(blameIllAnnouncedCall), #[allow(missing_docs)] @@ -5939,7 +6106,6 @@ function write(PodECDSA.CertifiedLog memory certifiedLog) external; /// Prefer using `SolInterface` methods instead. pub const SELECTORS: &'static [[u8; 4usize]] = &[ [14u8, 205u8, 153u8, 14u8], - [38u8, 136u8, 69u8, 74u8], [56u8, 114u8, 51u8, 236u8], [60u8, 207u8, 214u8, 11u8], [74u8, 165u8, 232u8, 133u8], @@ -5952,6 +6118,8 @@ function write(PodECDSA.CertifiedLog memory certifiedLog) external; [128u8, 243u8, 35u8, 167u8], [141u8, 165u8, 203u8, 91u8], [154u8, 98u8, 194u8, 163u8], + [165u8, 187u8, 226u8, 43u8], + [197u8, 220u8, 198u8, 145u8], [233u8, 117u8, 27u8, 55u8], [242u8, 253u8, 227u8, 139u8], ]; @@ -5960,14 +6128,19 @@ function write(PodECDSA.CertifiedLog memory certifiedLog) external; impl alloy_sol_types::SolInterface for PodAuctionConsumerCalls { const NAME: &'static str = "PodAuctionConsumerCalls"; const MIN_DATA_LENGTH: usize = 0usize; - const COUNT: usize = 16usize; + const COUNT: usize = 17usize; #[inline] fn selector(&self) -> [u8; 4] { match self { + Self::DISPUTE_PERIOD(_) => { + ::SELECTOR + } Self::LOG_TOPIC_0(_) => { ::SELECTOR } - Self::U(_) => ::SELECTOR, + Self::TWO_TIMES_DISPUTE_PERIOD(_) => { + ::SELECTOR + } Self::blameIllAnnounced(_) => { ::SELECTOR } @@ -6024,15 +6197,6 @@ function write(PodECDSA.CertifiedLog memory certifiedLog) external; } blameIllAnnounced }, - { - fn U( - data: &[u8], - ) -> alloy_sol_types::Result { - ::abi_decode_raw(data) - .map(PodAuctionConsumerCalls::U) - } - U - }, { fn podRegistry( data: &[u8], @@ -6149,6 +6313,28 @@ function write(PodECDSA.CertifiedLog memory certifiedLog) external; } blameNoShow }, + { + fn DISPUTE_PERIOD( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw( + data, + ) + .map(PodAuctionConsumerCalls::DISPUTE_PERIOD) + } + DISPUTE_PERIOD + }, + { + fn TWO_TIMES_DISPUTE_PERIOD( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw( + data, + ) + .map(PodAuctionConsumerCalls::TWO_TIMES_DISPUTE_PERIOD) + } + TWO_TIMES_DISPUTE_PERIOD + }, { fn LOG_TOPIC_0( data: &[u8], @@ -6202,17 +6388,6 @@ function write(PodECDSA.CertifiedLog memory certifiedLog) external; } blameIllAnnounced }, - { - fn U( - data: &[u8], - ) -> alloy_sol_types::Result { - ::abi_decode_raw_validate( - data, - ) - .map(PodAuctionConsumerCalls::U) - } - U - }, { fn podRegistry( data: &[u8], @@ -6345,6 +6520,28 @@ function write(PodECDSA.CertifiedLog memory certifiedLog) external; } blameNoShow }, + { + fn DISPUTE_PERIOD( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(PodAuctionConsumerCalls::DISPUTE_PERIOD) + } + DISPUTE_PERIOD + }, + { + fn TWO_TIMES_DISPUTE_PERIOD( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(PodAuctionConsumerCalls::TWO_TIMES_DISPUTE_PERIOD) + } + TWO_TIMES_DISPUTE_PERIOD + }, { fn LOG_TOPIC_0( data: &[u8], @@ -6381,13 +6578,20 @@ function write(PodECDSA.CertifiedLog memory certifiedLog) external; #[inline] fn abi_encoded_size(&self) -> usize { match self { + Self::DISPUTE_PERIOD(inner) => { + ::abi_encoded_size( + inner, + ) + } Self::LOG_TOPIC_0(inner) => { ::abi_encoded_size( inner, ) } - Self::U(inner) => { - ::abi_encoded_size(inner) + Self::TWO_TIMES_DISPUTE_PERIOD(inner) => { + ::abi_encoded_size( + inner, + ) } Self::blameIllAnnounced(inner) => { ::abi_encoded_size( @@ -6446,14 +6650,23 @@ function write(PodECDSA.CertifiedLog memory certifiedLog) external; #[inline] fn abi_encode_raw(&self, out: &mut alloy_sol_types::private::Vec) { match self { + Self::DISPUTE_PERIOD(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } Self::LOG_TOPIC_0(inner) => { ::abi_encode_raw( inner, out, ) } - Self::U(inner) => { - ::abi_encode_raw(inner, out) + Self::TWO_TIMES_DISPUTE_PERIOD(inner) => { + ::abi_encode_raw( + inner, + out, + ) } Self::blameIllAnnounced(inner) => { ::abi_encode_raw( @@ -6956,15 +7169,23 @@ See the [wrapper's documentation](`PodAuctionConsumerInstance`) for more details ) -> alloy_contract::SolCallBuilder<&P, C, N> { alloy_contract::SolCallBuilder::new_sol(&self.provider, &self.address, call) } + ///Creates a new call builder for the [`DISPUTE_PERIOD`] function. + pub fn DISPUTE_PERIOD( + &self, + ) -> alloy_contract::SolCallBuilder<&P, DISPUTE_PERIODCall, N> { + self.call_builder(&DISPUTE_PERIODCall) + } ///Creates a new call builder for the [`LOG_TOPIC_0`] function. pub fn LOG_TOPIC_0( &self, ) -> alloy_contract::SolCallBuilder<&P, LOG_TOPIC_0Call, N> { self.call_builder(&LOG_TOPIC_0Call) } - ///Creates a new call builder for the [`U`] function. - pub fn U(&self) -> alloy_contract::SolCallBuilder<&P, UCall, N> { - self.call_builder(&UCall) + ///Creates a new call builder for the [`TWO_TIMES_DISPUTE_PERIOD`] function. + pub fn TWO_TIMES_DISPUTE_PERIOD( + &self, + ) -> alloy_contract::SolCallBuilder<&P, TWO_TIMES_DISPUTE_PERIODCall, N> { + self.call_builder(&TWO_TIMES_DISPUTE_PERIODCall) } ///Creates a new call builder for the [`blameIllAnnounced`] function. pub fn blameIllAnnounced( From a9d11af5bf8d1d0a4604c6c85330c2e5531ea4ca Mon Sep 17 00:00:00 2001 From: Jakov Mitrovski Date: Mon, 18 Aug 2025 15:18:42 +0200 Subject: [PATCH 27/64] feat(registry): add fast path of findSnapSHotIndex --- solidity-sdk/src/verifier/PodRegistry.sol | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/solidity-sdk/src/verifier/PodRegistry.sol b/solidity-sdk/src/verifier/PodRegistry.sol index 978ca885..14043d10 100644 --- a/solidity-sdk/src/verifier/PodRegistry.sol +++ b/solidity-sdk/src/verifier/PodRegistry.sol @@ -176,6 +176,8 @@ interface IPodRegistry { * Since this is a view function, it can be called off-chain to compute the correct snapshotIndex * corresponding to a particular timestamp. * Then, the function computeWeight can be called on-chain with the correct snapshotIndex. + * The function also supports a fast path: scan the last few snapshots linearly before falling + * back to binary search. This is useful when we expect to validate recent certificates. * @param timestamp The timestamp to find a snapshot for * @return snapshotIndex The index of the most recent snapshot at or before the timestamp * @dev Uses binary search for efficient lookup @@ -448,6 +450,16 @@ contract PodRegistry is IPodRegistry, Ownable { revert NoHistoricalSnapshots(); } + for (uint256 i = 0; i < 3; i++) { + if (i >= history.length) { + break; + } + uint256 idx = history.length - 1 - i; + if (history[idx].activeAsOfTimestamp <= timestamp) { + return idx; + } + } + uint256 low = 0; uint256 high = history.length - 1; From 660994ca36f4f21ed3fe01fb1e32120d15edfd39 Mon Sep 17 00:00:00 2001 From: Jakov Mitrovski Date: Mon, 18 Aug 2025 17:48:54 +0200 Subject: [PATCH 28/64] refactor(registry): remove index from addValidator function --- solidity-sdk/src/verifier/PodRegistry.sol | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/solidity-sdk/src/verifier/PodRegistry.sol b/solidity-sdk/src/verifier/PodRegistry.sol index 14043d10..a6820e0e 100644 --- a/solidity-sdk/src/verifier/PodRegistry.sol +++ b/solidity-sdk/src/verifier/PodRegistry.sol @@ -279,7 +279,7 @@ contract PodRegistry is IPodRegistry, Ownable { } for (uint8 i = 0; i < initialValidators.length; i++) { - _addValidator(initialValidators[i], i + 1); + _addValidator(initialValidators[i]); activeValidatorBitmap |= (1 << i); } @@ -289,10 +289,9 @@ contract PodRegistry is IPodRegistry, Ownable { /** * @notice Add a validator to the registry * @param validator The address of the validator to add - * @param index The 1-based index of the validator * @dev Internal function called by addValidator */ - function _addValidator(address validator, uint8 index) internal { + function _addValidator(address validator) internal { if (validator == address(0)) { revert ValidatorIsZeroAddress(); } @@ -300,8 +299,8 @@ contract PodRegistry is IPodRegistry, Ownable { revert ValidatorAlreadyExists(); } - validatorIndex[validator] = index; validators.push(validator); + validatorIndex[validator] = uint8(validators.length); } /** @@ -311,11 +310,9 @@ contract PodRegistry is IPodRegistry, Ownable { if (validators.length >= MAX_VALIDATOR_COUNT) { revert MaxValidatorCountReached(); } - uint8 index = uint8(validators.length + 1); - _addValidator(validator, index); - if (!_isValidatorActive(index)) { - _activateValidator(index); - } + _addValidator(validator); + uint8 index = uint8(validators.length); + _activateValidator(index); emit ValidatorAdded(validator); } From fe97d82436cd1cd7920359ef883871398b6c9a9b Mon Sep 17 00:00:00 2001 From: Jakov Mitrovski Date: Wed, 20 Aug 2025 14:18:03 +0200 Subject: [PATCH 29/64] refactor(registry): address PR comments, update median to be verified onchian --- solidity-sdk/src/interfaces/IPodRegistry.sol | 229 +++++++++++++ solidity-sdk/src/verifier/PodECDSA.sol | 64 +++- solidity-sdk/src/verifier/PodRegistry.sol | 333 ++++--------------- solidity-sdk/test/PodECDSA.t.sol | 89 ++++- solidity-sdk/test/PodRegistry.t.sol | 17 +- 5 files changed, 435 insertions(+), 297 deletions(-) create mode 100644 solidity-sdk/src/interfaces/IPodRegistry.sol diff --git a/solidity-sdk/src/interfaces/IPodRegistry.sol b/solidity-sdk/src/interfaces/IPodRegistry.sol new file mode 100644 index 00000000..442caff4 --- /dev/null +++ b/solidity-sdk/src/interfaces/IPodRegistry.sol @@ -0,0 +1,229 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +/** + * @title IPodRegistry + * @notice Interface for the Pod Registry contract that manages the validator committee and committee rotation. + * This is the source of truth for what the active pod validator set is at any given timestamp. + * @dev This interface defines the core functionality for committee rotation. It is responsible + * for adding, banning, unbanning, activating and deactivating validators. It also provides + * ways to compute the weight of a subset of validators at a specific timestamp. + * In order to allow this, snapshots are created whenever the validator set changes. + */ +interface IPodRegistry { + /** + * @notice Represents a snapshot of the validator set at a specific timestamp + * @param activeAsOfTimestamp The timestamp when this snapshot was created + * @param bitmap Bitmap representing which validators were active at this snapshot + */ + struct Snapshot { + uint256 activeAsOfTimestamp; + uint256 bitmap; + } + + /// @notice Error thrown when a validator is a zero address + error ValidatorIsZeroAddress(); + + /// @notice Error thrown when a validator already exists + error ValidatorAlreadyExists(); + + /// @notice Error thrown when the maximum validator count is reached + error MaxValidatorCountReached(); + + /// @notice Error thrown when a validator does not exist + error ValidatorDoesNotExist(); + + /// @notice Error thrown when a validator is not banned + error ValidatorNotBanned(); + + /// @notice Error thrown when the caller is not a validator + error CallerNotValidator(); + + /// @notice Error thrown when the caller is already inactive + error CallerAlreadyInactive(); + + /// @notice Error thrown when the caller is banned + error CallerBanned(); + + /// @notice Error thrown when the caller is already active + error CallerAlreadyActive(); + + /// @notice Error thrown when the snapshot index is invalid + error InvalidSnapshotIndex(); + + /// @notice Error thrown when the snapshot is too new + error SnapshotTooNew(); + + /// @notice Error thrown when the snapshot is too old + error SnapshotTooOld(); + + /// @notice Error thrown when there are no historical snapshots + error NoHistoricalSnapshots(); + + /// @notice Event emitted when a validator is added + event ValidatorAdded(address indexed validator); + + /// @notice Event emitted when a validator is banned + event ValidatorBanned(address indexed validator); + + /// @notice Event emitted when a validator is unbanned + event ValidatorUnbanned(address indexed validator); + + /// @notice Event emitted when a validator is deactivated + event ValidatorDeactivated(address indexed validator); + + /// @notice Event emitted when a validator is reactivated + event ValidatorReactivated(address indexed validator); + + /// @notice Event emitted when a snapshot is created + event SnapshotCreated(uint256 indexed activeAsOfTimestamp, uint256 bitmap); + + /** + * @notice Get the index of a validator in the registry + * @param validator The address of the validator + * @return index The 1-based index of the validator (0 if not found) + */ + function validatorIndex(address validator) external view returns (uint8 index); + + /** + * @notice Check if a validator is banned + * @param validator The address of the validator + * @return isBanned True if the validator is banned, false otherwise + */ + function isValidatorBanned(address validator) external view returns (bool isBanned); + + /** + * @notice Get the total number of validators in the registry. Includes active, inactive, and banned validators. + * @return count The total count of validators + */ + function validatorCount() external view returns (uint8 count); + + /** + * @notice Get the current bitmap of active validators + * @return bitmap The bitmap representing which validators are currently active + */ + function activeValidatorBitmap() external view returns (uint256 bitmap); + + /** + * @notice Add a new validator to the registry and activate them. Modifies the current validator set + * therefore creates a new snapshot. + * @param validator The address of the validator to add + * @dev Only callable by the contract owner + */ + function addValidator(address validator) external; + + /** + * @notice Ban a validator from the registry. + * If they are active, they are deactivated first. Modifies the current validator set + * therefore creates a new snapshot. + * @param validator The address of the validator to ban + * @dev Only callable by the contract owner + */ + function banValidator(address validator) external; + + /** + * @notice Unban a previously banned validator. Does not automatically reactivate the validator. + * Hence, it does not modify the current validator set, so no new snapshot is created. + * @param validator The address of the validator to unban + * @dev Only callable by the contract owner + */ + function unbanValidator(address validator) external; + + /** + * @notice Deactivate the caller's validator status. Modifies the current validator set + * therefore creates a new snapshot. + * @dev Only callable by registered validators + */ + function deactivate() external; + + /** + * @notice Reactivate the caller's validator status. Modifies the current validator set + * therefore creates a new snapshot. + * @dev Only callable by registered validators who are not banned + */ + function reactivate() external; + + /** + * @notice Compute the weight of a subset of currently active validators + * @param subset Array of validator addresses to compute weight for + * @return weight The computed weight (count of unique active validators in the subset) + * @dev Uses the most recent snapshot for computation + */ + function computeWeight(address[] memory subset) external view returns (uint256 weight); + + /** + * @notice Compute the weight of a subset of validators at a specific historical point + * @param subset Array of validator addresses to compute weight for + * @param timestamp The timestamp to compute weight at + * @param snapshotIndex The snapshot index to use for computation + * @return weight The computed weight at the specified historical point + * @dev Validates that the snapshot is appropriate for the given timestamp + */ + function computeWeight(address[] memory subset, uint256 timestamp, uint256 snapshotIndex) + external + view + returns (uint256 weight); + + /** + * @notice Find the appropriate snapshot index for a given timestamp + * Since this is a view function, it can be called off-chain to compute the correct snapshotIndex + * corresponding to a particular timestamp. + * Then, the function computeWeight can be called on-chain with the correct snapshotIndex. + * The function also supports a fast path: scan the last few snapshots linearly before falling + * back to binary search. This is useful when we expect to validate recent certificates. + * @param timestamp The timestamp to find a snapshot for + * @return snapshotIndex The index of the most recent snapshot at or before the timestamp + * @dev Uses binary search for efficient lookup + */ + function findSnapshotIndex(uint256 timestamp) external view returns (uint256 snapshotIndex); + + /** + * @notice Get the count of currently active validators + * @return count The number of active validators + */ + function getActiveValidatorCount() external view returns (uint8 count); + + /** + * @notice Get the count of validators at a specific snapshot + * @param snapshotIndex The snapshot index to query + * @return count The number of validators at the specified snapshot + */ + function getValidatorCountAtIndex(uint256 snapshotIndex) external view returns (uint8 count); + + /** + * @notice Get all currently active validators + * @return Array of addresses of currently active validators + */ + function getActiveValidators() external view returns (address[] memory); + + /** + * @notice Get all validators that were active at a specific timestamp + * @param timestamp The timestamp to query + * @return Array of addresses of validators active at the specified timestamp + */ + function getActiveValidatorsAtTimestamp(uint256 timestamp) external view returns (address[] memory); + + /** + * @notice Get all validators at a specific snapshot + * @param snapshotIndex The snapshot index to query + * @return Array of addresses of validators at the specified snapshot + */ + function getValidatorsAtIndex(uint256 snapshotIndex) external view returns (address[] memory); + + /** + * @notice Get snapshot details at a specific index + * @param snapshotIndex The snapshot index to query + * @return activeAsOfTimestamp The timestamp when the snapshot was created + * @return bitmap The bitmap of active validators at this snapshot + */ + function getSnapshotAtIndex(uint256 snapshotIndex) + external + view + returns (uint256 activeAsOfTimestamp, uint256 bitmap); + + /** + * @notice Get the total number of snapshots in the history + * @return The length of the snapshot history + */ + function getHistoryLength() external view returns (uint256); +} diff --git a/solidity-sdk/src/verifier/PodECDSA.sol b/solidity-sdk/src/verifier/PodECDSA.sol index e9551d05..127201d1 100644 --- a/solidity-sdk/src/verifier/PodECDSA.sol +++ b/solidity-sdk/src/verifier/PodECDSA.sol @@ -9,8 +9,8 @@ import {Math} from "@openzeppelin/contracts/utils/math/Math.sol"; library PodECDSA { struct PodConfig { - uint256 thresholdNumerator; - uint256 thresholdDenominator; + uint8 thresholdNumerator; + uint8 thresholdDenominator; IPodRegistry registry; } @@ -23,7 +23,7 @@ library PodECDSA { struct CertifiedReceipt { bytes32 receiptRoot; bytes aggregateSignature; - uint256 medianTimestamp; + uint256[] sortedAttestationTimestamps; } struct Certificate { @@ -44,16 +44,46 @@ library PodECDSA { MerkleTree.MultiProof proof; } + error InvalidTimestamps(); + error InvalidCertificate(); + error InvalidThreshold(); + function hashLog(Log calldata log) public pure returns (bytes32) { return keccak256(abi.encode(log)); } + function _getMedianTimestamp(uint256[] memory sortedAttestationTimestamps) internal pure returns (uint256) { + if (sortedAttestationTimestamps.length == 0) { + return 0; + } + + if (sortedAttestationTimestamps.length == 1) { + return sortedAttestationTimestamps[0]; + } + + for (uint256 i = 0; i < sortedAttestationTimestamps.length - 1; i++) { + if (sortedAttestationTimestamps[i] > sortedAttestationTimestamps[i + 1]) { + revert InvalidTimestamps(); + } + } + + if (sortedAttestationTimestamps.length % 2 == 1) { + return sortedAttestationTimestamps[sortedAttestationTimestamps.length / 2]; + } else { + return ( + sortedAttestationTimestamps[sortedAttestationTimestamps.length / 2] + + sortedAttestationTimestamps[sortedAttestationTimestamps.length / 2 - 1] + ) / 2; + } + } + function verifyCertifiedReceipt(PodConfig calldata podConfig, CertifiedReceipt calldata certifiedReceipt) public view returns (bool) { - uint256 snapshotIndex = podConfig.registry.findSnapshotIndex(certifiedReceipt.medianTimestamp); + uint256 medianTimestamp = _getMedianTimestamp(certifiedReceipt.sortedAttestationTimestamps); + uint256 snapshotIndex = podConfig.registry.findSnapshotIndex(medianTimestamp); return verifyCertifiedReceipt(podConfig, certifiedReceipt, snapshotIndex); } @@ -62,10 +92,19 @@ library PodECDSA { CertifiedReceipt calldata certifiedReceipt, uint256 snapshotIndex ) public view returns (bool) { + if ( + podConfig.thresholdNumerator > podConfig.thresholdDenominator || podConfig.thresholdNumerator > 100 + || podConfig.thresholdDenominator > 100 + ) { + revert InvalidThreshold(); + } + address[] memory validators = ECDSA.recoverSigners(certifiedReceipt.receiptRoot, certifiedReceipt.aggregateSignature); - uint256 weight = podConfig.registry.computeWeight(validators, certifiedReceipt.medianTimestamp, snapshotIndex); + uint256 medianTimestamp = _getMedianTimestamp(certifiedReceipt.sortedAttestationTimestamps); + uint256 weight = podConfig.registry.computeWeight(validators, medianTimestamp, snapshotIndex); + uint256 threshold = Math.mulDiv( podConfig.registry.getValidatorCountAtIndex(snapshotIndex), podConfig.thresholdNumerator, @@ -81,7 +120,8 @@ library PodECDSA { view returns (bool) { - uint256 snapshotIndex = podConfig.registry.findSnapshotIndex(certificate.certifiedReceipt.medianTimestamp); + uint256 medianTimestamp = _getMedianTimestamp(certificate.certifiedReceipt.sortedAttestationTimestamps); + uint256 snapshotIndex = podConfig.registry.findSnapshotIndex(medianTimestamp); return verifyCertificate(podConfig, certificate, snapshotIndex); } @@ -99,7 +139,8 @@ library PodECDSA { view returns (bool) { - uint256 snapshotIndex = podConfig.registry.findSnapshotIndex(certificate.certifiedReceipt.medianTimestamp); + uint256 medianTimestamp = _getMedianTimestamp(certificate.certifiedReceipt.sortedAttestationTimestamps); + uint256 snapshotIndex = podConfig.registry.findSnapshotIndex(medianTimestamp); return verifyMultiCertificate(podConfig, certificate, snapshotIndex); } @@ -117,8 +158,9 @@ library PodECDSA { view returns (bool) { - uint256 snapshotIndex = - podConfig.registry.findSnapshotIndex(certifiedLog.certificate.certifiedReceipt.medianTimestamp); + uint256 medianTimestamp = + _getMedianTimestamp(certifiedLog.certificate.certifiedReceipt.sortedAttestationTimestamps); + uint256 snapshotIndex = podConfig.registry.findSnapshotIndex(medianTimestamp); return verifyCertifiedLog(podConfig, certifiedLog, snapshotIndex); } @@ -133,7 +175,9 @@ library PodECDSA { bytes(string.concat("log_hashes[", Strings.toString(certifiedLog.logIndex), "]")), logHash ); - require(leaf == certifiedLog.certificate.leaf, "Invalid certificate"); + if (leaf != certifiedLog.certificate.leaf) { + revert InvalidCertificate(); + } return verifyCertificate(podConfig, certifiedLog.certificate, snapshotIndex); } diff --git a/solidity-sdk/src/verifier/PodRegistry.sol b/solidity-sdk/src/verifier/PodRegistry.sol index a6820e0e..3048a6f8 100644 --- a/solidity-sdk/src/verifier/PodRegistry.sol +++ b/solidity-sdk/src/verifier/PodRegistry.sol @@ -2,257 +2,47 @@ pragma solidity ^0.8.20; import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; - -/** - * @title IPodRegistry - * @notice Interface for the Pod Registry contract that manages the validator committee and committee rotation. - * @dev This interface defines the core functionality for committee rotation. It is responsible - * for adding, banning, unbanning, activating and deactivating validators. It also provides - * ways to compute the weight of a subset of validators at a specific timestamp. - * In order to allow this, snapshots are created whenever the validator set changes. - */ -interface IPodRegistry { - /** - * @notice Represents a snapshot of the validator set at a specific timestamp - * @param activeAsOfTimestamp The timestamp when this snapshot was created - * @param bitmap Bitmap representing which validators were active at this snapshot - */ - struct Snapshot { - uint256 activeAsOfTimestamp; - uint256 bitmap; - } - - /// @notice Error thrown when too many initial validators are provided - error TooManyInitialValidators(); - - /// @notice Error thrown when a validator is a zero address - error ValidatorIsZeroAddress(); - - /// @notice Error thrown when a validator already exists - error ValidatorAlreadyExists(); - - /// @notice Error thrown when the maximum validator count is reached - error MaxValidatorCountReached(); - - /// @notice Error thrown when a validator does not exist - error ValidatorDoesNotExist(); - - /// @notice Error thrown when a validator is already banned - error ValidatorAlreadyBanned(); - - /// @notice Error thrown when a validator is not banned - error ValidatorNotBanned(); - - /// @notice Error thrown when the caller is not a validator - error CallerNotValidator(); - - /// @notice Error thrown when the caller is already inactive - error CallerAlreadyInactive(); - - /// @notice Error thrown when the caller is already banned - error CallerAlreadyBanned(); - - /// @notice Error thrown when the caller is already active - error CallerAlreadyActive(); - - /// @notice Error thrown when the snapshot index is invalid - error InvalidSnapshotIndex(); - - /// @notice Error thrown when the snapshot is too new - error SnapshotTooNew(); - - /// @notice Error thrown when the snapshot is too old - error SnapshotTooOld(); - - /// @notice Error thrown when there are no historical snapshots - error NoHistoricalSnapshots(); - - /// @notice Event emitted when a validator is added - event ValidatorAdded(address indexed validator); - - /// @notice Event emitted when a validator is banned - event ValidatorBanned(address indexed validator); - - /// @notice Event emitted when a validator is unbanned - event ValidatorUnbanned(address indexed validator); - - /// @notice Event emitted when a validator is deactivated - event ValidatorDeactivated(address indexed validator); - - /// @notice Event emitted when a validator is reactivated - event ValidatorReactivated(address indexed validator); - - /// @notice Event emitted when a snapshot is created - event SnapshotCreated(uint256 indexed activeAsOfTimestamp, uint256 bitmap); - - /** - * @notice Get the index of a validator in the registry - * @param validator The address of the validator - * @return index The 1-based index of the validator (0 if not found) - */ - function validatorIndex(address validator) external view returns (uint8 index); - - /** - * @notice Check if a validator is banned - * @param validator The address of the validator - * @return isBanned True if the validator is banned, false otherwise - */ - function isValidatorBanned(address validator) external view returns (bool isBanned); - - /** - * @notice Get the total number of validators in the registry. Counts banned and active validators too. - * @return count The total count of validators - */ - function validatorCount() external view returns (uint8 count); - - /** - * @notice Get the current bitmap of active validators - * @return bitmap The bitmap representing which validators are currently active - */ - function activeValidatorBitmap() external view returns (uint256 bitmap); - - /** - * @notice Add a new validator to the registry and activates them. Modifies the current validator set - * therefore creates a new snapshot. - * @param validator The address of the validator to add - * @dev Only callable by the contract owner - */ - function addValidator(address validator) external; - - /** - * @notice Ban a validator from the registry - * if they are active, they are deactivated first. Modifies the current validator set - * therefore creates a new snapshot. - * @param validator The address of the validator to ban - * @dev Only callable by the contract owner - */ - function banValidator(address validator) external; - - /** - * @notice Unban a previously banned validator. Does not automatically reactivate the validator. - * So it does not modify the current validator set. - * @param validator The address of the validator to unban - * @dev Only callable by the contract owner - */ - function unbanValidator(address validator) external; - - /** - * @notice Deactivate the caller's validator status. Modifies the current validator set - * therefore creates a new snapshot. - * @dev Only callable by registered validators - */ - function deactivate() external; - - /** - * @notice Reactivate the caller's validator status. Modifies the current validator set - * therefore creates a new snapshot. - * @dev Only callable by registered validators who are not banned - */ - function reactivate() external; - - /** - * @notice Compute the weight of a subset of validators at the current time - * @param subset Array of validator addresses to compute weight for - * @return weight The computed weight (count of unique active validators in the subset) - * @dev Uses the most recent snapshot for computation - */ - function computeWeight(address[] memory subset) external view returns (uint256 weight); - - /** - * @notice Compute the weight of a subset of validators at a specific historical point - * @param subset Array of validator addresses to compute weight for - * @param timestamp The timestamp to compute weight at - * @param snapshotIndex The snapshot index to use for computation - * @return weight The computed weight at the specified historical point - * @dev Validates that the snapshot is appropriate for the given timestamp - */ - function computeWeight(address[] memory subset, uint256 timestamp, uint256 snapshotIndex) - external - view - returns (uint256 weight); - - /** - * @notice Find the appropriate snapshot index for a given timestamp - * Since this is a view function, it can be called off-chain to compute the correct snapshotIndex - * corresponding to a particular timestamp. - * Then, the function computeWeight can be called on-chain with the correct snapshotIndex. - * The function also supports a fast path: scan the last few snapshots linearly before falling - * back to binary search. This is useful when we expect to validate recent certificates. - * @param timestamp The timestamp to find a snapshot for - * @return snapshotIndex The index of the most recent snapshot at or before the timestamp - * @dev Uses binary search for efficient lookup - */ - function findSnapshotIndex(uint256 timestamp) external view returns (uint256 snapshotIndex); - - /** - * @notice Get the count of currently active validators - * @return count The number of active validators - */ - function getActiveValidatorCount() external view returns (uint8 count); - - /** - * @notice Get the count of validators at a specific snapshot - * @param snapshotIndex The snapshot index to query - * @return count The number of validators at the specified snapshot - */ - function getValidatorCountAtIndex(uint256 snapshotIndex) external view returns (uint8 count); - - /** - * @notice Get all currently active validators - * @return Array of addresses of currently active validators - */ - function getActiveValidators() external view returns (address[] memory); - - /** - * @notice Get all validators that were active at a specific timestamp - * @param timestamp The timestamp to query - * @return Array of addresses of validators active at the specified timestamp - */ - function getActiveValidatorsAtTimestamp(uint256 timestamp) external view returns (address[] memory); - - /** - * @notice Get all validators at a specific snapshot - * @param snapshotIndex The snapshot index to query - * @return Array of addresses of validators at the specified snapshot - */ - function getValidatorsAtIndex(uint256 snapshotIndex) external view returns (address[] memory); - - /** - * @notice Get snapshot details at a specific index - * @param snapshotIndex The snapshot index to query - * @return activeAsOfTimestamp The timestamp when the snapshot was created - * @return bitmap The bitmap of active validators at this snapshot - */ - function getSnapshotAtIndex(uint256 snapshotIndex) - external - view - returns (uint256 activeAsOfTimestamp, uint256 bitmap); - - /** - * @notice Get the total number of snapshots in the history - * @return The length of the snapshot history - */ - function getHistoryLength() external view returns (uint256); -} +import {IPodRegistry} from "../interfaces/IPodRegistry.sol"; /** * @title PodRegistry - * @notice Manages a dynamic set of validators with historical snapshots for quorum verification + * @notice Manages a dynamic set of validators with historical snapshots for quorum verification. + * This is the source of truth for what the active pod validator set is at any given timestamp. * @dev This contract maintains a bitmap-based validator set with the ability to create * historical snapshots for quorum verification of certificates signed by previously active committees. * It supports up to 255 validators * and uses bitmap operations for validator status tracking. + * Additionally, the 255 + * * * @custom:security This contract is Ownable and should only be deployed with trusted ownership */ contract PodRegistry is IPodRegistry, Ownable { - /// @notice Maximum number of validators allowed in the registry + /** + * @notice Maximum number of validators allowed in the registry + * @dev IMPORTANT: This is a hard limit on the total number of validators that can ever be registered. + * When a validator is banned/deactivated, their index position becomes permanently unavailable. + * New validators cannot reuse the indices of removed validators, so the effective capacity + * decreases over time. To maintain full capacity, you must either: + * 1) Unban/reactivate the same validator, or + * 2) Implement a validator replacement mechanism that reuses indices + */ uint256 constant MAX_VALIDATOR_COUNT = 255; - /// @notice Array of historical snapshots for time-based verification + /** + * @notice Number of snapshots to check when finding the closest snapshot to a given timestamp before + * falling back to binary search. + */ + uint256 constant CHECK_COUNT = 3; + + /** + * @notice Array of historical snapshots for time-based verification + */ Snapshot[] public history; - /// @notice Mapping from validator address to their 1-based index + /** + * @notice Mapping from validator address to their 1-based index + */ mapping(address => uint8) public validatorIndex; /** @@ -261,10 +51,14 @@ contract PodRegistry is IPodRegistry, Ownable { */ address[] public validators; - /// @notice Bitmap of the currently active validators + /** + * @notice Bitmap of the currently active validators + */ uint256 public activeValidatorBitmap; - /// @notice Bitmap of the currently banned validators + /** + * @notice Bitmap of the currently banned validators + */ uint256 public bannedValidatorBitmap; /** @@ -274,10 +68,6 @@ contract PodRegistry is IPodRegistry, Ownable { * @dev The contract owner will be set to msg.sender */ constructor(address[] memory initialValidators) Ownable(msg.sender) { - if (initialValidators.length >= MAX_VALIDATOR_COUNT) { - revert TooManyInitialValidators(); - } - for (uint8 i = 0; i < initialValidators.length; i++) { _addValidator(initialValidators[i]); activeValidatorBitmap |= (1 << i); @@ -298,6 +88,9 @@ contract PodRegistry is IPodRegistry, Ownable { if (validatorIndex[validator] != 0) { revert ValidatorAlreadyExists(); } + if (validators.length >= MAX_VALIDATOR_COUNT) { + revert MaxValidatorCountReached(); + } validators.push(validator); validatorIndex[validator] = uint8(validators.length); @@ -307,12 +100,11 @@ contract PodRegistry is IPodRegistry, Ownable { * @inheritdoc IPodRegistry */ function addValidator(address validator) external onlyOwner { - if (validators.length >= MAX_VALIDATOR_COUNT) { - revert MaxValidatorCountReached(); - } _addValidator(validator); + uint8 index = uint8(validators.length); _activateValidator(index); + emit ValidatorAdded(validator); } @@ -325,9 +117,8 @@ contract PodRegistry is IPodRegistry, Ownable { revert ValidatorDoesNotExist(); } if (_isValidatorBanned(index)) { - revert ValidatorAlreadyBanned(); + revert CallerBanned(); } - if (_isValidatorActive(index)) { _deactivateValidator(index); } @@ -347,6 +138,7 @@ contract PodRegistry is IPodRegistry, Ownable { if (!_isValidatorBanned(index)) { revert ValidatorNotBanned(); } + bannedValidatorBitmap = _clearBit(bannedValidatorBitmap, index - 1); emit ValidatorUnbanned(validator); } @@ -362,6 +154,7 @@ contract PodRegistry is IPodRegistry, Ownable { if (!_isValidatorActive(index)) { revert CallerAlreadyInactive(); } + _deactivateValidator(index); emit ValidatorDeactivated(msg.sender); } @@ -375,11 +168,12 @@ contract PodRegistry is IPodRegistry, Ownable { revert CallerNotValidator(); } if (_isValidatorBanned(index)) { - revert CallerAlreadyBanned(); + revert CallerBanned(); } if (_isValidatorActive(index)) { revert CallerAlreadyActive(); } + _activateValidator(index); emit ValidatorReactivated(msg.sender); } @@ -424,10 +218,8 @@ contract PodRegistry is IPodRegistry, Ownable { } uint256 counted = 0; - for (uint256 i = 0; i < subset.length; i++) { uint8 index = validatorIndex[subset[i]]; - if (index == 0) { continue; } @@ -447,10 +239,11 @@ contract PodRegistry is IPodRegistry, Ownable { revert NoHistoricalSnapshots(); } - for (uint256 i = 0; i < 3; i++) { + for (uint256 i = 0; i < CHECK_COUNT; i++) { if (i >= history.length) { break; } + uint256 idx = history.length - 1 - i; if (history[idx].activeAsOfTimestamp <= timestamp) { return idx; @@ -487,19 +280,6 @@ contract PodRegistry is IPodRegistry, Ownable { return _popCount(bitmap); } - /** - * @notice Count the number of set bits in a bitmap (pop count) - * @param bitmap The bitmap to count set bits in - * @return count The number of set bits - * @dev Efficient implementation using Brian Kernighan's algorithm - */ - function _popCount(uint256 bitmap) internal pure returns (uint8 count) { - while (bitmap != 0) { - count++; - bitmap &= bitmap - 1; - } - } - /** * @inheritdoc IPodRegistry */ @@ -624,11 +404,36 @@ contract PodRegistry is IPodRegistry, Ownable { return (bitmap & (1 << i)) != 0; } + /** + * @notice Set a specific bit in a bitmap + * @param bitmap The bitmap to set the bit in + * @param i The 0-based bit position to set + * @return The bitmap with the bit set + */ function _setBit(uint256 bitmap, uint8 i) internal pure returns (uint256) { return bitmap | (1 << i); } + /** + * @notice Clear a specific bit in a bitmap + * @param bitmap The bitmap to clear the bit in + * @param i The 0-based bit position to clear + * @return The bitmap with the bit cleared + */ function _clearBit(uint256 bitmap, uint8 i) internal pure returns (uint256) { return bitmap & ~(1 << i); } + + /** + * @notice Count the number of set bits in a bitmap (pop count) + * @param bitmap The bitmap to count set bits in + * @return count The number of set bits + * @dev Efficient implementation using Brian Kernighan's algorithm + */ + function _popCount(uint256 bitmap) internal pure returns (uint8 count) { + while (bitmap != 0) { + count++; + bitmap &= bitmap - 1; + } + } } diff --git a/solidity-sdk/test/PodECDSA.t.sol b/solidity-sdk/test/PodECDSA.t.sol index ffddbac3..8967f7de 100644 --- a/solidity-sdk/test/PodECDSA.t.sol +++ b/solidity-sdk/test/PodECDSA.t.sol @@ -54,7 +54,7 @@ contract PodECDSATest is Test { certifiedReceipt: PodECDSA.CertifiedReceipt({ receiptRoot: receiptRoot, aggregateSignature: aggregateSignature, - medianTimestamp: attestationTimestamps[attestationTimestamps.length / 2] + sortedAttestationTimestamps: attestationTimestamps }), proof: MerkleTree.Proof({path: path}) }); @@ -112,7 +112,7 @@ contract PodECDSATest is Test { certifiedReceipt: PodECDSA.CertifiedReceipt({ receiptRoot: receiptRoot, aggregateSignature: aggregateSignature, - medianTimestamp: attestationTimestamps[attestationTimestamps.length / 2] + sortedAttestationTimestamps: attestationTimestamps }), proof: MerkleTree.MultiProof({path: path, flags: flags}) }); @@ -137,7 +137,7 @@ contract PodECDSATest is Test { PodECDSA.CertifiedReceipt memory receipt = PodECDSA.CertifiedReceipt({ receiptRoot: receiptRoot, aggregateSignature: aggregateSignature, - medianTimestamp: attestationTimestamps[attestationTimestamps.length / 2] + sortedAttestationTimestamps: attestationTimestamps }); bytes32[] memory topics = new bytes32[](4); @@ -207,7 +207,7 @@ contract PodECDSATest is Test { PodECDSA.CertifiedReceipt memory receipt = PodECDSA.CertifiedReceipt({ receiptRoot: receiptRoot, aggregateSignature: aggregateSignature, - medianTimestamp: medianTimestamp + sortedAttestationTimestamps: attestationTimestamps }); PodECDSA.PodConfig memory podConfig = @@ -216,7 +216,7 @@ contract PodECDSATest is Test { assertTrue(podRegistry.getHistoryLength() == 2); } - function test_verifyOld() public { + function test_verifyWithOldSnapshot() public { bytes32 receiptRoot = 0x32bf7ef0c0291bc3b73afd18a62cca74ff8ee51c801b8b619c360e1c1dac9c84; bytes[] memory signatures = new bytes[](validatorPrivateKeys.length); uint256[] memory attestationTimestamps = new uint256[](validatorPrivateKeys.length); @@ -233,7 +233,7 @@ contract PodECDSATest is Test { PodECDSA.CertifiedReceipt memory receipt = PodECDSA.CertifiedReceipt({ receiptRoot: receiptRoot, aggregateSignature: aggregateSignature, - medianTimestamp: medianTimestamp + sortedAttestationTimestamps: attestationTimestamps }); uint256 snapshotIndex = podRegistry.findSnapshotIndex(medianTimestamp); @@ -255,7 +255,7 @@ contract PodECDSATest is Test { assertTrue(podRegistry.getHistoryLength() == 4); } - function test_verifyBeforeTresholdFails() public view { + function test_verify_RevertIfNoTresholdSignatures() public view { bytes32 receiptRoot = 0x32bf7ef0c0291bc3b73afd18a62cca74ff8ee51c801b8b619c360e1c1dac9c84; uint256 threshold = Math.mulDiv(validatorPrivateKeys.length, 2, 3, Math.Rounding.Ceil); bytes[] memory signatures = new bytes[](threshold - 1); @@ -271,7 +271,7 @@ contract PodECDSATest is Test { PodECDSA.CertifiedReceipt memory receipt = PodECDSA.CertifiedReceipt({ receiptRoot: receiptRoot, aggregateSignature: aggregateSignature, - medianTimestamp: attestationTimestamps[attestationTimestamps.length / 2] + sortedAttestationTimestamps: attestationTimestamps }); PodECDSA.PodConfig memory podConfig = @@ -279,7 +279,7 @@ contract PodECDSATest is Test { assertFalse(PodECDSA.verifyCertifiedReceipt(podConfig, receipt)); } - function test_verifyExactlyThresholdPasses() public view { + function test_verifyExactThresholdSignatures() public view { bytes32 receiptRoot = 0x32bf7ef0c0291bc3b73afd18a62cca74ff8ee51c801b8b619c360e1c1dac9c84; uint256 threshold = Math.mulDiv(validatorPrivateKeys.length, 4, 5, Math.Rounding.Ceil); bytes[] memory signatures = new bytes[](threshold); @@ -295,11 +295,80 @@ contract PodECDSATest is Test { PodECDSA.CertifiedReceipt memory receipt = PodECDSA.CertifiedReceipt({ receiptRoot: receiptRoot, aggregateSignature: aggregateSignature, - medianTimestamp: attestationTimestamps[attestationTimestamps.length / 2] + sortedAttestationTimestamps: attestationTimestamps }); PodECDSA.PodConfig memory podConfig = PodECDSA.PodConfig({thresholdNumerator: 4, thresholdDenominator: 5, registry: podRegistry}); assertTrue(PodECDSA.verifyCertifiedReceipt(podConfig, receipt)); } + + function test_verify_RevertIfUnsortedMedianTimestamp() public { + bytes32 receiptRoot = 0x32bf7ef0c0291bc3b73afd18a62cca74ff8ee51c801b8b619c360e1c1dac9c84; + bytes[] memory signatures = new bytes[](validatorPrivateKeys.length); + uint256[] memory attestationTimestamps = new uint256[](validatorPrivateKeys.length); + for (uint256 i = 0; i < validatorPrivateKeys.length; i++) { + (uint8 v, bytes32 r, bytes32 s) = vm.sign(validatorPrivateKeys[i], receiptRoot); + signatures[i] = ECDSA._serialize_signature(v, r, s); + attestationTimestamps[i] = i + 1; + } + + attestationTimestamps[0] = 2; + attestationTimestamps[1] = 1; + + bytes memory aggregateSignature = ECDSA.aggregate_signatures(signatures); + + PodECDSA.CertifiedReceipt memory receipt = PodECDSA.CertifiedReceipt({ + receiptRoot: receiptRoot, + aggregateSignature: aggregateSignature, + sortedAttestationTimestamps: attestationTimestamps + }); + + PodECDSA.PodConfig memory podConfig = + PodECDSA.PodConfig({thresholdNumerator: 2, thresholdDenominator: 3, registry: podRegistry}); + + vm.expectRevert(abi.encodeWithSignature("InvalidTimestamps()")); + PodECDSA.verifyCertifiedReceipt(podConfig, receipt); + } + + function _getReceipt() internal view returns (PodECDSA.CertifiedReceipt memory) { + bytes32 receiptRoot = 0x32bf7ef0c0291bc3b73afd18a62cca74ff8ee51c801b8b619c360e1c1dac9c84; + bytes[] memory signatures = new bytes[](validatorPrivateKeys.length); + uint256[] memory attestationTimestamps = new uint256[](validatorPrivateKeys.length); + for (uint256 i = 0; i < validatorPrivateKeys.length; i++) { + (uint8 v, bytes32 r, bytes32 s) = vm.sign(validatorPrivateKeys[i], receiptRoot); + signatures[i] = ECDSA._serialize_signature(v, r, s); + attestationTimestamps[i] = i + 1; + } + + bytes memory aggregateSignature = ECDSA.aggregate_signatures(signatures); + + PodECDSA.CertifiedReceipt memory receipt = PodECDSA.CertifiedReceipt({ + receiptRoot: receiptRoot, + aggregateSignature: aggregateSignature, + sortedAttestationTimestamps: attestationTimestamps + }); + + return receipt; + } + + function test_verify_RevertIfInvalidThreshold() public { + PodECDSA.CertifiedReceipt memory receipt = _getReceipt(); + PodECDSA.PodConfig memory podConfig = + PodECDSA.PodConfig({thresholdNumerator: 101, thresholdDenominator: 100, registry: podRegistry}); + vm.expectRevert(abi.encodeWithSignature("InvalidThreshold()")); + PodECDSA.verifyCertifiedReceipt(podConfig, receipt); + + podConfig = PodECDSA.PodConfig({thresholdNumerator: 100, thresholdDenominator: 101, registry: podRegistry}); + vm.expectRevert(abi.encodeWithSignature("InvalidThreshold()")); + PodECDSA.verifyCertifiedReceipt(podConfig, receipt); + + podConfig = PodECDSA.PodConfig({thresholdNumerator: 0, thresholdDenominator: 0, registry: podRegistry}); + vm.expectRevert(); + PodECDSA.verifyCertifiedReceipt(podConfig, receipt); + + podConfig = PodECDSA.PodConfig({thresholdNumerator: 87, thresholdDenominator: 55, registry: podRegistry}); + vm.expectRevert(abi.encodeWithSignature("InvalidThreshold()")); + PodECDSA.verifyCertifiedReceipt(podConfig, receipt); + } } diff --git a/solidity-sdk/test/PodRegistry.t.sol b/solidity-sdk/test/PodRegistry.t.sol index d0e163da..e0adec5c 100644 --- a/solidity-sdk/test/PodRegistry.t.sol +++ b/solidity-sdk/test/PodRegistry.t.sol @@ -57,15 +57,6 @@ contract PodRegistryTest is Test { registry.addValidator(validator1); } - function test_Initialize_RevertIfTooManyValidators() public { - address[] memory initialValidators = new address[](255); - for (uint8 i = 0; i < 255; i++) { - initialValidators[i] = address(uint160(1000 + i)); - } - vm.expectRevert(abi.encodeWithSignature("TooManyInitialValidators()")); - new PodRegistry(initialValidators); - } - function test_AddValidator_RevertIfMaxCountReached() public { vm.startPrank(owner); for (uint8 i = 0; i < 253; i++) { @@ -118,7 +109,7 @@ contract PodRegistryTest is Test { registry.banValidator(validator1); vm.prank(owner); - vm.expectRevert(abi.encodeWithSignature("ValidatorAlreadyBanned()")); + vm.expectRevert(abi.encodeWithSignature("CallerBanned()")); registry.banValidator(validator1); } @@ -149,7 +140,7 @@ contract PodRegistryTest is Test { registry.banValidator(validator1); vm.prank(validator1); - vm.expectRevert(abi.encodeWithSignature("CallerAlreadyBanned()")); + vm.expectRevert(abi.encodeWithSignature("CallerBanned()")); registry.reactivate(); vm.prank(owner); @@ -212,7 +203,7 @@ contract PodRegistryTest is Test { registry.banValidator(validator1); vm.prank(validator1); - vm.expectRevert(abi.encodeWithSignature("CallerAlreadyBanned()")); + vm.expectRevert(abi.encodeWithSignature("CallerBanned()")); registry.reactivate(); } @@ -221,7 +212,7 @@ contract PodRegistryTest is Test { registry.banValidator(validator1); vm.prank(validator1); - vm.expectRevert(abi.encodeWithSignature("CallerAlreadyBanned()")); + vm.expectRevert(abi.encodeWithSignature("CallerBanned()")); registry.reactivate(); } From 9b21a858b296dd9bd2fce7ec2aa748781c4840aa Mon Sep 17 00:00:00 2001 From: Jakov Mitrovski Date: Wed, 20 Aug 2025 14:45:04 +0200 Subject: [PATCH 30/64] update optimistic auction to reflect registry changes, update log type to expose sorted timestamps and sorted attestations --- examples/optimistic-auction/.env.example | 2 +- .../bindings/src/pod_auction_consumer.rs | 204 +++++++++--------- examples/optimistic-auction/client/main.rs | 2 +- .../test/PodAuctionConsumer.t.sol | 4 +- types/src/ledger/log.rs | 24 +++ 5 files changed, 136 insertions(+), 100 deletions(-) diff --git a/examples/optimistic-auction/.env.example b/examples/optimistic-auction/.env.example index 6d361b1c..029bec83 100644 --- a/examples/optimistic-auction/.env.example +++ b/examples/optimistic-auction/.env.example @@ -1,6 +1,6 @@ PRIVATE_KEY_1= PRIVATE_KEY_2= -AUCTION_CONTRACT_ADDRESS=0x217F5658c6ecC27D439922263AD9Bb8e992e0373 +AUCTION_CONTRACT_ADDRESS=0xf6D39FB8492dC21293043f5E39F566D4A4ce2206 CONSUMER_CONTRACT_ADDRESS= POD_RPC_URL=ws://localhost:8545 CONSUMER_RPC_URL=http://localhost:8546 \ No newline at end of file diff --git a/examples/optimistic-auction/bindings/src/pod_auction_consumer.rs b/examples/optimistic-auction/bindings/src/pod_auction_consumer.rs index 336a4d06..40ec5fbe 100644 --- a/examples/optimistic-auction/bindings/src/pod_auction_consumer.rs +++ b/examples/optimistic-auction/bindings/src/pod_auction_consumer.rs @@ -348,7 +348,7 @@ See the [wrapper's documentation](`MerkleTreeInstance`) for more details.*/ library PodECDSA { struct Certificate { CertifiedReceipt certifiedReceipt; bytes32 leaf; MerkleTree.Proof proof; } struct CertifiedLog { Log log; uint256 logIndex; Certificate certificate; } - struct CertifiedReceipt { bytes32 receiptRoot; bytes aggregateSignature; uint256 medianTimestamp; } + struct CertifiedReceipt { bytes32 receiptRoot; bytes aggregateSignature; uint256[] sortedAttestationTimestamps; } struct Log { address addr; bytes32[] topics; bytes data; } } ```*/ @@ -865,7 +865,7 @@ struct CertifiedLog { Log log; uint256 logIndex; Certificate certificate; } #[derive(serde::Serialize, serde::Deserialize)] #[derive(Default, Debug, PartialEq, Eq, Hash)] /**```solidity -struct CertifiedReceipt { bytes32 receiptRoot; bytes aggregateSignature; uint256 medianTimestamp; } +struct CertifiedReceipt { bytes32 receiptRoot; bytes aggregateSignature; uint256[] sortedAttestationTimestamps; } ```*/ #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] #[derive(Clone)] @@ -875,7 +875,9 @@ struct CertifiedReceipt { bytes32 receiptRoot; bytes aggregateSignature; uint256 #[allow(missing_docs)] pub aggregateSignature: alloy::sol_types::private::Bytes, #[allow(missing_docs)] - pub medianTimestamp: alloy::sol_types::private::primitives::aliases::U256, + pub sortedAttestationTimestamps: alloy::sol_types::private::Vec< + alloy::sol_types::private::primitives::aliases::U256, + >, } #[allow( non_camel_case_types, @@ -889,13 +891,15 @@ struct CertifiedReceipt { bytes32 receiptRoot; bytes aggregateSignature; uint256 type UnderlyingSolTuple<'a> = ( alloy::sol_types::sol_data::FixedBytes<32>, alloy::sol_types::sol_data::Bytes, - alloy::sol_types::sol_data::Uint<256>, + alloy::sol_types::sol_data::Array>, ); #[doc(hidden)] type UnderlyingRustTuple<'a> = ( alloy::sol_types::private::FixedBytes<32>, alloy::sol_types::private::Bytes, - alloy::sol_types::private::primitives::aliases::U256, + alloy::sol_types::private::Vec< + alloy::sol_types::private::primitives::aliases::U256, + >, ); #[cfg(test)] #[allow(dead_code, unreachable_patterns)] @@ -912,7 +916,11 @@ struct CertifiedReceipt { bytes32 receiptRoot; bytes aggregateSignature; uint256 #[doc(hidden)] impl ::core::convert::From for UnderlyingRustTuple<'_> { fn from(value: CertifiedReceipt) -> Self { - (value.receiptRoot, value.aggregateSignature, value.medianTimestamp) + ( + value.receiptRoot, + value.aggregateSignature, + value.sortedAttestationTimestamps, + ) } } #[automatically_derived] @@ -922,7 +930,7 @@ struct CertifiedReceipt { bytes32 receiptRoot; bytes aggregateSignature; uint256 Self { receiptRoot: tuple.0, aggregateSignature: tuple.1, - medianTimestamp: tuple.2, + sortedAttestationTimestamps: tuple.2, } } } @@ -941,9 +949,11 @@ struct CertifiedReceipt { bytes32 receiptRoot; bytes aggregateSignature; uint256 ::tokenize( &self.aggregateSignature, ), - as alloy_sol_types::SolType>::tokenize(&self.medianTimestamp), + , + > as alloy_sol_types::SolType>::tokenize( + &self.sortedAttestationTimestamps, + ), ) } #[inline] @@ -1018,7 +1028,7 @@ struct CertifiedReceipt { bytes32 receiptRoot; bytes aggregateSignature; uint256 #[inline] fn eip712_root_type() -> alloy_sol_types::private::Cow<'static, str> { alloy_sol_types::private::Cow::Borrowed( - "CertifiedReceipt(bytes32 receiptRoot,bytes aggregateSignature,uint256 medianTimestamp)", + "CertifiedReceipt(bytes32 receiptRoot,bytes aggregateSignature,uint256[] sortedAttestationTimestamps)", ) } #[inline] @@ -1042,10 +1052,10 @@ struct CertifiedReceipt { bytes32 receiptRoot; bytes aggregateSignature; uint256 &self.aggregateSignature, ) .0, - , > as alloy_sol_types::SolType>::eip712_data_word( - &self.medianTimestamp, + &self.sortedAttestationTimestamps, ) .0, ] @@ -1065,10 +1075,10 @@ struct CertifiedReceipt { bytes32 receiptRoot; bytes aggregateSignature; uint256 + ::topic_preimage_length( &rust.aggregateSignature, ) - + , > as alloy_sol_types::EventTopic>::topic_preimage_length( - &rust.medianTimestamp, + &rust.sortedAttestationTimestamps, ) } #[inline] @@ -1089,10 +1099,10 @@ struct CertifiedReceipt { bytes32 receiptRoot; bytes aggregateSignature; uint256 &rust.aggregateSignature, out, ); - , > as alloy_sol_types::EventTopic>::encode_topic_preimage( - &rust.medianTimestamp, + &rust.sortedAttestationTimestamps, out, ); } @@ -1506,7 +1516,7 @@ library PodECDSA { struct CertifiedReceipt { bytes32 receiptRoot; bytes aggregateSignature; - uint256 medianTimestamp; + uint256[] sortedAttestationTimestamps; } struct Log { address addr; @@ -1672,9 +1682,9 @@ interface PodAuctionConsumer { "internalType": "bytes" }, { - "name": "medianTimestamp", - "type": "uint256", - "internalType": "uint256" + "name": "sortedAttestationTimestamps", + "type": "uint256[]", + "internalType": "uint256[]" } ] }, @@ -1760,9 +1770,9 @@ interface PodAuctionConsumer { "internalType": "bytes" }, { - "name": "medianTimestamp", - "type": "uint256", - "internalType": "uint256" + "name": "sortedAttestationTimestamps", + "type": "uint256[]", + "internalType": "uint256[]" } ] }, @@ -2055,9 +2065,9 @@ interface PodAuctionConsumer { "internalType": "bytes" }, { - "name": "medianTimestamp", - "type": "uint256", - "internalType": "uint256" + "name": "sortedAttestationTimestamps", + "type": "uint256[]", + "internalType": "uint256[]" } ] }, @@ -4035,7 +4045,7 @@ function TWO_TIMES_DISPUTE_PERIOD() external view returns (uint256); }; #[derive(serde::Serialize, serde::Deserialize)] #[derive()] - /**Function with signature `blameIllAnnounced(((address,bytes32[],bytes),uint256,((bytes32,bytes,uint256),bytes32,(bytes32[]))))` and selector `0x0ecd990e`. + /**Function with signature `blameIllAnnounced(((address,bytes32[],bytes),uint256,((bytes32,bytes,uint256[]),bytes32,(bytes32[]))))` and selector `0xbb10a9b8`. ```solidity function blameIllAnnounced(PodECDSA.CertifiedLog memory certifiedLog) external; ```*/ @@ -4045,7 +4055,7 @@ function blameIllAnnounced(PodECDSA.CertifiedLog memory certifiedLog) external; #[allow(missing_docs)] pub certifiedLog: ::RustType, } - ///Container type for the return parameters of the [`blameIllAnnounced(((address,bytes32[],bytes),uint256,((bytes32,bytes,uint256),bytes32,(bytes32[]))))`](blameIllAnnouncedCall) function. + ///Container type for the return parameters of the [`blameIllAnnounced(((address,bytes32[],bytes),uint256,((bytes32,bytes,uint256[]),bytes32,(bytes32[]))))`](blameIllAnnouncedCall) function. #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] #[derive(Clone)] pub struct blameIllAnnouncedReturn {} @@ -4143,8 +4153,8 @@ function blameIllAnnounced(PodECDSA.CertifiedLog memory certifiedLog) external; type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; - const SIGNATURE: &'static str = "blameIllAnnounced(((address,bytes32[],bytes),uint256,((bytes32,bytes,uint256),bytes32,(bytes32[]))))"; - const SELECTOR: [u8; 4] = [14u8, 205u8, 153u8, 14u8]; + const SIGNATURE: &'static str = "blameIllAnnounced(((address,bytes32[],bytes),uint256,((bytes32,bytes,uint256[]),bytes32,(bytes32[]))))"; + const SELECTOR: [u8; 4] = [187u8, 16u8, 169u8, 184u8]; #[inline] fn new<'a>( tuple: as alloy_sol_types::SolType>::RustType, @@ -4183,7 +4193,7 @@ function blameIllAnnounced(PodECDSA.CertifiedLog memory certifiedLog) external; }; #[derive(serde::Serialize, serde::Deserialize)] #[derive()] - /**Function with signature `blameNoShow(((address,bytes32[],bytes),uint256,((bytes32,bytes,uint256),bytes32,(bytes32[]))))` and selector `0x9a62c2a3`. + /**Function with signature `blameNoShow(((address,bytes32[],bytes),uint256,((bytes32,bytes,uint256[]),bytes32,(bytes32[]))))` and selector `0xcf4c7f91`. ```solidity function blameNoShow(PodECDSA.CertifiedLog memory certifiedLog) external; ```*/ @@ -4193,7 +4203,7 @@ function blameNoShow(PodECDSA.CertifiedLog memory certifiedLog) external; #[allow(missing_docs)] pub certifiedLog: ::RustType, } - ///Container type for the return parameters of the [`blameNoShow(((address,bytes32[],bytes),uint256,((bytes32,bytes,uint256),bytes32,(bytes32[]))))`](blameNoShowCall) function. + ///Container type for the return parameters of the [`blameNoShow(((address,bytes32[],bytes),uint256,((bytes32,bytes,uint256[]),bytes32,(bytes32[]))))`](blameNoShowCall) function. #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] #[derive(Clone)] pub struct blameNoShowReturn {} @@ -4287,8 +4297,8 @@ function blameNoShow(PodECDSA.CertifiedLog memory certifiedLog) external; type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; - const SIGNATURE: &'static str = "blameNoShow(((address,bytes32[],bytes),uint256,((bytes32,bytes,uint256),bytes32,(bytes32[]))))"; - const SELECTOR: [u8; 4] = [154u8, 98u8, 194u8, 163u8]; + const SIGNATURE: &'static str = "blameNoShow(((address,bytes32[],bytes),uint256,((bytes32,bytes,uint256[]),bytes32,(bytes32[]))))"; + const SELECTOR: [u8; 4] = [207u8, 76u8, 127u8, 145u8]; #[inline] fn new<'a>( tuple: as alloy_sol_types::SolType>::RustType, @@ -5915,7 +5925,7 @@ function withdraw() external; }; #[derive(serde::Serialize, serde::Deserialize)] #[derive()] - /**Function with signature `write(((address,bytes32[],bytes),uint256,((bytes32,bytes,uint256),bytes32,(bytes32[]))))` and selector `0x52070195`. + /**Function with signature `write(((address,bytes32[],bytes),uint256,((bytes32,bytes,uint256[]),bytes32,(bytes32[]))))` and selector `0xa09b80b9`. ```solidity function write(PodECDSA.CertifiedLog memory certifiedLog) external; ```*/ @@ -5925,7 +5935,7 @@ function write(PodECDSA.CertifiedLog memory certifiedLog) external; #[allow(missing_docs)] pub certifiedLog: ::RustType, } - ///Container type for the return parameters of the [`write(((address,bytes32[],bytes),uint256,((bytes32,bytes,uint256),bytes32,(bytes32[]))))`](writeCall) function. + ///Container type for the return parameters of the [`write(((address,bytes32[],bytes),uint256,((bytes32,bytes,uint256[]),bytes32,(bytes32[]))))`](writeCall) function. #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] #[derive(Clone)] pub struct writeReturn {} @@ -6019,8 +6029,8 @@ function write(PodECDSA.CertifiedLog memory certifiedLog) external; type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; - const SIGNATURE: &'static str = "write(((address,bytes32[],bytes),uint256,((bytes32,bytes,uint256),bytes32,(bytes32[]))))"; - const SELECTOR: [u8; 4] = [82u8, 7u8, 1u8, 149u8]; + const SIGNATURE: &'static str = "write(((address,bytes32[],bytes),uint256,((bytes32,bytes,uint256[]),bytes32,(bytes32[]))))"; + const SELECTOR: [u8; 4] = [160u8, 155u8, 128u8, 185u8]; #[inline] fn new<'a>( tuple: as alloy_sol_types::SolType>::RustType, @@ -6105,11 +6115,9 @@ function write(PodECDSA.CertifiedLog memory certifiedLog) external; /// /// Prefer using `SolInterface` methods instead. pub const SELECTORS: &'static [[u8; 4usize]] = &[ - [14u8, 205u8, 153u8, 14u8], [56u8, 114u8, 51u8, 236u8], [60u8, 207u8, 214u8, 11u8], [74u8, 165u8, 232u8, 133u8], - [82u8, 7u8, 1u8, 149u8], [93u8, 246u8, 166u8, 188u8], [97u8, 213u8, 133u8, 218u8], [100u8, 201u8, 236u8, 111u8], @@ -6117,9 +6125,11 @@ function write(PodECDSA.CertifiedLog memory certifiedLog) external; [117u8, 8u8, 9u8, 151u8], [128u8, 243u8, 35u8, 167u8], [141u8, 165u8, 203u8, 91u8], - [154u8, 98u8, 194u8, 163u8], + [160u8, 155u8, 128u8, 185u8], [165u8, 187u8, 226u8, 43u8], + [187u8, 16u8, 169u8, 184u8], [197u8, 220u8, 198u8, 145u8], + [207u8, 76u8, 127u8, 145u8], [233u8, 117u8, 27u8, 55u8], [242u8, 253u8, 227u8, 139u8], ]; @@ -6186,17 +6196,6 @@ function write(PodECDSA.CertifiedLog memory certifiedLog) external; static DECODE_SHIMS: &[fn( &[u8], ) -> alloy_sol_types::Result] = &[ - { - fn blameIllAnnounced( - data: &[u8], - ) -> alloy_sol_types::Result { - ::abi_decode_raw( - data, - ) - .map(PodAuctionConsumerCalls::blameIllAnnounced) - } - blameIllAnnounced - }, { fn podRegistry( data: &[u8], @@ -6226,15 +6225,6 @@ function write(PodECDSA.CertifiedLog memory certifiedLog) external; } isBonded }, - { - fn write( - data: &[u8], - ) -> alloy_sol_types::Result { - ::abi_decode_raw(data) - .map(PodAuctionConsumerCalls::write) - } - write - }, { fn unbond( data: &[u8], @@ -6303,15 +6293,13 @@ function write(PodECDSA.CertifiedLog memory certifiedLog) external; owner }, { - fn blameNoShow( + fn write( data: &[u8], ) -> alloy_sol_types::Result { - ::abi_decode_raw( - data, - ) - .map(PodAuctionConsumerCalls::blameNoShow) + ::abi_decode_raw(data) + .map(PodAuctionConsumerCalls::write) } - blameNoShow + write }, { fn DISPUTE_PERIOD( @@ -6324,6 +6312,17 @@ function write(PodECDSA.CertifiedLog memory certifiedLog) external; } DISPUTE_PERIOD }, + { + fn blameIllAnnounced( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw( + data, + ) + .map(PodAuctionConsumerCalls::blameIllAnnounced) + } + blameIllAnnounced + }, { fn TWO_TIMES_DISPUTE_PERIOD( data: &[u8], @@ -6335,6 +6334,17 @@ function write(PodECDSA.CertifiedLog memory certifiedLog) external; } TWO_TIMES_DISPUTE_PERIOD }, + { + fn blameNoShow( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw( + data, + ) + .map(PodAuctionConsumerCalls::blameNoShow) + } + blameNoShow + }, { fn LOG_TOPIC_0( data: &[u8], @@ -6377,17 +6387,6 @@ function write(PodECDSA.CertifiedLog memory certifiedLog) external; static DECODE_VALIDATE_SHIMS: &[fn( &[u8], ) -> alloy_sol_types::Result] = &[ - { - fn blameIllAnnounced( - data: &[u8], - ) -> alloy_sol_types::Result { - ::abi_decode_raw_validate( - data, - ) - .map(PodAuctionConsumerCalls::blameIllAnnounced) - } - blameIllAnnounced - }, { fn podRegistry( data: &[u8], @@ -6421,17 +6420,6 @@ function write(PodECDSA.CertifiedLog memory certifiedLog) external; } isBonded }, - { - fn write( - data: &[u8], - ) -> alloy_sol_types::Result { - ::abi_decode_raw_validate( - data, - ) - .map(PodAuctionConsumerCalls::write) - } - write - }, { fn unbond( data: &[u8], @@ -6510,15 +6498,15 @@ function write(PodECDSA.CertifiedLog memory certifiedLog) external; owner }, { - fn blameNoShow( + fn write( data: &[u8], ) -> alloy_sol_types::Result { - ::abi_decode_raw_validate( + ::abi_decode_raw_validate( data, ) - .map(PodAuctionConsumerCalls::blameNoShow) + .map(PodAuctionConsumerCalls::write) } - blameNoShow + write }, { fn DISPUTE_PERIOD( @@ -6531,6 +6519,17 @@ function write(PodECDSA.CertifiedLog memory certifiedLog) external; } DISPUTE_PERIOD }, + { + fn blameIllAnnounced( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(PodAuctionConsumerCalls::blameIllAnnounced) + } + blameIllAnnounced + }, { fn TWO_TIMES_DISPUTE_PERIOD( data: &[u8], @@ -6542,6 +6541,17 @@ function write(PodECDSA.CertifiedLog memory certifiedLog) external; } TWO_TIMES_DISPUTE_PERIOD }, + { + fn blameNoShow( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(PodAuctionConsumerCalls::blameNoShow) + } + blameNoShow + }, { fn LOG_TOPIC_0( data: &[u8], diff --git a/examples/optimistic-auction/client/main.rs b/examples/optimistic-auction/client/main.rs index e58b5f5f..f3928993 100644 --- a/examples/optimistic-auction/client/main.rs +++ b/examples/optimistic-auction/client/main.rs @@ -79,7 +79,7 @@ fn get_certified_log(log: &VerifiableLog) -> Result { certifiedReceipt: CertifiedReceipt { receiptRoot: log.pod_metadata.receipt.hash_custom(), aggregateSignature: log.aggregate_signatures().into(), - medianTimestamp: U256::from(log.inner.block_timestamp.unwrap()), + sortedAttestationTimestamps: log.get_sorted_attestation_timestamps(), }, leaf, proof: Proof { path: proof.path }, diff --git a/examples/optimistic-auction/test/PodAuctionConsumer.t.sol b/examples/optimistic-auction/test/PodAuctionConsumer.t.sol index 491ab9c0..b722b6c2 100644 --- a/examples/optimistic-auction/test/PodAuctionConsumer.t.sol +++ b/examples/optimistic-auction/test/PodAuctionConsumer.t.sol @@ -293,9 +293,11 @@ contract PodAuctionConsumerTest is Test { ); bytes[] memory signatures = new bytes[](numberOfRequiredSignatures); + uint256[] memory sortedAttestationTimestamps = new uint256[](numberOfRequiredSignatures); for (uint256 i = 0; i < numberOfRequiredSignatures; i++) { (uint8 v, bytes32 r, bytes32 s) = vm.sign(validatorPrivateKeys[i], receiptRoot); signatures[i] = ECDSA._serialize_signature(v, r, s); + sortedAttestationTimestamps[i] = i + 1; } bytes memory aggregateSignature = ECDSA.aggregate_signatures(signatures); @@ -303,7 +305,7 @@ contract PodAuctionConsumerTest is Test { PodECDSA.CertifiedReceipt memory certifiedReceipt = PodECDSA.CertifiedReceipt({ receiptRoot: receiptRoot, aggregateSignature: aggregateSignature, - medianTimestamp: 2 + sortedAttestationTimestamps: sortedAttestationTimestamps }); PodECDSA.Log memory log = diff --git a/types/src/ledger/log.rs b/types/src/ledger/log.rs index 5541b217..23230a2f 100644 --- a/types/src/ledger/log.rs +++ b/types/src/ledger/log.rs @@ -1,8 +1,10 @@ use std::ops::Deref; +use alloy_primitives::Uint; pub use alloy_primitives::{Log, LogData}; use alloy_rpc_types::Log as RPCLog; use alloy_sol_types::SolValue; +use itertools::Itertools; use serde::{Deserialize, Serialize}; use crate::{ @@ -121,6 +123,28 @@ impl VerifiableLog { }) } + fn sort_attestations_by_timestamp(&self) -> Vec<&TimestampedHeadlessAttestation> { + self.pod_metadata + .attestations + .iter() + .sorted_by_key(|a| a.timestamp.as_seconds()) + .collect() + } + + pub fn get_sorted_attestation_timestamps(&self) -> Vec> { + self.sort_attestations_by_timestamp() + .iter() + .map(|a| a.timestamp.as_seconds().try_into().unwrap()) + .collect() + } + + pub fn get_sorted_attestation_signatures(&self) -> Vec<[u8; 65]> { + self.sort_attestations_by_timestamp() + .iter() + .map(|a| a.signature.as_bytes()) + .collect() + } + pub fn verify_proof(&self, receipt_root: Hash, proof: MerkleProof) -> bool { let leaf = self.get_leaf(); StandardMerkleTree::verify_proof(receipt_root, leaf, proof) From e36b80354a68fc92a7b53d6fcecb41915403d0f7 Mon Sep 17 00:00:00 2001 From: Jakov Mitrovski Date: Wed, 20 Aug 2025 15:25:08 +0200 Subject: [PATCH 31/64] update podauctionconsumer to reflect changes --- .../contracts/PodAuctionConsumer.sol | 39 +++++++++++-------- .../test/PodAuctionConsumer.t.sol | 6 ++- 2 files changed, 27 insertions(+), 18 deletions(-) diff --git a/examples/optimistic-auction/contracts/PodAuctionConsumer.sol b/examples/optimistic-auction/contracts/PodAuctionConsumer.sol index c4ceabf1..19a57250 100644 --- a/examples/optimistic-auction/contracts/PodAuctionConsumer.sol +++ b/examples/optimistic-auction/contracts/PodAuctionConsumer.sol @@ -37,15 +37,19 @@ contract PodAuctionConsumer is AbsBonding { _; } + function _convertToSeconds(uint256 timestamp) internal pure returns (uint256) { + return timestamp / 1e6; + } + /** * @notice deadline in seconds */ - function getUniqueAuctionId(uint256 auctionId, uint256 deadline) internal pure returns (bytes32) { - return keccak256(abi.encodePacked(auctionId, deadline)); + function getUniqueAuctionId(uint256 auctionId, uint256 deadlineInSeconds) internal pure returns (bytes32) { + return keccak256(abi.encodePacked(auctionId, deadlineInSeconds)); } /** - * @notice deadline in seconds + * @notice deadline in microseconds */ function decodeBid(PodECDSA.Log calldata log) internal @@ -56,16 +60,16 @@ contract PodAuctionConsumer is AbsBonding { require(log.topics[0] == LOG_TOPIC_0, "Invalid log topic"); auctionId = uint256(log.topics[1]); bidder = address(uint160(uint256(log.topics[2]))); - deadline = uint256(log.topics[3]); + deadline = _convertToSeconds(uint256(log.topics[3])); bid = abi.decode(log.data, (uint256)); } function write(PodECDSA.CertifiedLog calldata certifiedLog) external validLog(certifiedLog.log) onlyBonded { - (uint256 auctionId, address bidder, uint256 deadline, uint256 bid) = decodeBid(certifiedLog.log); - bytes32 uniqueAuctionId = getUniqueAuctionId(auctionId, deadline); + (uint256 auctionId, address bidder, uint256 deadlineInSeconds, uint256 bid) = decodeBid(certifiedLog.log); + bytes32 uniqueAuctionId = getUniqueAuctionId(auctionId, deadlineInSeconds); State storage s = state[uniqueAuctionId]; - require(block.timestamp >= deadline, "Writing period has not started"); - require(block.timestamp < deadline + DISPUTE_PERIOD, "Writing period ended"); + require(block.timestamp >= deadlineInSeconds, "Writing period has not started"); + require(block.timestamp < deadlineInSeconds + DISPUTE_PERIOD, "Writing period ended"); require(s.winner.bid == 0, "Bid already exists"); require(msg.sender == bidder, "Invalid caller"); @@ -84,8 +88,9 @@ contract PodAuctionConsumer is AbsBonding { * @notice deadline in microseconds */ function read(uint256 auctionId, uint256 deadline) external view returns (State memory) { - bytes32 uniqueAuctionId = getUniqueAuctionId(auctionId, deadline); - require(block.timestamp >= deadline + TWO_TIMES_DISPUTE_PERIOD, "Dispute period NOT ended"); + uint256 deadlineInSeconds = _convertToSeconds(deadline); + bytes32 uniqueAuctionId = getUniqueAuctionId(auctionId, deadlineInSeconds); + require(block.timestamp >= deadlineInSeconds + TWO_TIMES_DISPUTE_PERIOD, "Dispute period NOT ended"); return state[uniqueAuctionId]; } @@ -94,11 +99,11 @@ contract PodAuctionConsumer is AbsBonding { validLog(certifiedLog.log) onlyBonded { - (uint256 auctionId, address bidder, uint256 deadline, uint256 bid) = decodeBid(certifiedLog.log); - bytes32 uniqueAuctionId = getUniqueAuctionId(auctionId, deadline); + (uint256 auctionId, address bidder, uint256 deadlineInSeconds, uint256 bid) = decodeBid(certifiedLog.log); + bytes32 uniqueAuctionId = getUniqueAuctionId(auctionId, deadlineInSeconds); State storage s = state[uniqueAuctionId]; require(s.winner.bid != 0, "Bid not written"); - require(block.timestamp < deadline + TWO_TIMES_DISPUTE_PERIOD, "Dispute period ended"); + require(block.timestamp < deadlineInSeconds + TWO_TIMES_DISPUTE_PERIOD, "Dispute period ended"); bool verified = PodECDSA.verifyCertifiedLog( PodECDSA.PodConfig({thresholdNumerator: 2, thresholdDenominator: 3, registry: podRegistry}), certifiedLog @@ -116,13 +121,13 @@ contract PodAuctionConsumer is AbsBonding { } function blameNoShow(PodECDSA.CertifiedLog calldata certifiedLog) external validLog(certifiedLog.log) onlyBonded { - (uint256 auctionId, address bidder, uint256 deadline, uint256 bid) = decodeBid(certifiedLog.log); - bytes32 uniqueAuctionId = getUniqueAuctionId(auctionId, deadline); + (uint256 auctionId, address bidder, uint256 deadlineInSeconds, uint256 bid) = decodeBid(certifiedLog.log); + bytes32 uniqueAuctionId = getUniqueAuctionId(auctionId, deadlineInSeconds); State storage s = state[uniqueAuctionId]; require(s.winner.bid == 0, "Bid already exists"); - require(block.timestamp >= deadline + DISPUTE_PERIOD, "Still in waiting period"); - require(block.timestamp < deadline + TWO_TIMES_DISPUTE_PERIOD, "Dispute period ended"); + require(block.timestamp >= deadlineInSeconds + DISPUTE_PERIOD, "Still in waiting period"); + require(block.timestamp < deadlineInSeconds + TWO_TIMES_DISPUTE_PERIOD, "Dispute period ended"); require(s.blamed.bid < bid, "Invalid blamed bid"); bool verified = PodECDSA.verifyCertifiedLog( diff --git a/examples/optimistic-auction/test/PodAuctionConsumer.t.sol b/examples/optimistic-auction/test/PodAuctionConsumer.t.sol index b722b6c2..43a2813b 100644 --- a/examples/optimistic-auction/test/PodAuctionConsumer.t.sol +++ b/examples/optimistic-auction/test/PodAuctionConsumer.t.sol @@ -31,6 +31,10 @@ contract PodAuctionConsumerTest is Test { return Math.mulDiv(thresholdNumerator, NUMBER_OF_VALIDATORS, thresholdDenominator, rounding); } + function _convertToSeconds(uint256 timestamp) internal pure returns (uint256) { + return timestamp / 1e6; + } + function setUp() public { address[] memory initialValidators = new address[](NUMBER_OF_VALIDATORS); @@ -55,7 +59,7 @@ contract PodAuctionConsumerTest is Test { vm.prank(BONDED_ADDRESS); consumer.bond{value: 1 ether}(); - vm.warp(DEADLINE); + vm.warp(_convertToSeconds(DEADLINE)); } function test_Write_Success() public { From e6ab12610211e73c99c0073305f8cf8c7a7091b6 Mon Sep 17 00:00:00 2001 From: Jakov Mitrovski Date: Thu, 21 Aug 2025 15:12:00 +0200 Subject: [PATCH 32/64] update optimistic auction example to reflect changes --- examples/optimistic-auction/.env.example | 3 +- examples/optimistic-auction/README.md | 4 ++ examples/optimistic-auction/client/main.rs | 74 ++++++++++++---------- 3 files changed, 46 insertions(+), 35 deletions(-) diff --git a/examples/optimistic-auction/.env.example b/examples/optimistic-auction/.env.example index 029bec83..f6f8c241 100644 --- a/examples/optimistic-auction/.env.example +++ b/examples/optimistic-auction/.env.example @@ -3,4 +3,5 @@ PRIVATE_KEY_2= AUCTION_CONTRACT_ADDRESS=0xf6D39FB8492dC21293043f5E39F566D4A4ce2206 CONSUMER_CONTRACT_ADDRESS= POD_RPC_URL=ws://localhost:8545 -CONSUMER_RPC_URL=http://localhost:8546 \ No newline at end of file +CONSUMER_RPC_URL=http://localhost:8546 +POD_COMMITTEE_KEYS= \ No newline at end of file diff --git a/examples/optimistic-auction/README.md b/examples/optimistic-auction/README.md index 9e7b654b..6c400515 100644 --- a/examples/optimistic-auction/README.md +++ b/examples/optimistic-auction/README.md @@ -54,6 +54,10 @@ For pod cast send
--value 10ether --private-key --rpc-url localhost:8545 --legacy ``` +The consumer contract depends on the pod registry. Since we want to deploy the consumer contract on anvil, +we also need the registry. The script below automatically deploys the registry but we need the appropriate +committee addresses. Make sure the `POD_COMMITTEE_KEYS` is set to a list of validator addresses separated by a comma. + The next step is to deploy the consumer contract on anvil. ```shell diff --git a/examples/optimistic-auction/client/main.rs b/examples/optimistic-auction/client/main.rs index f3928993..8ab225ea 100644 --- a/examples/optimistic-auction/client/main.rs +++ b/examples/optimistic-auction/client/main.rs @@ -129,8 +129,8 @@ impl AuctionClient { let tx = self .auction_contract .submitBid(auction_id, deadline, value, data.into()) - .gas(1000000) - .gas_price(1000000000) + .max_fee_per_gas(1_000_000_000u128) + .max_priority_fee_per_gas(0) .send() .await .unwrap(); @@ -189,6 +189,8 @@ impl AuctionClient { let blame_tx = match self .consumer_contract .blameIllAnnounced(certified_log) + .max_fee_per_gas(1_000_000_000u128) + .max_priority_fee_per_gas(0) .send() .await { @@ -208,32 +210,32 @@ impl AuctionClient { Ok(()) } - // TODO: uncomment if you wish to use - // pub async fn blame_no_show(&self, certified_log: CertifiedLog) -> Result<()> { - // let blame_tx = match self - // .consumer_contract - // .blameNoShow(certified_log) - // .send() - // .await - // { - // Ok(tx) => tx, - // Err(e) => { - // println!("{:?}", e); - // return Ok(()); - // } - // }; - - // println!( - // "Waiting for receipt - BLAME NO SHOW... {:?}", - // blame_tx.tx_hash() - // ); - // sleep(Duration::from_millis(100)); - - // check_receipt_status::<_, _, Ethereum>(self.consumer_provider.clone(), *blame_tx.tx_hash()) - // .await?; - - // Ok(()) - // } + #[allow(dead_code)] + pub async fn blame_no_show(&self, certified_log: CertifiedLog) -> Result<()> { + let blame_tx = match self + .consumer_contract + .blameNoShow(certified_log) + .send() + .await + { + Ok(tx) => tx, + Err(e) => { + println!("{:?}", e); + return Ok(()); + } + }; + + println!( + "Waiting for receipt - BLAME NO SHOW... {:?}", + blame_tx.tx_hash() + ); + sleep(Duration::from_millis(100)); + + check_receipt_status::<_, Ethereum>(self.consumer_provider.clone(), *blame_tx.tx_hash()) + .await?; + + Ok(()) + } pub async fn read_state(&self, auction_id: U256, deadline: U256) -> Result<()> { let state = self @@ -274,6 +276,8 @@ impl AuctionClient { } async fn advance_time(provider: P, timestamp: u64) -> Result<()> { + let timestamp = timestamp / MICROSECONDS_PER_SECOND; + provider .raw_request::<_, ()>( std::borrow::Cow::Borrowed("evm_setNextBlockTimestamp"), @@ -342,14 +346,14 @@ async fn main() -> Result<()> { let now = (std::time::SystemTime::now() .duration_since(std::time::UNIX_EPOCH)? .as_micros() as u64) - + (4 * WAITING_PERIOD * args.iteration); + + (4 * WAITING_PERIOD * MICROSECONDS_PER_SECOND * args.iteration); let deadline = now + 5 * MICROSECONDS_PER_SECOND; #[allow(clippy::identity_op)] - let writing_period_ends = deadline + WAITING_PERIOD + 1 * MICROSECONDS_PER_SECOND; + let writing_period_ends = deadline + (WAITING_PERIOD + 1) * MICROSECONDS_PER_SECOND; #[allow(clippy::identity_op)] - let dispute_period_ends = writing_period_ends + WAITING_PERIOD + 1 * MICROSECONDS_PER_SECOND; + let dispute_period_ends = writing_period_ends + (WAITING_PERIOD + 1) * MICROSECONDS_PER_SECOND; let data = vec![0x12, 0x34, 0x56]; @@ -399,7 +403,9 @@ async fn main() -> Result<()> { sleep(Duration::from_secs(1)); + // TODO: comment the next 10 lines if you wish to use the blame no show function auction_client_1.write(certified_log1).await?; + sleep(Duration::from_secs(1)); advance_time( auction_client_1.consumer_provider.clone(), @@ -409,6 +415,9 @@ async fn main() -> Result<()> { let _ = auction_client_2.blame_ill_announced(certified_log2).await; + // TODO: uncomment if you wish to use, to use this, we need to comment the write + blame ill announced calls + // let _ = auction_client_1.blame_no_show(certified_log1).await; + advance_time( auction_client_1.consumer_provider.clone(), dispute_period_ends, @@ -419,8 +428,5 @@ async fn main() -> Result<()> { .read_state(auction_id, U256::from(deadline)) .await?; - // TODO: uncomment if you wish to use, to use this, we need to comment the write + blame ill announced calls - // let _ = auction_client_1.blame_no_show(certified_log1).await; - Ok(()) } From 753a88949faeb2eb41b39ea02120cd4239953873 Mon Sep 17 00:00:00 2001 From: Jakov Mitrovski Date: Thu, 21 Aug 2025 15:14:47 +0200 Subject: [PATCH 33/64] clippy --- examples/optimistic-auction/client/main.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/optimistic-auction/client/main.rs b/examples/optimistic-auction/client/main.rs index 8ab225ea..d2c536a1 100644 --- a/examples/optimistic-auction/client/main.rs +++ b/examples/optimistic-auction/client/main.rs @@ -220,7 +220,7 @@ impl AuctionClient { { Ok(tx) => tx, Err(e) => { - println!("{:?}", e); + println!("{e:?}"); return Ok(()); } }; @@ -351,9 +351,9 @@ async fn main() -> Result<()> { let deadline = now + 5 * MICROSECONDS_PER_SECOND; #[allow(clippy::identity_op)] - let writing_period_ends = deadline + (WAITING_PERIOD + 1) * MICROSECONDS_PER_SECOND; + let writing_period_ends = deadline + (WAITING_PERIOD) * MICROSECONDS_PER_SECOND; #[allow(clippy::identity_op)] - let dispute_period_ends = writing_period_ends + (WAITING_PERIOD + 1) * MICROSECONDS_PER_SECOND; + let dispute_period_ends = writing_period_ends + WAITING_PERIOD * MICROSECONDS_PER_SECOND; let data = vec![0x12, 0x34, 0x56]; From e26f91e708b8ad8c709595a68f5432bcfa7865ca Mon Sep 17 00:00:00 2001 From: Jakov Mitrovski Date: Mon, 25 Aug 2025 11:03:34 +0200 Subject: [PATCH 34/64] Repo restructuring - Add protocol folder containing contracts related to pod protocol - Move registry, tests and related scripts to protocol - Update references and remappings - Upd foundry to v1.3.1 - Upd bindings --- .github/workflows/test.yml | 48 ++- .gitmodules | 6 + examples/bsky/contract/foundry.toml | 2 +- examples/hashchallenge/foundry.toml | 2 +- examples/notary/bindings/src/notary.rs | 8 +- examples/notary/bindings/src/time.rs | 8 +- examples/notary/foundry.toml | 2 +- .../bindings/src/pod_auction_consumer.rs | 406 +++++++++--------- .../contracts/AbsBonding.sol | 8 +- .../contracts/PodAuctionConsumer.sol | 15 +- examples/optimistic-auction/foundry.toml | 11 +- .../script/PodAuctionConsumerDeployer.s.sol | 4 +- .../test/PodAuctionConsumer.t.sol | 2 +- examples/solidity/foundry.toml | 11 +- examples/solidity/script/Deploy.s.sol | 4 +- examples/voting/bindings/src/voting.rs | 8 +- examples/voting/contract/foundry.toml | 2 +- foundry.toml | 2 +- protocol/.gitignore | 14 + protocol/README.md | 66 +++ protocol/foundry.lock | 20 + protocol/foundry.toml | 21 + protocol/lib/forge-std | 1 + protocol/lib/openzeppelin-contracts | 1 + .../script/BaseDeployer.s.sol | 0 .../script/PodRegistryDeployer.s.sol | 2 +- .../verifier => protocol/src}/PodRegistry.sol | 2 +- .../src/interfaces/IPodRegistry.sol | 0 .../test/PodRegistry.t.sol | 6 +- solidity-sdk/README.md | 6 - solidity-sdk/foundry.toml | 11 +- solidity-sdk/src/verifier/PodECDSA.sol | 8 +- solidity-sdk/test/PodECDSA.t.sol | 13 +- 33 files changed, 454 insertions(+), 266 deletions(-) create mode 100644 protocol/.gitignore create mode 100644 protocol/README.md create mode 100644 protocol/foundry.lock create mode 100644 protocol/foundry.toml create mode 160000 protocol/lib/forge-std create mode 160000 protocol/lib/openzeppelin-contracts rename {solidity-sdk => protocol}/script/BaseDeployer.s.sol (100%) rename {solidity-sdk => protocol}/script/PodRegistryDeployer.s.sol (89%) rename {solidity-sdk/src/verifier => protocol/src}/PodRegistry.sol (99%) rename {solidity-sdk => protocol}/src/interfaces/IPodRegistry.sol (100%) rename {solidity-sdk => protocol}/test/PodRegistry.t.sol (99%) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 3733445a..950f4267 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -36,7 +36,7 @@ jobs: - name: Install Foundry uses: foundry-rs/foundry-toolchain@v1 with: - version: v1.3.0 + version: v1.3.1 - name: Show Forge version run: | @@ -66,7 +66,43 @@ jobs: make check working-directory: examples/solidity id: bindings - + + protocol: + name: protocol + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + submodules: recursive + + - name: Install Foundry + uses: foundry-rs/foundry-toolchain@v1 + with: + version: v1.3.1 + + + - name: Show Forge version + run: | + forge --version + + - name: Run Forge fmt + run: | + forge fmt --check + id: fmt + working-directory: protocol + + - name: Run Forge build + run: | + forge build --sizes + id: build + working-directory: protocol + + - name: Run Forge tests + run: | + forge test -vvv + id: test + working-directory: protocol + solidity-sdk: name: solidity-sdk runs-on: ubuntu-latest @@ -78,7 +114,7 @@ jobs: - name: Install Foundry uses: foundry-rs/foundry-toolchain@v1 with: - version: v1.3.0 + version: v1.3.1 - name: Show Forge version run: | @@ -113,7 +149,7 @@ jobs: - name: Install Foundry uses: foundry-rs/foundry-toolchain@v1 with: - version: v1.3.0 + version: v1.3.1 - name: Show Forge version run: | @@ -154,7 +190,7 @@ jobs: - name: Install Foundry uses: foundry-rs/foundry-toolchain@v1 with: - version: v1.3.0 + version: v1.3.1 - name: Show Forge version run: | @@ -195,7 +231,7 @@ jobs: - name: Install Foundry uses: foundry-rs/foundry-toolchain@v1 with: - version: v1.3.0 + version: v1.3.1 - name: Show Forge version run: | diff --git a/.gitmodules b/.gitmodules index 508322dd..c9b89d6d 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,3 +4,9 @@ [submodule "solidity-sdk/lib/openzeppelin-contracts"] path = solidity-sdk/lib/openzeppelin-contracts url = https://github.com/OpenZeppelin/openzeppelin-contracts +[submodule "protocol/lib/forge-std"] + path = protocol/lib/forge-std + url = https://github.com/foundry-rs/forge-std +[submodule "protocol/lib/openzeppelin-contracts"] + path = protocol/lib/openzeppelin-contracts + url = https://github.com/OpenZeppelin/openzeppelin-contracts diff --git a/examples/bsky/contract/foundry.toml b/examples/bsky/contract/foundry.toml index 97770db0..e6b88270 100644 --- a/examples/bsky/contract/foundry.toml +++ b/examples/bsky/contract/foundry.toml @@ -3,7 +3,7 @@ src = "src" out = "out" libs = ["lib"] solc = "0.8.28" -evm_version = "berlin" +evm_version = "prague" bytecode_hash = "none" cbor_metadata = false remappings = ["pod-sdk/=../../../solidity-sdk/src/"] diff --git a/examples/hashchallenge/foundry.toml b/examples/hashchallenge/foundry.toml index 660d75a3..56a2fde2 100644 --- a/examples/hashchallenge/foundry.toml +++ b/examples/hashchallenge/foundry.toml @@ -3,7 +3,7 @@ src = "src" out = "out" libs = ["lib"] solc = "0.8.28" -evm_version = "berlin" +evm_version = "prague" bytecode_hash = "none" cbor_metadata = false remappings = [ diff --git a/examples/notary/bindings/src/notary.rs b/examples/notary/bindings/src/notary.rs index f0e7e569..0daf17c5 100644 --- a/examples/notary/bindings/src/notary.rs +++ b/examples/notary/bindings/src/notary.rs @@ -371,22 +371,22 @@ pub mod Notary { /// The creation / init bytecode of the contract. /// /// ```text - ///0x6080604052348015600f57600080fd5b50610a5d8061001f6000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c8063b58729581461003b578063e8d600891461006b575b600080fd5b6100556004803603810190610050919061063d565b610087565b60405161006291906106b9565b60405180910390f35b61008560048036038101906100809190610700565b6100ae565b005b60006020528060005260406000206000915054906101000a900467ffffffffffffffff1681565b6100ed816040518060400160405280601f81526020017f74696d657374616d70206d75737420626520696e2074686520667574757265008152506102cf565b61012660008084815260200190815260200160002060009054906101000a900467ffffffffffffffff1667ffffffffffffffff16610300565b156101b8578060008084815260200190815260200160002060006101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055503373ffffffffffffffffffffffffffffffffffffffff16827fc8502b80f9a4eddb29943d46e36f689055a259a8be737b8e3d2c902da42a6e83836040516101ab91906106b9565b60405180910390a36102cb565b60006101ea8260008086815260200190815260200160002060009054906101000a900467ffffffffffffffff16610316565b9050600061023160008086815260200190815260200160002060009054906101000a900467ffffffffffffffff168367ffffffffffffffff1661034990919063ffffffff16565b67ffffffffffffffff16146102c9578060008085815260200190815260200160002060006101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055503373ffffffffffffffffffffffffffffffffffffffff16837fc8502b80f9a4eddb29943d46e36f689055a259a8be737b8e3d2c902da42a6e83836040516102c091906106b9565b60405180910390a35b505b5050565b6102fc6102f6836102de610395565b67ffffffffffffffff166104ca90919063ffffffff16565b826104eb565b5050565b6000808267ffffffffffffffff16149050919050565b6000610335828467ffffffffffffffff166104ca90919063ffffffff16565b61033f5781610341565b825b905092915050565b6000610368828467ffffffffffffffff166105e190919063ffffffff16565b15610380578183610379919061076f565b905061038f565b828261038c919061076f565b90505b92915050565b60008060007fba286e4d89dabf4b2878e896423bb123d9d5143e662606fd343b6766d7bcf72160001c73ffffffffffffffffffffffffffffffffffffffff166040516103e0906107dc565b600060405180830381855afa9150503d806000811461041b576040519150601f19603f3d011682016040523d82523d6000602084013e610420565b606091505b509150915081610465576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161045c9061084e565b60405180910390fd5b60208151146104a9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104a0906108ba565b60405180910390fd5b6000818060200190518101906104bf9190610906565b905080935050505090565b60008167ffffffffffffffff168367ffffffffffffffff1610905092915050565b60007f3dcdf63b41c103567d7225976ad9145e866c7a7dccc6c277ea86abbd268fbac960001c73ffffffffffffffffffffffffffffffffffffffff1683604051602001610538919061094e565b60405160208183030381529060405260405161055491906109cf565b600060405180830381855afa9150503d806000811461058f576040519150601f19603f3d011682016040523d82523d6000602084013e610594565b606091505b505090508082906105db576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105d29190610a3b565b60405180910390fd5b50505050565b60008167ffffffffffffffff168367ffffffffffffffff1611905092915050565b600080fd5b6000819050919050565b61061a81610607565b811461062557600080fd5b50565b60008135905061063781610611565b92915050565b60006020828403121561065357610652610602565b5b600061066184828501610628565b91505092915050565b600067ffffffffffffffff82169050919050565b6000819050919050565b60006106a361069e6106998461066a565b61067e565b61066a565b9050919050565b6106b381610688565b82525050565b60006020820190506106ce60008301846106aa565b92915050565b6106dd8161066a565b81146106e857600080fd5b50565b6000813590506106fa816106d4565b92915050565b6000806040838503121561071757610716610602565b5b600061072585828601610628565b9250506020610736858286016106eb565b9150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061077a8261066a565b91506107858361066a565b9250828203905067ffffffffffffffff8111156107a5576107a4610740565b5b92915050565b600081905092915050565b50565b60006107c66000836107ab565b91506107d1826107b6565b600082019050919050565b60006107e7826107b9565b9150819050919050565b600082825260208201905092915050565b7f507265636f6d70696c652063616c6c206661696c656400000000000000000000600082015250565b60006108386016836107f1565b915061084382610802565b602082019050919050565b600060208201905081810360008301526108678161082b565b9050919050565b7f496e76616c6964206f7574707574206c656e6774680000000000000000000000600082015250565b60006108a46015836107f1565b91506108af8261086e565b602082019050919050565b600060208201905081810360008301526108d381610897565b9050919050565b6108e38161066a565b81146108ee57600080fd5b50565b600081519050610900816108da565b92915050565b60006020828403121561091c5761091b610602565b5b600061092a848285016108f1565b91505092915050565b60008115159050919050565b61094881610933565b82525050565b6000602082019050610963600083018461093f565b92915050565b600081519050919050565b60005b83811015610992578082015181840152602081019050610977565b60008484015250505050565b60006109a982610969565b6109b381856107ab565b93506109c3818560208601610974565b80840191505092915050565b60006109db828461099e565b915081905092915050565b600081519050919050565b6000601f19601f8301169050919050565b6000610a0d826109e6565b610a1781856107f1565b9350610a27818560208601610974565b610a30816109f1565b840191505092915050565b60006020820190508181036000830152610a558184610a02565b90509291505056 + ///0x6080604052348015600e575f5ffd5b506109e98061001c5f395ff3fe608060405234801561000f575f5ffd5b5060043610610034575f3560e01c8063b587295814610038578063e8d6008914610068575b5f5ffd5b610052600480360381019061004d9190610610565b610084565b60405161005f9190610687565b60405180910390f35b610082600480360381019061007d91906106ca565b6100a7565b005b5f602052805f5260405f205f915054906101000a900467ffffffffffffffff1681565b6100e6816040518060400160405280601f81526020017f74696d657374616d70206d75737420626520696e2074686520667574757265008152506102b7565b61011c5f5f8481526020019081526020015f205f9054906101000a900467ffffffffffffffff1667ffffffffffffffff166102e8565b156101ab57805f5f8481526020019081526020015f205f6101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055503373ffffffffffffffffffffffffffffffffffffffff16827fc8502b80f9a4eddb29943d46e36f689055a259a8be737b8e3d2c902da42a6e838360405161019e9190610687565b60405180910390a36102b3565b5f6101d9825f5f8681526020019081526020015f205f9054906101000a900467ffffffffffffffff166102fd565b90505f61021c5f5f8681526020019081526020015f205f9054906101000a900467ffffffffffffffff168367ffffffffffffffff1661032f90919063ffffffff16565b67ffffffffffffffff16146102b157805f5f8581526020019081526020015f205f6101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055503373ffffffffffffffffffffffffffffffffffffffff16837fc8502b80f9a4eddb29943d46e36f689055a259a8be737b8e3d2c902da42a6e83836040516102a89190610687565b60405180910390a35b505b5050565b6102e46102de836102c661037a565b67ffffffffffffffff166104a890919063ffffffff16565b826104c8565b5050565b5f5f8267ffffffffffffffff16149050919050565b5f61031b828467ffffffffffffffff166104a890919063ffffffff16565b6103255781610327565b825b905092915050565b5f61034d828467ffffffffffffffff166105b990919063ffffffff16565b1561036557818361035e9190610735565b9050610374565b82826103719190610735565b90505b92915050565b5f5f5f7fba286e4d89dabf4b2878e896423bb123d9d5143e662606fd343b6766d7bcf7215f1c73ffffffffffffffffffffffffffffffffffffffff166040516103c29061079d565b5f60405180830381855afa9150503d805f81146103fa576040519150601f19603f3d011682016040523d82523d5f602084013e6103ff565b606091505b509150915081610444576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161043b9061080b565b60405180910390fd5b6020815114610488576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161047f90610873565b60405180910390fd5b5f8180602001905181019061049d91906108bb565b905080935050505090565b5f8167ffffffffffffffff168367ffffffffffffffff1610905092915050565b5f7f3dcdf63b41c103567d7225976ad9145e866c7a7dccc6c277ea86abbd268fbac95f1c73ffffffffffffffffffffffffffffffffffffffff16836040516020016105139190610900565b60405160208183030381529060405260405161052f9190610961565b5f60405180830381855afa9150503d805f8114610567576040519150601f19603f3d011682016040523d82523d5f602084013e61056c565b606091505b505090508082906105b3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105aa91906109c9565b60405180910390fd5b50505050565b5f8167ffffffffffffffff168367ffffffffffffffff1611905092915050565b5f5ffd5b5f819050919050565b6105ef816105dd565b81146105f9575f5ffd5b50565b5f8135905061060a816105e6565b92915050565b5f60208284031215610625576106246105d9565b5b5f610632848285016105fc565b91505092915050565b5f67ffffffffffffffff82169050919050565b5f819050919050565b5f61067161066c6106678461063b565b61064e565b61063b565b9050919050565b61068181610657565b82525050565b5f60208201905061069a5f830184610678565b92915050565b6106a98161063b565b81146106b3575f5ffd5b50565b5f813590506106c4816106a0565b92915050565b5f5f604083850312156106e0576106df6105d9565b5b5f6106ed858286016105fc565b92505060206106fe858286016106b6565b9150509250929050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f61073f8261063b565b915061074a8361063b565b9250828203905067ffffffffffffffff81111561076a57610769610708565b5b92915050565b5f81905092915050565b50565b5f6107885f83610770565b91506107938261077a565b5f82019050919050565b5f6107a78261077d565b9150819050919050565b5f82825260208201905092915050565b7f507265636f6d70696c652063616c6c206661696c6564000000000000000000005f82015250565b5f6107f56016836107b1565b9150610800826107c1565b602082019050919050565b5f6020820190508181035f830152610822816107e9565b9050919050565b7f496e76616c6964206f7574707574206c656e67746800000000000000000000005f82015250565b5f61085d6015836107b1565b915061086882610829565b602082019050919050565b5f6020820190508181035f83015261088a81610851565b9050919050565b61089a8161063b565b81146108a4575f5ffd5b50565b5f815190506108b581610891565b92915050565b5f602082840312156108d0576108cf6105d9565b5b5f6108dd848285016108a7565b91505092915050565b5f8115159050919050565b6108fa816108e6565b82525050565b5f6020820190506109135f8301846108f1565b92915050565b5f81519050919050565b8281835e5f83830152505050565b5f61093b82610919565b6109458185610770565b9350610955818560208601610923565b80840191505092915050565b5f61096c8284610931565b915081905092915050565b5f81519050919050565b5f601f19601f8301169050919050565b5f61099b82610977565b6109a581856107b1565b93506109b5818560208601610923565b6109be81610981565b840191505092915050565b5f6020820190508181035f8301526109e18184610991565b90509291505056 /// ``` #[rustfmt::skip] #[allow(clippy::all)] pub static BYTECODE: alloy_sol_types::private::Bytes = alloy_sol_types::private::Bytes::from_static( - b"`\x80`@R4\x80\x15`\x0FW`\0\x80\xFD[Pa\n]\x80a\0\x1F`\09`\0\xF3\xFE`\x80`@R4\x80\x15a\0\x10W`\0\x80\xFD[P`\x046\x10a\x006W`\x005`\xE0\x1C\x80c\xB5\x87)X\x14a\0;W\x80c\xE8\xD6\0\x89\x14a\0kW[`\0\x80\xFD[a\0U`\x04\x806\x03\x81\x01\x90a\0P\x91\x90a\x06=V[a\0\x87V[`@Qa\0b\x91\x90a\x06\xB9V[`@Q\x80\x91\x03\x90\xF3[a\0\x85`\x04\x806\x03\x81\x01\x90a\0\x80\x91\x90a\x07\0V[a\0\xAEV[\0[`\0` R\x80`\0R`@`\0 `\0\x91PT\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81V[a\0\xED\x81`@Q\x80`@\x01`@R\x80`\x1F\x81R` \x01\x7Ftimestamp must be in the future\0\x81RPa\x02\xCFV[a\x01&`\0\x80\x84\x81R` \x01\x90\x81R` \x01`\0 `\0\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x03\0V[\x15a\x01\xB8W\x80`\0\x80\x84\x81R` \x01\x90\x81R` \x01`\0 `\0a\x01\0\n\x81T\x81g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UP3s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x82\x7F\xC8P+\x80\xF9\xA4\xED\xDB)\x94=F\xE3oh\x90U\xA2Y\xA8\xBEs{\x8E=,\x90-\xA4*n\x83\x83`@Qa\x01\xAB\x91\x90a\x06\xB9V[`@Q\x80\x91\x03\x90\xA3a\x02\xCBV[`\0a\x01\xEA\x82`\0\x80\x86\x81R` \x01\x90\x81R` \x01`\0 `\0\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x03\x16V[\x90P`\0a\x021`\0\x80\x86\x81R` \x01\x90\x81R` \x01`\0 `\0\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x83g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x03I\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x02\xC9W\x80`\0\x80\x85\x81R` \x01\x90\x81R` \x01`\0 `\0a\x01\0\n\x81T\x81g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UP3s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x83\x7F\xC8P+\x80\xF9\xA4\xED\xDB)\x94=F\xE3oh\x90U\xA2Y\xA8\xBEs{\x8E=,\x90-\xA4*n\x83\x83`@Qa\x02\xC0\x91\x90a\x06\xB9V[`@Q\x80\x91\x03\x90\xA3[P[PPV[a\x02\xFCa\x02\xF6\x83a\x02\xDEa\x03\x95V[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x04\xCA\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[\x82a\x04\xEBV[PPV[`\0\x80\x82g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14\x90P\x91\x90PV[`\0a\x035\x82\x84g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x04\xCA\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[a\x03?W\x81a\x03AV[\x82[\x90P\x92\x91PPV[`\0a\x03h\x82\x84g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x05\xE1\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[\x15a\x03\x80W\x81\x83a\x03y\x91\x90a\x07oV[\x90Pa\x03\x8FV[\x82\x82a\x03\x8C\x91\x90a\x07oV[\x90P[\x92\x91PPV[`\0\x80`\0\x7F\xBA(nM\x89\xDA\xBFK(x\xE8\x96B;\xB1#\xD9\xD5\x14>f&\x06\xFD4;gf\xD7\xBC\xF7!`\0\x1Cs\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\x03\xE0\x90a\x07\xDCV[`\0`@Q\x80\x83\x03\x81\x85Z\xFA\x91PP=\x80`\0\x81\x14a\x04\x1BW`@Q\x91P`\x1F\x19`?=\x01\x16\x82\x01`@R=\x82R=`\0` \x84\x01>a\x04 V[``\x91P[P\x91P\x91P\x81a\x04eW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x04\\\x90a\x08NV[`@Q\x80\x91\x03\x90\xFD[` \x81Q\x14a\x04\xA9W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x04\xA0\x90a\x08\xBAV[`@Q\x80\x91\x03\x90\xFD[`\0\x81\x80` \x01\x90Q\x81\x01\x90a\x04\xBF\x91\x90a\t\x06V[\x90P\x80\x93PPPP\x90V[`\0\x81g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x83g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x10\x90P\x92\x91PPV[`\0\x7F=\xCD\xF6;A\xC1\x03V}r%\x97j\xD9\x14^\x86lz}\xCC\xC6\xC2w\xEA\x86\xAB\xBD&\x8F\xBA\xC9`\0\x1Cs\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x83`@Q` \x01a\x058\x91\x90a\tNV[`@Q` \x81\x83\x03\x03\x81R\x90`@R`@Qa\x05T\x91\x90a\t\xCFV[`\0`@Q\x80\x83\x03\x81\x85Z\xFA\x91PP=\x80`\0\x81\x14a\x05\x8FW`@Q\x91P`\x1F\x19`?=\x01\x16\x82\x01`@R=\x82R=`\0` \x84\x01>a\x05\x94V[``\x91P[PP\x90P\x80\x82\x90a\x05\xDBW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x05\xD2\x91\x90a\n;V[`@Q\x80\x91\x03\x90\xFD[PPPPV[`\0\x81g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x83g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x11\x90P\x92\x91PPV[`\0\x80\xFD[`\0\x81\x90P\x91\x90PV[a\x06\x1A\x81a\x06\x07V[\x81\x14a\x06%W`\0\x80\xFD[PV[`\0\x815\x90Pa\x067\x81a\x06\x11V[\x92\x91PPV[`\0` \x82\x84\x03\x12\x15a\x06SWa\x06Ra\x06\x02V[[`\0a\x06a\x84\x82\x85\x01a\x06(V[\x91PP\x92\x91PPV[`\0g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x16\x90P\x91\x90PV[`\0\x81\x90P\x91\x90PV[`\0a\x06\xA3a\x06\x9Ea\x06\x99\x84a\x06jV[a\x06~V[a\x06jV[\x90P\x91\x90PV[a\x06\xB3\x81a\x06\x88V[\x82RPPV[`\0` \x82\x01\x90Pa\x06\xCE`\0\x83\x01\x84a\x06\xAAV[\x92\x91PPV[a\x06\xDD\x81a\x06jV[\x81\x14a\x06\xE8W`\0\x80\xFD[PV[`\0\x815\x90Pa\x06\xFA\x81a\x06\xD4V[\x92\x91PPV[`\0\x80`@\x83\x85\x03\x12\x15a\x07\x17Wa\x07\x16a\x06\x02V[[`\0a\x07%\x85\x82\x86\x01a\x06(V[\x92PP` a\x076\x85\x82\x86\x01a\x06\xEBV[\x91PP\x92P\x92\x90PV[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0`\0R`\x11`\x04R`$`\0\xFD[`\0a\x07z\x82a\x06jV[\x91Pa\x07\x85\x83a\x06jV[\x92P\x82\x82\x03\x90Pg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\x07\xA5Wa\x07\xA4a\x07@V[[\x92\x91PPV[`\0\x81\x90P\x92\x91PPV[PV[`\0a\x07\xC6`\0\x83a\x07\xABV[\x91Pa\x07\xD1\x82a\x07\xB6V[`\0\x82\x01\x90P\x91\x90PV[`\0a\x07\xE7\x82a\x07\xB9V[\x91P\x81\x90P\x91\x90PV[`\0\x82\x82R` \x82\x01\x90P\x92\x91PPV[\x7FPrecompile call failed\0\0\0\0\0\0\0\0\0\0`\0\x82\x01RPV[`\0a\x088`\x16\x83a\x07\xF1V[\x91Pa\x08C\x82a\x08\x02V[` \x82\x01\x90P\x91\x90PV[`\0` \x82\x01\x90P\x81\x81\x03`\0\x83\x01Ra\x08g\x81a\x08+V[\x90P\x91\x90PV[\x7FInvalid output length\0\0\0\0\0\0\0\0\0\0\0`\0\x82\x01RPV[`\0a\x08\xA4`\x15\x83a\x07\xF1V[\x91Pa\x08\xAF\x82a\x08nV[` \x82\x01\x90P\x91\x90PV[`\0` \x82\x01\x90P\x81\x81\x03`\0\x83\x01Ra\x08\xD3\x81a\x08\x97V[\x90P\x91\x90PV[a\x08\xE3\x81a\x06jV[\x81\x14a\x08\xEEW`\0\x80\xFD[PV[`\0\x81Q\x90Pa\t\0\x81a\x08\xDAV[\x92\x91PPV[`\0` \x82\x84\x03\x12\x15a\t\x1CWa\t\x1Ba\x06\x02V[[`\0a\t*\x84\x82\x85\x01a\x08\xF1V[\x91PP\x92\x91PPV[`\0\x81\x15\x15\x90P\x91\x90PV[a\tH\x81a\t3V[\x82RPPV[`\0` \x82\x01\x90Pa\tc`\0\x83\x01\x84a\t?V[\x92\x91PPV[`\0\x81Q\x90P\x91\x90PV[`\0[\x83\x81\x10\x15a\t\x92W\x80\x82\x01Q\x81\x84\x01R` \x81\x01\x90Pa\twV[`\0\x84\x84\x01RPPPPV[`\0a\t\xA9\x82a\tiV[a\t\xB3\x81\x85a\x07\xABV[\x93Pa\t\xC3\x81\x85` \x86\x01a\ttV[\x80\x84\x01\x91PP\x92\x91PPV[`\0a\t\xDB\x82\x84a\t\x9EV[\x91P\x81\x90P\x92\x91PPV[`\0\x81Q\x90P\x91\x90PV[`\0`\x1F\x19`\x1F\x83\x01\x16\x90P\x91\x90PV[`\0a\n\r\x82a\t\xE6V[a\n\x17\x81\x85a\x07\xF1V[\x93Pa\n'\x81\x85` \x86\x01a\ttV[a\n0\x81a\t\xF1V[\x84\x01\x91PP\x92\x91PPV[`\0` \x82\x01\x90P\x81\x81\x03`\0\x83\x01Ra\nU\x81\x84a\n\x02V[\x90P\x92\x91PPV", + b"`\x80`@R4\x80\x15`\x0EW__\xFD[Pa\t\xE9\x80a\0\x1C_9_\xF3\xFE`\x80`@R4\x80\x15a\0\x0FW__\xFD[P`\x046\x10a\x004W_5`\xE0\x1C\x80c\xB5\x87)X\x14a\08W\x80c\xE8\xD6\0\x89\x14a\0hW[__\xFD[a\0R`\x04\x806\x03\x81\x01\x90a\0M\x91\x90a\x06\x10V[a\0\x84V[`@Qa\0_\x91\x90a\x06\x87V[`@Q\x80\x91\x03\x90\xF3[a\0\x82`\x04\x806\x03\x81\x01\x90a\0}\x91\x90a\x06\xCAV[a\0\xA7V[\0[_` R\x80_R`@_ _\x91PT\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81V[a\0\xE6\x81`@Q\x80`@\x01`@R\x80`\x1F\x81R` \x01\x7Ftimestamp must be in the future\0\x81RPa\x02\xB7V[a\x01\x1C__\x84\x81R` \x01\x90\x81R` \x01_ _\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x02\xE8V[\x15a\x01\xABW\x80__\x84\x81R` \x01\x90\x81R` \x01_ _a\x01\0\n\x81T\x81g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UP3s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x82\x7F\xC8P+\x80\xF9\xA4\xED\xDB)\x94=F\xE3oh\x90U\xA2Y\xA8\xBEs{\x8E=,\x90-\xA4*n\x83\x83`@Qa\x01\x9E\x91\x90a\x06\x87V[`@Q\x80\x91\x03\x90\xA3a\x02\xB3V[_a\x01\xD9\x82__\x86\x81R` \x01\x90\x81R` \x01_ _\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x02\xFDV[\x90P_a\x02\x1C__\x86\x81R` \x01\x90\x81R` \x01_ _\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x83g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x03/\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x02\xB1W\x80__\x85\x81R` \x01\x90\x81R` \x01_ _a\x01\0\n\x81T\x81g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UP3s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x83\x7F\xC8P+\x80\xF9\xA4\xED\xDB)\x94=F\xE3oh\x90U\xA2Y\xA8\xBEs{\x8E=,\x90-\xA4*n\x83\x83`@Qa\x02\xA8\x91\x90a\x06\x87V[`@Q\x80\x91\x03\x90\xA3[P[PPV[a\x02\xE4a\x02\xDE\x83a\x02\xC6a\x03zV[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x04\xA8\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[\x82a\x04\xC8V[PPV[__\x82g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14\x90P\x91\x90PV[_a\x03\x1B\x82\x84g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x04\xA8\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[a\x03%W\x81a\x03'V[\x82[\x90P\x92\x91PPV[_a\x03M\x82\x84g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x05\xB9\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[\x15a\x03eW\x81\x83a\x03^\x91\x90a\x075V[\x90Pa\x03tV[\x82\x82a\x03q\x91\x90a\x075V[\x90P[\x92\x91PPV[___\x7F\xBA(nM\x89\xDA\xBFK(x\xE8\x96B;\xB1#\xD9\xD5\x14>f&\x06\xFD4;gf\xD7\xBC\xF7!_\x1Cs\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\x03\xC2\x90a\x07\x9DV[_`@Q\x80\x83\x03\x81\x85Z\xFA\x91PP=\x80_\x81\x14a\x03\xFAW`@Q\x91P`\x1F\x19`?=\x01\x16\x82\x01`@R=\x82R=_` \x84\x01>a\x03\xFFV[``\x91P[P\x91P\x91P\x81a\x04DW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x04;\x90a\x08\x0BV[`@Q\x80\x91\x03\x90\xFD[` \x81Q\x14a\x04\x88W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x04\x7F\x90a\x08sV[`@Q\x80\x91\x03\x90\xFD[_\x81\x80` \x01\x90Q\x81\x01\x90a\x04\x9D\x91\x90a\x08\xBBV[\x90P\x80\x93PPPP\x90V[_\x81g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x83g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x10\x90P\x92\x91PPV[_\x7F=\xCD\xF6;A\xC1\x03V}r%\x97j\xD9\x14^\x86lz}\xCC\xC6\xC2w\xEA\x86\xAB\xBD&\x8F\xBA\xC9_\x1Cs\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x83`@Q` \x01a\x05\x13\x91\x90a\t\0V[`@Q` \x81\x83\x03\x03\x81R\x90`@R`@Qa\x05/\x91\x90a\taV[_`@Q\x80\x83\x03\x81\x85Z\xFA\x91PP=\x80_\x81\x14a\x05gW`@Q\x91P`\x1F\x19`?=\x01\x16\x82\x01`@R=\x82R=_` \x84\x01>a\x05lV[``\x91P[PP\x90P\x80\x82\x90a\x05\xB3W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x05\xAA\x91\x90a\t\xC9V[`@Q\x80\x91\x03\x90\xFD[PPPPV[_\x81g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x83g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x11\x90P\x92\x91PPV[__\xFD[_\x81\x90P\x91\x90PV[a\x05\xEF\x81a\x05\xDDV[\x81\x14a\x05\xF9W__\xFD[PV[_\x815\x90Pa\x06\n\x81a\x05\xE6V[\x92\x91PPV[_` \x82\x84\x03\x12\x15a\x06%Wa\x06$a\x05\xD9V[[_a\x062\x84\x82\x85\x01a\x05\xFCV[\x91PP\x92\x91PPV[_g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x16\x90P\x91\x90PV[_\x81\x90P\x91\x90PV[_a\x06qa\x06la\x06g\x84a\x06;V[a\x06NV[a\x06;V[\x90P\x91\x90PV[a\x06\x81\x81a\x06WV[\x82RPPV[_` \x82\x01\x90Pa\x06\x9A_\x83\x01\x84a\x06xV[\x92\x91PPV[a\x06\xA9\x81a\x06;V[\x81\x14a\x06\xB3W__\xFD[PV[_\x815\x90Pa\x06\xC4\x81a\x06\xA0V[\x92\x91PPV[__`@\x83\x85\x03\x12\x15a\x06\xE0Wa\x06\xDFa\x05\xD9V[[_a\x06\xED\x85\x82\x86\x01a\x05\xFCV[\x92PP` a\x06\xFE\x85\x82\x86\x01a\x06\xB6V[\x91PP\x92P\x92\x90PV[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_R`\x11`\x04R`$_\xFD[_a\x07?\x82a\x06;V[\x91Pa\x07J\x83a\x06;V[\x92P\x82\x82\x03\x90Pg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\x07jWa\x07ia\x07\x08V[[\x92\x91PPV[_\x81\x90P\x92\x91PPV[PV[_a\x07\x88_\x83a\x07pV[\x91Pa\x07\x93\x82a\x07zV[_\x82\x01\x90P\x91\x90PV[_a\x07\xA7\x82a\x07}V[\x91P\x81\x90P\x91\x90PV[_\x82\x82R` \x82\x01\x90P\x92\x91PPV[\x7FPrecompile call failed\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_a\x07\xF5`\x16\x83a\x07\xB1V[\x91Pa\x08\0\x82a\x07\xC1V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01Ra\x08\"\x81a\x07\xE9V[\x90P\x91\x90PV[\x7FInvalid output length\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_a\x08]`\x15\x83a\x07\xB1V[\x91Pa\x08h\x82a\x08)V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01Ra\x08\x8A\x81a\x08QV[\x90P\x91\x90PV[a\x08\x9A\x81a\x06;V[\x81\x14a\x08\xA4W__\xFD[PV[_\x81Q\x90Pa\x08\xB5\x81a\x08\x91V[\x92\x91PPV[_` \x82\x84\x03\x12\x15a\x08\xD0Wa\x08\xCFa\x05\xD9V[[_a\x08\xDD\x84\x82\x85\x01a\x08\xA7V[\x91PP\x92\x91PPV[_\x81\x15\x15\x90P\x91\x90PV[a\x08\xFA\x81a\x08\xE6V[\x82RPPV[_` \x82\x01\x90Pa\t\x13_\x83\x01\x84a\x08\xF1V[\x92\x91PPV[_\x81Q\x90P\x91\x90PV[\x82\x81\x83^_\x83\x83\x01RPPPV[_a\t;\x82a\t\x19V[a\tE\x81\x85a\x07pV[\x93Pa\tU\x81\x85` \x86\x01a\t#V[\x80\x84\x01\x91PP\x92\x91PPV[_a\tl\x82\x84a\t1V[\x91P\x81\x90P\x92\x91PPV[_\x81Q\x90P\x91\x90PV[_`\x1F\x19`\x1F\x83\x01\x16\x90P\x91\x90PV[_a\t\x9B\x82a\twV[a\t\xA5\x81\x85a\x07\xB1V[\x93Pa\t\xB5\x81\x85` \x86\x01a\t#V[a\t\xBE\x81a\t\x81V[\x84\x01\x91PP\x92\x91PPV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01Ra\t\xE1\x81\x84a\t\x91V[\x90P\x92\x91PPV", ); /// The runtime bytecode of the contract, as deployed on the network. /// /// ```text - ///0x608060405234801561001057600080fd5b50600436106100365760003560e01c8063b58729581461003b578063e8d600891461006b575b600080fd5b6100556004803603810190610050919061063d565b610087565b60405161006291906106b9565b60405180910390f35b61008560048036038101906100809190610700565b6100ae565b005b60006020528060005260406000206000915054906101000a900467ffffffffffffffff1681565b6100ed816040518060400160405280601f81526020017f74696d657374616d70206d75737420626520696e2074686520667574757265008152506102cf565b61012660008084815260200190815260200160002060009054906101000a900467ffffffffffffffff1667ffffffffffffffff16610300565b156101b8578060008084815260200190815260200160002060006101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055503373ffffffffffffffffffffffffffffffffffffffff16827fc8502b80f9a4eddb29943d46e36f689055a259a8be737b8e3d2c902da42a6e83836040516101ab91906106b9565b60405180910390a36102cb565b60006101ea8260008086815260200190815260200160002060009054906101000a900467ffffffffffffffff16610316565b9050600061023160008086815260200190815260200160002060009054906101000a900467ffffffffffffffff168367ffffffffffffffff1661034990919063ffffffff16565b67ffffffffffffffff16146102c9578060008085815260200190815260200160002060006101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055503373ffffffffffffffffffffffffffffffffffffffff16837fc8502b80f9a4eddb29943d46e36f689055a259a8be737b8e3d2c902da42a6e83836040516102c091906106b9565b60405180910390a35b505b5050565b6102fc6102f6836102de610395565b67ffffffffffffffff166104ca90919063ffffffff16565b826104eb565b5050565b6000808267ffffffffffffffff16149050919050565b6000610335828467ffffffffffffffff166104ca90919063ffffffff16565b61033f5781610341565b825b905092915050565b6000610368828467ffffffffffffffff166105e190919063ffffffff16565b15610380578183610379919061076f565b905061038f565b828261038c919061076f565b90505b92915050565b60008060007fba286e4d89dabf4b2878e896423bb123d9d5143e662606fd343b6766d7bcf72160001c73ffffffffffffffffffffffffffffffffffffffff166040516103e0906107dc565b600060405180830381855afa9150503d806000811461041b576040519150601f19603f3d011682016040523d82523d6000602084013e610420565b606091505b509150915081610465576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161045c9061084e565b60405180910390fd5b60208151146104a9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104a0906108ba565b60405180910390fd5b6000818060200190518101906104bf9190610906565b905080935050505090565b60008167ffffffffffffffff168367ffffffffffffffff1610905092915050565b60007f3dcdf63b41c103567d7225976ad9145e866c7a7dccc6c277ea86abbd268fbac960001c73ffffffffffffffffffffffffffffffffffffffff1683604051602001610538919061094e565b60405160208183030381529060405260405161055491906109cf565b600060405180830381855afa9150503d806000811461058f576040519150601f19603f3d011682016040523d82523d6000602084013e610594565b606091505b505090508082906105db576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105d29190610a3b565b60405180910390fd5b50505050565b60008167ffffffffffffffff168367ffffffffffffffff1611905092915050565b600080fd5b6000819050919050565b61061a81610607565b811461062557600080fd5b50565b60008135905061063781610611565b92915050565b60006020828403121561065357610652610602565b5b600061066184828501610628565b91505092915050565b600067ffffffffffffffff82169050919050565b6000819050919050565b60006106a361069e6106998461066a565b61067e565b61066a565b9050919050565b6106b381610688565b82525050565b60006020820190506106ce60008301846106aa565b92915050565b6106dd8161066a565b81146106e857600080fd5b50565b6000813590506106fa816106d4565b92915050565b6000806040838503121561071757610716610602565b5b600061072585828601610628565b9250506020610736858286016106eb565b9150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061077a8261066a565b91506107858361066a565b9250828203905067ffffffffffffffff8111156107a5576107a4610740565b5b92915050565b600081905092915050565b50565b60006107c66000836107ab565b91506107d1826107b6565b600082019050919050565b60006107e7826107b9565b9150819050919050565b600082825260208201905092915050565b7f507265636f6d70696c652063616c6c206661696c656400000000000000000000600082015250565b60006108386016836107f1565b915061084382610802565b602082019050919050565b600060208201905081810360008301526108678161082b565b9050919050565b7f496e76616c6964206f7574707574206c656e6774680000000000000000000000600082015250565b60006108a46015836107f1565b91506108af8261086e565b602082019050919050565b600060208201905081810360008301526108d381610897565b9050919050565b6108e38161066a565b81146108ee57600080fd5b50565b600081519050610900816108da565b92915050565b60006020828403121561091c5761091b610602565b5b600061092a848285016108f1565b91505092915050565b60008115159050919050565b61094881610933565b82525050565b6000602082019050610963600083018461093f565b92915050565b600081519050919050565b60005b83811015610992578082015181840152602081019050610977565b60008484015250505050565b60006109a982610969565b6109b381856107ab565b93506109c3818560208601610974565b80840191505092915050565b60006109db828461099e565b915081905092915050565b600081519050919050565b6000601f19601f8301169050919050565b6000610a0d826109e6565b610a1781856107f1565b9350610a27818560208601610974565b610a30816109f1565b840191505092915050565b60006020820190508181036000830152610a558184610a02565b90509291505056 + ///0x608060405234801561000f575f5ffd5b5060043610610034575f3560e01c8063b587295814610038578063e8d6008914610068575b5f5ffd5b610052600480360381019061004d9190610610565b610084565b60405161005f9190610687565b60405180910390f35b610082600480360381019061007d91906106ca565b6100a7565b005b5f602052805f5260405f205f915054906101000a900467ffffffffffffffff1681565b6100e6816040518060400160405280601f81526020017f74696d657374616d70206d75737420626520696e2074686520667574757265008152506102b7565b61011c5f5f8481526020019081526020015f205f9054906101000a900467ffffffffffffffff1667ffffffffffffffff166102e8565b156101ab57805f5f8481526020019081526020015f205f6101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055503373ffffffffffffffffffffffffffffffffffffffff16827fc8502b80f9a4eddb29943d46e36f689055a259a8be737b8e3d2c902da42a6e838360405161019e9190610687565b60405180910390a36102b3565b5f6101d9825f5f8681526020019081526020015f205f9054906101000a900467ffffffffffffffff166102fd565b90505f61021c5f5f8681526020019081526020015f205f9054906101000a900467ffffffffffffffff168367ffffffffffffffff1661032f90919063ffffffff16565b67ffffffffffffffff16146102b157805f5f8581526020019081526020015f205f6101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055503373ffffffffffffffffffffffffffffffffffffffff16837fc8502b80f9a4eddb29943d46e36f689055a259a8be737b8e3d2c902da42a6e83836040516102a89190610687565b60405180910390a35b505b5050565b6102e46102de836102c661037a565b67ffffffffffffffff166104a890919063ffffffff16565b826104c8565b5050565b5f5f8267ffffffffffffffff16149050919050565b5f61031b828467ffffffffffffffff166104a890919063ffffffff16565b6103255781610327565b825b905092915050565b5f61034d828467ffffffffffffffff166105b990919063ffffffff16565b1561036557818361035e9190610735565b9050610374565b82826103719190610735565b90505b92915050565b5f5f5f7fba286e4d89dabf4b2878e896423bb123d9d5143e662606fd343b6766d7bcf7215f1c73ffffffffffffffffffffffffffffffffffffffff166040516103c29061079d565b5f60405180830381855afa9150503d805f81146103fa576040519150601f19603f3d011682016040523d82523d5f602084013e6103ff565b606091505b509150915081610444576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161043b9061080b565b60405180910390fd5b6020815114610488576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161047f90610873565b60405180910390fd5b5f8180602001905181019061049d91906108bb565b905080935050505090565b5f8167ffffffffffffffff168367ffffffffffffffff1610905092915050565b5f7f3dcdf63b41c103567d7225976ad9145e866c7a7dccc6c277ea86abbd268fbac95f1c73ffffffffffffffffffffffffffffffffffffffff16836040516020016105139190610900565b60405160208183030381529060405260405161052f9190610961565b5f60405180830381855afa9150503d805f8114610567576040519150601f19603f3d011682016040523d82523d5f602084013e61056c565b606091505b505090508082906105b3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105aa91906109c9565b60405180910390fd5b50505050565b5f8167ffffffffffffffff168367ffffffffffffffff1611905092915050565b5f5ffd5b5f819050919050565b6105ef816105dd565b81146105f9575f5ffd5b50565b5f8135905061060a816105e6565b92915050565b5f60208284031215610625576106246105d9565b5b5f610632848285016105fc565b91505092915050565b5f67ffffffffffffffff82169050919050565b5f819050919050565b5f61067161066c6106678461063b565b61064e565b61063b565b9050919050565b61068181610657565b82525050565b5f60208201905061069a5f830184610678565b92915050565b6106a98161063b565b81146106b3575f5ffd5b50565b5f813590506106c4816106a0565b92915050565b5f5f604083850312156106e0576106df6105d9565b5b5f6106ed858286016105fc565b92505060206106fe858286016106b6565b9150509250929050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f61073f8261063b565b915061074a8361063b565b9250828203905067ffffffffffffffff81111561076a57610769610708565b5b92915050565b5f81905092915050565b50565b5f6107885f83610770565b91506107938261077a565b5f82019050919050565b5f6107a78261077d565b9150819050919050565b5f82825260208201905092915050565b7f507265636f6d70696c652063616c6c206661696c6564000000000000000000005f82015250565b5f6107f56016836107b1565b9150610800826107c1565b602082019050919050565b5f6020820190508181035f830152610822816107e9565b9050919050565b7f496e76616c6964206f7574707574206c656e67746800000000000000000000005f82015250565b5f61085d6015836107b1565b915061086882610829565b602082019050919050565b5f6020820190508181035f83015261088a81610851565b9050919050565b61089a8161063b565b81146108a4575f5ffd5b50565b5f815190506108b581610891565b92915050565b5f602082840312156108d0576108cf6105d9565b5b5f6108dd848285016108a7565b91505092915050565b5f8115159050919050565b6108fa816108e6565b82525050565b5f6020820190506109135f8301846108f1565b92915050565b5f81519050919050565b8281835e5f83830152505050565b5f61093b82610919565b6109458185610770565b9350610955818560208601610923565b80840191505092915050565b5f61096c8284610931565b915081905092915050565b5f81519050919050565b5f601f19601f8301169050919050565b5f61099b82610977565b6109a581856107b1565b93506109b5818560208601610923565b6109be81610981565b840191505092915050565b5f6020820190508181035f8301526109e18184610991565b90509291505056 /// ``` #[rustfmt::skip] #[allow(clippy::all)] pub static DEPLOYED_BYTECODE: alloy_sol_types::private::Bytes = alloy_sol_types::private::Bytes::from_static( - b"`\x80`@R4\x80\x15a\0\x10W`\0\x80\xFD[P`\x046\x10a\x006W`\x005`\xE0\x1C\x80c\xB5\x87)X\x14a\0;W\x80c\xE8\xD6\0\x89\x14a\0kW[`\0\x80\xFD[a\0U`\x04\x806\x03\x81\x01\x90a\0P\x91\x90a\x06=V[a\0\x87V[`@Qa\0b\x91\x90a\x06\xB9V[`@Q\x80\x91\x03\x90\xF3[a\0\x85`\x04\x806\x03\x81\x01\x90a\0\x80\x91\x90a\x07\0V[a\0\xAEV[\0[`\0` R\x80`\0R`@`\0 `\0\x91PT\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81V[a\0\xED\x81`@Q\x80`@\x01`@R\x80`\x1F\x81R` \x01\x7Ftimestamp must be in the future\0\x81RPa\x02\xCFV[a\x01&`\0\x80\x84\x81R` \x01\x90\x81R` \x01`\0 `\0\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x03\0V[\x15a\x01\xB8W\x80`\0\x80\x84\x81R` \x01\x90\x81R` \x01`\0 `\0a\x01\0\n\x81T\x81g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UP3s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x82\x7F\xC8P+\x80\xF9\xA4\xED\xDB)\x94=F\xE3oh\x90U\xA2Y\xA8\xBEs{\x8E=,\x90-\xA4*n\x83\x83`@Qa\x01\xAB\x91\x90a\x06\xB9V[`@Q\x80\x91\x03\x90\xA3a\x02\xCBV[`\0a\x01\xEA\x82`\0\x80\x86\x81R` \x01\x90\x81R` \x01`\0 `\0\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x03\x16V[\x90P`\0a\x021`\0\x80\x86\x81R` \x01\x90\x81R` \x01`\0 `\0\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x83g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x03I\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x02\xC9W\x80`\0\x80\x85\x81R` \x01\x90\x81R` \x01`\0 `\0a\x01\0\n\x81T\x81g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UP3s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x83\x7F\xC8P+\x80\xF9\xA4\xED\xDB)\x94=F\xE3oh\x90U\xA2Y\xA8\xBEs{\x8E=,\x90-\xA4*n\x83\x83`@Qa\x02\xC0\x91\x90a\x06\xB9V[`@Q\x80\x91\x03\x90\xA3[P[PPV[a\x02\xFCa\x02\xF6\x83a\x02\xDEa\x03\x95V[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x04\xCA\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[\x82a\x04\xEBV[PPV[`\0\x80\x82g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14\x90P\x91\x90PV[`\0a\x035\x82\x84g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x04\xCA\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[a\x03?W\x81a\x03AV[\x82[\x90P\x92\x91PPV[`\0a\x03h\x82\x84g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x05\xE1\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[\x15a\x03\x80W\x81\x83a\x03y\x91\x90a\x07oV[\x90Pa\x03\x8FV[\x82\x82a\x03\x8C\x91\x90a\x07oV[\x90P[\x92\x91PPV[`\0\x80`\0\x7F\xBA(nM\x89\xDA\xBFK(x\xE8\x96B;\xB1#\xD9\xD5\x14>f&\x06\xFD4;gf\xD7\xBC\xF7!`\0\x1Cs\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\x03\xE0\x90a\x07\xDCV[`\0`@Q\x80\x83\x03\x81\x85Z\xFA\x91PP=\x80`\0\x81\x14a\x04\x1BW`@Q\x91P`\x1F\x19`?=\x01\x16\x82\x01`@R=\x82R=`\0` \x84\x01>a\x04 V[``\x91P[P\x91P\x91P\x81a\x04eW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x04\\\x90a\x08NV[`@Q\x80\x91\x03\x90\xFD[` \x81Q\x14a\x04\xA9W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x04\xA0\x90a\x08\xBAV[`@Q\x80\x91\x03\x90\xFD[`\0\x81\x80` \x01\x90Q\x81\x01\x90a\x04\xBF\x91\x90a\t\x06V[\x90P\x80\x93PPPP\x90V[`\0\x81g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x83g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x10\x90P\x92\x91PPV[`\0\x7F=\xCD\xF6;A\xC1\x03V}r%\x97j\xD9\x14^\x86lz}\xCC\xC6\xC2w\xEA\x86\xAB\xBD&\x8F\xBA\xC9`\0\x1Cs\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x83`@Q` \x01a\x058\x91\x90a\tNV[`@Q` \x81\x83\x03\x03\x81R\x90`@R`@Qa\x05T\x91\x90a\t\xCFV[`\0`@Q\x80\x83\x03\x81\x85Z\xFA\x91PP=\x80`\0\x81\x14a\x05\x8FW`@Q\x91P`\x1F\x19`?=\x01\x16\x82\x01`@R=\x82R=`\0` \x84\x01>a\x05\x94V[``\x91P[PP\x90P\x80\x82\x90a\x05\xDBW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x05\xD2\x91\x90a\n;V[`@Q\x80\x91\x03\x90\xFD[PPPPV[`\0\x81g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x83g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x11\x90P\x92\x91PPV[`\0\x80\xFD[`\0\x81\x90P\x91\x90PV[a\x06\x1A\x81a\x06\x07V[\x81\x14a\x06%W`\0\x80\xFD[PV[`\0\x815\x90Pa\x067\x81a\x06\x11V[\x92\x91PPV[`\0` \x82\x84\x03\x12\x15a\x06SWa\x06Ra\x06\x02V[[`\0a\x06a\x84\x82\x85\x01a\x06(V[\x91PP\x92\x91PPV[`\0g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x16\x90P\x91\x90PV[`\0\x81\x90P\x91\x90PV[`\0a\x06\xA3a\x06\x9Ea\x06\x99\x84a\x06jV[a\x06~V[a\x06jV[\x90P\x91\x90PV[a\x06\xB3\x81a\x06\x88V[\x82RPPV[`\0` \x82\x01\x90Pa\x06\xCE`\0\x83\x01\x84a\x06\xAAV[\x92\x91PPV[a\x06\xDD\x81a\x06jV[\x81\x14a\x06\xE8W`\0\x80\xFD[PV[`\0\x815\x90Pa\x06\xFA\x81a\x06\xD4V[\x92\x91PPV[`\0\x80`@\x83\x85\x03\x12\x15a\x07\x17Wa\x07\x16a\x06\x02V[[`\0a\x07%\x85\x82\x86\x01a\x06(V[\x92PP` a\x076\x85\x82\x86\x01a\x06\xEBV[\x91PP\x92P\x92\x90PV[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0`\0R`\x11`\x04R`$`\0\xFD[`\0a\x07z\x82a\x06jV[\x91Pa\x07\x85\x83a\x06jV[\x92P\x82\x82\x03\x90Pg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\x07\xA5Wa\x07\xA4a\x07@V[[\x92\x91PPV[`\0\x81\x90P\x92\x91PPV[PV[`\0a\x07\xC6`\0\x83a\x07\xABV[\x91Pa\x07\xD1\x82a\x07\xB6V[`\0\x82\x01\x90P\x91\x90PV[`\0a\x07\xE7\x82a\x07\xB9V[\x91P\x81\x90P\x91\x90PV[`\0\x82\x82R` \x82\x01\x90P\x92\x91PPV[\x7FPrecompile call failed\0\0\0\0\0\0\0\0\0\0`\0\x82\x01RPV[`\0a\x088`\x16\x83a\x07\xF1V[\x91Pa\x08C\x82a\x08\x02V[` \x82\x01\x90P\x91\x90PV[`\0` \x82\x01\x90P\x81\x81\x03`\0\x83\x01Ra\x08g\x81a\x08+V[\x90P\x91\x90PV[\x7FInvalid output length\0\0\0\0\0\0\0\0\0\0\0`\0\x82\x01RPV[`\0a\x08\xA4`\x15\x83a\x07\xF1V[\x91Pa\x08\xAF\x82a\x08nV[` \x82\x01\x90P\x91\x90PV[`\0` \x82\x01\x90P\x81\x81\x03`\0\x83\x01Ra\x08\xD3\x81a\x08\x97V[\x90P\x91\x90PV[a\x08\xE3\x81a\x06jV[\x81\x14a\x08\xEEW`\0\x80\xFD[PV[`\0\x81Q\x90Pa\t\0\x81a\x08\xDAV[\x92\x91PPV[`\0` \x82\x84\x03\x12\x15a\t\x1CWa\t\x1Ba\x06\x02V[[`\0a\t*\x84\x82\x85\x01a\x08\xF1V[\x91PP\x92\x91PPV[`\0\x81\x15\x15\x90P\x91\x90PV[a\tH\x81a\t3V[\x82RPPV[`\0` \x82\x01\x90Pa\tc`\0\x83\x01\x84a\t?V[\x92\x91PPV[`\0\x81Q\x90P\x91\x90PV[`\0[\x83\x81\x10\x15a\t\x92W\x80\x82\x01Q\x81\x84\x01R` \x81\x01\x90Pa\twV[`\0\x84\x84\x01RPPPPV[`\0a\t\xA9\x82a\tiV[a\t\xB3\x81\x85a\x07\xABV[\x93Pa\t\xC3\x81\x85` \x86\x01a\ttV[\x80\x84\x01\x91PP\x92\x91PPV[`\0a\t\xDB\x82\x84a\t\x9EV[\x91P\x81\x90P\x92\x91PPV[`\0\x81Q\x90P\x91\x90PV[`\0`\x1F\x19`\x1F\x83\x01\x16\x90P\x91\x90PV[`\0a\n\r\x82a\t\xE6V[a\n\x17\x81\x85a\x07\xF1V[\x93Pa\n'\x81\x85` \x86\x01a\ttV[a\n0\x81a\t\xF1V[\x84\x01\x91PP\x92\x91PPV[`\0` \x82\x01\x90P\x81\x81\x03`\0\x83\x01Ra\nU\x81\x84a\n\x02V[\x90P\x92\x91PPV", + b"`\x80`@R4\x80\x15a\0\x0FW__\xFD[P`\x046\x10a\x004W_5`\xE0\x1C\x80c\xB5\x87)X\x14a\08W\x80c\xE8\xD6\0\x89\x14a\0hW[__\xFD[a\0R`\x04\x806\x03\x81\x01\x90a\0M\x91\x90a\x06\x10V[a\0\x84V[`@Qa\0_\x91\x90a\x06\x87V[`@Q\x80\x91\x03\x90\xF3[a\0\x82`\x04\x806\x03\x81\x01\x90a\0}\x91\x90a\x06\xCAV[a\0\xA7V[\0[_` R\x80_R`@_ _\x91PT\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81V[a\0\xE6\x81`@Q\x80`@\x01`@R\x80`\x1F\x81R` \x01\x7Ftimestamp must be in the future\0\x81RPa\x02\xB7V[a\x01\x1C__\x84\x81R` \x01\x90\x81R` \x01_ _\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x02\xE8V[\x15a\x01\xABW\x80__\x84\x81R` \x01\x90\x81R` \x01_ _a\x01\0\n\x81T\x81g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UP3s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x82\x7F\xC8P+\x80\xF9\xA4\xED\xDB)\x94=F\xE3oh\x90U\xA2Y\xA8\xBEs{\x8E=,\x90-\xA4*n\x83\x83`@Qa\x01\x9E\x91\x90a\x06\x87V[`@Q\x80\x91\x03\x90\xA3a\x02\xB3V[_a\x01\xD9\x82__\x86\x81R` \x01\x90\x81R` \x01_ _\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x02\xFDV[\x90P_a\x02\x1C__\x86\x81R` \x01\x90\x81R` \x01_ _\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x83g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x03/\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x02\xB1W\x80__\x85\x81R` \x01\x90\x81R` \x01_ _a\x01\0\n\x81T\x81g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UP3s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x83\x7F\xC8P+\x80\xF9\xA4\xED\xDB)\x94=F\xE3oh\x90U\xA2Y\xA8\xBEs{\x8E=,\x90-\xA4*n\x83\x83`@Qa\x02\xA8\x91\x90a\x06\x87V[`@Q\x80\x91\x03\x90\xA3[P[PPV[a\x02\xE4a\x02\xDE\x83a\x02\xC6a\x03zV[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x04\xA8\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[\x82a\x04\xC8V[PPV[__\x82g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14\x90P\x91\x90PV[_a\x03\x1B\x82\x84g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x04\xA8\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[a\x03%W\x81a\x03'V[\x82[\x90P\x92\x91PPV[_a\x03M\x82\x84g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x05\xB9\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[\x15a\x03eW\x81\x83a\x03^\x91\x90a\x075V[\x90Pa\x03tV[\x82\x82a\x03q\x91\x90a\x075V[\x90P[\x92\x91PPV[___\x7F\xBA(nM\x89\xDA\xBFK(x\xE8\x96B;\xB1#\xD9\xD5\x14>f&\x06\xFD4;gf\xD7\xBC\xF7!_\x1Cs\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\x03\xC2\x90a\x07\x9DV[_`@Q\x80\x83\x03\x81\x85Z\xFA\x91PP=\x80_\x81\x14a\x03\xFAW`@Q\x91P`\x1F\x19`?=\x01\x16\x82\x01`@R=\x82R=_` \x84\x01>a\x03\xFFV[``\x91P[P\x91P\x91P\x81a\x04DW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x04;\x90a\x08\x0BV[`@Q\x80\x91\x03\x90\xFD[` \x81Q\x14a\x04\x88W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x04\x7F\x90a\x08sV[`@Q\x80\x91\x03\x90\xFD[_\x81\x80` \x01\x90Q\x81\x01\x90a\x04\x9D\x91\x90a\x08\xBBV[\x90P\x80\x93PPPP\x90V[_\x81g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x83g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x10\x90P\x92\x91PPV[_\x7F=\xCD\xF6;A\xC1\x03V}r%\x97j\xD9\x14^\x86lz}\xCC\xC6\xC2w\xEA\x86\xAB\xBD&\x8F\xBA\xC9_\x1Cs\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x83`@Q` \x01a\x05\x13\x91\x90a\t\0V[`@Q` \x81\x83\x03\x03\x81R\x90`@R`@Qa\x05/\x91\x90a\taV[_`@Q\x80\x83\x03\x81\x85Z\xFA\x91PP=\x80_\x81\x14a\x05gW`@Q\x91P`\x1F\x19`?=\x01\x16\x82\x01`@R=\x82R=_` \x84\x01>a\x05lV[``\x91P[PP\x90P\x80\x82\x90a\x05\xB3W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x05\xAA\x91\x90a\t\xC9V[`@Q\x80\x91\x03\x90\xFD[PPPPV[_\x81g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x83g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x11\x90P\x92\x91PPV[__\xFD[_\x81\x90P\x91\x90PV[a\x05\xEF\x81a\x05\xDDV[\x81\x14a\x05\xF9W__\xFD[PV[_\x815\x90Pa\x06\n\x81a\x05\xE6V[\x92\x91PPV[_` \x82\x84\x03\x12\x15a\x06%Wa\x06$a\x05\xD9V[[_a\x062\x84\x82\x85\x01a\x05\xFCV[\x91PP\x92\x91PPV[_g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x16\x90P\x91\x90PV[_\x81\x90P\x91\x90PV[_a\x06qa\x06la\x06g\x84a\x06;V[a\x06NV[a\x06;V[\x90P\x91\x90PV[a\x06\x81\x81a\x06WV[\x82RPPV[_` \x82\x01\x90Pa\x06\x9A_\x83\x01\x84a\x06xV[\x92\x91PPV[a\x06\xA9\x81a\x06;V[\x81\x14a\x06\xB3W__\xFD[PV[_\x815\x90Pa\x06\xC4\x81a\x06\xA0V[\x92\x91PPV[__`@\x83\x85\x03\x12\x15a\x06\xE0Wa\x06\xDFa\x05\xD9V[[_a\x06\xED\x85\x82\x86\x01a\x05\xFCV[\x92PP` a\x06\xFE\x85\x82\x86\x01a\x06\xB6V[\x91PP\x92P\x92\x90PV[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_R`\x11`\x04R`$_\xFD[_a\x07?\x82a\x06;V[\x91Pa\x07J\x83a\x06;V[\x92P\x82\x82\x03\x90Pg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\x07jWa\x07ia\x07\x08V[[\x92\x91PPV[_\x81\x90P\x92\x91PPV[PV[_a\x07\x88_\x83a\x07pV[\x91Pa\x07\x93\x82a\x07zV[_\x82\x01\x90P\x91\x90PV[_a\x07\xA7\x82a\x07}V[\x91P\x81\x90P\x91\x90PV[_\x82\x82R` \x82\x01\x90P\x92\x91PPV[\x7FPrecompile call failed\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_a\x07\xF5`\x16\x83a\x07\xB1V[\x91Pa\x08\0\x82a\x07\xC1V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01Ra\x08\"\x81a\x07\xE9V[\x90P\x91\x90PV[\x7FInvalid output length\0\0\0\0\0\0\0\0\0\0\0_\x82\x01RPV[_a\x08]`\x15\x83a\x07\xB1V[\x91Pa\x08h\x82a\x08)V[` \x82\x01\x90P\x91\x90PV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01Ra\x08\x8A\x81a\x08QV[\x90P\x91\x90PV[a\x08\x9A\x81a\x06;V[\x81\x14a\x08\xA4W__\xFD[PV[_\x81Q\x90Pa\x08\xB5\x81a\x08\x91V[\x92\x91PPV[_` \x82\x84\x03\x12\x15a\x08\xD0Wa\x08\xCFa\x05\xD9V[[_a\x08\xDD\x84\x82\x85\x01a\x08\xA7V[\x91PP\x92\x91PPV[_\x81\x15\x15\x90P\x91\x90PV[a\x08\xFA\x81a\x08\xE6V[\x82RPPV[_` \x82\x01\x90Pa\t\x13_\x83\x01\x84a\x08\xF1V[\x92\x91PPV[_\x81Q\x90P\x91\x90PV[\x82\x81\x83^_\x83\x83\x01RPPPV[_a\t;\x82a\t\x19V[a\tE\x81\x85a\x07pV[\x93Pa\tU\x81\x85` \x86\x01a\t#V[\x80\x84\x01\x91PP\x92\x91PPV[_a\tl\x82\x84a\t1V[\x91P\x81\x90P\x92\x91PPV[_\x81Q\x90P\x91\x90PV[_`\x1F\x19`\x1F\x83\x01\x16\x90P\x91\x90PV[_a\t\x9B\x82a\twV[a\t\xA5\x81\x85a\x07\xB1V[\x93Pa\t\xB5\x81\x85` \x86\x01a\t#V[a\t\xBE\x81a\t\x81V[\x84\x01\x91PP\x92\x91PPV[_` \x82\x01\x90P\x81\x81\x03_\x83\x01Ra\t\xE1\x81\x84a\t\x91V[\x90P\x92\x91PPV", ); #[derive(serde::Serialize, serde::Deserialize)] #[derive(Default, Debug, PartialEq, Eq, Hash)] diff --git a/examples/notary/bindings/src/time.rs b/examples/notary/bindings/src/time.rs index a6d12b78..c7cf30a7 100644 --- a/examples/notary/bindings/src/time.rs +++ b/examples/notary/bindings/src/time.rs @@ -22,22 +22,22 @@ pub mod Time { /// The creation / init bytecode of the contract. /// /// ```text - ///0x60206050600b82828239805160001a6073146043577f4e487b7100000000000000000000000000000000000000000000000000000000600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fd + ///0x601f604b600b8282823980515f1a607314603f577f4e487b71000000000000000000000000000000000000000000000000000000005f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040525f5ffd /// ``` #[rustfmt::skip] #[allow(clippy::all)] pub static BYTECODE: alloy_sol_types::private::Bytes = alloy_sol_types::private::Bytes::from_static( - b"` `P`\x0B\x82\x82\x829\x80Q`\0\x1A`s\x14`CW\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0`\0R`\0`\x04R`$`\0\xFD[0`\0R`s\x81S\x82\x81\xF3\xFEs\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x000\x14`\x80`@R`\0\x80\xFD", + b"`\x1F`K`\x0B\x82\x82\x829\x80Q_\x1A`s\x14`?W\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_R_`\x04R`$_\xFD[0_R`s\x81S\x82\x81\xF3\xFEs\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x000\x14`\x80`@R__\xFD", ); /// The runtime bytecode of the contract, as deployed on the network. /// /// ```text - ///0x73000000000000000000000000000000000000000030146080604052600080fd + ///0x730000000000000000000000000000000000000000301460806040525f5ffd /// ``` #[rustfmt::skip] #[allow(clippy::all)] pub static DEPLOYED_BYTECODE: alloy_sol_types::private::Bytes = alloy_sol_types::private::Bytes::from_static( - b"s\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x000\x14`\x80`@R`\0\x80\xFD", + b"s\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x000\x14`\x80`@R__\xFD", ); use alloy::contract as alloy_contract; /**Creates a new wrapper around an on-chain [`Time`](self) contract instance. diff --git a/examples/notary/foundry.toml b/examples/notary/foundry.toml index b85c875f..f518db2b 100644 --- a/examples/notary/foundry.toml +++ b/examples/notary/foundry.toml @@ -3,7 +3,7 @@ src = "." out = "out" libs = ["lib"] solc = "0.8.28" -evm_version = "berlin" +evm_version = "prague" bytecode_hash = "none" cbor_metadata = false remappings = [ diff --git a/examples/optimistic-auction/bindings/src/pod_auction_consumer.rs b/examples/optimistic-auction/bindings/src/pod_auction_consumer.rs index 40ec5fbe..b9115e1f 100644 --- a/examples/optimistic-auction/bindings/src/pod_auction_consumer.rs +++ b/examples/optimistic-auction/bindings/src/pod_auction_consumer.rs @@ -1547,13 +1547,13 @@ interface PodAuctionConsumer { constructor(address _podRegistry, uint256 _bondAmount); + function BOND_AMOUNT() external view returns (uint256); function DISPUTE_PERIOD() external view returns (uint256); function LOG_TOPIC_0() external view returns (bytes32); function TWO_TIMES_DISPUTE_PERIOD() external view returns (uint256); function blameIllAnnounced(PodECDSA.CertifiedLog memory certifiedLog) external; function blameNoShow(PodECDSA.CertifiedLog memory certifiedLog) external; function bond() external payable; - function bondAmount() external view returns (uint256); function isBonded(address) external view returns (bool); function owner() external view returns (address); function podRegistry() external view returns (address); @@ -1586,6 +1586,19 @@ interface PodAuctionConsumer { ], "stateMutability": "nonpayable" }, + { + "type": "function", + "name": "BOND_AMOUNT", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, { "type": "function", "name": "DISPUTE_PERIOD", @@ -1808,19 +1821,6 @@ interface PodAuctionConsumer { "outputs": [], "stateMutability": "payable" }, - { - "type": "function", - "name": "bondAmount", - "inputs": [], - "outputs": [ - { - "name": "", - "type": "uint256", - "internalType": "uint256" - } - ], - "stateMutability": "view" - }, { "type": "function", "name": "isBonded", @@ -3606,6 +3606,151 @@ constructor(address _podRegistry, uint256 _bondAmount); }; #[derive(serde::Serialize, serde::Deserialize)] #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Function with signature `BOND_AMOUNT()` and selector `0xbcacc70a`. +```solidity +function BOND_AMOUNT() external view returns (uint256); +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct BOND_AMOUNTCall; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + ///Container type for the return parameters of the [`BOND_AMOUNT()`](BOND_AMOUNTCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct BOND_AMOUNTReturn { + #[allow(missing_docs)] + pub _0: alloy::sol_types::private::primitives::aliases::U256, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: BOND_AMOUNTCall) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for BOND_AMOUNTCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self + } + } + } + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (alloy::sol_types::sol_data::Uint<256>,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = ( + alloy::sol_types::private::primitives::aliases::U256, + ); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: BOND_AMOUNTReturn) -> Self { + (value._0,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for BOND_AMOUNTReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { _0: tuple.0 } + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for BOND_AMOUNTCall { + type Parameters<'a> = (); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = alloy::sol_types::private::primitives::aliases::U256; + type ReturnTuple<'a> = (alloy::sol_types::sol_data::Uint<256>,); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "BOND_AMOUNT()"; + const SELECTOR: [u8; 4] = [188u8, 172u8, 199u8, 10u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + () + } + #[inline] + fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> { + ( + as alloy_sol_types::SolType>::tokenize(ret), + ) + } + #[inline] + fn abi_decode_returns(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data) + .map(|r| { + let r: BOND_AMOUNTReturn = r.into(); + r._0 + }) + } + #[inline] + fn abi_decode_returns_validate( + data: &[u8], + ) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(|r| { + let r: BOND_AMOUNTReturn = r.into(); + r._0 + }) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] /**Function with signature `DISPUTE_PERIOD()` and selector `0xa5bbe22b`. ```solidity function DISPUTE_PERIOD() external view returns (uint256); @@ -4472,151 +4617,6 @@ function bond() external payable; }; #[derive(serde::Serialize, serde::Deserialize)] #[derive(Default, Debug, PartialEq, Eq, Hash)] - /**Function with signature `bondAmount()` and selector `0x80f323a7`. -```solidity -function bondAmount() external view returns (uint256); -```*/ - #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] - #[derive(Clone)] - pub struct bondAmountCall; - #[derive(serde::Serialize, serde::Deserialize)] - #[derive(Default, Debug, PartialEq, Eq, Hash)] - ///Container type for the return parameters of the [`bondAmount()`](bondAmountCall) function. - #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] - #[derive(Clone)] - pub struct bondAmountReturn { - #[allow(missing_docs)] - pub _0: alloy::sol_types::private::primitives::aliases::U256, - } - #[allow( - non_camel_case_types, - non_snake_case, - clippy::pub_underscore_fields, - clippy::style - )] - const _: () = { - use alloy::sol_types as alloy_sol_types; - { - #[doc(hidden)] - type UnderlyingSolTuple<'a> = (); - #[doc(hidden)] - type UnderlyingRustTuple<'a> = (); - #[cfg(test)] - #[allow(dead_code, unreachable_patterns)] - fn _type_assertion( - _t: alloy_sol_types::private::AssertTypeEq, - ) { - match _t { - alloy_sol_types::private::AssertTypeEq::< - ::RustType, - >(_) => {} - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From for UnderlyingRustTuple<'_> { - fn from(value: bondAmountCall) -> Self { - () - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From> for bondAmountCall { - fn from(tuple: UnderlyingRustTuple<'_>) -> Self { - Self - } - } - } - { - #[doc(hidden)] - type UnderlyingSolTuple<'a> = (alloy::sol_types::sol_data::Uint<256>,); - #[doc(hidden)] - type UnderlyingRustTuple<'a> = ( - alloy::sol_types::private::primitives::aliases::U256, - ); - #[cfg(test)] - #[allow(dead_code, unreachable_patterns)] - fn _type_assertion( - _t: alloy_sol_types::private::AssertTypeEq, - ) { - match _t { - alloy_sol_types::private::AssertTypeEq::< - ::RustType, - >(_) => {} - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From for UnderlyingRustTuple<'_> { - fn from(value: bondAmountReturn) -> Self { - (value._0,) - } - } - #[automatically_derived] - #[doc(hidden)] - impl ::core::convert::From> for bondAmountReturn { - fn from(tuple: UnderlyingRustTuple<'_>) -> Self { - Self { _0: tuple.0 } - } - } - } - #[automatically_derived] - impl alloy_sol_types::SolCall for bondAmountCall { - type Parameters<'a> = (); - type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; - type Return = alloy::sol_types::private::primitives::aliases::U256; - type ReturnTuple<'a> = (alloy::sol_types::sol_data::Uint<256>,); - type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; - const SIGNATURE: &'static str = "bondAmount()"; - const SELECTOR: [u8; 4] = [128u8, 243u8, 35u8, 167u8]; - #[inline] - fn new<'a>( - tuple: as alloy_sol_types::SolType>::RustType, - ) -> Self { - tuple.into() - } - #[inline] - fn tokenize(&self) -> Self::Token<'_> { - () - } - #[inline] - fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> { - ( - as alloy_sol_types::SolType>::tokenize(ret), - ) - } - #[inline] - fn abi_decode_returns(data: &[u8]) -> alloy_sol_types::Result { - as alloy_sol_types::SolType>::abi_decode_sequence(data) - .map(|r| { - let r: bondAmountReturn = r.into(); - r._0 - }) - } - #[inline] - fn abi_decode_returns_validate( - data: &[u8], - ) -> alloy_sol_types::Result { - as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) - .map(|r| { - let r: bondAmountReturn = r.into(); - r._0 - }) - } - } - }; - #[derive(serde::Serialize, serde::Deserialize)] - #[derive(Default, Debug, PartialEq, Eq, Hash)] /**Function with signature `isBonded(address)` and selector `0x4aa5e885`. ```solidity function isBonded(address) external view returns (bool); @@ -6071,6 +6071,8 @@ function write(PodECDSA.CertifiedLog memory certifiedLog) external; #[derive(serde::Serialize, serde::Deserialize)] #[derive()] pub enum PodAuctionConsumerCalls { + #[allow(missing_docs)] + BOND_AMOUNT(BOND_AMOUNTCall), #[allow(missing_docs)] DISPUTE_PERIOD(DISPUTE_PERIODCall), #[allow(missing_docs)] @@ -6084,8 +6086,6 @@ function write(PodECDSA.CertifiedLog memory certifiedLog) external; #[allow(missing_docs)] bond(bondCall), #[allow(missing_docs)] - bondAmount(bondAmountCall), - #[allow(missing_docs)] isBonded(isBondedCall), #[allow(missing_docs)] owner(ownerCall), @@ -6123,11 +6123,11 @@ function write(PodECDSA.CertifiedLog memory certifiedLog) external; [100u8, 201u8, 236u8, 111u8], [113u8, 80u8, 24u8, 166u8], [117u8, 8u8, 9u8, 151u8], - [128u8, 243u8, 35u8, 167u8], [141u8, 165u8, 203u8, 91u8], [160u8, 155u8, 128u8, 185u8], [165u8, 187u8, 226u8, 43u8], [187u8, 16u8, 169u8, 184u8], + [188u8, 172u8, 199u8, 10u8], [197u8, 220u8, 198u8, 145u8], [207u8, 76u8, 127u8, 145u8], [233u8, 117u8, 27u8, 55u8], @@ -6142,6 +6142,9 @@ function write(PodECDSA.CertifiedLog memory certifiedLog) external; #[inline] fn selector(&self) -> [u8; 4] { match self { + Self::BOND_AMOUNT(_) => { + ::SELECTOR + } Self::DISPUTE_PERIOD(_) => { ::SELECTOR } @@ -6158,9 +6161,6 @@ function write(PodECDSA.CertifiedLog memory certifiedLog) external; ::SELECTOR } Self::bond(_) => ::SELECTOR, - Self::bondAmount(_) => { - ::SELECTOR - } Self::isBonded(_) => ::SELECTOR, Self::owner(_) => ::SELECTOR, Self::podRegistry(_) => { @@ -6272,17 +6272,6 @@ function write(PodECDSA.CertifiedLog memory certifiedLog) external; } read }, - { - fn bondAmount( - data: &[u8], - ) -> alloy_sol_types::Result { - ::abi_decode_raw( - data, - ) - .map(PodAuctionConsumerCalls::bondAmount) - } - bondAmount - }, { fn owner( data: &[u8], @@ -6323,6 +6312,17 @@ function write(PodECDSA.CertifiedLog memory certifiedLog) external; } blameIllAnnounced }, + { + fn BOND_AMOUNT( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw( + data, + ) + .map(PodAuctionConsumerCalls::BOND_AMOUNT) + } + BOND_AMOUNT + }, { fn TWO_TIMES_DISPUTE_PERIOD( data: &[u8], @@ -6475,17 +6475,6 @@ function write(PodECDSA.CertifiedLog memory certifiedLog) external; } read }, - { - fn bondAmount( - data: &[u8], - ) -> alloy_sol_types::Result { - ::abi_decode_raw_validate( - data, - ) - .map(PodAuctionConsumerCalls::bondAmount) - } - bondAmount - }, { fn owner( data: &[u8], @@ -6530,6 +6519,17 @@ function write(PodECDSA.CertifiedLog memory certifiedLog) external; } blameIllAnnounced }, + { + fn BOND_AMOUNT( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(PodAuctionConsumerCalls::BOND_AMOUNT) + } + BOND_AMOUNT + }, { fn TWO_TIMES_DISPUTE_PERIOD( data: &[u8], @@ -6588,6 +6588,11 @@ function write(PodECDSA.CertifiedLog memory certifiedLog) external; #[inline] fn abi_encoded_size(&self) -> usize { match self { + Self::BOND_AMOUNT(inner) => { + ::abi_encoded_size( + inner, + ) + } Self::DISPUTE_PERIOD(inner) => { ::abi_encoded_size( inner, @@ -6616,9 +6621,6 @@ function write(PodECDSA.CertifiedLog memory certifiedLog) external; Self::bond(inner) => { ::abi_encoded_size(inner) } - Self::bondAmount(inner) => { - ::abi_encoded_size(inner) - } Self::isBonded(inner) => { ::abi_encoded_size(inner) } @@ -6660,6 +6662,12 @@ function write(PodECDSA.CertifiedLog memory certifiedLog) external; #[inline] fn abi_encode_raw(&self, out: &mut alloy_sol_types::private::Vec) { match self { + Self::BOND_AMOUNT(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } Self::DISPUTE_PERIOD(inner) => { ::abi_encode_raw( inner, @@ -6693,12 +6701,6 @@ function write(PodECDSA.CertifiedLog memory certifiedLog) external; Self::bond(inner) => { ::abi_encode_raw(inner, out) } - Self::bondAmount(inner) => { - ::abi_encode_raw( - inner, - out, - ) - } Self::isBonded(inner) => { ::abi_encode_raw( inner, @@ -7179,6 +7181,12 @@ See the [wrapper's documentation](`PodAuctionConsumerInstance`) for more details ) -> alloy_contract::SolCallBuilder<&P, C, N> { alloy_contract::SolCallBuilder::new_sol(&self.provider, &self.address, call) } + ///Creates a new call builder for the [`BOND_AMOUNT`] function. + pub fn BOND_AMOUNT( + &self, + ) -> alloy_contract::SolCallBuilder<&P, BOND_AMOUNTCall, N> { + self.call_builder(&BOND_AMOUNTCall) + } ///Creates a new call builder for the [`DISPUTE_PERIOD`] function. pub fn DISPUTE_PERIOD( &self, @@ -7219,12 +7227,6 @@ See the [wrapper's documentation](`PodAuctionConsumerInstance`) for more details pub fn bond(&self) -> alloy_contract::SolCallBuilder<&P, bondCall, N> { self.call_builder(&bondCall) } - ///Creates a new call builder for the [`bondAmount`] function. - pub fn bondAmount( - &self, - ) -> alloy_contract::SolCallBuilder<&P, bondAmountCall, N> { - self.call_builder(&bondAmountCall) - } ///Creates a new call builder for the [`isBonded`] function. pub fn isBonded( &self, diff --git a/examples/optimistic-auction/contracts/AbsBonding.sol b/examples/optimistic-auction/contracts/AbsBonding.sol index e5161bc2..b06326a8 100644 --- a/examples/optimistic-auction/contracts/AbsBonding.sol +++ b/examples/optimistic-auction/contracts/AbsBonding.sol @@ -4,7 +4,7 @@ pragma solidity ^0.8.20; import {Ownable} from "openzeppelin-contracts/access/Ownable.sol"; abstract contract AbsBonding is Ownable { - uint256 public immutable bondAmount; + uint256 public immutable BOND_AMOUNT; mapping(address => bool) public isBonded; @@ -13,7 +13,7 @@ abstract contract AbsBonding is Ownable { event Slashed(address indexed validator); constructor(uint256 _bondAmount) Ownable(msg.sender) { - bondAmount = _bondAmount; + BOND_AMOUNT = _bondAmount; } modifier onlyBonded() { @@ -23,7 +23,7 @@ abstract contract AbsBonding is Ownable { function bond() external payable { require(!isBonded[msg.sender], "Already bonded"); - require(msg.value >= bondAmount, "Not enough bond"); + require(msg.value >= BOND_AMOUNT, "Not enough bond"); isBonded[msg.sender] = true; emit Bonded(msg.sender); @@ -31,7 +31,7 @@ abstract contract AbsBonding is Ownable { function unbond() external onlyBonded { isBonded[msg.sender] = false; - payable(msg.sender).transfer(bondAmount); + payable(msg.sender).transfer(BOND_AMOUNT); emit Unbonded(msg.sender); } diff --git a/examples/optimistic-auction/contracts/PodAuctionConsumer.sol b/examples/optimistic-auction/contracts/PodAuctionConsumer.sol index 19a57250..245a7afb 100644 --- a/examples/optimistic-auction/contracts/PodAuctionConsumer.sol +++ b/examples/optimistic-auction/contracts/PodAuctionConsumer.sol @@ -2,8 +2,7 @@ pragma solidity ^0.8.20; import {PodECDSA} from "pod-sdk/verifier/PodECDSA.sol"; -import {MerkleTree} from "pod-sdk/verifier/MerkleTree.sol"; -import {IPodRegistry} from "pod-sdk/verifier/PodRegistry.sol"; +import {IPodRegistry} from "pod-protocol/interfaces/IPodRegistry.sol"; import {AbsBonding} from "./AbsBonding.sol"; contract PodAuctionConsumer is AbsBonding { @@ -44,8 +43,16 @@ contract PodAuctionConsumer is AbsBonding { /** * @notice deadline in seconds */ - function getUniqueAuctionId(uint256 auctionId, uint256 deadlineInSeconds) internal pure returns (bytes32) { - return keccak256(abi.encodePacked(auctionId, deadlineInSeconds)); + function getUniqueAuctionId(uint256 auctionId, uint256 deadlineInSeconds) + internal + pure + returns (bytes32 hashedVal) + { + assembly { + mstore(0x00, auctionId) + mstore(0x20, deadlineInSeconds) + hashedVal := keccak256(0x00, 0x40) + } } /** diff --git a/examples/optimistic-auction/foundry.toml b/examples/optimistic-auction/foundry.toml index 505b6542..fbb4eef8 100644 --- a/examples/optimistic-auction/foundry.toml +++ b/examples/optimistic-auction/foundry.toml @@ -3,16 +3,19 @@ src = "contracts" out = "out" libs = ["lib"] solc = "0.8.28" -evm_version = "berlin" +evm_version = "prague" bytecode_hash = "none" cbor_metadata = false remappings = [ "pod-sdk/=../../solidity-sdk/src/", - "pod-sdk-scripts/=../../solidity-sdk/script/", + "pod-protocol/=../../protocol/src", + "pod-protocol-scripts/=../../protocol/script/", "optimistic-auction/=contracts/" - ] -allow_paths = ["../../solidity-sdk"] +allow_paths = [ + "../../solidity-sdk", + "../../protocol" +] # See more config options https://github.com/foundry-rs/foundry/blob/master/crates/config/README.md#all-options diff --git a/examples/optimistic-auction/script/PodAuctionConsumerDeployer.s.sol b/examples/optimistic-auction/script/PodAuctionConsumerDeployer.s.sol index c6f4cfc1..a680fda4 100644 --- a/examples/optimistic-auction/script/PodAuctionConsumerDeployer.s.sol +++ b/examples/optimistic-auction/script/PodAuctionConsumerDeployer.s.sol @@ -2,9 +2,9 @@ pragma solidity ^0.8.20; import {console} from "forge-std/console.sol"; -import {BaseDeployer} from "pod-sdk-scripts/BaseDeployer.s.sol"; +import {BaseDeployer} from "pod-protocol-scripts/BaseDeployer.s.sol"; -import {PodRegistry} from "pod-sdk/verifier/PodRegistry.sol"; +import {PodRegistry} from "pod-protocol/PodRegistry.sol"; import {PodAuctionConsumer} from "../contracts/PodAuctionConsumer.sol"; contract PodAuctionConsumerDeployer is BaseDeployer { diff --git a/examples/optimistic-auction/test/PodAuctionConsumer.t.sol b/examples/optimistic-auction/test/PodAuctionConsumer.t.sol index 43a2813b..8b63b7b0 100644 --- a/examples/optimistic-auction/test/PodAuctionConsumer.t.sol +++ b/examples/optimistic-auction/test/PodAuctionConsumer.t.sol @@ -4,7 +4,7 @@ pragma solidity ^0.8.20; import {Test} from "forge-std/Test.sol"; import {PodECDSA, ECDSA} from "pod-sdk/verifier/PodECDSA.sol"; import {MerkleTree} from "pod-sdk/verifier/MerkleTree.sol"; -import {PodRegistry} from "pod-sdk/verifier/PodRegistry.sol"; +import {PodRegistry} from "pod-protocol/PodRegistry.sol"; import {PodAuctionConsumer} from "../contracts/PodAuctionConsumer.sol"; import {console} from "forge-std/console.sol"; import {Math} from "openzeppelin-contracts/utils/math/Math.sol"; diff --git a/examples/solidity/foundry.toml b/examples/solidity/foundry.toml index 73cec62a..6074c6a2 100644 --- a/examples/solidity/foundry.toml +++ b/examples/solidity/foundry.toml @@ -8,10 +8,15 @@ bytecode_hash = "none" cbor_metadata = false remappings = [ "pod-sdk/=../../solidity-sdk/src/", - "pod-sdk-scripts/=../../solidity-sdk/script/", - "optimistic-auction/=../optimistic-auction/contracts/", + "pod-protocol/=../../protocol/src", + "pod-protocol-scripts/=../../protocol/script/", + "optimistic-auction/=../optimistic-auction/contracts/" +] +allow_paths = [ + "../../solidity-sdk", + "../../protocol", + "../optimistic-auction" ] -allow_paths = ["../../solidity-sdk", "../optimistic-auction"] [fmt] exclude = ["lib/**"] diff --git a/examples/solidity/script/Deploy.s.sol b/examples/solidity/script/Deploy.s.sol index 29e193be..e7ddc3bb 100644 --- a/examples/solidity/script/Deploy.s.sol +++ b/examples/solidity/script/Deploy.s.sol @@ -2,12 +2,12 @@ pragma solidity ^0.8.28; import {console} from "forge-std/console.sol"; -import {BaseDeployer} from "pod-sdk-scripts/BaseDeployer.s.sol"; import {Auction} from "../src/Auction.sol"; import {RankedFeed} from "../src/RankedFeed.sol"; import {Voting} from "../src/Voting.sol"; -import {PodRegistry} from "pod-sdk/verifier/PodRegistry.sol"; +import {BaseDeployer} from "pod-protocol-scripts/BaseDeployer.s.sol"; +import {PodRegistry} from "pod-protocol/PodRegistry.sol"; import {PodAuctionConsumer} from "optimistic-auction/PodAuctionConsumer.sol"; contract Deployer is BaseDeployer { diff --git a/examples/voting/bindings/src/voting.rs b/examples/voting/bindings/src/voting.rs index dd4eb362..b39335c2 100644 --- a/examples/voting/bindings/src/voting.rs +++ b/examples/voting/bindings/src/voting.rs @@ -470,22 +470,22 @@ pub mod Voting { /// The creation / init bytecode of the contract. /// /// ```text - ///0x6080604052348015600f57600080fd5b5061199e8061001f6000396000f3fe608060405234801561001057600080fd5b506004361061004c5760003560e01c8063b4b0713e14610051578063b829966f1461006d578063cf75ee2a1461009d578063e751f271146100cd575b600080fd5b61006b60048036038101906100669190610cc8565b6100e9565b005b61008760048036038101906100829190610e0b565b6102f1565b6040516100949190610e8e565b60405180910390f35b6100b760048036038101906100b29190610f35565b610350565b6040516100c49190610e8e565b60405180910390f35b6100e760048036038101906100e29190610fdc565b610602565b005b600080600084815260200190815260200160002090506101398160000160009054906101000a900467ffffffffffffffff166040518060600160405280603781526020016119676037913961077b565b6001600281111561014d5761014c611009565b5b8160030160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1660028111156101ae576101ad611009565b5b146101ee576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101e590611095565b60405180910390fd5b6000610206843360026107ac9092919063ffffffff16565b14610246576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161023d90611101565b60405180910390fd5b61025f833360016002610878909392919063ffffffff16565b61029d8383604051602001610275929190611130565b604051602081830303815290604052805190602001206001806109559092919063ffffffff16565b3373ffffffffffffffffffffffffffffffffffffffff16837fd8a95ca05e9a2656fe21d836329d9cd77830e7fef7acb7c0fd3bf5421ea7ad9a846040516102e49190611159565b60405180910390a3505050565b600084848484604051602001610308929190611231565b6040516020818303038152906040528051906020012060405160200161033093929190611294565b604051602081830303815290604052805190602001209050949350505050565b6000610391876040518060400160405280601e81526020017f446561646c696e65206d75737420626520696e2074686520667574757265000081525061077b565b600086116103d4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103cb90611317565b60405180910390fd5b6000858590501161041a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161041190611383565b60405180910390fd5b6000610428883388886102f1565b9050600080600083815260200190815260200160002090506000816005015414610487576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161047e906113ef565b60405180910390fd5b888160000160006101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550338160020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555086869050816005018190555060005b878790508110156105ad5760018260030160008a8a8581811061052a5761052961140f565b5b905060200201602081019061053f919061143e565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083600281111561059b5761059a611009565b5b02179055508080600101915050610504565b508867ffffffffffffffff16827fdd1d43a415e6cf502dcd7b333d320f416829c0f6a43aa9e32d81cd9a3a7147e687876040516105eb9291906114c9565b60405180910390a381925050509695505050505050565b600080600083815260200190815260200160002090506106528160000160009054906101000a900467ffffffffffffffff1660405180606001604052806024815260200161194360249139610986565b8060060160009054906101000a900460ff16156106a4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161069b90611539565b60405180910390fd5b60008260016040516020016106ba929190611594565b6040516020818303038152906040528051906020012090506107238183600101546040518060400160405280601081526020017f4e6f7420656e6f75676820766f7465730000000000000000000000000000000081525060016109b7909392919063ffffffff16565b60018260060160006101000a81548160ff021916908315150217905550610749836109df565b827f7b1bcf1ccf901a11589afff5504d59fd0a53780eed2a952adade0348985139e060405160405180910390a2505050565b6107a86107a28361078a6109e2565b67ffffffffffffffff16610b1790919063ffffffff16565b82610b38565b5050565b60003273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161461081c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108139061162f565b60405180910390fd5b83600001600084815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205490509392505050565b3273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16146108e6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108dd9061162f565b60405180910390fd5b8084600001600085815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254610948919061167e565b9250508190555050505050565b80836000016000848152602001908152602001600020600082825461097a919061167e565b92505081905550505050565b6109b36109ad836109956109e2565b67ffffffffffffffff16610c2e90919063ffffffff16565b82610b38565b5050565b6109d98285600001600086815260200190815260200160002054101582610b38565b50505050565b50565b60008060007fba286e4d89dabf4b2878e896423bb123d9d5143e662606fd343b6766d7bcf72160001c73ffffffffffffffffffffffffffffffffffffffff16604051610a2d906116e3565b600060405180830381855afa9150503d8060008114610a68576040519150601f19603f3d011682016040523d82523d6000602084013e610a6d565b606091505b509150915081610ab2576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610aa990611744565b60405180910390fd5b6020815114610af6576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610aed906117b0565b60405180910390fd5b600081806020019051810190610b0c91906117fc565b905080935050505090565b60008167ffffffffffffffff168367ffffffffffffffff1610905092915050565b60007f3dcdf63b41c103567d7225976ad9145e866c7a7dccc6c277ea86abbd268fbac960001c73ffffffffffffffffffffffffffffffffffffffff1683604051602001610b859190611844565b604051602081830303815290604052604051610ba191906118c5565b600060405180830381855afa9150503d8060008114610bdc576040519150601f19603f3d011682016040523d82523d6000602084013e610be1565b606091505b50509050808290610c28576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c1f9190611920565b60405180910390fd5b50505050565b60008167ffffffffffffffff168367ffffffffffffffff1611905092915050565b600080fd5b600080fd5b6000819050919050565b610c6c81610c59565b8114610c7757600080fd5b50565b600081359050610c8981610c63565b92915050565b600060ff82169050919050565b610ca581610c8f565b8114610cb057600080fd5b50565b600081359050610cc281610c9c565b92915050565b60008060408385031215610cdf57610cde610c4f565b5b6000610ced85828601610c7a565b9250506020610cfe85828601610cb3565b9150509250929050565b600067ffffffffffffffff82169050919050565b610d2581610d08565b8114610d3057600080fd5b50565b600081359050610d4281610d1c565b92915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000610d7382610d48565b9050919050565b610d8381610d68565b8114610d8e57600080fd5b50565b600081359050610da081610d7a565b92915050565b600080fd5b600080fd5b600080fd5b60008083601f840112610dcb57610dca610da6565b5b8235905067ffffffffffffffff811115610de857610de7610dab565b5b602083019150836020820283011115610e0457610e03610db0565b5b9250929050565b60008060008060608587031215610e2557610e24610c4f565b5b6000610e3387828801610d33565b9450506020610e4487828801610d91565b935050604085013567ffffffffffffffff811115610e6557610e64610c54565b5b610e7187828801610db5565b925092505092959194509250565b610e8881610c59565b82525050565b6000602082019050610ea36000830184610e7f565b92915050565b6000819050919050565b610ebc81610ea9565b8114610ec757600080fd5b50565b600081359050610ed981610eb3565b92915050565b60008083601f840112610ef557610ef4610da6565b5b8235905067ffffffffffffffff811115610f1257610f11610dab565b5b602083019150836001820283011115610f2e57610f2d610db0565b5b9250929050565b60008060008060008060808789031215610f5257610f51610c4f565b5b6000610f6089828a01610d33565b9650506020610f7189828a01610eca565b955050604087013567ffffffffffffffff811115610f9257610f91610c54565b5b610f9e89828a01610db5565b9450945050606087013567ffffffffffffffff811115610fc157610fc0610c54565b5b610fcd89828a01610edf565b92509250509295509295509295565b600060208284031215610ff257610ff1610c4f565b5b600061100084828501610c7a565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b600082825260208201905092915050565b7f73656e646572206e6f74206120766f7465720000000000000000000000000000600082015250565b600061107f601283611038565b915061108a82611049565b602082019050919050565b600060208201905081810360008301526110ae81611072565b9050919050565b7f616c726561647920766f74656400000000000000000000000000000000000000600082015250565b60006110eb600d83611038565b91506110f6826110b5565b602082019050919050565b6000602082019050818103600083015261111a816110de565b9050919050565b61112a81610c8f565b82525050565b60006040820190506111456000830185610e7f565b6111526020830184611121565b9392505050565b600060208201905061116e6000830184611121565b92915050565b600081905092915050565b6000819050919050565b61119281610d68565b82525050565b60006111a48383611189565b60208301905092915050565b60006111bf6020840184610d91565b905092915050565b6000602082019050919050565b60006111e08385611174565b93506111eb8261117f565b8060005b858110156112245761120182846111b0565b61120b8882611198565b9750611216836111c7565b9250506001810190506111ef565b5085925050509392505050565b600061123e8284866111d4565b91508190509392505050565b6000819050919050565b600061126f61126a61126584610d08565b61124a565b610d08565b9050919050565b61127f81611254565b82525050565b61128e81610d68565b82525050565b60006060820190506112a96000830186611276565b6112b66020830185611285565b6112c36040830184610e7f565b949350505050565b7f5468726573686f6c642073686f756c64206e6f74206265203000000000000000600082015250565b6000611301601983611038565b915061130c826112cb565b602082019050919050565b60006020820190508181036000830152611330816112f4565b9050919050565b7f5468657265206d757374206265206174206c65617374206f6e6520766f746572600082015250565b600061136d602083611038565b915061137882611337565b602082019050919050565b6000602082019050818103600083015261139c81611360565b9050919050565b7f70726f706f73616c20616c726561647920657869737473000000000000000000600082015250565b60006113d9601783611038565b91506113e4826113a3565b602082019050919050565b60006020820190508181036000830152611408816113cc565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006020828403121561145457611453610c4f565b5b600061146284828501610d91565b91505092915050565b600082825260208201905092915050565b82818337600083830152505050565b6000601f19601f8301169050919050565b60006114a8838561146b565b93506114b583858461147c565b6114be8361148b565b840190509392505050565b600060208201905081810360008301526114e481848661149c565b90509392505050565b7f50726f706f73616c20616c726561647920657865637574656400000000000000600082015250565b6000611523601983611038565b915061152e826114ed565b602082019050919050565b6000602082019050818103600083015261155281611516565b9050919050565b6000819050919050565b600061157e61157961157484611559565b61124a565b610c8f565b9050919050565b61158e81611563565b82525050565b60006040820190506115a96000830185610e7f565b6115b66020830184611585565b9392505050565b7f43616e6e6f7420616363657373204f776e6564436f756e746572206f776e656460008201527f20627920616e6f74686572206164647265737300000000000000000000000000602082015250565b6000611619603383611038565b9150611624826115bd565b604082019050919050565b600060208201905081810360008301526116488161160c565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061168982610ea9565b915061169483610ea9565b92508282019050808211156116ac576116ab61164f565b5b92915050565b600081905092915050565b50565b60006116cd6000836116b2565b91506116d8826116bd565b600082019050919050565b60006116ee826116c0565b9150819050919050565b7f507265636f6d70696c652063616c6c206661696c656400000000000000000000600082015250565b600061172e601683611038565b9150611739826116f8565b602082019050919050565b6000602082019050818103600083015261175d81611721565b9050919050565b7f496e76616c6964206f7574707574206c656e6774680000000000000000000000600082015250565b600061179a601583611038565b91506117a582611764565b602082019050919050565b600060208201905081810360008301526117c98161178d565b9050919050565b6117d981610d08565b81146117e457600080fd5b50565b6000815190506117f6816117d0565b92915050565b60006020828403121561181257611811610c4f565b5b6000611820848285016117e7565b91505092915050565b60008115159050919050565b61183e81611829565b82525050565b60006020820190506118596000830184611835565b92915050565b600081519050919050565b60005b8381101561188857808201518184015260208101905061186d565b60008484015250505050565b600061189f8261185f565b6118a981856116b2565b93506118b981856020860161186a565b80840191505092915050565b60006118d18284611894565b915081905092915050565b600081519050919050565b60006118f2826118dc565b6118fc8185611038565b935061190c81856020860161186a565b6119158161148b565b840191505092915050565b6000602082019050818103600083015261193a81846118e7565b90509291505056fe50726f706f73616c20646561646c696e6520686173206e6f74207061737365642079657450726f706f73616c20646561646c696e652068617320706173736564206f722070726f706f73616c20646f6573206e6f74206578697374 + ///0x6080604052348015600e575f5ffd5b506118c18061001c5f395ff3fe608060405234801561000f575f5ffd5b506004361061004a575f3560e01c8063b4b0713e1461004e578063b829966f1461006a578063cf75ee2a1461009a578063e751f271146100ca575b5f5ffd5b61006860048036038101906100639190610c7e565b6100e6565b005b610084600480360381019061007f9190610db4565b6102e5565b6040516100919190610e34565b60405180910390f35b6100b460048036038101906100af9190610ed5565b610343565b6040516100c19190610e34565b60405180910390f35b6100e460048036038101906100df9190610f78565b6105e9565b005b5f5f5f8481526020019081526020015f209050610131815f015f9054906101000a900467ffffffffffffffff1660405180606001604052806037815260200161188a6037913961075a565b6001600281111561014557610144610fa3565b5b816003015f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff1660028111156101a3576101a2610fa3565b5b146101e3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101da9061102a565b60405180910390fd5b5f6101fa8433600261078b9092919063ffffffff16565b1461023a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161023190611092565b60405180910390fd5b610253833360016002610851909392919063ffffffff16565b61029183836040516020016102699291906110bf565b604051602081830303815290604052805190602001206001806109289092919063ffffffff16565b3373ffffffffffffffffffffffffffffffffffffffff16837fd8a95ca05e9a2656fe21d836329d9cd77830e7fef7acb7c0fd3bf5421ea7ad9a846040516102d891906110e6565b60405180910390a3505050565b5f848484846040516020016102fb9291906111b5565b6040516020818303038152906040528051906020012060405160200161032393929190611215565b604051602081830303815290604052805190602001209050949350505050565b5f610383876040518060400160405280601e81526020017f446561646c696e65206d75737420626520696e2074686520667574757265000081525061075a565b5f86116103c5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103bc90611294565b60405180910390fd5b5f858590501161040a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610401906112fc565b60405180910390fd5b5f610417883388886102e5565b90505f5f5f8381526020019081526020015f2090505f816005015414610472576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161046990611364565b60405180910390fd5b88815f015f6101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555033816002015f6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508686905081600501819055505f5f90505b87879050811015610594576001826003015f8a8a8581811061051357610512611382565b5b905060200201602081019061052891906113af565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff0219169083600281111561058257610581610fa3565b5b021790555080806001019150506104ee565b508867ffffffffffffffff16827fdd1d43a415e6cf502dcd7b333d320f416829c0f6a43aa9e32d81cd9a3a7147e687876040516105d2929190611434565b60405180910390a381925050509695505050505050565b5f5f5f8381526020019081526020015f209050610634815f015f9054906101000a900467ffffffffffffffff1660405180606001604052806024815260200161186660249139610955565b806006015f9054906101000a900460ff1615610685576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161067c906114a0565b60405180910390fd5b5f82600160405160200161069a9291906114f7565b6040516020818303038152906040528051906020012090506107038183600101546040518060400160405280601081526020017f4e6f7420656e6f75676820766f746573000000000000000000000000000000008152506001610986909392919063ffffffff16565b6001826006015f6101000a81548160ff021916908315150217905550610728836109ab565b827f7b1bcf1ccf901a11589afff5504d59fd0a53780eed2a952adade0348985139e060405160405180910390a2505050565b610787610781836107696109ae565b67ffffffffffffffff16610adc90919063ffffffff16565b82610afc565b5050565b5f3273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16146107fa576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107f19061158e565b60405180910390fd5b835f015f8481526020019081526020015f205f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205490509392505050565b3273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16146108bf576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108b69061158e565b60405180910390fd5b80845f015f8581526020019081526020015f205f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461091b91906115d9565b9250508190555050505050565b80835f015f8481526020019081526020015f205f82825461094991906115d9565b92505081905550505050565b61098261097c836109646109ae565b67ffffffffffffffff16610bed90919063ffffffff16565b82610afc565b5050565b6109a582855f015f8681526020019081526020015f2054101582610afc565b50505050565b50565b5f5f5f7fba286e4d89dabf4b2878e896423bb123d9d5143e662606fd343b6766d7bcf7215f1c73ffffffffffffffffffffffffffffffffffffffff166040516109f690611639565b5f60405180830381855afa9150503d805f8114610a2e576040519150601f19603f3d011682016040523d82523d5f602084013e610a33565b606091505b509150915081610a78576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a6f90611697565b60405180910390fd5b6020815114610abc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ab3906116ff565b60405180910390fd5b5f81806020019051810190610ad19190611747565b905080935050505090565b5f8167ffffffffffffffff168367ffffffffffffffff1610905092915050565b5f7f3dcdf63b41c103567d7225976ad9145e866c7a7dccc6c277ea86abbd268fbac95f1c73ffffffffffffffffffffffffffffffffffffffff1683604051602001610b47919061178c565b604051602081830303815290604052604051610b6391906117ed565b5f60405180830381855afa9150503d805f8114610b9b576040519150601f19603f3d011682016040523d82523d5f602084013e610ba0565b606091505b50509050808290610be7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bde9190611845565b60405180910390fd5b50505050565b5f8167ffffffffffffffff168367ffffffffffffffff1611905092915050565b5f5ffd5b5f5ffd5b5f819050919050565b610c2781610c15565b8114610c31575f5ffd5b50565b5f81359050610c4281610c1e565b92915050565b5f60ff82169050919050565b610c5d81610c48565b8114610c67575f5ffd5b50565b5f81359050610c7881610c54565b92915050565b5f5f60408385031215610c9457610c93610c0d565b5b5f610ca185828601610c34565b9250506020610cb285828601610c6a565b9150509250929050565b5f67ffffffffffffffff82169050919050565b610cd881610cbc565b8114610ce2575f5ffd5b50565b5f81359050610cf381610ccf565b92915050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f610d2282610cf9565b9050919050565b610d3281610d18565b8114610d3c575f5ffd5b50565b5f81359050610d4d81610d29565b92915050565b5f5ffd5b5f5ffd5b5f5ffd5b5f5f83601f840112610d7457610d73610d53565b5b8235905067ffffffffffffffff811115610d9157610d90610d57565b5b602083019150836020820283011115610dad57610dac610d5b565b5b9250929050565b5f5f5f5f60608587031215610dcc57610dcb610c0d565b5b5f610dd987828801610ce5565b9450506020610dea87828801610d3f565b935050604085013567ffffffffffffffff811115610e0b57610e0a610c11565b5b610e1787828801610d5f565b925092505092959194509250565b610e2e81610c15565b82525050565b5f602082019050610e475f830184610e25565b92915050565b5f819050919050565b610e5f81610e4d565b8114610e69575f5ffd5b50565b5f81359050610e7a81610e56565b92915050565b5f5f83601f840112610e9557610e94610d53565b5b8235905067ffffffffffffffff811115610eb257610eb1610d57565b5b602083019150836001820283011115610ece57610ecd610d5b565b5b9250929050565b5f5f5f5f5f5f60808789031215610eef57610eee610c0d565b5b5f610efc89828a01610ce5565b9650506020610f0d89828a01610e6c565b955050604087013567ffffffffffffffff811115610f2e57610f2d610c11565b5b610f3a89828a01610d5f565b9450945050606087013567ffffffffffffffff811115610f5d57610f5c610c11565b5b610f6989828a01610e80565b92509250509295509295509295565b5f60208284031215610f8d57610f8c610c0d565b5b5f610f9a84828501610c34565b91505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b5f82825260208201905092915050565b7f73656e646572206e6f74206120766f74657200000000000000000000000000005f82015250565b5f611014601283610fd0565b915061101f82610fe0565b602082019050919050565b5f6020820190508181035f83015261104181611008565b9050919050565b7f616c726561647920766f746564000000000000000000000000000000000000005f82015250565b5f61107c600d83610fd0565b915061108782611048565b602082019050919050565b5f6020820190508181035f8301526110a981611070565b9050919050565b6110b981610c48565b82525050565b5f6040820190506110d25f830185610e25565b6110df60208301846110b0565b9392505050565b5f6020820190506110f95f8301846110b0565b92915050565b5f81905092915050565b5f819050919050565b61111b81610d18565b82525050565b5f61112c8383611112565b60208301905092915050565b5f6111466020840184610d3f565b905092915050565b5f602082019050919050565b5f61116583856110ff565b935061117082611109565b805f5b858110156111a8576111858284611138565b61118f8882611121565b975061119a8361114e565b925050600181019050611173565b5085925050509392505050565b5f6111c182848661115a565b91508190509392505050565b5f819050919050565b5f6111f06111eb6111e684610cbc565b6111cd565b610cbc565b9050919050565b611200816111d6565b82525050565b61120f81610d18565b82525050565b5f6060820190506112285f8301866111f7565b6112356020830185611206565b6112426040830184610e25565b949350505050565b7f5468726573686f6c642073686f756c64206e6f742062652030000000000000005f82015250565b5f61127e601983610fd0565b91506112898261124a565b602082019050919050565b5f6020820190508181035f8301526112ab81611272565b9050919050565b7f5468657265206d757374206265206174206c65617374206f6e6520766f7465725f82015250565b5f6112e6602083610fd0565b91506112f1826112b2565b602082019050919050565b5f6020820190508181035f830152611313816112da565b9050919050565b7f70726f706f73616c20616c7265616479206578697374730000000000000000005f82015250565b5f61134e601783610fd0565b91506113598261131a565b602082019050919050565b5f6020820190508181035f83015261137b81611342565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b5f602082840312156113c4576113c3610c0d565b5b5f6113d184828501610d3f565b91505092915050565b5f82825260208201905092915050565b828183375f83830152505050565b5f601f19601f8301169050919050565b5f61141383856113da565b93506114208385846113ea565b611429836113f8565b840190509392505050565b5f6020820190508181035f83015261144d818486611408565b90509392505050565b7f50726f706f73616c20616c7265616479206578656375746564000000000000005f82015250565b5f61148a601983610fd0565b915061149582611456565b602082019050919050565b5f6020820190508181035f8301526114b78161147e565b9050919050565b5f819050919050565b5f6114e16114dc6114d7846114be565b6111cd565b610c48565b9050919050565b6114f1816114c7565b82525050565b5f60408201905061150a5f830185610e25565b61151760208301846114e8565b9392505050565b7f43616e6e6f7420616363657373204f776e6564436f756e746572206f776e65645f8201527f20627920616e6f74686572206164647265737300000000000000000000000000602082015250565b5f611578603383610fd0565b91506115838261151e565b604082019050919050565b5f6020820190508181035f8301526115a58161156c565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f6115e382610e4d565b91506115ee83610e4d565b9250828201905080821115611606576116056115ac565b5b92915050565b5f81905092915050565b50565b5f6116245f8361160c565b915061162f82611616565b5f82019050919050565b5f61164382611619565b9150819050919050565b7f507265636f6d70696c652063616c6c206661696c6564000000000000000000005f82015250565b5f611681601683610fd0565b915061168c8261164d565b602082019050919050565b5f6020820190508181035f8301526116ae81611675565b9050919050565b7f496e76616c6964206f7574707574206c656e67746800000000000000000000005f82015250565b5f6116e9601583610fd0565b91506116f4826116b5565b602082019050919050565b5f6020820190508181035f830152611716816116dd565b9050919050565b61172681610cbc565b8114611730575f5ffd5b50565b5f815190506117418161171d565b92915050565b5f6020828403121561175c5761175b610c0d565b5b5f61176984828501611733565b91505092915050565b5f8115159050919050565b61178681611772565b82525050565b5f60208201905061179f5f83018461177d565b92915050565b5f81519050919050565b8281835e5f83830152505050565b5f6117c7826117a5565b6117d1818561160c565b93506117e18185602086016117af565b80840191505092915050565b5f6117f882846117bd565b915081905092915050565b5f81519050919050565b5f61181782611803565b6118218185610fd0565b93506118318185602086016117af565b61183a816113f8565b840191505092915050565b5f6020820190508181035f83015261185d818461180d565b90509291505056fe50726f706f73616c20646561646c696e6520686173206e6f74207061737365642079657450726f706f73616c20646561646c696e652068617320706173736564206f722070726f706f73616c20646f6573206e6f74206578697374 /// ``` #[rustfmt::skip] #[allow(clippy::all)] pub static BYTECODE: alloy_sol_types::private::Bytes = alloy_sol_types::private::Bytes::from_static( - b"`\x80`@R4\x80\x15`\x0FW`\0\x80\xFD[Pa\x19\x9E\x80a\0\x1F`\09`\0\xF3\xFE`\x80`@R4\x80\x15a\0\x10W`\0\x80\xFD[P`\x046\x10a\0LW`\x005`\xE0\x1C\x80c\xB4\xB0q>\x14a\0QW\x80c\xB8)\x96o\x14a\0mW\x80c\xCFu\xEE*\x14a\0\x9DW\x80c\xE7Q\xF2q\x14a\0\xCDW[`\0\x80\xFD[a\0k`\x04\x806\x03\x81\x01\x90a\0f\x91\x90a\x0C\xC8V[a\0\xE9V[\0[a\0\x87`\x04\x806\x03\x81\x01\x90a\0\x82\x91\x90a\x0E\x0BV[a\x02\xF1V[`@Qa\0\x94\x91\x90a\x0E\x8EV[`@Q\x80\x91\x03\x90\xF3[a\0\xB7`\x04\x806\x03\x81\x01\x90a\0\xB2\x91\x90a\x0F5V[a\x03PV[`@Qa\0\xC4\x91\x90a\x0E\x8EV[`@Q\x80\x91\x03\x90\xF3[a\0\xE7`\x04\x806\x03\x81\x01\x90a\0\xE2\x91\x90a\x0F\xDCV[a\x06\x02V[\0[`\0\x80`\0\x84\x81R` \x01\x90\x81R` \x01`\0 \x90Pa\x019\x81`\0\x01`\0\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Q\x80``\x01`@R\x80`7\x81R` \x01a\x19g`7\x919a\x07{V[`\x01`\x02\x81\x11\x15a\x01MWa\x01La\x10\tV[[\x81`\x03\x01`\x003s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01\x90\x81R` \x01`\0 `\0\x90T\x90a\x01\0\n\x90\x04`\xFF\x16`\x02\x81\x11\x15a\x01\xAEWa\x01\xADa\x10\tV[[\x14a\x01\xEEW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x01\xE5\x90a\x10\x95V[`@Q\x80\x91\x03\x90\xFD[`\0a\x02\x06\x843`\x02a\x07\xAC\x90\x92\x91\x90c\xFF\xFF\xFF\xFF\x16V[\x14a\x02FW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x02=\x90a\x11\x01V[`@Q\x80\x91\x03\x90\xFD[a\x02_\x833`\x01`\x02a\x08x\x90\x93\x92\x91\x90c\xFF\xFF\xFF\xFF\x16V[a\x02\x9D\x83\x83`@Q` \x01a\x02u\x92\x91\x90a\x110V[`@Q` \x81\x83\x03\x03\x81R\x90`@R\x80Q\x90` \x01 `\x01\x80a\tU\x90\x92\x91\x90c\xFF\xFF\xFF\xFF\x16V[3s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x83\x7F\xD8\xA9\\\xA0^\x9A&V\xFE!\xD862\x9D\x9C\xD7x0\xE7\xFE\xF7\xAC\xB7\xC0\xFD;\xF5B\x1E\xA7\xAD\x9A\x84`@Qa\x02\xE4\x91\x90a\x11YV[`@Q\x80\x91\x03\x90\xA3PPPV[`\0\x84\x84\x84\x84`@Q` \x01a\x03\x08\x92\x91\x90a\x121V[`@Q` \x81\x83\x03\x03\x81R\x90`@R\x80Q\x90` \x01 `@Q` \x01a\x030\x93\x92\x91\x90a\x12\x94V[`@Q` \x81\x83\x03\x03\x81R\x90`@R\x80Q\x90` \x01 \x90P\x94\x93PPPPV[`\0a\x03\x91\x87`@Q\x80`@\x01`@R\x80`\x1E\x81R` \x01\x7FDeadline must be in the future\0\0\x81RPa\x07{V[`\0\x86\x11a\x03\xD4W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x03\xCB\x90a\x13\x17V[`@Q\x80\x91\x03\x90\xFD[`\0\x85\x85\x90P\x11a\x04\x1AW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x04\x11\x90a\x13\x83V[`@Q\x80\x91\x03\x90\xFD[`\0a\x04(\x883\x88\x88a\x02\xF1V[\x90P`\0\x80`\0\x83\x81R` \x01\x90\x81R` \x01`\0 \x90P`\0\x81`\x05\x01T\x14a\x04\x87W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x04~\x90a\x13\xEFV[`@Q\x80\x91\x03\x90\xFD[\x88\x81`\0\x01`\0a\x01\0\n\x81T\x81g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UP3\x81`\x02\x01`\0a\x01\0\n\x81T\x81s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UP\x86\x86\x90P\x81`\x05\x01\x81\x90UP`\0[\x87\x87\x90P\x81\x10\x15a\x05\xADW`\x01\x82`\x03\x01`\0\x8A\x8A\x85\x81\x81\x10a\x05*Wa\x05)a\x14\x0FV[[\x90P` \x02\x01` \x81\x01\x90a\x05?\x91\x90a\x14>V[s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01\x90\x81R` \x01`\0 `\0a\x01\0\n\x81T\x81`\xFF\x02\x19\x16\x90\x83`\x02\x81\x11\x15a\x05\x9BWa\x05\x9Aa\x10\tV[[\x02\x17\x90UP\x80\x80`\x01\x01\x91PPa\x05\x04V[P\x88g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x82\x7F\xDD\x1DC\xA4\x15\xE6\xCFP-\xCD{3=2\x0FAh)\xC0\xF6\xA4:\xA9\xE3-\x81\xCD\x9A:qG\xE6\x87\x87`@Qa\x05\xEB\x92\x91\x90a\x14\xC9V[`@Q\x80\x91\x03\x90\xA3\x81\x92PPP\x96\x95PPPPPPV[`\0\x80`\0\x83\x81R` \x01\x90\x81R` \x01`\0 \x90Pa\x06R\x81`\0\x01`\0\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Q\x80``\x01`@R\x80`$\x81R` \x01a\x19C`$\x919a\t\x86V[\x80`\x06\x01`\0\x90T\x90a\x01\0\n\x90\x04`\xFF\x16\x15a\x06\xA4W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x06\x9B\x90a\x159V[`@Q\x80\x91\x03\x90\xFD[`\0\x82`\x01`@Q` \x01a\x06\xBA\x92\x91\x90a\x15\x94V[`@Q` \x81\x83\x03\x03\x81R\x90`@R\x80Q\x90` \x01 \x90Pa\x07#\x81\x83`\x01\x01T`@Q\x80`@\x01`@R\x80`\x10\x81R` \x01\x7FNot enough votes\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81RP`\x01a\t\xB7\x90\x93\x92\x91\x90c\xFF\xFF\xFF\xFF\x16V[`\x01\x82`\x06\x01`\0a\x01\0\n\x81T\x81`\xFF\x02\x19\x16\x90\x83\x15\x15\x02\x17\x90UPa\x07I\x83a\t\xDFV[\x82\x7F{\x1B\xCF\x1C\xCF\x90\x1A\x11X\x9A\xFF\xF5PMY\xFD\nSx\x0E\xED*\x95*\xDA\xDE\x03H\x98Q9\xE0`@Q`@Q\x80\x91\x03\x90\xA2PPPV[a\x07\xA8a\x07\xA2\x83a\x07\x8Aa\t\xE2V[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x0B\x17\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[\x82a\x0B8V[PPV[`\x002s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x82s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x08\x1CW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x08\x13\x90a\x16/V[`@Q\x80\x91\x03\x90\xFD[\x83`\0\x01`\0\x84\x81R` \x01\x90\x81R` \x01`\0 `\0\x83s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01\x90\x81R` \x01`\0 T\x90P\x93\x92PPPV[2s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x82s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x08\xE6W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x08\xDD\x90a\x16/V[`@Q\x80\x91\x03\x90\xFD[\x80\x84`\0\x01`\0\x85\x81R` \x01\x90\x81R` \x01`\0 `\0\x84s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01\x90\x81R` \x01`\0 `\0\x82\x82Ta\tH\x91\x90a\x16~V[\x92PP\x81\x90UPPPPPV[\x80\x83`\0\x01`\0\x84\x81R` \x01\x90\x81R` \x01`\0 `\0\x82\x82Ta\tz\x91\x90a\x16~V[\x92PP\x81\x90UPPPPV[a\t\xB3a\t\xAD\x83a\t\x95a\t\xE2V[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x0C.\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[\x82a\x0B8V[PPV[a\t\xD9\x82\x85`\0\x01`\0\x86\x81R` \x01\x90\x81R` \x01`\0 T\x10\x15\x82a\x0B8V[PPPPV[PV[`\0\x80`\0\x7F\xBA(nM\x89\xDA\xBFK(x\xE8\x96B;\xB1#\xD9\xD5\x14>f&\x06\xFD4;gf\xD7\xBC\xF7!`\0\x1Cs\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\n-\x90a\x16\xE3V[`\0`@Q\x80\x83\x03\x81\x85Z\xFA\x91PP=\x80`\0\x81\x14a\nhW`@Q\x91P`\x1F\x19`?=\x01\x16\x82\x01`@R=\x82R=`\0` \x84\x01>a\nmV[``\x91P[P\x91P\x91P\x81a\n\xB2W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\n\xA9\x90a\x17DV[`@Q\x80\x91\x03\x90\xFD[` \x81Q\x14a\n\xF6W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\n\xED\x90a\x17\xB0V[`@Q\x80\x91\x03\x90\xFD[`\0\x81\x80` \x01\x90Q\x81\x01\x90a\x0B\x0C\x91\x90a\x17\xFCV[\x90P\x80\x93PPPP\x90V[`\0\x81g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x83g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x10\x90P\x92\x91PPV[`\0\x7F=\xCD\xF6;A\xC1\x03V}r%\x97j\xD9\x14^\x86lz}\xCC\xC6\xC2w\xEA\x86\xAB\xBD&\x8F\xBA\xC9`\0\x1Cs\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x83`@Q` \x01a\x0B\x85\x91\x90a\x18DV[`@Q` \x81\x83\x03\x03\x81R\x90`@R`@Qa\x0B\xA1\x91\x90a\x18\xC5V[`\0`@Q\x80\x83\x03\x81\x85Z\xFA\x91PP=\x80`\0\x81\x14a\x0B\xDCW`@Q\x91P`\x1F\x19`?=\x01\x16\x82\x01`@R=\x82R=`\0` \x84\x01>a\x0B\xE1V[``\x91P[PP\x90P\x80\x82\x90a\x0C(W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x0C\x1F\x91\x90a\x19 V[`@Q\x80\x91\x03\x90\xFD[PPPPV[`\0\x81g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x83g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x11\x90P\x92\x91PPV[`\0\x80\xFD[`\0\x80\xFD[`\0\x81\x90P\x91\x90PV[a\x0Cl\x81a\x0CYV[\x81\x14a\x0CwW`\0\x80\xFD[PV[`\0\x815\x90Pa\x0C\x89\x81a\x0CcV[\x92\x91PPV[`\0`\xFF\x82\x16\x90P\x91\x90PV[a\x0C\xA5\x81a\x0C\x8FV[\x81\x14a\x0C\xB0W`\0\x80\xFD[PV[`\0\x815\x90Pa\x0C\xC2\x81a\x0C\x9CV[\x92\x91PPV[`\0\x80`@\x83\x85\x03\x12\x15a\x0C\xDFWa\x0C\xDEa\x0COV[[`\0a\x0C\xED\x85\x82\x86\x01a\x0CzV[\x92PP` a\x0C\xFE\x85\x82\x86\x01a\x0C\xB3V[\x91PP\x92P\x92\x90PV[`\0g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x16\x90P\x91\x90PV[a\r%\x81a\r\x08V[\x81\x14a\r0W`\0\x80\xFD[PV[`\0\x815\x90Pa\rB\x81a\r\x1CV[\x92\x91PPV[`\0s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x16\x90P\x91\x90PV[`\0a\rs\x82a\rHV[\x90P\x91\x90PV[a\r\x83\x81a\rhV[\x81\x14a\r\x8EW`\0\x80\xFD[PV[`\0\x815\x90Pa\r\xA0\x81a\rzV[\x92\x91PPV[`\0\x80\xFD[`\0\x80\xFD[`\0\x80\xFD[`\0\x80\x83`\x1F\x84\x01\x12a\r\xCBWa\r\xCAa\r\xA6V[[\x825\x90Pg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\r\xE8Wa\r\xE7a\r\xABV[[` \x83\x01\x91P\x83` \x82\x02\x83\x01\x11\x15a\x0E\x04Wa\x0E\x03a\r\xB0V[[\x92P\x92\x90PV[`\0\x80`\0\x80``\x85\x87\x03\x12\x15a\x0E%Wa\x0E$a\x0COV[[`\0a\x0E3\x87\x82\x88\x01a\r3V[\x94PP` a\x0ED\x87\x82\x88\x01a\r\x91V[\x93PP`@\x85\x015g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\x0EeWa\x0Eda\x0CTV[[a\x0Eq\x87\x82\x88\x01a\r\xB5V[\x92P\x92PP\x92\x95\x91\x94P\x92PV[a\x0E\x88\x81a\x0CYV[\x82RPPV[`\0` \x82\x01\x90Pa\x0E\xA3`\0\x83\x01\x84a\x0E\x7FV[\x92\x91PPV[`\0\x81\x90P\x91\x90PV[a\x0E\xBC\x81a\x0E\xA9V[\x81\x14a\x0E\xC7W`\0\x80\xFD[PV[`\0\x815\x90Pa\x0E\xD9\x81a\x0E\xB3V[\x92\x91PPV[`\0\x80\x83`\x1F\x84\x01\x12a\x0E\xF5Wa\x0E\xF4a\r\xA6V[[\x825\x90Pg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\x0F\x12Wa\x0F\x11a\r\xABV[[` \x83\x01\x91P\x83`\x01\x82\x02\x83\x01\x11\x15a\x0F.Wa\x0F-a\r\xB0V[[\x92P\x92\x90PV[`\0\x80`\0\x80`\0\x80`\x80\x87\x89\x03\x12\x15a\x0FRWa\x0FQa\x0COV[[`\0a\x0F`\x89\x82\x8A\x01a\r3V[\x96PP` a\x0Fq\x89\x82\x8A\x01a\x0E\xCAV[\x95PP`@\x87\x015g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\x0F\x92Wa\x0F\x91a\x0CTV[[a\x0F\x9E\x89\x82\x8A\x01a\r\xB5V[\x94P\x94PP``\x87\x015g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\x0F\xC1Wa\x0F\xC0a\x0CTV[[a\x0F\xCD\x89\x82\x8A\x01a\x0E\xDFV[\x92P\x92PP\x92\x95P\x92\x95P\x92\x95V[`\0` \x82\x84\x03\x12\x15a\x0F\xF2Wa\x0F\xF1a\x0COV[[`\0a\x10\0\x84\x82\x85\x01a\x0CzV[\x91PP\x92\x91PPV[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0`\0R`!`\x04R`$`\0\xFD[`\0\x82\x82R` \x82\x01\x90P\x92\x91PPV[\x7Fsender not a voter\0\0\0\0\0\0\0\0\0\0\0\0\0\0`\0\x82\x01RPV[`\0a\x10\x7F`\x12\x83a\x108V[\x91Pa\x10\x8A\x82a\x10IV[` \x82\x01\x90P\x91\x90PV[`\0` \x82\x01\x90P\x81\x81\x03`\0\x83\x01Ra\x10\xAE\x81a\x10rV[\x90P\x91\x90PV[\x7Falready voted\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0`\0\x82\x01RPV[`\0a\x10\xEB`\r\x83a\x108V[\x91Pa\x10\xF6\x82a\x10\xB5V[` \x82\x01\x90P\x91\x90PV[`\0` \x82\x01\x90P\x81\x81\x03`\0\x83\x01Ra\x11\x1A\x81a\x10\xDEV[\x90P\x91\x90PV[a\x11*\x81a\x0C\x8FV[\x82RPPV[`\0`@\x82\x01\x90Pa\x11E`\0\x83\x01\x85a\x0E\x7FV[a\x11R` \x83\x01\x84a\x11!V[\x93\x92PPPV[`\0` \x82\x01\x90Pa\x11n`\0\x83\x01\x84a\x11!V[\x92\x91PPV[`\0\x81\x90P\x92\x91PPV[`\0\x81\x90P\x91\x90PV[a\x11\x92\x81a\rhV[\x82RPPV[`\0a\x11\xA4\x83\x83a\x11\x89V[` \x83\x01\x90P\x92\x91PPV[`\0a\x11\xBF` \x84\x01\x84a\r\x91V[\x90P\x92\x91PPV[`\0` \x82\x01\x90P\x91\x90PV[`\0a\x11\xE0\x83\x85a\x11tV[\x93Pa\x11\xEB\x82a\x11\x7FV[\x80`\0[\x85\x81\x10\x15a\x12$Wa\x12\x01\x82\x84a\x11\xB0V[a\x12\x0B\x88\x82a\x11\x98V[\x97Pa\x12\x16\x83a\x11\xC7V[\x92PP`\x01\x81\x01\x90Pa\x11\xEFV[P\x85\x92PPP\x93\x92PPPV[`\0a\x12>\x82\x84\x86a\x11\xD4V[\x91P\x81\x90P\x93\x92PPPV[`\0\x81\x90P\x91\x90PV[`\0a\x12oa\x12ja\x12e\x84a\r\x08V[a\x12JV[a\r\x08V[\x90P\x91\x90PV[a\x12\x7F\x81a\x12TV[\x82RPPV[a\x12\x8E\x81a\rhV[\x82RPPV[`\0``\x82\x01\x90Pa\x12\xA9`\0\x83\x01\x86a\x12vV[a\x12\xB6` \x83\x01\x85a\x12\x85V[a\x12\xC3`@\x83\x01\x84a\x0E\x7FV[\x94\x93PPPPV[\x7FThreshold should not be 0\0\0\0\0\0\0\0`\0\x82\x01RPV[`\0a\x13\x01`\x19\x83a\x108V[\x91Pa\x13\x0C\x82a\x12\xCBV[` \x82\x01\x90P\x91\x90PV[`\0` \x82\x01\x90P\x81\x81\x03`\0\x83\x01Ra\x130\x81a\x12\xF4V[\x90P\x91\x90PV[\x7FThere must be at least one voter`\0\x82\x01RPV[`\0a\x13m` \x83a\x108V[\x91Pa\x13x\x82a\x137V[` \x82\x01\x90P\x91\x90PV[`\0` \x82\x01\x90P\x81\x81\x03`\0\x83\x01Ra\x13\x9C\x81a\x13`V[\x90P\x91\x90PV[\x7Fproposal already exists\0\0\0\0\0\0\0\0\0`\0\x82\x01RPV[`\0a\x13\xD9`\x17\x83a\x108V[\x91Pa\x13\xE4\x82a\x13\xA3V[` \x82\x01\x90P\x91\x90PV[`\0` \x82\x01\x90P\x81\x81\x03`\0\x83\x01Ra\x14\x08\x81a\x13\xCCV[\x90P\x91\x90PV[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0`\0R`2`\x04R`$`\0\xFD[`\0` \x82\x84\x03\x12\x15a\x14TWa\x14Sa\x0COV[[`\0a\x14b\x84\x82\x85\x01a\r\x91V[\x91PP\x92\x91PPV[`\0\x82\x82R` \x82\x01\x90P\x92\x91PPV[\x82\x81\x837`\0\x83\x83\x01RPPPV[`\0`\x1F\x19`\x1F\x83\x01\x16\x90P\x91\x90PV[`\0a\x14\xA8\x83\x85a\x14kV[\x93Pa\x14\xB5\x83\x85\x84a\x14|V[a\x14\xBE\x83a\x14\x8BV[\x84\x01\x90P\x93\x92PPPV[`\0` \x82\x01\x90P\x81\x81\x03`\0\x83\x01Ra\x14\xE4\x81\x84\x86a\x14\x9CV[\x90P\x93\x92PPPV[\x7FProposal already executed\0\0\0\0\0\0\0`\0\x82\x01RPV[`\0a\x15#`\x19\x83a\x108V[\x91Pa\x15.\x82a\x14\xEDV[` \x82\x01\x90P\x91\x90PV[`\0` \x82\x01\x90P\x81\x81\x03`\0\x83\x01Ra\x15R\x81a\x15\x16V[\x90P\x91\x90PV[`\0\x81\x90P\x91\x90PV[`\0a\x15~a\x15ya\x15t\x84a\x15YV[a\x12JV[a\x0C\x8FV[\x90P\x91\x90PV[a\x15\x8E\x81a\x15cV[\x82RPPV[`\0`@\x82\x01\x90Pa\x15\xA9`\0\x83\x01\x85a\x0E\x7FV[a\x15\xB6` \x83\x01\x84a\x15\x85V[\x93\x92PPPV[\x7FCannot access OwnedCounter owned`\0\x82\x01R\x7F by another address\0\0\0\0\0\0\0\0\0\0\0\0\0` \x82\x01RPV[`\0a\x16\x19`3\x83a\x108V[\x91Pa\x16$\x82a\x15\xBDV[`@\x82\x01\x90P\x91\x90PV[`\0` \x82\x01\x90P\x81\x81\x03`\0\x83\x01Ra\x16H\x81a\x16\x0CV[\x90P\x91\x90PV[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0`\0R`\x11`\x04R`$`\0\xFD[`\0a\x16\x89\x82a\x0E\xA9V[\x91Pa\x16\x94\x83a\x0E\xA9V[\x92P\x82\x82\x01\x90P\x80\x82\x11\x15a\x16\xACWa\x16\xABa\x16OV[[\x92\x91PPV[`\0\x81\x90P\x92\x91PPV[PV[`\0a\x16\xCD`\0\x83a\x16\xB2V[\x91Pa\x16\xD8\x82a\x16\xBDV[`\0\x82\x01\x90P\x91\x90PV[`\0a\x16\xEE\x82a\x16\xC0V[\x91P\x81\x90P\x91\x90PV[\x7FPrecompile call failed\0\0\0\0\0\0\0\0\0\0`\0\x82\x01RPV[`\0a\x17.`\x16\x83a\x108V[\x91Pa\x179\x82a\x16\xF8V[` \x82\x01\x90P\x91\x90PV[`\0` \x82\x01\x90P\x81\x81\x03`\0\x83\x01Ra\x17]\x81a\x17!V[\x90P\x91\x90PV[\x7FInvalid output length\0\0\0\0\0\0\0\0\0\0\0`\0\x82\x01RPV[`\0a\x17\x9A`\x15\x83a\x108V[\x91Pa\x17\xA5\x82a\x17dV[` \x82\x01\x90P\x91\x90PV[`\0` \x82\x01\x90P\x81\x81\x03`\0\x83\x01Ra\x17\xC9\x81a\x17\x8DV[\x90P\x91\x90PV[a\x17\xD9\x81a\r\x08V[\x81\x14a\x17\xE4W`\0\x80\xFD[PV[`\0\x81Q\x90Pa\x17\xF6\x81a\x17\xD0V[\x92\x91PPV[`\0` \x82\x84\x03\x12\x15a\x18\x12Wa\x18\x11a\x0COV[[`\0a\x18 \x84\x82\x85\x01a\x17\xE7V[\x91PP\x92\x91PPV[`\0\x81\x15\x15\x90P\x91\x90PV[a\x18>\x81a\x18)V[\x82RPPV[`\0` \x82\x01\x90Pa\x18Y`\0\x83\x01\x84a\x185V[\x92\x91PPV[`\0\x81Q\x90P\x91\x90PV[`\0[\x83\x81\x10\x15a\x18\x88W\x80\x82\x01Q\x81\x84\x01R` \x81\x01\x90Pa\x18mV[`\0\x84\x84\x01RPPPPV[`\0a\x18\x9F\x82a\x18_V[a\x18\xA9\x81\x85a\x16\xB2V[\x93Pa\x18\xB9\x81\x85` \x86\x01a\x18jV[\x80\x84\x01\x91PP\x92\x91PPV[`\0a\x18\xD1\x82\x84a\x18\x94V[\x91P\x81\x90P\x92\x91PPV[`\0\x81Q\x90P\x91\x90PV[`\0a\x18\xF2\x82a\x18\xDCV[a\x18\xFC\x81\x85a\x108V[\x93Pa\x19\x0C\x81\x85` \x86\x01a\x18jV[a\x19\x15\x81a\x14\x8BV[\x84\x01\x91PP\x92\x91PPV[`\0` \x82\x01\x90P\x81\x81\x03`\0\x83\x01Ra\x19:\x81\x84a\x18\xE7V[\x90P\x92\x91PPV\xFEProposal deadline has not passed yetProposal deadline has passed or proposal does not exist", + b"`\x80`@R4\x80\x15`\x0EW__\xFD[Pa\x18\xC1\x80a\0\x1C_9_\xF3\xFE`\x80`@R4\x80\x15a\0\x0FW__\xFD[P`\x046\x10a\0JW_5`\xE0\x1C\x80c\xB4\xB0q>\x14a\0NW\x80c\xB8)\x96o\x14a\0jW\x80c\xCFu\xEE*\x14a\0\x9AW\x80c\xE7Q\xF2q\x14a\0\xCAW[__\xFD[a\0h`\x04\x806\x03\x81\x01\x90a\0c\x91\x90a\x0C~V[a\0\xE6V[\0[a\0\x84`\x04\x806\x03\x81\x01\x90a\0\x7F\x91\x90a\r\xB4V[a\x02\xE5V[`@Qa\0\x91\x91\x90a\x0E4V[`@Q\x80\x91\x03\x90\xF3[a\0\xB4`\x04\x806\x03\x81\x01\x90a\0\xAF\x91\x90a\x0E\xD5V[a\x03CV[`@Qa\0\xC1\x91\x90a\x0E4V[`@Q\x80\x91\x03\x90\xF3[a\0\xE4`\x04\x806\x03\x81\x01\x90a\0\xDF\x91\x90a\x0FxV[a\x05\xE9V[\0[___\x84\x81R` \x01\x90\x81R` \x01_ \x90Pa\x011\x81_\x01_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Q\x80``\x01`@R\x80`7\x81R` \x01a\x18\x8A`7\x919a\x07ZV[`\x01`\x02\x81\x11\x15a\x01EWa\x01Da\x0F\xA3V[[\x81`\x03\x01_3s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01\x90\x81R` \x01_ _\x90T\x90a\x01\0\n\x90\x04`\xFF\x16`\x02\x81\x11\x15a\x01\xA3Wa\x01\xA2a\x0F\xA3V[[\x14a\x01\xE3W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x01\xDA\x90a\x10*V[`@Q\x80\x91\x03\x90\xFD[_a\x01\xFA\x843`\x02a\x07\x8B\x90\x92\x91\x90c\xFF\xFF\xFF\xFF\x16V[\x14a\x02:W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x021\x90a\x10\x92V[`@Q\x80\x91\x03\x90\xFD[a\x02S\x833`\x01`\x02a\x08Q\x90\x93\x92\x91\x90c\xFF\xFF\xFF\xFF\x16V[a\x02\x91\x83\x83`@Q` \x01a\x02i\x92\x91\x90a\x10\xBFV[`@Q` \x81\x83\x03\x03\x81R\x90`@R\x80Q\x90` \x01 `\x01\x80a\t(\x90\x92\x91\x90c\xFF\xFF\xFF\xFF\x16V[3s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x83\x7F\xD8\xA9\\\xA0^\x9A&V\xFE!\xD862\x9D\x9C\xD7x0\xE7\xFE\xF7\xAC\xB7\xC0\xFD;\xF5B\x1E\xA7\xAD\x9A\x84`@Qa\x02\xD8\x91\x90a\x10\xE6V[`@Q\x80\x91\x03\x90\xA3PPPV[_\x84\x84\x84\x84`@Q` \x01a\x02\xFB\x92\x91\x90a\x11\xB5V[`@Q` \x81\x83\x03\x03\x81R\x90`@R\x80Q\x90` \x01 `@Q` \x01a\x03#\x93\x92\x91\x90a\x12\x15V[`@Q` \x81\x83\x03\x03\x81R\x90`@R\x80Q\x90` \x01 \x90P\x94\x93PPPPV[_a\x03\x83\x87`@Q\x80`@\x01`@R\x80`\x1E\x81R` \x01\x7FDeadline must be in the future\0\0\x81RPa\x07ZV[_\x86\x11a\x03\xC5W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x03\xBC\x90a\x12\x94V[`@Q\x80\x91\x03\x90\xFD[_\x85\x85\x90P\x11a\x04\nW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x04\x01\x90a\x12\xFCV[`@Q\x80\x91\x03\x90\xFD[_a\x04\x17\x883\x88\x88a\x02\xE5V[\x90P___\x83\x81R` \x01\x90\x81R` \x01_ \x90P_\x81`\x05\x01T\x14a\x04rW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x04i\x90a\x13dV[`@Q\x80\x91\x03\x90\xFD[\x88\x81_\x01_a\x01\0\n\x81T\x81g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UP3\x81`\x02\x01_a\x01\0\n\x81T\x81s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UP\x86\x86\x90P\x81`\x05\x01\x81\x90UP__\x90P[\x87\x87\x90P\x81\x10\x15a\x05\x94W`\x01\x82`\x03\x01_\x8A\x8A\x85\x81\x81\x10a\x05\x13Wa\x05\x12a\x13\x82V[[\x90P` \x02\x01` \x81\x01\x90a\x05(\x91\x90a\x13\xAFV[s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01\x90\x81R` \x01_ _a\x01\0\n\x81T\x81`\xFF\x02\x19\x16\x90\x83`\x02\x81\x11\x15a\x05\x82Wa\x05\x81a\x0F\xA3V[[\x02\x17\x90UP\x80\x80`\x01\x01\x91PPa\x04\xEEV[P\x88g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x82\x7F\xDD\x1DC\xA4\x15\xE6\xCFP-\xCD{3=2\x0FAh)\xC0\xF6\xA4:\xA9\xE3-\x81\xCD\x9A:qG\xE6\x87\x87`@Qa\x05\xD2\x92\x91\x90a\x144V[`@Q\x80\x91\x03\x90\xA3\x81\x92PPP\x96\x95PPPPPPV[___\x83\x81R` \x01\x90\x81R` \x01_ \x90Pa\x064\x81_\x01_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Q\x80``\x01`@R\x80`$\x81R` \x01a\x18f`$\x919a\tUV[\x80`\x06\x01_\x90T\x90a\x01\0\n\x90\x04`\xFF\x16\x15a\x06\x85W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x06|\x90a\x14\xA0V[`@Q\x80\x91\x03\x90\xFD[_\x82`\x01`@Q` \x01a\x06\x9A\x92\x91\x90a\x14\xF7V[`@Q` \x81\x83\x03\x03\x81R\x90`@R\x80Q\x90` \x01 \x90Pa\x07\x03\x81\x83`\x01\x01T`@Q\x80`@\x01`@R\x80`\x10\x81R` \x01\x7FNot enough votes\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81RP`\x01a\t\x86\x90\x93\x92\x91\x90c\xFF\xFF\xFF\xFF\x16V[`\x01\x82`\x06\x01_a\x01\0\n\x81T\x81`\xFF\x02\x19\x16\x90\x83\x15\x15\x02\x17\x90UPa\x07(\x83a\t\xABV[\x82\x7F{\x1B\xCF\x1C\xCF\x90\x1A\x11X\x9A\xFF\xF5PMY\xFD\nSx\x0E\xED*\x95*\xDA\xDE\x03H\x98Q9\xE0`@Q`@Q\x80\x91\x03\x90\xA2PPPV[a\x07\x87a\x07\x81\x83a\x07ia\t\xAEV[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\n\xDC\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[\x82a\n\xFCV[PPV[_2s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x82s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x07\xFAW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x07\xF1\x90a\x15\x8EV[`@Q\x80\x91\x03\x90\xFD[\x83_\x01_\x84\x81R` \x01\x90\x81R` \x01_ _\x83s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01\x90\x81R` \x01_ T\x90P\x93\x92PPPV[2s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x82s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x08\xBFW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x08\xB6\x90a\x15\x8EV[`@Q\x80\x91\x03\x90\xFD[\x80\x84_\x01_\x85\x81R` \x01\x90\x81R` \x01_ _\x84s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01\x90\x81R` \x01_ _\x82\x82Ta\t\x1B\x91\x90a\x15\xD9V[\x92PP\x81\x90UPPPPPV[\x80\x83_\x01_\x84\x81R` \x01\x90\x81R` \x01_ _\x82\x82Ta\tI\x91\x90a\x15\xD9V[\x92PP\x81\x90UPPPPV[a\t\x82a\t|\x83a\tda\t\xAEV[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x0B\xED\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[\x82a\n\xFCV[PPV[a\t\xA5\x82\x85_\x01_\x86\x81R` \x01\x90\x81R` \x01_ T\x10\x15\x82a\n\xFCV[PPPPV[PV[___\x7F\xBA(nM\x89\xDA\xBFK(x\xE8\x96B;\xB1#\xD9\xD5\x14>f&\x06\xFD4;gf\xD7\xBC\xF7!_\x1Cs\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\t\xF6\x90a\x169V[_`@Q\x80\x83\x03\x81\x85Z\xFA\x91PP=\x80_\x81\x14a\n.W`@Q\x91P`\x1F\x19`?=\x01\x16\x82\x01`@R=\x82R=_` \x84\x01>a\n3V[``\x91P[P\x91P\x91P\x81a\nxW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\no\x90a\x16\x97V[`@Q\x80\x91\x03\x90\xFD[` \x81Q\x14a\n\xBCW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\n\xB3\x90a\x16\xFFV[`@Q\x80\x91\x03\x90\xFD[_\x81\x80` \x01\x90Q\x81\x01\x90a\n\xD1\x91\x90a\x17GV[\x90P\x80\x93PPPP\x90V[_\x81g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x83g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x10\x90P\x92\x91PPV[_\x7F=\xCD\xF6;A\xC1\x03V}r%\x97j\xD9\x14^\x86lz}\xCC\xC6\xC2w\xEA\x86\xAB\xBD&\x8F\xBA\xC9_\x1Cs\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x83`@Q` \x01a\x0BG\x91\x90a\x17\x8CV[`@Q` \x81\x83\x03\x03\x81R\x90`@R`@Qa\x0Bc\x91\x90a\x17\xEDV[_`@Q\x80\x83\x03\x81\x85Z\xFA\x91PP=\x80_\x81\x14a\x0B\x9BW`@Q\x91P`\x1F\x19`?=\x01\x16\x82\x01`@R=\x82R=_` \x84\x01>a\x0B\xA0V[``\x91P[PP\x90P\x80\x82\x90a\x0B\xE7W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x0B\xDE\x91\x90a\x18EV[`@Q\x80\x91\x03\x90\xFD[PPPPV[_\x81g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x83g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x11\x90P\x92\x91PPV[__\xFD[__\xFD[_\x81\x90P\x91\x90PV[a\x0C'\x81a\x0C\x15V[\x81\x14a\x0C1W__\xFD[PV[_\x815\x90Pa\x0CB\x81a\x0C\x1EV[\x92\x91PPV[_`\xFF\x82\x16\x90P\x91\x90PV[a\x0C]\x81a\x0CHV[\x81\x14a\x0CgW__\xFD[PV[_\x815\x90Pa\x0Cx\x81a\x0CTV[\x92\x91PPV[__`@\x83\x85\x03\x12\x15a\x0C\x94Wa\x0C\x93a\x0C\rV[[_a\x0C\xA1\x85\x82\x86\x01a\x0C4V[\x92PP` a\x0C\xB2\x85\x82\x86\x01a\x0CjV[\x91PP\x92P\x92\x90PV[_g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x16\x90P\x91\x90PV[a\x0C\xD8\x81a\x0C\xBCV[\x81\x14a\x0C\xE2W__\xFD[PV[_\x815\x90Pa\x0C\xF3\x81a\x0C\xCFV[\x92\x91PPV[_s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x16\x90P\x91\x90PV[_a\r\"\x82a\x0C\xF9V[\x90P\x91\x90PV[a\r2\x81a\r\x18V[\x81\x14a\r\x14a\0QW\x80c\xB8)\x96o\x14a\0mW\x80c\xCFu\xEE*\x14a\0\x9DW\x80c\xE7Q\xF2q\x14a\0\xCDW[`\0\x80\xFD[a\0k`\x04\x806\x03\x81\x01\x90a\0f\x91\x90a\x0C\xC8V[a\0\xE9V[\0[a\0\x87`\x04\x806\x03\x81\x01\x90a\0\x82\x91\x90a\x0E\x0BV[a\x02\xF1V[`@Qa\0\x94\x91\x90a\x0E\x8EV[`@Q\x80\x91\x03\x90\xF3[a\0\xB7`\x04\x806\x03\x81\x01\x90a\0\xB2\x91\x90a\x0F5V[a\x03PV[`@Qa\0\xC4\x91\x90a\x0E\x8EV[`@Q\x80\x91\x03\x90\xF3[a\0\xE7`\x04\x806\x03\x81\x01\x90a\0\xE2\x91\x90a\x0F\xDCV[a\x06\x02V[\0[`\0\x80`\0\x84\x81R` \x01\x90\x81R` \x01`\0 \x90Pa\x019\x81`\0\x01`\0\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Q\x80``\x01`@R\x80`7\x81R` \x01a\x19g`7\x919a\x07{V[`\x01`\x02\x81\x11\x15a\x01MWa\x01La\x10\tV[[\x81`\x03\x01`\x003s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01\x90\x81R` \x01`\0 `\0\x90T\x90a\x01\0\n\x90\x04`\xFF\x16`\x02\x81\x11\x15a\x01\xAEWa\x01\xADa\x10\tV[[\x14a\x01\xEEW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x01\xE5\x90a\x10\x95V[`@Q\x80\x91\x03\x90\xFD[`\0a\x02\x06\x843`\x02a\x07\xAC\x90\x92\x91\x90c\xFF\xFF\xFF\xFF\x16V[\x14a\x02FW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x02=\x90a\x11\x01V[`@Q\x80\x91\x03\x90\xFD[a\x02_\x833`\x01`\x02a\x08x\x90\x93\x92\x91\x90c\xFF\xFF\xFF\xFF\x16V[a\x02\x9D\x83\x83`@Q` \x01a\x02u\x92\x91\x90a\x110V[`@Q` \x81\x83\x03\x03\x81R\x90`@R\x80Q\x90` \x01 `\x01\x80a\tU\x90\x92\x91\x90c\xFF\xFF\xFF\xFF\x16V[3s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x83\x7F\xD8\xA9\\\xA0^\x9A&V\xFE!\xD862\x9D\x9C\xD7x0\xE7\xFE\xF7\xAC\xB7\xC0\xFD;\xF5B\x1E\xA7\xAD\x9A\x84`@Qa\x02\xE4\x91\x90a\x11YV[`@Q\x80\x91\x03\x90\xA3PPPV[`\0\x84\x84\x84\x84`@Q` \x01a\x03\x08\x92\x91\x90a\x121V[`@Q` \x81\x83\x03\x03\x81R\x90`@R\x80Q\x90` \x01 `@Q` \x01a\x030\x93\x92\x91\x90a\x12\x94V[`@Q` \x81\x83\x03\x03\x81R\x90`@R\x80Q\x90` \x01 \x90P\x94\x93PPPPV[`\0a\x03\x91\x87`@Q\x80`@\x01`@R\x80`\x1E\x81R` \x01\x7FDeadline must be in the future\0\0\x81RPa\x07{V[`\0\x86\x11a\x03\xD4W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x03\xCB\x90a\x13\x17V[`@Q\x80\x91\x03\x90\xFD[`\0\x85\x85\x90P\x11a\x04\x1AW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x04\x11\x90a\x13\x83V[`@Q\x80\x91\x03\x90\xFD[`\0a\x04(\x883\x88\x88a\x02\xF1V[\x90P`\0\x80`\0\x83\x81R` \x01\x90\x81R` \x01`\0 \x90P`\0\x81`\x05\x01T\x14a\x04\x87W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x04~\x90a\x13\xEFV[`@Q\x80\x91\x03\x90\xFD[\x88\x81`\0\x01`\0a\x01\0\n\x81T\x81g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UP3\x81`\x02\x01`\0a\x01\0\n\x81T\x81s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UP\x86\x86\x90P\x81`\x05\x01\x81\x90UP`\0[\x87\x87\x90P\x81\x10\x15a\x05\xADW`\x01\x82`\x03\x01`\0\x8A\x8A\x85\x81\x81\x10a\x05*Wa\x05)a\x14\x0FV[[\x90P` \x02\x01` \x81\x01\x90a\x05?\x91\x90a\x14>V[s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01\x90\x81R` \x01`\0 `\0a\x01\0\n\x81T\x81`\xFF\x02\x19\x16\x90\x83`\x02\x81\x11\x15a\x05\x9BWa\x05\x9Aa\x10\tV[[\x02\x17\x90UP\x80\x80`\x01\x01\x91PPa\x05\x04V[P\x88g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x82\x7F\xDD\x1DC\xA4\x15\xE6\xCFP-\xCD{3=2\x0FAh)\xC0\xF6\xA4:\xA9\xE3-\x81\xCD\x9A:qG\xE6\x87\x87`@Qa\x05\xEB\x92\x91\x90a\x14\xC9V[`@Q\x80\x91\x03\x90\xA3\x81\x92PPP\x96\x95PPPPPPV[`\0\x80`\0\x83\x81R` \x01\x90\x81R` \x01`\0 \x90Pa\x06R\x81`\0\x01`\0\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Q\x80``\x01`@R\x80`$\x81R` \x01a\x19C`$\x919a\t\x86V[\x80`\x06\x01`\0\x90T\x90a\x01\0\n\x90\x04`\xFF\x16\x15a\x06\xA4W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x06\x9B\x90a\x159V[`@Q\x80\x91\x03\x90\xFD[`\0\x82`\x01`@Q` \x01a\x06\xBA\x92\x91\x90a\x15\x94V[`@Q` \x81\x83\x03\x03\x81R\x90`@R\x80Q\x90` \x01 \x90Pa\x07#\x81\x83`\x01\x01T`@Q\x80`@\x01`@R\x80`\x10\x81R` \x01\x7FNot enough votes\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81RP`\x01a\t\xB7\x90\x93\x92\x91\x90c\xFF\xFF\xFF\xFF\x16V[`\x01\x82`\x06\x01`\0a\x01\0\n\x81T\x81`\xFF\x02\x19\x16\x90\x83\x15\x15\x02\x17\x90UPa\x07I\x83a\t\xDFV[\x82\x7F{\x1B\xCF\x1C\xCF\x90\x1A\x11X\x9A\xFF\xF5PMY\xFD\nSx\x0E\xED*\x95*\xDA\xDE\x03H\x98Q9\xE0`@Q`@Q\x80\x91\x03\x90\xA2PPPV[a\x07\xA8a\x07\xA2\x83a\x07\x8Aa\t\xE2V[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x0B\x17\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[\x82a\x0B8V[PPV[`\x002s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x82s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x08\x1CW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x08\x13\x90a\x16/V[`@Q\x80\x91\x03\x90\xFD[\x83`\0\x01`\0\x84\x81R` \x01\x90\x81R` \x01`\0 `\0\x83s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01\x90\x81R` \x01`\0 T\x90P\x93\x92PPPV[2s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x82s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x08\xE6W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x08\xDD\x90a\x16/V[`@Q\x80\x91\x03\x90\xFD[\x80\x84`\0\x01`\0\x85\x81R` \x01\x90\x81R` \x01`\0 `\0\x84s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01\x90\x81R` \x01`\0 `\0\x82\x82Ta\tH\x91\x90a\x16~V[\x92PP\x81\x90UPPPPPV[\x80\x83`\0\x01`\0\x84\x81R` \x01\x90\x81R` \x01`\0 `\0\x82\x82Ta\tz\x91\x90a\x16~V[\x92PP\x81\x90UPPPPV[a\t\xB3a\t\xAD\x83a\t\x95a\t\xE2V[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x0C.\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[\x82a\x0B8V[PPV[a\t\xD9\x82\x85`\0\x01`\0\x86\x81R` \x01\x90\x81R` \x01`\0 T\x10\x15\x82a\x0B8V[PPPPV[PV[`\0\x80`\0\x7F\xBA(nM\x89\xDA\xBFK(x\xE8\x96B;\xB1#\xD9\xD5\x14>f&\x06\xFD4;gf\xD7\xBC\xF7!`\0\x1Cs\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\n-\x90a\x16\xE3V[`\0`@Q\x80\x83\x03\x81\x85Z\xFA\x91PP=\x80`\0\x81\x14a\nhW`@Q\x91P`\x1F\x19`?=\x01\x16\x82\x01`@R=\x82R=`\0` \x84\x01>a\nmV[``\x91P[P\x91P\x91P\x81a\n\xB2W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\n\xA9\x90a\x17DV[`@Q\x80\x91\x03\x90\xFD[` \x81Q\x14a\n\xF6W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\n\xED\x90a\x17\xB0V[`@Q\x80\x91\x03\x90\xFD[`\0\x81\x80` \x01\x90Q\x81\x01\x90a\x0B\x0C\x91\x90a\x17\xFCV[\x90P\x80\x93PPPP\x90V[`\0\x81g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x83g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x10\x90P\x92\x91PPV[`\0\x7F=\xCD\xF6;A\xC1\x03V}r%\x97j\xD9\x14^\x86lz}\xCC\xC6\xC2w\xEA\x86\xAB\xBD&\x8F\xBA\xC9`\0\x1Cs\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x83`@Q` \x01a\x0B\x85\x91\x90a\x18DV[`@Q` \x81\x83\x03\x03\x81R\x90`@R`@Qa\x0B\xA1\x91\x90a\x18\xC5V[`\0`@Q\x80\x83\x03\x81\x85Z\xFA\x91PP=\x80`\0\x81\x14a\x0B\xDCW`@Q\x91P`\x1F\x19`?=\x01\x16\x82\x01`@R=\x82R=`\0` \x84\x01>a\x0B\xE1V[``\x91P[PP\x90P\x80\x82\x90a\x0C(W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x0C\x1F\x91\x90a\x19 V[`@Q\x80\x91\x03\x90\xFD[PPPPV[`\0\x81g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x83g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x11\x90P\x92\x91PPV[`\0\x80\xFD[`\0\x80\xFD[`\0\x81\x90P\x91\x90PV[a\x0Cl\x81a\x0CYV[\x81\x14a\x0CwW`\0\x80\xFD[PV[`\0\x815\x90Pa\x0C\x89\x81a\x0CcV[\x92\x91PPV[`\0`\xFF\x82\x16\x90P\x91\x90PV[a\x0C\xA5\x81a\x0C\x8FV[\x81\x14a\x0C\xB0W`\0\x80\xFD[PV[`\0\x815\x90Pa\x0C\xC2\x81a\x0C\x9CV[\x92\x91PPV[`\0\x80`@\x83\x85\x03\x12\x15a\x0C\xDFWa\x0C\xDEa\x0COV[[`\0a\x0C\xED\x85\x82\x86\x01a\x0CzV[\x92PP` a\x0C\xFE\x85\x82\x86\x01a\x0C\xB3V[\x91PP\x92P\x92\x90PV[`\0g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x16\x90P\x91\x90PV[a\r%\x81a\r\x08V[\x81\x14a\r0W`\0\x80\xFD[PV[`\0\x815\x90Pa\rB\x81a\r\x1CV[\x92\x91PPV[`\0s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x16\x90P\x91\x90PV[`\0a\rs\x82a\rHV[\x90P\x91\x90PV[a\r\x83\x81a\rhV[\x81\x14a\r\x8EW`\0\x80\xFD[PV[`\0\x815\x90Pa\r\xA0\x81a\rzV[\x92\x91PPV[`\0\x80\xFD[`\0\x80\xFD[`\0\x80\xFD[`\0\x80\x83`\x1F\x84\x01\x12a\r\xCBWa\r\xCAa\r\xA6V[[\x825\x90Pg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\r\xE8Wa\r\xE7a\r\xABV[[` \x83\x01\x91P\x83` \x82\x02\x83\x01\x11\x15a\x0E\x04Wa\x0E\x03a\r\xB0V[[\x92P\x92\x90PV[`\0\x80`\0\x80``\x85\x87\x03\x12\x15a\x0E%Wa\x0E$a\x0COV[[`\0a\x0E3\x87\x82\x88\x01a\r3V[\x94PP` a\x0ED\x87\x82\x88\x01a\r\x91V[\x93PP`@\x85\x015g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\x0EeWa\x0Eda\x0CTV[[a\x0Eq\x87\x82\x88\x01a\r\xB5V[\x92P\x92PP\x92\x95\x91\x94P\x92PV[a\x0E\x88\x81a\x0CYV[\x82RPPV[`\0` \x82\x01\x90Pa\x0E\xA3`\0\x83\x01\x84a\x0E\x7FV[\x92\x91PPV[`\0\x81\x90P\x91\x90PV[a\x0E\xBC\x81a\x0E\xA9V[\x81\x14a\x0E\xC7W`\0\x80\xFD[PV[`\0\x815\x90Pa\x0E\xD9\x81a\x0E\xB3V[\x92\x91PPV[`\0\x80\x83`\x1F\x84\x01\x12a\x0E\xF5Wa\x0E\xF4a\r\xA6V[[\x825\x90Pg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\x0F\x12Wa\x0F\x11a\r\xABV[[` \x83\x01\x91P\x83`\x01\x82\x02\x83\x01\x11\x15a\x0F.Wa\x0F-a\r\xB0V[[\x92P\x92\x90PV[`\0\x80`\0\x80`\0\x80`\x80\x87\x89\x03\x12\x15a\x0FRWa\x0FQa\x0COV[[`\0a\x0F`\x89\x82\x8A\x01a\r3V[\x96PP` a\x0Fq\x89\x82\x8A\x01a\x0E\xCAV[\x95PP`@\x87\x015g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\x0F\x92Wa\x0F\x91a\x0CTV[[a\x0F\x9E\x89\x82\x8A\x01a\r\xB5V[\x94P\x94PP``\x87\x015g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\x0F\xC1Wa\x0F\xC0a\x0CTV[[a\x0F\xCD\x89\x82\x8A\x01a\x0E\xDFV[\x92P\x92PP\x92\x95P\x92\x95P\x92\x95V[`\0` \x82\x84\x03\x12\x15a\x0F\xF2Wa\x0F\xF1a\x0COV[[`\0a\x10\0\x84\x82\x85\x01a\x0CzV[\x91PP\x92\x91PPV[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0`\0R`!`\x04R`$`\0\xFD[`\0\x82\x82R` \x82\x01\x90P\x92\x91PPV[\x7Fsender not a voter\0\0\0\0\0\0\0\0\0\0\0\0\0\0`\0\x82\x01RPV[`\0a\x10\x7F`\x12\x83a\x108V[\x91Pa\x10\x8A\x82a\x10IV[` \x82\x01\x90P\x91\x90PV[`\0` \x82\x01\x90P\x81\x81\x03`\0\x83\x01Ra\x10\xAE\x81a\x10rV[\x90P\x91\x90PV[\x7Falready voted\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0`\0\x82\x01RPV[`\0a\x10\xEB`\r\x83a\x108V[\x91Pa\x10\xF6\x82a\x10\xB5V[` \x82\x01\x90P\x91\x90PV[`\0` \x82\x01\x90P\x81\x81\x03`\0\x83\x01Ra\x11\x1A\x81a\x10\xDEV[\x90P\x91\x90PV[a\x11*\x81a\x0C\x8FV[\x82RPPV[`\0`@\x82\x01\x90Pa\x11E`\0\x83\x01\x85a\x0E\x7FV[a\x11R` \x83\x01\x84a\x11!V[\x93\x92PPPV[`\0` \x82\x01\x90Pa\x11n`\0\x83\x01\x84a\x11!V[\x92\x91PPV[`\0\x81\x90P\x92\x91PPV[`\0\x81\x90P\x91\x90PV[a\x11\x92\x81a\rhV[\x82RPPV[`\0a\x11\xA4\x83\x83a\x11\x89V[` \x83\x01\x90P\x92\x91PPV[`\0a\x11\xBF` \x84\x01\x84a\r\x91V[\x90P\x92\x91PPV[`\0` \x82\x01\x90P\x91\x90PV[`\0a\x11\xE0\x83\x85a\x11tV[\x93Pa\x11\xEB\x82a\x11\x7FV[\x80`\0[\x85\x81\x10\x15a\x12$Wa\x12\x01\x82\x84a\x11\xB0V[a\x12\x0B\x88\x82a\x11\x98V[\x97Pa\x12\x16\x83a\x11\xC7V[\x92PP`\x01\x81\x01\x90Pa\x11\xEFV[P\x85\x92PPP\x93\x92PPPV[`\0a\x12>\x82\x84\x86a\x11\xD4V[\x91P\x81\x90P\x93\x92PPPV[`\0\x81\x90P\x91\x90PV[`\0a\x12oa\x12ja\x12e\x84a\r\x08V[a\x12JV[a\r\x08V[\x90P\x91\x90PV[a\x12\x7F\x81a\x12TV[\x82RPPV[a\x12\x8E\x81a\rhV[\x82RPPV[`\0``\x82\x01\x90Pa\x12\xA9`\0\x83\x01\x86a\x12vV[a\x12\xB6` \x83\x01\x85a\x12\x85V[a\x12\xC3`@\x83\x01\x84a\x0E\x7FV[\x94\x93PPPPV[\x7FThreshold should not be 0\0\0\0\0\0\0\0`\0\x82\x01RPV[`\0a\x13\x01`\x19\x83a\x108V[\x91Pa\x13\x0C\x82a\x12\xCBV[` \x82\x01\x90P\x91\x90PV[`\0` \x82\x01\x90P\x81\x81\x03`\0\x83\x01Ra\x130\x81a\x12\xF4V[\x90P\x91\x90PV[\x7FThere must be at least one voter`\0\x82\x01RPV[`\0a\x13m` \x83a\x108V[\x91Pa\x13x\x82a\x137V[` \x82\x01\x90P\x91\x90PV[`\0` \x82\x01\x90P\x81\x81\x03`\0\x83\x01Ra\x13\x9C\x81a\x13`V[\x90P\x91\x90PV[\x7Fproposal already exists\0\0\0\0\0\0\0\0\0`\0\x82\x01RPV[`\0a\x13\xD9`\x17\x83a\x108V[\x91Pa\x13\xE4\x82a\x13\xA3V[` \x82\x01\x90P\x91\x90PV[`\0` \x82\x01\x90P\x81\x81\x03`\0\x83\x01Ra\x14\x08\x81a\x13\xCCV[\x90P\x91\x90PV[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0`\0R`2`\x04R`$`\0\xFD[`\0` \x82\x84\x03\x12\x15a\x14TWa\x14Sa\x0COV[[`\0a\x14b\x84\x82\x85\x01a\r\x91V[\x91PP\x92\x91PPV[`\0\x82\x82R` \x82\x01\x90P\x92\x91PPV[\x82\x81\x837`\0\x83\x83\x01RPPPV[`\0`\x1F\x19`\x1F\x83\x01\x16\x90P\x91\x90PV[`\0a\x14\xA8\x83\x85a\x14kV[\x93Pa\x14\xB5\x83\x85\x84a\x14|V[a\x14\xBE\x83a\x14\x8BV[\x84\x01\x90P\x93\x92PPPV[`\0` \x82\x01\x90P\x81\x81\x03`\0\x83\x01Ra\x14\xE4\x81\x84\x86a\x14\x9CV[\x90P\x93\x92PPPV[\x7FProposal already executed\0\0\0\0\0\0\0`\0\x82\x01RPV[`\0a\x15#`\x19\x83a\x108V[\x91Pa\x15.\x82a\x14\xEDV[` \x82\x01\x90P\x91\x90PV[`\0` \x82\x01\x90P\x81\x81\x03`\0\x83\x01Ra\x15R\x81a\x15\x16V[\x90P\x91\x90PV[`\0\x81\x90P\x91\x90PV[`\0a\x15~a\x15ya\x15t\x84a\x15YV[a\x12JV[a\x0C\x8FV[\x90P\x91\x90PV[a\x15\x8E\x81a\x15cV[\x82RPPV[`\0`@\x82\x01\x90Pa\x15\xA9`\0\x83\x01\x85a\x0E\x7FV[a\x15\xB6` \x83\x01\x84a\x15\x85V[\x93\x92PPPV[\x7FCannot access OwnedCounter owned`\0\x82\x01R\x7F by another address\0\0\0\0\0\0\0\0\0\0\0\0\0` \x82\x01RPV[`\0a\x16\x19`3\x83a\x108V[\x91Pa\x16$\x82a\x15\xBDV[`@\x82\x01\x90P\x91\x90PV[`\0` \x82\x01\x90P\x81\x81\x03`\0\x83\x01Ra\x16H\x81a\x16\x0CV[\x90P\x91\x90PV[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0`\0R`\x11`\x04R`$`\0\xFD[`\0a\x16\x89\x82a\x0E\xA9V[\x91Pa\x16\x94\x83a\x0E\xA9V[\x92P\x82\x82\x01\x90P\x80\x82\x11\x15a\x16\xACWa\x16\xABa\x16OV[[\x92\x91PPV[`\0\x81\x90P\x92\x91PPV[PV[`\0a\x16\xCD`\0\x83a\x16\xB2V[\x91Pa\x16\xD8\x82a\x16\xBDV[`\0\x82\x01\x90P\x91\x90PV[`\0a\x16\xEE\x82a\x16\xC0V[\x91P\x81\x90P\x91\x90PV[\x7FPrecompile call failed\0\0\0\0\0\0\0\0\0\0`\0\x82\x01RPV[`\0a\x17.`\x16\x83a\x108V[\x91Pa\x179\x82a\x16\xF8V[` \x82\x01\x90P\x91\x90PV[`\0` \x82\x01\x90P\x81\x81\x03`\0\x83\x01Ra\x17]\x81a\x17!V[\x90P\x91\x90PV[\x7FInvalid output length\0\0\0\0\0\0\0\0\0\0\0`\0\x82\x01RPV[`\0a\x17\x9A`\x15\x83a\x108V[\x91Pa\x17\xA5\x82a\x17dV[` \x82\x01\x90P\x91\x90PV[`\0` \x82\x01\x90P\x81\x81\x03`\0\x83\x01Ra\x17\xC9\x81a\x17\x8DV[\x90P\x91\x90PV[a\x17\xD9\x81a\r\x08V[\x81\x14a\x17\xE4W`\0\x80\xFD[PV[`\0\x81Q\x90Pa\x17\xF6\x81a\x17\xD0V[\x92\x91PPV[`\0` \x82\x84\x03\x12\x15a\x18\x12Wa\x18\x11a\x0COV[[`\0a\x18 \x84\x82\x85\x01a\x17\xE7V[\x91PP\x92\x91PPV[`\0\x81\x15\x15\x90P\x91\x90PV[a\x18>\x81a\x18)V[\x82RPPV[`\0` \x82\x01\x90Pa\x18Y`\0\x83\x01\x84a\x185V[\x92\x91PPV[`\0\x81Q\x90P\x91\x90PV[`\0[\x83\x81\x10\x15a\x18\x88W\x80\x82\x01Q\x81\x84\x01R` \x81\x01\x90Pa\x18mV[`\0\x84\x84\x01RPPPPV[`\0a\x18\x9F\x82a\x18_V[a\x18\xA9\x81\x85a\x16\xB2V[\x93Pa\x18\xB9\x81\x85` \x86\x01a\x18jV[\x80\x84\x01\x91PP\x92\x91PPV[`\0a\x18\xD1\x82\x84a\x18\x94V[\x91P\x81\x90P\x92\x91PPV[`\0\x81Q\x90P\x91\x90PV[`\0a\x18\xF2\x82a\x18\xDCV[a\x18\xFC\x81\x85a\x108V[\x93Pa\x19\x0C\x81\x85` \x86\x01a\x18jV[a\x19\x15\x81a\x14\x8BV[\x84\x01\x91PP\x92\x91PPV[`\0` \x82\x01\x90P\x81\x81\x03`\0\x83\x01Ra\x19:\x81\x84a\x18\xE7V[\x90P\x92\x91PPV\xFEProposal deadline has not passed yetProposal deadline has passed or proposal does not exist", + b"`\x80`@R4\x80\x15a\0\x0FW__\xFD[P`\x046\x10a\0JW_5`\xE0\x1C\x80c\xB4\xB0q>\x14a\0NW\x80c\xB8)\x96o\x14a\0jW\x80c\xCFu\xEE*\x14a\0\x9AW\x80c\xE7Q\xF2q\x14a\0\xCAW[__\xFD[a\0h`\x04\x806\x03\x81\x01\x90a\0c\x91\x90a\x0C~V[a\0\xE6V[\0[a\0\x84`\x04\x806\x03\x81\x01\x90a\0\x7F\x91\x90a\r\xB4V[a\x02\xE5V[`@Qa\0\x91\x91\x90a\x0E4V[`@Q\x80\x91\x03\x90\xF3[a\0\xB4`\x04\x806\x03\x81\x01\x90a\0\xAF\x91\x90a\x0E\xD5V[a\x03CV[`@Qa\0\xC1\x91\x90a\x0E4V[`@Q\x80\x91\x03\x90\xF3[a\0\xE4`\x04\x806\x03\x81\x01\x90a\0\xDF\x91\x90a\x0FxV[a\x05\xE9V[\0[___\x84\x81R` \x01\x90\x81R` \x01_ \x90Pa\x011\x81_\x01_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Q\x80``\x01`@R\x80`7\x81R` \x01a\x18\x8A`7\x919a\x07ZV[`\x01`\x02\x81\x11\x15a\x01EWa\x01Da\x0F\xA3V[[\x81`\x03\x01_3s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01\x90\x81R` \x01_ _\x90T\x90a\x01\0\n\x90\x04`\xFF\x16`\x02\x81\x11\x15a\x01\xA3Wa\x01\xA2a\x0F\xA3V[[\x14a\x01\xE3W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x01\xDA\x90a\x10*V[`@Q\x80\x91\x03\x90\xFD[_a\x01\xFA\x843`\x02a\x07\x8B\x90\x92\x91\x90c\xFF\xFF\xFF\xFF\x16V[\x14a\x02:W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x021\x90a\x10\x92V[`@Q\x80\x91\x03\x90\xFD[a\x02S\x833`\x01`\x02a\x08Q\x90\x93\x92\x91\x90c\xFF\xFF\xFF\xFF\x16V[a\x02\x91\x83\x83`@Q` \x01a\x02i\x92\x91\x90a\x10\xBFV[`@Q` \x81\x83\x03\x03\x81R\x90`@R\x80Q\x90` \x01 `\x01\x80a\t(\x90\x92\x91\x90c\xFF\xFF\xFF\xFF\x16V[3s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x83\x7F\xD8\xA9\\\xA0^\x9A&V\xFE!\xD862\x9D\x9C\xD7x0\xE7\xFE\xF7\xAC\xB7\xC0\xFD;\xF5B\x1E\xA7\xAD\x9A\x84`@Qa\x02\xD8\x91\x90a\x10\xE6V[`@Q\x80\x91\x03\x90\xA3PPPV[_\x84\x84\x84\x84`@Q` \x01a\x02\xFB\x92\x91\x90a\x11\xB5V[`@Q` \x81\x83\x03\x03\x81R\x90`@R\x80Q\x90` \x01 `@Q` \x01a\x03#\x93\x92\x91\x90a\x12\x15V[`@Q` \x81\x83\x03\x03\x81R\x90`@R\x80Q\x90` \x01 \x90P\x94\x93PPPPV[_a\x03\x83\x87`@Q\x80`@\x01`@R\x80`\x1E\x81R` \x01\x7FDeadline must be in the future\0\0\x81RPa\x07ZV[_\x86\x11a\x03\xC5W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x03\xBC\x90a\x12\x94V[`@Q\x80\x91\x03\x90\xFD[_\x85\x85\x90P\x11a\x04\nW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x04\x01\x90a\x12\xFCV[`@Q\x80\x91\x03\x90\xFD[_a\x04\x17\x883\x88\x88a\x02\xE5V[\x90P___\x83\x81R` \x01\x90\x81R` \x01_ \x90P_\x81`\x05\x01T\x14a\x04rW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x04i\x90a\x13dV[`@Q\x80\x91\x03\x90\xFD[\x88\x81_\x01_a\x01\0\n\x81T\x81g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UP3\x81`\x02\x01_a\x01\0\n\x81T\x81s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x02\x19\x16\x90\x83s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x02\x17\x90UP\x86\x86\x90P\x81`\x05\x01\x81\x90UP__\x90P[\x87\x87\x90P\x81\x10\x15a\x05\x94W`\x01\x82`\x03\x01_\x8A\x8A\x85\x81\x81\x10a\x05\x13Wa\x05\x12a\x13\x82V[[\x90P` \x02\x01` \x81\x01\x90a\x05(\x91\x90a\x13\xAFV[s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01\x90\x81R` \x01_ _a\x01\0\n\x81T\x81`\xFF\x02\x19\x16\x90\x83`\x02\x81\x11\x15a\x05\x82Wa\x05\x81a\x0F\xA3V[[\x02\x17\x90UP\x80\x80`\x01\x01\x91PPa\x04\xEEV[P\x88g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x82\x7F\xDD\x1DC\xA4\x15\xE6\xCFP-\xCD{3=2\x0FAh)\xC0\xF6\xA4:\xA9\xE3-\x81\xCD\x9A:qG\xE6\x87\x87`@Qa\x05\xD2\x92\x91\x90a\x144V[`@Q\x80\x91\x03\x90\xA3\x81\x92PPP\x96\x95PPPPPPV[___\x83\x81R` \x01\x90\x81R` \x01_ \x90Pa\x064\x81_\x01_\x90T\x90a\x01\0\n\x90\x04g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Q\x80``\x01`@R\x80`$\x81R` \x01a\x18f`$\x919a\tUV[\x80`\x06\x01_\x90T\x90a\x01\0\n\x90\x04`\xFF\x16\x15a\x06\x85W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x06|\x90a\x14\xA0V[`@Q\x80\x91\x03\x90\xFD[_\x82`\x01`@Q` \x01a\x06\x9A\x92\x91\x90a\x14\xF7V[`@Q` \x81\x83\x03\x03\x81R\x90`@R\x80Q\x90` \x01 \x90Pa\x07\x03\x81\x83`\x01\x01T`@Q\x80`@\x01`@R\x80`\x10\x81R` \x01\x7FNot enough votes\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81RP`\x01a\t\x86\x90\x93\x92\x91\x90c\xFF\xFF\xFF\xFF\x16V[`\x01\x82`\x06\x01_a\x01\0\n\x81T\x81`\xFF\x02\x19\x16\x90\x83\x15\x15\x02\x17\x90UPa\x07(\x83a\t\xABV[\x82\x7F{\x1B\xCF\x1C\xCF\x90\x1A\x11X\x9A\xFF\xF5PMY\xFD\nSx\x0E\xED*\x95*\xDA\xDE\x03H\x98Q9\xE0`@Q`@Q\x80\x91\x03\x90\xA2PPPV[a\x07\x87a\x07\x81\x83a\x07ia\t\xAEV[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\n\xDC\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[\x82a\n\xFCV[PPV[_2s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x82s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x07\xFAW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x07\xF1\x90a\x15\x8EV[`@Q\x80\x91\x03\x90\xFD[\x83_\x01_\x84\x81R` \x01\x90\x81R` \x01_ _\x83s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01\x90\x81R` \x01_ T\x90P\x93\x92PPPV[2s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x82s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x08\xBFW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x08\xB6\x90a\x15\x8EV[`@Q\x80\x91\x03\x90\xFD[\x80\x84_\x01_\x85\x81R` \x01\x90\x81R` \x01_ _\x84s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01\x90\x81R` \x01_ _\x82\x82Ta\t\x1B\x91\x90a\x15\xD9V[\x92PP\x81\x90UPPPPPV[\x80\x83_\x01_\x84\x81R` \x01\x90\x81R` \x01_ _\x82\x82Ta\tI\x91\x90a\x15\xD9V[\x92PP\x81\x90UPPPPV[a\t\x82a\t|\x83a\tda\t\xAEV[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16a\x0B\xED\x90\x91\x90c\xFF\xFF\xFF\xFF\x16V[\x82a\n\xFCV[PPV[a\t\xA5\x82\x85_\x01_\x86\x81R` \x01\x90\x81R` \x01_ T\x10\x15\x82a\n\xFCV[PPPPV[PV[___\x7F\xBA(nM\x89\xDA\xBFK(x\xE8\x96B;\xB1#\xD9\xD5\x14>f&\x06\xFD4;gf\xD7\xBC\xF7!_\x1Cs\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16`@Qa\t\xF6\x90a\x169V[_`@Q\x80\x83\x03\x81\x85Z\xFA\x91PP=\x80_\x81\x14a\n.W`@Q\x91P`\x1F\x19`?=\x01\x16\x82\x01`@R=\x82R=_` \x84\x01>a\n3V[``\x91P[P\x91P\x91P\x81a\nxW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\no\x90a\x16\x97V[`@Q\x80\x91\x03\x90\xFD[` \x81Q\x14a\n\xBCW`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\n\xB3\x90a\x16\xFFV[`@Q\x80\x91\x03\x90\xFD[_\x81\x80` \x01\x90Q\x81\x01\x90a\n\xD1\x91\x90a\x17GV[\x90P\x80\x93PPPP\x90V[_\x81g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x83g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x10\x90P\x92\x91PPV[_\x7F=\xCD\xF6;A\xC1\x03V}r%\x97j\xD9\x14^\x86lz}\xCC\xC6\xC2w\xEA\x86\xAB\xBD&\x8F\xBA\xC9_\x1Cs\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x83`@Q` \x01a\x0BG\x91\x90a\x17\x8CV[`@Q` \x81\x83\x03\x03\x81R\x90`@R`@Qa\x0Bc\x91\x90a\x17\xEDV[_`@Q\x80\x83\x03\x81\x85Z\xFA\x91PP=\x80_\x81\x14a\x0B\x9BW`@Q\x91P`\x1F\x19`?=\x01\x16\x82\x01`@R=\x82R=_` \x84\x01>a\x0B\xA0V[``\x91P[PP\x90P\x80\x82\x90a\x0B\xE7W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x0B\xDE\x91\x90a\x18EV[`@Q\x80\x91\x03\x90\xFD[PPPPV[_\x81g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x83g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x11\x90P\x92\x91PPV[__\xFD[__\xFD[_\x81\x90P\x91\x90PV[a\x0C'\x81a\x0C\x15V[\x81\x14a\x0C1W__\xFD[PV[_\x815\x90Pa\x0CB\x81a\x0C\x1EV[\x92\x91PPV[_`\xFF\x82\x16\x90P\x91\x90PV[a\x0C]\x81a\x0CHV[\x81\x14a\x0CgW__\xFD[PV[_\x815\x90Pa\x0Cx\x81a\x0CTV[\x92\x91PPV[__`@\x83\x85\x03\x12\x15a\x0C\x94Wa\x0C\x93a\x0C\rV[[_a\x0C\xA1\x85\x82\x86\x01a\x0C4V[\x92PP` a\x0C\xB2\x85\x82\x86\x01a\x0CjV[\x91PP\x92P\x92\x90PV[_g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x16\x90P\x91\x90PV[a\x0C\xD8\x81a\x0C\xBCV[\x81\x14a\x0C\xE2W__\xFD[PV[_\x815\x90Pa\x0C\xF3\x81a\x0C\xCFV[\x92\x91PPV[_s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x16\x90P\x91\x90PV[_a\r\"\x82a\x0C\xF9V[\x90P\x91\x90PV[a\r2\x81a\r\x18V[\x81\x14a\r --private-key +``` + +### Cast + +```shell +$ cast +``` + +### Help + +```shell +$ forge --help +$ anvil --help +$ cast --help +``` diff --git a/protocol/foundry.lock b/protocol/foundry.lock new file mode 100644 index 00000000..59be75d5 --- /dev/null +++ b/protocol/foundry.lock @@ -0,0 +1,20 @@ +{ + "../solidity-sdk/lib/forge-std": { + "rev": "77041d2ce690e692d6e03cc812b57d1ddaa4d505" + }, + "lib/openzeppelin-contracts": { + "tag": { + "name": "v5.4.0", + "rev": "c64a1edb67b6e3f4a15cca8909c9482ad33a02b0" + } + }, + "../solidity-sdk/lib/openzeppelin-contracts": { + "rev": "e4f70216d759d8e6a64144a9e1f7bbeed78e7079" + }, + "lib/forge-std": { + "tag": { + "name": "v1.10.0", + "rev": "8bbcf6e3f8f62f419e5429a0bd89331c85c37824" + } + } +} \ No newline at end of file diff --git a/protocol/foundry.toml b/protocol/foundry.toml new file mode 100644 index 00000000..14cb474b --- /dev/null +++ b/protocol/foundry.toml @@ -0,0 +1,21 @@ +[profile.default] +src = "src" +out = "out" +libs = ["lib"] +solc = "0.8.28" +evm_version = "prague" +bytecode_hash = "none" +cbor_metadata = false +remappings = [ + "@openzeppelin/=lib/openzeppelin-contracts/", + "pod-sdk/=../solidity-sdk/src/" +] +allow_paths = ["../solidity-sdk"] + +# See more config options https://github.com/foundry-rs/foundry/blob/master/crates/config/README.md#all-options + +[fmt] +exclude = ["lib/**"] + +[lint] +exclude_lints = ["incorrect-shift"] \ No newline at end of file diff --git a/protocol/lib/forge-std b/protocol/lib/forge-std new file mode 160000 index 00000000..8bbcf6e3 --- /dev/null +++ b/protocol/lib/forge-std @@ -0,0 +1 @@ +Subproject commit 8bbcf6e3f8f62f419e5429a0bd89331c85c37824 diff --git a/protocol/lib/openzeppelin-contracts b/protocol/lib/openzeppelin-contracts new file mode 160000 index 00000000..c64a1edb --- /dev/null +++ b/protocol/lib/openzeppelin-contracts @@ -0,0 +1 @@ +Subproject commit c64a1edb67b6e3f4a15cca8909c9482ad33a02b0 diff --git a/solidity-sdk/script/BaseDeployer.s.sol b/protocol/script/BaseDeployer.s.sol similarity index 100% rename from solidity-sdk/script/BaseDeployer.s.sol rename to protocol/script/BaseDeployer.s.sol diff --git a/solidity-sdk/script/PodRegistryDeployer.s.sol b/protocol/script/PodRegistryDeployer.s.sol similarity index 89% rename from solidity-sdk/script/PodRegistryDeployer.s.sol rename to protocol/script/PodRegistryDeployer.s.sol index 7cb696c5..3eea022c 100644 --- a/solidity-sdk/script/PodRegistryDeployer.s.sol +++ b/protocol/script/PodRegistryDeployer.s.sol @@ -4,7 +4,7 @@ pragma solidity ^0.8.20; import {console} from "forge-std/console.sol"; import {BaseDeployer} from "./BaseDeployer.s.sol"; -import {PodRegistry} from "../src/verifier/PodRegistry.sol"; +import {PodRegistry} from "../src/PodRegistry.sol"; contract PodRegistryDeployer is BaseDeployer { function run() public { diff --git a/solidity-sdk/src/verifier/PodRegistry.sol b/protocol/src/PodRegistry.sol similarity index 99% rename from solidity-sdk/src/verifier/PodRegistry.sol rename to protocol/src/PodRegistry.sol index 3048a6f8..38e00261 100644 --- a/solidity-sdk/src/verifier/PodRegistry.sol +++ b/protocol/src/PodRegistry.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.20; import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; -import {IPodRegistry} from "../interfaces/IPodRegistry.sol"; +import {IPodRegistry} from "./interfaces/IPodRegistry.sol"; /** * @title PodRegistry diff --git a/solidity-sdk/src/interfaces/IPodRegistry.sol b/protocol/src/interfaces/IPodRegistry.sol similarity index 100% rename from solidity-sdk/src/interfaces/IPodRegistry.sol rename to protocol/src/interfaces/IPodRegistry.sol diff --git a/solidity-sdk/test/PodRegistry.t.sol b/protocol/test/PodRegistry.t.sol similarity index 99% rename from solidity-sdk/test/PodRegistry.t.sol rename to protocol/test/PodRegistry.t.sol index e0adec5c..389e224d 100644 --- a/solidity-sdk/test/PodRegistry.t.sol +++ b/protocol/test/PodRegistry.t.sol @@ -1,9 +1,9 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.20; -import "forge-std/Test.sol"; -import "../src/verifier/PodRegistry.sol"; -import "forge-std/console.sol"; +import {Test} from "forge-std/Test.sol"; +import {PodRegistry} from "../src/PodRegistry.sol"; +import {IPodRegistry} from "../src/interfaces/IPodRegistry.sol"; contract PodRegistryTest is Test { PodRegistry public registry; diff --git a/solidity-sdk/README.md b/solidity-sdk/README.md index 33746409..bece3f3f 100644 --- a/solidity-sdk/README.md +++ b/solidity-sdk/README.md @@ -21,9 +21,3 @@ $ forge test ```shell $ forge fmt ``` - -### Bindings - -```shell -forge bind --crate-name pod-solidity-sdk --bindings-path ./bindings --alloy-version 0.12.1 --overwrite --force --no-metadata --overwrite -``` diff --git a/solidity-sdk/foundry.toml b/solidity-sdk/foundry.toml index 100d405f..7a7edf45 100644 --- a/solidity-sdk/foundry.toml +++ b/solidity-sdk/foundry.toml @@ -2,12 +2,17 @@ src = "src" out = "out" libs = ["lib"] -remappings = ["@openzeppelin/=lib/openzeppelin-contracts/"] solc = "0.8.28" -evm_version = "berlin" +evm_version = "prague" bytecode_hash = "none" cbor_metadata = false - +remappings = [ + "pod-protocol/=../protocol/src", + "@openzeppelin/=lib/openzeppelin-contracts/" +] +allow_paths = [ + "../protocol" +] # See more config options https://github.com/foundry-rs/foundry/blob/master/crates/config/README.md#all-options [fmt] exclude = ["lib/**"] \ No newline at end of file diff --git a/solidity-sdk/src/verifier/PodECDSA.sol b/solidity-sdk/src/verifier/PodECDSA.sol index 127201d1..8c36e2b0 100644 --- a/solidity-sdk/src/verifier/PodECDSA.sol +++ b/solidity-sdk/src/verifier/PodECDSA.sol @@ -3,7 +3,7 @@ pragma solidity ^0.8.20; import {ECDSA} from "./ECDSA.sol"; import {MerkleTree} from "./MerkleTree.sol"; -import {IPodRegistry} from "./PodRegistry.sol"; +import {IPodRegistry} from "pod-protocol/interfaces/IPodRegistry.sol"; import {Strings} from "@openzeppelin/contracts/utils/Strings.sol"; import {Math} from "@openzeppelin/contracts/utils/math/Math.sol"; @@ -54,11 +54,7 @@ library PodECDSA { function _getMedianTimestamp(uint256[] memory sortedAttestationTimestamps) internal pure returns (uint256) { if (sortedAttestationTimestamps.length == 0) { - return 0; - } - - if (sortedAttestationTimestamps.length == 1) { - return sortedAttestationTimestamps[0]; + revert InvalidTimestamps(); } for (uint256 i = 0; i < sortedAttestationTimestamps.length - 1; i++) { diff --git a/solidity-sdk/test/PodECDSA.t.sol b/solidity-sdk/test/PodECDSA.t.sol index 8967f7de..b2ef7ee0 100644 --- a/solidity-sdk/test/PodECDSA.t.sol +++ b/solidity-sdk/test/PodECDSA.t.sol @@ -5,7 +5,7 @@ import {Test} from "forge-std/Test.sol"; import {PodECDSA} from "../src/verifier/PodECDSA.sol"; import {ECDSA} from "../src/verifier/ECDSA.sol"; import {MerkleTree} from "../src/verifier/MerkleTree.sol"; -import {PodRegistry} from "../src/verifier/PodRegistry.sol"; +import {PodRegistry} from "pod-protocol/PodRegistry.sol"; import {console} from "forge-std/console.sol"; import {Math} from "@openzeppelin/contracts/utils/math/Math.sol"; @@ -352,6 +352,17 @@ contract PodECDSATest is Test { return receipt; } + function test_getMedianTimestamp() public pure { + uint256[] memory timestamps = new uint256[](3); + timestamps[0] = 1; + timestamps[1] = 2; + timestamps[2] = 3; + assertEq(PodECDSA._getMedianTimestamp(timestamps), 2); + timestamps = new uint256[](1); + timestamps[0] = 5; + assertEq(PodECDSA._getMedianTimestamp(timestamps), 5); + } + function test_verify_RevertIfInvalidThreshold() public { PodECDSA.CertifiedReceipt memory receipt = _getReceipt(); PodECDSA.PodConfig memory podConfig = From 96aabbe8ae26706553ce2cb78767c435f200c4a9 Mon Sep 17 00:00:00 2001 From: Jakov Mitrovski Date: Fri, 29 Aug 2025 17:57:16 +0200 Subject: [PATCH 35/64] save --- protocol/src/BridgeDepositWithdraw.sol | 34 +++++ protocol/src/BridgeMintBurn.sol | 64 ++++++++ protocol/src/WrappedToken.sol | 40 +++++ protocol/src/abstract/Bridge.sol | 140 ++++++++++++++++++ protocol/src/interfaces/IBridge.sol | 78 ++++++++++ .../src/interfaces/IBridgeDepositWithdraw.sol | 8 + protocol/src/interfaces/IBridgeMintBurn.sol | 15 ++ .../interfaces/IERC20MintableAndBurnable.sol | 9 ++ 8 files changed, 388 insertions(+) create mode 100644 protocol/src/BridgeDepositWithdraw.sol create mode 100644 protocol/src/BridgeMintBurn.sol create mode 100644 protocol/src/WrappedToken.sol create mode 100644 protocol/src/abstract/Bridge.sol create mode 100644 protocol/src/interfaces/IBridge.sol create mode 100644 protocol/src/interfaces/IBridgeDepositWithdraw.sol create mode 100644 protocol/src/interfaces/IBridgeMintBurn.sol create mode 100644 protocol/src/interfaces/IERC20MintableAndBurnable.sol diff --git a/protocol/src/BridgeDepositWithdraw.sol b/protocol/src/BridgeDepositWithdraw.sol new file mode 100644 index 00000000..b1bc0cfb --- /dev/null +++ b/protocol/src/BridgeDepositWithdraw.sol @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +import {IBridgeDepositWithdraw} from "./interfaces/IBridgeDepositWithdraw.sol"; +import {Bridge} from "./abstract/Bridge.sol"; +import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; + +contract BridgeDepositWithdraw is Bridge, IBridgeDepositWithdraw { + using SafeERC20 for IERC20; + + constructor() Bridge() {} + + function handleDeposit(address token, uint256 amount) internal override { + IERC20(token).safeTransferFrom(msg.sender, address(this), amount); + } + + function handleMigrate(address _newContract) internal override { + for (uint256 i = 0; i < whitelistedTokens.length; i++) { + address token = whitelistedTokens[i]; + uint256 tokenBalance = IERC20(token).balanceOf(address(this)); + if (tokenBalance > 0) { + IERC20(token).safeTransfer(_newContract, tokenBalance); + } + } + } + + function whiteListToken(address token, address mirrorToken, TokenLimits calldata limits) + external + onlyRole(DEFAULT_ADMIN_ROLE) + { + _whitelistToken(token, mirrorToken, limits); + } +} diff --git a/protocol/src/BridgeMintBurn.sol b/protocol/src/BridgeMintBurn.sol new file mode 100644 index 00000000..0cda3e8a --- /dev/null +++ b/protocol/src/BridgeMintBurn.sol @@ -0,0 +1,64 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +import {IBridgeMintBurn} from "./interfaces/IBridgeMintBurn.sol"; +import {Bridge} from "./abstract/Bridge.sol"; +import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; +import {IAccessControl} from "@openzeppelin/contracts/access/IAccessControl.sol"; +import {IERC20MintableAndBurnable} from "./interfaces/IERC20MintableAndBurnable.sol"; +import {WrappedToken} from "./WrappedToken.sol"; + +contract BridgeMintBurn is Bridge, IBridgeMintBurn { + using SafeERC20 for IERC20; + + bytes32 constant TOKEN_PAUSER_ROLE = keccak256("PAUSER_ROLE"); + bytes32 constant TOKEN_MINTER_ROLE = keccak256("MINTER_ROLE"); + + constructor() Bridge() {} + + function handleDeposit(address token, uint256 amount) internal override { + IERC20MintableAndBurnable(token).burnFrom(msg.sender, amount); + } + + function handleBridging(address token, uint256 amount, address to, bytes calldata data) internal override { + IERC20MintableAndBurnable(token).mint(to, amount); + } + + function handleMigrate(address _newContract) internal override { + // Transfer ownership of all the token contracts to the new address. + for (uint256 i = 0; i < whitelistedTokens.length; i++) { + address token = whitelistedTokens[i]; + // Grant the new contracts all the roles. + IAccessControl(token).grantRole(DEFAULT_ADMIN_ROLE, _newContract); + IAccessControl(token).grantRole(TOKEN_MINTER_ROLE, _newContract); + IAccessControl(token).grantRole(TOKEN_PAUSER_ROLE, _newContract); + + // Renounce all roles from the existing contract. + IAccessControl(token).renounceRole(DEFAULT_ADMIN_ROLE, address(this)); + IAccessControl(token).renounceRole(TOKEN_MINTER_ROLE, address(this)); + IAccessControl(token).renounceRole(TOKEN_PAUSER_ROLE, address(this)); + } + } + + function whitelistToken(address token, address mirrorToken, TokenLimits calldata limits) + external + onlyRole(DEFAULT_ADMIN_ROLE) + { + uint256 a = 5; + } + + function createAndWhitelistMirrorToken( + string memory tokenName, + string memory tokenSymbol, + address existingToken, + address mirrorToken, + uint8 mirrorTokenDecimals, + TokenLimits calldata limits + ) external returns (address token) { + token = existingToken == address(0) + ? address(new WrappedToken(tokenName, tokenSymbol, mirrorTokenDecimals)) + : existingToken; + _whitelistToken(token, mirrorToken, limits); + } +} diff --git a/protocol/src/WrappedToken.sol b/protocol/src/WrappedToken.sol new file mode 100644 index 00000000..a2f34f3f --- /dev/null +++ b/protocol/src/WrappedToken.sol @@ -0,0 +1,40 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +import {ERC20Burnable} from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol"; +import {ERC20Pausable} from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Pausable.sol"; +import {AccessControl} from "@openzeppelin/contracts/access/AccessControl.sol"; +import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; + +contract WrappedToken is ERC20Burnable, ERC20Pausable, AccessControl { + bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE"); + bytes32 public constant PAUSE_ROLE = keccak256("PAUSE_ROLE"); + uint8 private immutable _decimals; + + constructor(string memory name_, string memory symbol_, uint8 decimals_) ERC20(name_, symbol_) { + _decimals = decimals_; + _grantRole(DEFAULT_ADMIN_ROLE, msg.sender); + _grantRole(PAUSE_ROLE, msg.sender); + _grantRole(MINTER_ROLE, msg.sender); + } + + function decimals() public view override returns (uint8) { + return _decimals; + } + + function mint(address to, uint256 amount) external onlyRole(MINTER_ROLE) { + _mint(to, amount); // will revert when paused because ERC20Pausable guards _update + } + + function pause() external onlyRole(PAUSE_ROLE) { + _pause(); + } + + function unpause() external onlyRole(DEFAULT_ADMIN_ROLE) { + _unpause(); + } + + function _update(address from, address to, uint256 value) internal override(ERC20, ERC20Pausable) whenNotPaused { + super._update(from, to, value); + } +} diff --git a/protocol/src/abstract/Bridge.sol b/protocol/src/abstract/Bridge.sol new file mode 100644 index 00000000..23d5651d --- /dev/null +++ b/protocol/src/abstract/Bridge.sol @@ -0,0 +1,140 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +import {IBridge} from "../interfaces/IBridge.sol"; +import {AccessControl} from "@openzeppelin/contracts/access/AccessControl.sol"; +import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; +import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import {Pausable} from "@openzeppelin/contracts/utils/Pausable.sol"; + +abstract contract Bridge is IBridge, AccessControl, Pausable { + using SafeERC20 for IERC20; + + /// @dev The role ID for addresses that can pause the contract. + bytes32 public constant PAUSE_ROLE = keccak256("PAUSE_ROLE"); + + /// @dev Map token address to token info. + mapping(address => TokenData) public tokenData; + + /// @dev Map mirror token address to token address. + mapping(address => address) public mirrorTokens; + + /// @dev Array of all the whitelisted tokens. + /// @notice A token in the list might not be active. + address[] public whitelistedTokens; + + /// @dev The number of deposits. + uint256 public depositIndex; + + /// @dev Address of the migrated contract. + address public migratedContract; + + constructor() { + _grantRole(DEFAULT_ADMIN_ROLE, msg.sender); + } + + function handleDeposit(address token, uint256 amount) internal virtual; + function handleBridging(address token, uint256 amount, address to, bytes calldata data) internal virtual; + function handleMigrate(address _newContract) internal virtual; + + /// @dev Modifier to check that contract is not already migrated. + modifier notMigrated() { + if (migratedContract != address(0)) { + revert ContractMigrated(); + } + _; + } + + /// @dev Modifier to make a function callable only when the token and amount is correct. + modifier isValidTokenAmount(address token, uint256 amount, bool isDeposit) { + TokenData storage t = tokenData[token]; + + if (isDeposit && t.limits.deposit != 0) { + // Reset daily limit if the day is passed after last update. + if (block.timestamp > t.deposit.lastUpdated + 1 days) { + t.deposit.lastUpdated = block.timestamp; + t.deposit.consumed = 0; + } + + if (t.deposit.consumed + amount > t.limits.deposit) { + revert DailyLimitExhausted(); + } + t.deposit.consumed += amount; + } else if (!isDeposit && t.limits.withdraw != 0) { + if (block.timestamp > t.withdraw.lastUpdated + 1 days) { + t.withdraw.lastUpdated = block.timestamp; + t.withdraw.consumed = 0; + } + + if (t.withdraw.consumed + amount > t.limits.withdraw) { + revert DailyLimitExhausted(); + } + t.withdraw.consumed += amount; + } + _; + } + + function deposit(address token, uint256 amount, address to) + external + whenNotPaused + isValidTokenAmount(token, amount, true) + returns (uint256 id) + { + if (to == address(0)) revert InvalidToAddress(); + id = depositIndex++; + handleDeposit(token, amount); + emit Deposit(id, token, amount, to); + } + + function _hashRequest(uint256 id, address token, uint256 amount, address to) internal pure returns (bytes32) { + return keccak256(abi.encodePacked(id, token, amount, to)); + } + + function _configureTokenData(address token, TokenLimits calldata limits, bool newToken) internal { + uint256 currMinAmount = tokenData[token].limits.minAmount; + if (limits.minAmount == 0 || (newToken ? currMinAmount != 0 : currMinAmount == 0)) { + revert InvalidTokenConfig(); + } + + TokenUsage memory depositUsage = TokenUsage(0, block.timestamp); + TokenUsage memory withdrawUsage = TokenUsage(0, block.timestamp); + // configuring token also resets the daily volume limit + TokenData memory data = TokenData(limits, depositUsage, withdrawUsage); + tokenData[token] = data; + } + + /// @inheritdoc IBridge + function configureToken(address token, TokenLimits calldata limits) external onlyRole(DEFAULT_ADMIN_ROLE) { + _configureTokenData(token, limits, false); + } + + /// @dev Internal function to whitelist a new token. + /// @param token Token that will be deposited in the contract. + /// @param mirrorToken Token that will be deposited in the mirror contract. + /// @param limits Token limits associated with the token. + function _whitelistToken(address token, address mirrorToken, TokenLimits calldata limits) internal { + if (mirrorTokens[mirrorToken] != address(0)) { + revert InvalidTokenConfig(); + } + + _configureTokenData(token, limits, true); + whitelistedTokens.push(token); + mirrorTokens[mirrorToken] = token; + } + + /// @inheritdoc IBridge + function pause() external onlyRole(PAUSE_ROLE) { + _pause(); + } + + /// @inheritdoc IBridge + function unpause() external notMigrated onlyRole(DEFAULT_ADMIN_ROLE) { + _unpause(); + } + + /// @inheritdoc IBridge + function migrate(address _newContract) public whenPaused notMigrated onlyRole(DEFAULT_ADMIN_ROLE) { + handleMigrate(_newContract); + migratedContract = _newContract; + } +} diff --git a/protocol/src/interfaces/IBridge.sol b/protocol/src/interfaces/IBridge.sol new file mode 100644 index 00000000..6fa27c88 --- /dev/null +++ b/protocol/src/interfaces/IBridge.sol @@ -0,0 +1,78 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +/** + * @title IBridge + * @notice Interface for the Bridge contracts that allow for cross-chain communication. + */ +interface IBridge { + error ContractMigrated(); + error InvalidTokenAmount(); + error InvalidToAddress(); + error InvalidTokenConfig(); + error DailyLimitExhausted(); + + event Deposit(uint256 indexed id, address indexed token, uint256 amount, address to); + event Withdraw(uint256 indexed id, address indexed mirrorToken, address indexed token, uint256 amount, address to); + + struct TokenLimits { + uint256 minAmount; // The minimum amount of tokens that can be deposited. + uint256 deposit; // The daily deposit limit for the token. + uint256 withdraw; // The daily withdrawal limit for the token. + } + + struct TokenUsage { + uint256 consumed; // The amount of tokens that have been used. + uint256 lastUpdated; // The timestamp when the consumed limits were last updated. + } + + struct TokenData { + TokenLimits limits; + TokenUsage deposit; + TokenUsage withdraw; + } + + /// @dev Request information. + /// @param id ID associated with the request. + /// @param token Token requested. + /// @param amount Amount of tokens requested. + /// @param to Address to release the funds to. + struct RequestInfo { + uint256 id; + address token; + uint256 amount; + address to; + } + + /// @dev Returns the number of deposits. + function depositIndex() external view returns (uint256); + + /// @dev Update a token's configuration information. + /// @param limits The token's new configuration limits. + /// @notice Set maxAmount to zero to disable the token. + /// @notice Can only be called by the weak-admin. + function configureToken(address token, TokenLimits calldata limits) external; + + /// @dev Deposit tokens to bridge to the other side. + /// @param token Token being deposited. + /// @param amount Amount of tokens being deposited. + /// @param to Address to release the tokens to on the other side. + /// @return The ID associated to the request. + function deposit(address token, uint256 amount, address to) external returns (uint256); + + /// @dev Pauses the contract. + /// @notice The contract can be paused by all addresses + /// with pause role but can only be unpaused by the weak-admin. + function pause() external; + + /// @dev Unpauses the contract. + /// @notice The contract can be paused by all addresses + /// with pause role but can only be unpaused by the weak-admin. + function unpause() external; + + /// @dev Migrates the contract to a new address. + /// @param _newContract Address of the new contract. + /// @notice This function can only be called once in the lifetime of this + /// contract by the admin. + function migrate(address _newContract) external; +} diff --git a/protocol/src/interfaces/IBridgeDepositWithdraw.sol b/protocol/src/interfaces/IBridgeDepositWithdraw.sol new file mode 100644 index 00000000..8187919a --- /dev/null +++ b/protocol/src/interfaces/IBridgeDepositWithdraw.sol @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +import {IBridge} from "./IBridge.sol"; + +interface IBridgeDepositWithdraw is IBridge { + function whiteListToken(address token, address mirrorToken, TokenLimits calldata limits) external; +} diff --git a/protocol/src/interfaces/IBridgeMintBurn.sol b/protocol/src/interfaces/IBridgeMintBurn.sol new file mode 100644 index 00000000..6add935a --- /dev/null +++ b/protocol/src/interfaces/IBridgeMintBurn.sol @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +import {IBridge} from "./IBridge.sol"; + +interface IBridgeMintBurn is IBridge { + function createMirrorToken( + string memory tokenName, + string memory tokenSymbol, + address existingToken, + address mirrorToken, + uint8 mirrorTokenDecimals, + TokenLimits calldata limits + ) external returns (address); +} diff --git a/protocol/src/interfaces/IERC20MintableAndBurnable.sol b/protocol/src/interfaces/IERC20MintableAndBurnable.sol new file mode 100644 index 00000000..701738ef --- /dev/null +++ b/protocol/src/interfaces/IERC20MintableAndBurnable.sol @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; + +interface IERC20MintableAndBurnable is IERC20 { + function mint(address to, uint256 amount) external; + function burnFrom(address account, uint256 amount) external; +} From e4f4c8e76e6050cc26583e2f0514713b2b4e5eb1 Mon Sep 17 00:00:00 2001 From: Jakov Mitrovski Date: Fri, 29 Aug 2025 18:23:58 +0200 Subject: [PATCH 36/64] address PR comments --- .github/workflows/test.yml | 23 +------- .gitmodules | 6 -- examples/optimistic-auction/client/main.rs | 4 +- protocol/README.md | 67 +--------------------- types/src/ledger/log.rs | 6 +- 5 files changed, 8 insertions(+), 98 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 950f4267..ad4effa4 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -78,12 +78,7 @@ jobs: - name: Install Foundry uses: foundry-rs/foundry-toolchain@v1 with: - version: v1.3.1 - - - - name: Show Forge version - run: | - forge --version + version: v1.3.1 - name: Run Forge fmt run: | @@ -116,10 +111,6 @@ jobs: with: version: v1.3.1 - - name: Show Forge version - run: | - forge --version - - name: Run Forge fmt run: | forge fmt --check @@ -151,10 +142,6 @@ jobs: with: version: v1.3.1 - - name: Show Forge version - run: | - forge --version - - name: Run Forge fmt run: | forge fmt --check @@ -192,10 +179,6 @@ jobs: with: version: v1.3.1 - - name: Show Forge version - run: | - forge --version - - name: Run Forge fmt run: | forge fmt --check @@ -233,10 +216,6 @@ jobs: with: version: v1.3.1 - - name: Show Forge version - run: | - forge --version - - name: Run Forge fmt run: | forge fmt --check diff --git a/.gitmodules b/.gitmodules index c9b89d6d..508322dd 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,9 +4,3 @@ [submodule "solidity-sdk/lib/openzeppelin-contracts"] path = solidity-sdk/lib/openzeppelin-contracts url = https://github.com/OpenZeppelin/openzeppelin-contracts -[submodule "protocol/lib/forge-std"] - path = protocol/lib/forge-std - url = https://github.com/foundry-rs/forge-std -[submodule "protocol/lib/openzeppelin-contracts"] - path = protocol/lib/openzeppelin-contracts - url = https://github.com/OpenZeppelin/openzeppelin-contracts diff --git a/examples/optimistic-auction/client/main.rs b/examples/optimistic-auction/client/main.rs index d2c536a1..5ac7e699 100644 --- a/examples/optimistic-auction/client/main.rs +++ b/examples/optimistic-auction/client/main.rs @@ -79,7 +79,7 @@ fn get_certified_log(log: &VerifiableLog) -> Result { certifiedReceipt: CertifiedReceipt { receiptRoot: log.pod_metadata.receipt.hash_custom(), aggregateSignature: log.aggregate_signatures().into(), - sortedAttestationTimestamps: log.get_sorted_attestation_timestamps(), + sortedAttestationTimestamps: log.get_sorted_attestation_timestamps_in_seconds(), }, leaf, proof: Proof { path: proof.path }, @@ -351,7 +351,7 @@ async fn main() -> Result<()> { let deadline = now + 5 * MICROSECONDS_PER_SECOND; #[allow(clippy::identity_op)] - let writing_period_ends = deadline + (WAITING_PERIOD) * MICROSECONDS_PER_SECOND; + let writing_period_ends = deadline + WAITING_PERIOD * MICROSECONDS_PER_SECOND; #[allow(clippy::identity_op)] let dispute_period_ends = writing_period_ends + WAITING_PERIOD * MICROSECONDS_PER_SECOND; diff --git a/protocol/README.md b/protocol/README.md index 8817d6ab..5407e128 100644 --- a/protocol/README.md +++ b/protocol/README.md @@ -1,66 +1,3 @@ -## Foundry +# pod-protocol -**Foundry is a blazing fast, portable and modular toolkit for Ethereum application development written in Rust.** - -Foundry consists of: - -- **Forge**: Ethereum testing framework (like Truffle, Hardhat and DappTools). -- **Cast**: Swiss army knife for interacting with EVM smart contracts, sending transactions and getting chain data. -- **Anvil**: Local Ethereum node, akin to Ganache, Hardhat Network. -- **Chisel**: Fast, utilitarian, and verbose solidity REPL. - -## Documentation - -https://book.getfoundry.sh/ - -## Usage - -### Build - -```shell -$ forge build -``` - -### Test - -```shell -$ forge test -``` - -### Format - -```shell -$ forge fmt -``` - -### Gas Snapshots - -```shell -$ forge snapshot -``` - -### Anvil - -```shell -$ anvil -``` - -### Deploy - -```shell -$ forge script script/Counter.s.sol:CounterScript --rpc-url --private-key -``` - -### Cast - -```shell -$ cast -``` - -### Help - -```shell -$ forge --help -$ anvil --help -$ cast --help -``` +Solidity contracts deployed on Ethereum responsible for protocol management \ No newline at end of file diff --git a/types/src/ledger/log.rs b/types/src/ledger/log.rs index 23230a2f..892383fd 100644 --- a/types/src/ledger/log.rs +++ b/types/src/ledger/log.rs @@ -1,6 +1,6 @@ use std::ops::Deref; -use alloy_primitives::Uint; +use alloy_primitives::U256; pub use alloy_primitives::{Log, LogData}; use alloy_rpc_types::Log as RPCLog; use alloy_sol_types::SolValue; @@ -127,11 +127,11 @@ impl VerifiableLog { self.pod_metadata .attestations .iter() - .sorted_by_key(|a| a.timestamp.as_seconds()) + .sorted_by_key(|a| a.timestamp) .collect() } - pub fn get_sorted_attestation_timestamps(&self) -> Vec> { + pub fn get_sorted_attestation_timestamps_in_seconds(&self) -> Vec { self.sort_attestations_by_timestamp() .iter() .map(|a| a.timestamp.as_seconds().try_into().unwrap()) From 032b0eefc1d100953c66910ed6e46202816aa4d7 Mon Sep 17 00:00:00 2001 From: Jakov Mitrovski Date: Fri, 29 Aug 2025 18:28:46 +0200 Subject: [PATCH 37/64] add back modules --- .gitmodules | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.gitmodules b/.gitmodules index 508322dd..c9b89d6d 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,3 +4,9 @@ [submodule "solidity-sdk/lib/openzeppelin-contracts"] path = solidity-sdk/lib/openzeppelin-contracts url = https://github.com/OpenZeppelin/openzeppelin-contracts +[submodule "protocol/lib/forge-std"] + path = protocol/lib/forge-std + url = https://github.com/foundry-rs/forge-std +[submodule "protocol/lib/openzeppelin-contracts"] + path = protocol/lib/openzeppelin-contracts + url = https://github.com/OpenZeppelin/openzeppelin-contracts From 512cefc3d105fdadf0e905626b31106285c32b05 Mon Sep 17 00:00:00 2001 From: Jakov Mitrovski Date: Mon, 1 Sep 2025 10:40:36 +0200 Subject: [PATCH 38/64] upd symlink --- .gitmodules | 6 ------ protocol/lib | 1 + protocol/lib/forge-std | 1 - protocol/lib/openzeppelin-contracts | 1 - 4 files changed, 1 insertion(+), 8 deletions(-) create mode 120000 protocol/lib delete mode 160000 protocol/lib/forge-std delete mode 160000 protocol/lib/openzeppelin-contracts diff --git a/.gitmodules b/.gitmodules index c9b89d6d..508322dd 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,9 +4,3 @@ [submodule "solidity-sdk/lib/openzeppelin-contracts"] path = solidity-sdk/lib/openzeppelin-contracts url = https://github.com/OpenZeppelin/openzeppelin-contracts -[submodule "protocol/lib/forge-std"] - path = protocol/lib/forge-std - url = https://github.com/foundry-rs/forge-std -[submodule "protocol/lib/openzeppelin-contracts"] - path = protocol/lib/openzeppelin-contracts - url = https://github.com/OpenZeppelin/openzeppelin-contracts diff --git a/protocol/lib b/protocol/lib new file mode 120000 index 00000000..3dfa7214 --- /dev/null +++ b/protocol/lib @@ -0,0 +1 @@ +../solidity-sdk/lib \ No newline at end of file diff --git a/protocol/lib/forge-std b/protocol/lib/forge-std deleted file mode 160000 index 8bbcf6e3..00000000 --- a/protocol/lib/forge-std +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 8bbcf6e3f8f62f419e5429a0bd89331c85c37824 diff --git a/protocol/lib/openzeppelin-contracts b/protocol/lib/openzeppelin-contracts deleted file mode 160000 index c64a1edb..00000000 --- a/protocol/lib/openzeppelin-contracts +++ /dev/null @@ -1 +0,0 @@ -Subproject commit c64a1edb67b6e3f4a15cca8909c9482ad33a02b0 From 68f5b428f166f562689f1170caa50bd3bc82473d Mon Sep 17 00:00:00 2001 From: Jakov Mitrovski Date: Thu, 4 Sep 2025 15:57:51 +0200 Subject: [PATCH 39/64] implement bridge and tests --- protocol/.gitignore | 1 + protocol/foundry.toml | 3 +- protocol/script/CreateAndWhitelistToken.s.sol | 30 ++ protocol/script/DeployAndMintERC.s.sol | 27 ++ protocol/script/DeployDepositWithdraw.s.sol | 55 ++++ protocol/script/DeployMintBurn.s.sol | 24 ++ protocol/script/Deposit.s.sol | 36 +++ protocol/src/BridgeDepositWithdraw.sol | 39 ++- protocol/src/BridgeMintBurn.sol | 99 ++++-- protocol/src/WrappedToken.sol | 12 +- protocol/src/abstract/Bridge.sol | 61 ++-- protocol/src/interfaces/IBridge.sol | 8 +- .../src/interfaces/IBridgeDepositWithdraw.sol | 3 + protocol/src/interfaces/IBridgeMintBurn.sol | 6 +- protocol/test/BridgeDepositWithdraw.t.sol | 281 ++++++++++++++++++ protocol/test/BridgeMintBurn.t.sol | 218 ++++++++++++++ protocol/test/abstract/Bridge.t.sol | 199 +++++++++++++ 17 files changed, 1046 insertions(+), 56 deletions(-) create mode 100644 protocol/script/CreateAndWhitelistToken.s.sol create mode 100644 protocol/script/DeployAndMintERC.s.sol create mode 100644 protocol/script/DeployDepositWithdraw.s.sol create mode 100644 protocol/script/DeployMintBurn.s.sol create mode 100644 protocol/script/Deposit.s.sol create mode 100644 protocol/test/BridgeDepositWithdraw.t.sol create mode 100644 protocol/test/BridgeMintBurn.t.sol create mode 100644 protocol/test/abstract/Bridge.t.sol diff --git a/protocol/.gitignore b/protocol/.gitignore index 85198aaa..027d01a8 100644 --- a/protocol/.gitignore +++ b/protocol/.gitignore @@ -6,6 +6,7 @@ out/ !/broadcast /broadcast/*/31337/ /broadcast/**/dry-run/ +/broadcast/*/1293/ # Docs docs/ diff --git a/protocol/foundry.toml b/protocol/foundry.toml index 14cb474b..5c2988ad 100644 --- a/protocol/foundry.toml +++ b/protocol/foundry.toml @@ -8,7 +8,8 @@ bytecode_hash = "none" cbor_metadata = false remappings = [ "@openzeppelin/=lib/openzeppelin-contracts/", - "pod-sdk/=../solidity-sdk/src/" + "pod-sdk/=../solidity-sdk/src/", + "pod-protocol/=./src/" ] allow_paths = ["../solidity-sdk"] diff --git a/protocol/script/CreateAndWhitelistToken.s.sol b/protocol/script/CreateAndWhitelistToken.s.sol new file mode 100644 index 00000000..984c63fb --- /dev/null +++ b/protocol/script/CreateAndWhitelistToken.s.sol @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +import {Script} from "forge-std/Script.sol"; +import {console} from "forge-std/console.sol"; +import {IBridgeMintBurn} from "../src/interfaces/IBridgeMintBurn.sol"; +import {IBridge} from "../src/interfaces/IBridge.sol"; +import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import {WrappedToken} from "../src/WrappedToken.sol"; + +contract CreateAndWhitelistToken is Script { + function run() external { + vm.startBroadcast(); + + IERC20 testToken = IERC20(vm.envAddress("TEST_ERC")); + WrappedToken mirrorToken = WrappedToken(vm.envAddress("MIRROR_TEST_ERC")); + IBridgeMintBurn bridgeMintBurn = IBridgeMintBurn(vm.envAddress("BRIDGE_MINT_BURN_ADDRESS")); + + bridgeMintBurn.createAndWhitelistMirrorToken( + "Test Token", + "TEST", + address(mirrorToken), + address(testToken), + 18, + IBridge.TokenLimits({minAmount: 1e18, deposit: 10000e18, claim: 10000e18}) + ); + + vm.stopBroadcast(); + } +} diff --git a/protocol/script/DeployAndMintERC.s.sol b/protocol/script/DeployAndMintERC.s.sol new file mode 100644 index 00000000..d5747dd7 --- /dev/null +++ b/protocol/script/DeployAndMintERC.s.sol @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +import {Script} from "forge-std/Script.sol"; +import {console} from "forge-std/console.sol"; +import {WrappedToken} from "../src/WrappedToken.sol"; + +contract DeployAndMintERC is Script { + function run() external { + console.log("=== Minting tokens ==="); + + vm.startBroadcast(); + + address token = vm.envOr("MIRROR_TEST_ERC", address(0)); + + WrappedToken mirrorToken; + if (token == address(0)) { + mirrorToken = new WrappedToken("Test Token", "TEST", 18); + } else { + mirrorToken = WrappedToken(vm.envAddress("MIRROR_TEST_ERC")); + } + + mirrorToken.mint(vm.envAddress("USER_ADDRESS"), 100 * 1e18); + + vm.stopBroadcast(); + } +} diff --git a/protocol/script/DeployDepositWithdraw.s.sol b/protocol/script/DeployDepositWithdraw.s.sol new file mode 100644 index 00000000..53ed9461 --- /dev/null +++ b/protocol/script/DeployDepositWithdraw.s.sol @@ -0,0 +1,55 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +import {Script} from "forge-std/Script.sol"; +import {console} from "forge-std/console.sol"; +import {BridgeDepositWithdraw} from "../src/BridgeDepositWithdraw.sol"; +import {PodRegistry} from "../src/PodRegistry.sol"; +import {ERC20Mock} from "@openzeppelin/contracts/mocks/token/ERC20Mock.sol"; +import {IBridge} from "../src/interfaces/IBridge.sol"; +import {BaseDeployer} from "./BaseDeployer.s.sol"; + +contract DeployDepositWithdraw is BaseDeployer { + uint256 constant CHAIN_ID = 31337; + string constant RPC_URL = "http://localhost:8546"; + + function run() external { + console.log("=== Deploying BridgeDepositWithdraw to localhost:8546 (chainId 31337) ==="); + + // Create a fork of the deposit/withdraw network + vm.createSelectFork(RPC_URL); + require(block.chainid == CHAIN_ID, "Wrong chain ID for deposit/withdraw network"); + + // Deploy PodRegistry first + address[] memory initialValidators = getValidatorAddresses(); + + PodRegistry podRegistry = new PodRegistry(initialValidators); + console.log("PodRegistry deployed at:", address(podRegistry)); + + BridgeDepositWithdraw bridgeDepositWithdraw = new BridgeDepositWithdraw(address(podRegistry)); + console.log("BridgeDepositWithdraw deployed at:", address(bridgeDepositWithdraw)); + + // Deploy some test tokens + ERC20Mock testToken = new ERC20Mock(); + ERC20Mock mirrorToken = new ERC20Mock(); + console.log("Test token deployed at:", address(testToken)); + console.log("Mirror token deployed at:", address(mirrorToken)); + + // Configure the bridge + bridgeDepositWithdraw.whiteListToken( + address(testToken), + address(mirrorToken), + IBridge.TokenLimits({minAmount: 1e18, deposit: 10000e18, claim: 10000e18}) + ); + console.log("Token whitelisted on bridge"); + + vm.stopBroadcast(); + + console.log("=== BridgeDepositWithdraw deployment complete ==="); + console.log("Network: localhost:8546 (chainId 1337)"); + console.log("PodRegistry:", address(podRegistry)); + console.log("BridgeDepositWithdraw:", address(bridgeDepositWithdraw)); + console.log("Test Token:", address(testToken)); + console.log("Mirror Token:", address(mirrorToken)); + } +} diff --git a/protocol/script/DeployMintBurn.s.sol b/protocol/script/DeployMintBurn.s.sol new file mode 100644 index 00000000..94793627 --- /dev/null +++ b/protocol/script/DeployMintBurn.s.sol @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +import {Script} from "forge-std/Script.sol"; +import {console} from "forge-std/console.sol"; +import {BridgeMintBurn} from "../src/BridgeMintBurn.sol"; +import {PodRegistry} from "../src/PodRegistry.sol"; + +contract DeployMintBurn is Script { + function run() external { + console.log("=== Deploying BridgeMintBurn to localhost:8545 (chainId 1293) ==="); + + vm.startBroadcast(); + + BridgeMintBurn bridgeMintBurn = new BridgeMintBurn(); + console.log("BridgeMintBurn deployed at:", address(bridgeMintBurn)); + + vm.stopBroadcast(); + + console.log("=== BridgeMintBurn deployment complete ==="); + console.log("Network: localhost:8545 (chainId 1293)"); + console.log("BridgeMintBurn:", address(bridgeMintBurn)); + } +} diff --git a/protocol/script/Deposit.s.sol b/protocol/script/Deposit.s.sol new file mode 100644 index 00000000..5ea25d8f --- /dev/null +++ b/protocol/script/Deposit.s.sol @@ -0,0 +1,36 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +import {Script} from "forge-std/Script.sol"; +import {console} from "forge-std/console.sol"; +import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import {IBridge} from "../src/interfaces/IBridge.sol"; +import {Bridge} from "../src/abstract/Bridge.sol"; + +contract Deposit is Script { + function run() external { + console.log( + "=== Depositing tokens; needs to be called with the private key of the token holder because of approve ===" + ); + + vm.startBroadcast(); + + address mirrorToken = vm.envAddress("MIRROR_TEST_ERC"); + + Bridge bridge = Bridge(vm.envAddress("BRIDGE_MINT_BURN_ADDRESS")); + + uint256 amount = 1 * 1e18; + + IERC20(mirrorToken).approve(address(bridge), amount); + + vm.stopBroadcast(); + + vm.startBroadcast(); + + address to = vm.envAddress("USER_ADDRESS"); + + bridge.deposit(mirrorToken, amount, to); + + vm.stopBroadcast(); + } +} diff --git a/protocol/src/BridgeDepositWithdraw.sol b/protocol/src/BridgeDepositWithdraw.sol index b1bc0cfb..25f98dd9 100644 --- a/protocol/src/BridgeDepositWithdraw.sol +++ b/protocol/src/BridgeDepositWithdraw.sol @@ -5,11 +5,29 @@ import {IBridgeDepositWithdraw} from "./interfaces/IBridgeDepositWithdraw.sol"; import {Bridge} from "./abstract/Bridge.sol"; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; +import {PodECDSA} from "pod-sdk/verifier/PodECDSA.sol"; +import {IPodRegistry} from "./interfaces/IPodRegistry.sol"; contract BridgeDepositWithdraw is Bridge, IBridgeDepositWithdraw { using SafeERC20 for IERC20; - constructor() Bridge() {} + PodECDSA.PodConfig public podConfig; + + constructor(address _podRegistry) { + podConfig = + PodECDSA.PodConfig({thresholdNumerator: 2, thresholdDenominator: 3, registry: IPodRegistry(_podRegistry)}); + } + + function _decodeLog(PodECDSA.Log calldata log) + internal + pure + returns (uint256 id, address token, uint256 amount, address to) + { + if (log.topics.length != 3 || log.topics[0] != DEPOSIT_TOPIC_0) revert InvalidDepositLog(); + id = uint256(log.topics[1]); + token = address(uint160(uint256(log.topics[2]))); + (amount, to) = abi.decode(log.data, (uint256, address)); + } function handleDeposit(address token, uint256 amount) internal override { IERC20(token).safeTransferFrom(msg.sender, address(this), amount); @@ -25,6 +43,25 @@ contract BridgeDepositWithdraw is Bridge, IBridgeDepositWithdraw { } } + function claim(PodECDSA.CertifiedLog calldata certifiedLog) public whenNotPaused { + (uint256 id, address token, uint256 amount, address to) = _decodeLog(certifiedLog.log); + address mirrorToken = mirrorTokens[token]; + if (mirrorToken == address(0)) revert MirrorTokenNotFound(); + + if (!_isValidTokenAmount(mirrorToken, amount, false)) revert InvalidTokenAmount(); + + bytes32 requestId = _hashRequest(id, token, amount, to); + if (processedRequests[requestId]) revert RequestAlreadyProcessed(); + + bool verified = PodECDSA.verifyCertifiedLog(podConfig, certifiedLog); + if (!verified) revert InvalidCertificate(); + + processedRequests[requestId] = true; + + IERC20(mirrorToken).safeTransfer(to, amount); + emit Claim(id, mirrorToken, token, amount, to); + } + function whiteListToken(address token, address mirrorToken, TokenLimits calldata limits) external onlyRole(DEFAULT_ADMIN_ROLE) diff --git a/protocol/src/BridgeMintBurn.sol b/protocol/src/BridgeMintBurn.sol index 0cda3e8a..24d91d16 100644 --- a/protocol/src/BridgeMintBurn.sol +++ b/protocol/src/BridgeMintBurn.sol @@ -8,46 +8,107 @@ import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol import {IAccessControl} from "@openzeppelin/contracts/access/IAccessControl.sol"; import {IERC20MintableAndBurnable} from "./interfaces/IERC20MintableAndBurnable.sol"; import {WrappedToken} from "./WrappedToken.sol"; +import {console} from "forge-std/console.sol"; contract BridgeMintBurn is Bridge, IBridgeMintBurn { using SafeERC20 for IERC20; - bytes32 constant TOKEN_PAUSER_ROLE = keccak256("PAUSER_ROLE"); - bytes32 constant TOKEN_MINTER_ROLE = keccak256("MINTER_ROLE"); + bytes32 constant MINTER_ROLE = keccak256("MINTER_ROLE"); + address constant ETH_EXTERNAL_ETH_GET_LOGS_PRECOMPILE = + address(uint160(uint256(keccak256("ETH_EXTERNAL_ETH_GET_LOGS")))); + uint96 constant SOURCE_CHAIN_ID = 1; + bytes constant FINALIZED_BLOCK_BYTES = hex"66696e616c697a6564"; - constructor() Bridge() {} + struct EthGetLogsArgs { + bytes fromBlock; + bytes toBlock; + address addr; + bytes32 blockHash; + bytes32[] topics; + } + + struct ExternalEthGetLogsArgs { + uint256 chainId; + EthGetLogsArgs ethGetLogsArgs; + } + + struct RpcLog { + address addr; + bytes32[] topics; + bytes data; + bytes blockNumber; + bytes32 transactionHash; + bytes transactionIndex; + bytes32 blockHash; + bytes logIndex; + bool removed; + } + + constructor() {} function handleDeposit(address token, uint256 amount) internal override { IERC20MintableAndBurnable(token).burnFrom(msg.sender, amount); } - function handleBridging(address token, uint256 amount, address to, bytes calldata data) internal override { - IERC20MintableAndBurnable(token).mint(to, amount); + function claim(uint256 id, address token, bytes calldata blockNumberFrom) public whenNotPaused { + bytes32[] memory topics = new bytes32[](3); + topics[0] = DEPOSIT_TOPIC_0; + topics[1] = bytes32(id); + topics[2] = bytes32(uint256(uint160(token))); + + (bool success, bytes memory output) = ETH_EXTERNAL_ETH_GET_LOGS_PRECOMPILE.staticcall( + abi.encode( + ExternalEthGetLogsArgs( + SOURCE_CHAIN_ID, + EthGetLogsArgs(blockNumberFrom, FINALIZED_BLOCK_BYTES, address(token), bytes32(0), topics) + ) + ) + ); + if (!success) revert PrecompileCallFailed(); + + RpcLog[] memory logs = abi.decode(output, (RpcLog[])); + + if (logs.length == 0) revert NoDepositsFound(); + if (logs.length > 1) revert MultipleDepositsWithSameId(); + + (uint256 decodedAmount, address decodedTo) = abi.decode(logs[0].data, (uint256, address)); + + address mirrorToken = mirrorTokens[token]; + if (mirrorToken == address(0)) revert MirrorTokenNotFound(); + + console.log("mirrorToken"); + console.logAddress(mirrorToken); + console.log("decodedAmount"); + console.logUint(decodedAmount); + console.log("decodedTo"); + console.logAddress(decodedTo); + + if (!_isValidTokenAmount(mirrorToken, decodedAmount, false)) revert InvalidTokenAmount(); + + bytes32 requestId = _hashRequest(id, token, decodedAmount, decodedTo); + + if (processedRequests[requestId]) revert RequestAlreadyProcessed(); + + processedRequests[requestId] = true; + + IERC20MintableAndBurnable(mirrorToken).mint(decodedTo, decodedAmount); + + emit Claim(id, mirrorToken, token, decodedAmount, decodedTo); } function handleMigrate(address _newContract) internal override { - // Transfer ownership of all the token contracts to the new address. for (uint256 i = 0; i < whitelistedTokens.length; i++) { address token = whitelistedTokens[i]; - // Grant the new contracts all the roles. IAccessControl(token).grantRole(DEFAULT_ADMIN_ROLE, _newContract); - IAccessControl(token).grantRole(TOKEN_MINTER_ROLE, _newContract); - IAccessControl(token).grantRole(TOKEN_PAUSER_ROLE, _newContract); + IAccessControl(token).grantRole(MINTER_ROLE, _newContract); + IAccessControl(token).grantRole(PAUSER_ROLE, _newContract); - // Renounce all roles from the existing contract. IAccessControl(token).renounceRole(DEFAULT_ADMIN_ROLE, address(this)); - IAccessControl(token).renounceRole(TOKEN_MINTER_ROLE, address(this)); - IAccessControl(token).renounceRole(TOKEN_PAUSER_ROLE, address(this)); + IAccessControl(token).renounceRole(MINTER_ROLE, address(this)); + IAccessControl(token).renounceRole(PAUSER_ROLE, address(this)); } } - function whitelistToken(address token, address mirrorToken, TokenLimits calldata limits) - external - onlyRole(DEFAULT_ADMIN_ROLE) - { - uint256 a = 5; - } - function createAndWhitelistMirrorToken( string memory tokenName, string memory tokenSymbol, diff --git a/protocol/src/WrappedToken.sol b/protocol/src/WrappedToken.sol index a2f34f3f..6ac736b4 100644 --- a/protocol/src/WrappedToken.sol +++ b/protocol/src/WrappedToken.sol @@ -8,25 +8,25 @@ import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; contract WrappedToken is ERC20Burnable, ERC20Pausable, AccessControl { bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE"); - bytes32 public constant PAUSE_ROLE = keccak256("PAUSE_ROLE"); - uint8 private immutable _decimals; + bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE"); + uint8 private immutable DECIMALS; constructor(string memory name_, string memory symbol_, uint8 decimals_) ERC20(name_, symbol_) { - _decimals = decimals_; + DECIMALS = decimals_; _grantRole(DEFAULT_ADMIN_ROLE, msg.sender); - _grantRole(PAUSE_ROLE, msg.sender); + _grantRole(PAUSER_ROLE, msg.sender); _grantRole(MINTER_ROLE, msg.sender); } function decimals() public view override returns (uint8) { - return _decimals; + return DECIMALS; } function mint(address to, uint256 amount) external onlyRole(MINTER_ROLE) { _mint(to, amount); // will revert when paused because ERC20Pausable guards _update } - function pause() external onlyRole(PAUSE_ROLE) { + function pause() external onlyRole(PAUSER_ROLE) { _pause(); } diff --git a/protocol/src/abstract/Bridge.sol b/protocol/src/abstract/Bridge.sol index 23d5651d..b5a7a2c4 100644 --- a/protocol/src/abstract/Bridge.sol +++ b/protocol/src/abstract/Bridge.sol @@ -6,12 +6,15 @@ import {AccessControl} from "@openzeppelin/contracts/access/AccessControl.sol"; import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import {Pausable} from "@openzeppelin/contracts/utils/Pausable.sol"; +import {console} from "forge-std/console.sol"; abstract contract Bridge is IBridge, AccessControl, Pausable { using SafeERC20 for IERC20; /// @dev The role ID for addresses that can pause the contract. - bytes32 public constant PAUSE_ROLE = keccak256("PAUSE_ROLE"); + bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE"); + /// @dev The topic 0 (event signature) of the deposit event. + bytes32 constant DEPOSIT_TOPIC_0 = keccak256("Deposit(uint256,address,uint256,address)"); /// @dev Map token address to token info. mapping(address => TokenData) public tokenData; @@ -19,6 +22,9 @@ abstract contract Bridge is IBridge, AccessControl, Pausable { /// @dev Map mirror token address to token address. mapping(address => address) public mirrorTokens; + /// @dev Map request hash to processed requests. + mapping(bytes32 => bool) public processedRequests; + /// @dev Array of all the whitelisted tokens. /// @notice A token in the list might not be active. address[] public whitelistedTokens; @@ -31,10 +37,10 @@ abstract contract Bridge is IBridge, AccessControl, Pausable { constructor() { _grantRole(DEFAULT_ADMIN_ROLE, msg.sender); + _grantRole(PAUSER_ROLE, msg.sender); } function handleDeposit(address token, uint256 amount) internal virtual; - function handleBridging(address token, uint256 amount, address to, bytes calldata data) internal virtual; function handleMigrate(address _newContract) internal virtual; /// @dev Modifier to check that contract is not already migrated. @@ -45,13 +51,15 @@ abstract contract Bridge is IBridge, AccessControl, Pausable { _; } - /// @dev Modifier to make a function callable only when the token and amount is correct. - modifier isValidTokenAmount(address token, uint256 amount, bool isDeposit) { + function _isValidTokenAmount(address token, uint256 amount, bool isDeposit) internal returns (bool) { TokenData storage t = tokenData[token]; - if (isDeposit && t.limits.deposit != 0) { - // Reset daily limit if the day is passed after last update. - if (block.timestamp > t.deposit.lastUpdated + 1 days) { + if (t.limits.minAmount == 0 || amount < t.limits.minAmount) { + return false; + } + + if (isDeposit) { + if (block.timestamp >= t.deposit.lastUpdated + 1 days) { t.deposit.lastUpdated = block.timestamp; t.deposit.consumed = 0; } @@ -60,34 +68,37 @@ abstract contract Bridge is IBridge, AccessControl, Pausable { revert DailyLimitExhausted(); } t.deposit.consumed += amount; - } else if (!isDeposit && t.limits.withdraw != 0) { - if (block.timestamp > t.withdraw.lastUpdated + 1 days) { - t.withdraw.lastUpdated = block.timestamp; - t.withdraw.consumed = 0; + } else if (!isDeposit) { + if (block.timestamp >= t.claim.lastUpdated + 1 days) { + t.claim.lastUpdated = block.timestamp; + t.claim.consumed = 0; } - if (t.withdraw.consumed + amount > t.limits.withdraw) { + if (t.claim.consumed + amount > t.limits.claim) { revert DailyLimitExhausted(); } - t.withdraw.consumed += amount; + t.claim.consumed += amount; } - _; + return true; } - function deposit(address token, uint256 amount, address to) - external - whenNotPaused - isValidTokenAmount(token, amount, true) - returns (uint256 id) - { + function deposit(address token, uint256 amount, address to) external whenNotPaused returns (uint256 id) { + if (!_isValidTokenAmount(token, amount, true)) revert InvalidTokenAmount(); if (to == address(0)) revert InvalidToAddress(); id = depositIndex++; handleDeposit(token, amount); emit Deposit(id, token, amount, to); } - function _hashRequest(uint256 id, address token, uint256 amount, address to) internal pure returns (bytes32) { - return keccak256(abi.encodePacked(id, token, amount, to)); + function _hashRequest(uint256 id, address token, uint256 amount, address to) internal pure returns (bytes32 hash) { + assembly { + let ptr := mload(0x40) + mstore(ptr, id) + mstore(add(ptr, 0x20), shl(96, token)) + mstore(add(ptr, 0x34), amount) + mstore(add(ptr, 0x54), shl(96, to)) + hash := keccak256(ptr, 0x68) + } } function _configureTokenData(address token, TokenLimits calldata limits, bool newToken) internal { @@ -97,9 +108,9 @@ abstract contract Bridge is IBridge, AccessControl, Pausable { } TokenUsage memory depositUsage = TokenUsage(0, block.timestamp); - TokenUsage memory withdrawUsage = TokenUsage(0, block.timestamp); + TokenUsage memory claimUsage = TokenUsage(0, block.timestamp); // configuring token also resets the daily volume limit - TokenData memory data = TokenData(limits, depositUsage, withdrawUsage); + TokenData memory data = TokenData(limits, depositUsage, claimUsage); tokenData[token] = data; } @@ -123,7 +134,7 @@ abstract contract Bridge is IBridge, AccessControl, Pausable { } /// @inheritdoc IBridge - function pause() external onlyRole(PAUSE_ROLE) { + function pause() external onlyRole(PAUSER_ROLE) { _pause(); } diff --git a/protocol/src/interfaces/IBridge.sol b/protocol/src/interfaces/IBridge.sol index 6fa27c88..3e8d2eae 100644 --- a/protocol/src/interfaces/IBridge.sol +++ b/protocol/src/interfaces/IBridge.sol @@ -11,14 +11,16 @@ interface IBridge { error InvalidToAddress(); error InvalidTokenConfig(); error DailyLimitExhausted(); + error MirrorTokenNotFound(); + error RequestAlreadyProcessed(); event Deposit(uint256 indexed id, address indexed token, uint256 amount, address to); - event Withdraw(uint256 indexed id, address indexed mirrorToken, address indexed token, uint256 amount, address to); + event Claim(uint256 indexed id, address indexed mirrorToken, address indexed token, uint256 amount, address to); struct TokenLimits { uint256 minAmount; // The minimum amount of tokens that can be deposited. uint256 deposit; // The daily deposit limit for the token. - uint256 withdraw; // The daily withdrawal limit for the token. + uint256 claim; // The daily claim limit for the token. } struct TokenUsage { @@ -29,7 +31,7 @@ interface IBridge { struct TokenData { TokenLimits limits; TokenUsage deposit; - TokenUsage withdraw; + TokenUsage claim; } /// @dev Request information. diff --git a/protocol/src/interfaces/IBridgeDepositWithdraw.sol b/protocol/src/interfaces/IBridgeDepositWithdraw.sol index 8187919a..cc3a5567 100644 --- a/protocol/src/interfaces/IBridgeDepositWithdraw.sol +++ b/protocol/src/interfaces/IBridgeDepositWithdraw.sol @@ -5,4 +5,7 @@ import {IBridge} from "./IBridge.sol"; interface IBridgeDepositWithdraw is IBridge { function whiteListToken(address token, address mirrorToken, TokenLimits calldata limits) external; + + error InvalidDepositLog(); + error InvalidCertificate(); } diff --git a/protocol/src/interfaces/IBridgeMintBurn.sol b/protocol/src/interfaces/IBridgeMintBurn.sol index 6add935a..f0392f1d 100644 --- a/protocol/src/interfaces/IBridgeMintBurn.sol +++ b/protocol/src/interfaces/IBridgeMintBurn.sol @@ -4,7 +4,7 @@ pragma solidity ^0.8.20; import {IBridge} from "./IBridge.sol"; interface IBridgeMintBurn is IBridge { - function createMirrorToken( + function createAndWhitelistMirrorToken( string memory tokenName, string memory tokenSymbol, address existingToken, @@ -12,4 +12,8 @@ interface IBridgeMintBurn is IBridge { uint8 mirrorTokenDecimals, TokenLimits calldata limits ) external returns (address); + + error MultipleDepositsWithSameId(); + error NoDepositsFound(); + error PrecompileCallFailed(); } diff --git a/protocol/test/BridgeDepositWithdraw.t.sol b/protocol/test/BridgeDepositWithdraw.t.sol new file mode 100644 index 00000000..b6bc241a --- /dev/null +++ b/protocol/test/BridgeDepositWithdraw.t.sol @@ -0,0 +1,281 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +import {BridgeBehaviorTest} from "./abstract/Bridge.t.sol"; +import {BridgeDepositWithdraw} from "../src/BridgeDepositWithdraw.sol"; +import {IBridgeDepositWithdraw} from "../src/interfaces/IBridgeDepositWithdraw.sol"; +import {IBridge} from "../src/interfaces/IBridge.sol"; +import {Bridge} from "../src/abstract/Bridge.sol"; +import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import {IPodRegistry} from "../src/interfaces/IPodRegistry.sol"; +import {PodRegistry} from "../src/PodRegistry.sol"; +import {PodECDSA} from "pod-sdk/verifier/PodECDSA.sol"; +import {ECDSA} from "pod-sdk/verifier/ECDSA.sol"; +import {MerkleTree} from "pod-sdk/verifier/MerkleTree.sol"; +import {WrappedToken} from "../src/WrappedToken.sol"; +import {Pausable} from "@openzeppelin/contracts/utils/Pausable.sol"; + +contract BridgeDepositWithdrawTest is BridgeBehaviorTest { + BridgeDepositWithdraw private _bridge; + WrappedToken private _token; + IPodRegistry podRegistry; + uint256[] validatorPrivateKeys; + uint256 constant NUMBER_OF_VALIDATORS = 4; + address immutable MIRROR_TOKEN = makeAddr("mirrorToken"); + + function bridge() internal view override returns (Bridge) { + return _bridge; + } + + function token() internal view override returns (IERC20) { + return _token; + } + + function setUpSuite() public override { + vm.startPrank(admin); + address[] memory initialValidators = new address[](NUMBER_OF_VALIDATORS); + + validatorPrivateKeys = new uint256[](NUMBER_OF_VALIDATORS); + + for (uint256 i = 0; i < NUMBER_OF_VALIDATORS; i++) { + validatorPrivateKeys[i] = uint256(i + 1); + initialValidators[i] = vm.addr(validatorPrivateKeys[i]); + } + + podRegistry = new PodRegistry(initialValidators); + _bridge = new BridgeDepositWithdraw(address(podRegistry)); + _token = new WrappedToken("InitialToken", "ITKN", 18); + _token.mint(user, INITIAL_BALANCE); + _token.mint(admin, INITIAL_BALANCE); + _token.approve(address(_bridge), type(uint256).max); + _bridge.whiteListToken(address(_token), MIRROR_TOKEN, tokenLimits); + + vm.stopPrank(); + + vm.prank(user); + _token.approve(address(_bridge), type(uint256).max); + } + + function test_Deposit_TransfersIntoBridge() public { + uint256 ub = _token.balanceOf(user); + uint256 bb = _token.balanceOf(address(_bridge)); + vm.prank(user); + _bridge.deposit(address(_token), DEPOSIT_AMOUNT, recipient); + assertEq(_token.balanceOf(user), ub - DEPOSIT_AMOUNT); + assertEq(_token.balanceOf(address(_bridge)), bb + DEPOSIT_AMOUNT); + } + + function test_Claim() public { + vm.prank(admin); + _bridge.deposit(address(_token), DEPOSIT_AMOUNT, recipient); + + vm.prank(user); + PodECDSA.CertifiedLog memory certifiedLog = createCertifiedLog(3); + assertEq(_token.balanceOf(recipient), 0); + assertEq(_token.balanceOf(address(_bridge)), DEPOSIT_AMOUNT); + vm.expectEmit(true, true, true, true); + emit IBridge.Claim(0, address(_token), MIRROR_TOKEN, DEPOSIT_AMOUNT, recipient); + _bridge.claim(certifiedLog); + assertEq(_token.balanceOf(recipient), DEPOSIT_AMOUNT); + assertEq(_token.balanceOf(address(_bridge)), 0); + + (, IBridge.TokenUsage memory depositUsage, IBridge.TokenUsage memory claimUsage) = + bridge().tokenData(address(_token)); + assertEq(depositUsage.consumed, DEPOSIT_AMOUNT); + assertEq(claimUsage.consumed, DEPOSIT_AMOUNT); + } + + function test_Claim_RevertIfInvalidCertificate() public { + // not enough signatures + PodECDSA.CertifiedLog memory certifiedLog = createCertifiedLog(2); + vm.expectRevert(abi.encodeWithSelector(IBridgeDepositWithdraw.InvalidCertificate.selector)); + _bridge.claim(certifiedLog); + + // invalid leaf + certifiedLog = createCertifiedLog(3); + certifiedLog.certificate.leaf = bytes32(0); + vm.expectRevert(abi.encodeWithSelector(IBridgeDepositWithdraw.InvalidCertificate.selector)); + _bridge.claim(certifiedLog); + + // tampered proof + certifiedLog = createCertifiedLog(3); + certifiedLog.certificate.proof.path[0] = bytes32(uint256(1232)); + vm.expectRevert(abi.encodeWithSelector(IBridgeDepositWithdraw.InvalidCertificate.selector)); + _bridge.claim(certifiedLog); + } + + function test_Claim_RevertIfAlreadyClaimed() public { + vm.prank(admin); + _bridge.deposit(address(_token), DEPOSIT_AMOUNT, recipient); + PodECDSA.CertifiedLog memory certifiedLog = createCertifiedLog(3); + _bridge.claim(certifiedLog); + vm.expectRevert(abi.encodeWithSelector(IBridge.RequestAlreadyProcessed.selector)); + _bridge.claim(certifiedLog); + } + + function test_Claim_RevertIfInvalidDepositLog() public { + PodECDSA.CertifiedLog memory certifiedLog = createCertifiedLog(3); + certifiedLog.log.topics[0] = bytes32(uint256(1232)); + vm.expectRevert(abi.encodeWithSelector(IBridgeDepositWithdraw.InvalidDepositLog.selector)); + _bridge.claim(certifiedLog); + + certifiedLog = createCertifiedLog(3); + certifiedLog.log.topics = new bytes32[](1); + certifiedLog.log.topics[0] = bytes32(uint256(1232)); + vm.expectRevert(abi.encodeWithSelector(IBridgeDepositWithdraw.InvalidDepositLog.selector)); + _bridge.claim(certifiedLog); + } + + function test_Claim_RevertIfMirrorTokenNotFound() public { + PodECDSA.CertifiedLog memory certifiedLog = createCertifiedLog(3); + certifiedLog.log.topics[2] = bytes32(uint256(0xBEEF)); + vm.expectRevert(abi.encodeWithSelector(IBridge.MirrorTokenNotFound.selector)); + _bridge.claim(certifiedLog); + } + + function test_Claim_RevertIfPaused() public { + vm.prank(admin); + _bridge.pause(); + PodECDSA.CertifiedLog memory certifiedLog = createCertifiedLog(3); + vm.expectRevert(abi.encodeWithSelector(Pausable.EnforcedPause.selector)); + _bridge.claim(certifiedLog); + } + + function test_Migrate_TransfersAllTokenBalances() public { + vm.prank(user); + _bridge.deposit(address(_token), DEPOSIT_AMOUNT, recipient); + vm.prank(admin); + _bridge.pause(); + uint256 beforeAmt = _token.balanceOf(address(_bridge)); + vm.prank(admin); + _bridge.migrate(newBridge); + assertEq(_token.balanceOf(newBridge), beforeAmt); + assertEq(_token.balanceOf(address(_bridge)), 0); + } + + function test_Whitelist_RevertIfSameTokenTwiceDifferentMirror() public { + WrappedToken anotherMirror = new WrappedToken("Token", "TKN", 18); + vm.prank(admin); + vm.expectRevert(abi.encodeWithSelector(IBridge.InvalidTokenConfig.selector)); + _bridge.whiteListToken(address(_token), address(anotherMirror), tokenLimits); + } + + function test_Deposit_RevertWithoutAllowance() public { + address u = makeAddr("noapprove"); + vm.prank(admin); + _token.mint(u, DEPOSIT_AMOUNT); + vm.prank(u); + vm.expectRevert(); + _bridge.deposit(address(_token), DEPOSIT_AMOUNT, recipient); + } + + function test_Migrate_NoWhitelistedTokens() public { + vm.prank(admin); + BridgeDepositWithdraw fresh = new BridgeDepositWithdraw(address(podRegistry)); + vm.prank(admin); + fresh.pause(); + vm.prank(admin); + fresh.migrate(newBridge); + assertEq(fresh.migratedContract(), newBridge); + } + + function test_Migrate_SkipsZeroBalanceTokens() public { + WrappedToken t2 = new WrappedToken("Token", "TKN", 18); + WrappedToken m2 = new WrappedToken("Mirror", "MRR", 18); + vm.prank(admin); + _bridge.whiteListToken(address(t2), address(m2), tokenLimits); + vm.prank(user); + _token.approve(address(_bridge), type(uint256).max); + vm.prank(user); + _bridge.deposit(address(_token), DEPOSIT_AMOUNT, address(1)); + vm.prank(admin); + _bridge.pause(); + vm.prank(admin); + _bridge.migrate(newBridge); + assertEq(_token.balanceOf(newBridge), DEPOSIT_AMOUNT); + assertEq(t2.balanceOf(newBridge), 0); + } + + function test_WhitelistedTokens_ListGrowsAndOrder() public { + WrappedToken t2 = new WrappedToken("Token", "TKN", 18); + WrappedToken m2 = new WrappedToken("Mirror", "MRR", 18); + vm.prank(admin); + _bridge.whiteListToken(address(t2), address(m2), tokenLimits); + assertEq(_bridge.whitelistedTokens(0), address(_token)); + assertEq(_bridge.whitelistedTokens(1), address(t2)); + } + + function test_MultiToken_DepositTracksUsageSeparately() public { + address t2 = address(0xB0B2); + WrappedToken t2Mock = new WrappedToken("Token", "TKN", 18); + vm.prank(admin); + _bridge.whiteListToken( + t2, + address(t2Mock), + IBridge.TokenLimits({ + minAmount: tokenLimits.minAmount, + deposit: tokenLimits.deposit, + claim: tokenLimits.claim + }) + ); + + vm.prank(user); + bridge().deposit(address(token()), tokenLimits.minAmount, recipient); + (, IBridge.TokenUsage memory dep1,) = bridge().tokenData(address(token())); + assertEq(dep1.consumed, tokenLimits.minAmount); + + (, IBridge.TokenUsage memory dep2,) = bridge().tokenData(t2); + assertEq(dep2.consumed, 0); + } + + function createCertifiedLog(uint256 numberOfRequiredSignatures) + internal + view + returns (PodECDSA.CertifiedLog memory) + { + bytes32 receiptRoot = 0xca35a1783abe48ca23da757fb7253a1315777b4e8820262c67e85e6f87eb340f; + bytes32[] memory topics = new bytes32[](3); + topics[0] = keccak256("Deposit(uint256,address,uint256,address)"); + topics[1] = bytes32(uint256(0)); + topics[2] = bytes32(uint256(uint160(MIRROR_TOKEN))); + + bytes memory data = abi.encode(DEPOSIT_AMOUNT, recipient); + + bytes32[] memory merklePath = new bytes32[](4); + + merklePath[0] = 0x8a998be39bd3962defce6fb56ba8a10da89ae208743fa4147503adebfb32005d; + merklePath[1] = 0x2498e05df11f1325b6f78c1d181cb7db187233732812af1f16efe9a129abe618; + merklePath[2] = 0xaae4eb6d4b3989ffc690c918484b530f4d853427b635b39e8f70975dd7cbff1b; + merklePath[3] = 0x996db2475c7d59b0652b50c24aeca2454967b3e7101a667e2ce9d03567202483; + + bytes[] memory signatures = new bytes[](numberOfRequiredSignatures); + uint256[] memory sortedAttestationTimestamps = new uint256[](numberOfRequiredSignatures); + for (uint256 i = 0; i < numberOfRequiredSignatures; i++) { + (uint8 v, bytes32 r, bytes32 s) = vm.sign(validatorPrivateKeys[i], receiptRoot); + signatures[i] = ECDSA._serialize_signature(v, r, s); + sortedAttestationTimestamps[i] = i + 1; + } + + bytes memory aggregateSignature = ECDSA.aggregate_signatures(signatures); + + PodECDSA.CertifiedReceipt memory certifiedReceipt = PodECDSA.CertifiedReceipt({ + receiptRoot: receiptRoot, + aggregateSignature: aggregateSignature, + sortedAttestationTimestamps: sortedAttestationTimestamps + }); + + PodECDSA.Log memory log = PodECDSA.Log({addr: address(_bridge), topics: topics, data: data}); + + bytes32 logHash = PodECDSA.hashLog(log); + bytes32 leaf = MerkleTree.hashLeaf(bytes("log_hashes[1]"), logHash); + MerkleTree.Proof memory proof = MerkleTree.Proof({path: merklePath}); + + PodECDSA.CertifiedLog memory certifiedLog = PodECDSA.CertifiedLog({ + log: log, + logIndex: 1, + certificate: PodECDSA.Certificate({leaf: leaf, certifiedReceipt: certifiedReceipt, proof: proof}) + }); + + return certifiedLog; + } +} diff --git a/protocol/test/BridgeMintBurn.t.sol b/protocol/test/BridgeMintBurn.t.sol new file mode 100644 index 00000000..aeeb499c --- /dev/null +++ b/protocol/test/BridgeMintBurn.t.sol @@ -0,0 +1,218 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +import {BridgeBehaviorTest} from "./abstract/Bridge.t.sol"; +import {BridgeMintBurn} from "../src/BridgeMintBurn.sol"; +import {IBridgeMintBurn} from "../src/interfaces/IBridgeMintBurn.sol"; +import {IBridge} from "../src/interfaces/IBridge.sol"; +import {Bridge} from "../src/abstract/Bridge.sol"; +import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import {WrappedToken} from "../src/WrappedToken.sol"; +import {MerkleTree} from "pod-sdk/verifier/MerkleTree.sol"; +import {Pausable} from "@openzeppelin/contracts/utils/Pausable.sol"; + +contract BridgeMintBurnTest is BridgeBehaviorTest { + BridgeMintBurn private _bridge; + WrappedToken private _token; + address immutable _mirror = makeAddr("mirrorToken"); + + function bridge() internal view override returns (Bridge) { + return _bridge; + } + + function token() internal view override returns (IERC20) { + return _token; + } + + function setUpSuite() public override { + vm.startPrank(admin); + _bridge = new BridgeMintBurn(); + + _token = WrappedToken( + _bridge.createAndWhitelistMirrorToken("Token", "TKN", address(0), address(_mirror), 18, tokenLimits) + ); + vm.stopPrank(); + + vm.prank(address(_bridge)); + _token.mint(user, INITIAL_BALANCE); + + vm.prank(user); + _token.approve(address(_bridge), type(uint256).max); + } + + function test_Deposit_BurnsFromUser() public { + uint256 ub = _token.balanceOf(user); + uint256 ts = _token.totalSupply(); + vm.prank(user); + bridge().deposit(address(_token), DEPOSIT_AMOUNT, recipient); + assertEq(_token.balanceOf(user), ub - DEPOSIT_AMOUNT); + assertEq(_token.totalSupply(), ts - DEPOSIT_AMOUNT); + } + + function test_Claim_SingleLog_MintsToRecipient() public { + BridgeMintBurn.RpcLog[] memory logs = new BridgeMintBurn.RpcLog[](1); + logs[0] = _makeLog(0, _mirror, DEPOSIT_AMOUNT, recipient); + _mockEthGetLogs(0, bytes("0x1"), _mirror, logs); + assertEq(_token.balanceOf(recipient), 0); + + vm.expectEmit(true, true, true, true); + emit IBridge.Claim(0, address(_token), _mirror, DEPOSIT_AMOUNT, recipient); + _bridge.claim(0, _mirror, bytes("0x1")); + + assertEq(_token.balanceOf(recipient), DEPOSIT_AMOUNT); + + (, IBridge.TokenUsage memory depositUsage, IBridge.TokenUsage memory claimUsage) = + bridge().tokenData(address(_token)); + + assertEq(depositUsage.consumed, 0); + assertEq(claimUsage.consumed, DEPOSIT_AMOUNT); + } + + function test_Claim_RevertIfDailyLimitExhausted() public { + BridgeMintBurn.RpcLog[] memory logs = new BridgeMintBurn.RpcLog[](1); + logs[0] = _makeLog(0, _mirror, tokenLimits.claim + 1, recipient); + _mockEthGetLogs(0, bytes("0x1"), _mirror, logs); + vm.expectRevert(abi.encodeWithSelector(IBridge.DailyLimitExhausted.selector)); + _bridge.claim(0, _mirror, bytes("0x1")); + } + + function test_Claim_RevertIfDailyLimitExhausted_ButSucceedAfterOneDay() public { + BridgeMintBurn.RpcLog[] memory logs = new BridgeMintBurn.RpcLog[](1); + logs[0] = _makeLog(0, _mirror, DEPOSIT_AMOUNT, recipient); + _mockEthGetLogs(0, bytes("0x1"), _mirror, logs); + _bridge.claim(0, _mirror, bytes("0x1")); + logs[0] = _makeLog(1, _mirror, tokenLimits.claim, recipient); + _mockEthGetLogs(1, bytes("0x1"), _mirror, logs); + vm.expectRevert(abi.encodeWithSelector(IBridge.DailyLimitExhausted.selector)); + _bridge.claim(1, _mirror, bytes("0x1")); + vm.warp(block.timestamp + 1 days + 1); + _mockEthGetLogs(1, bytes("0x1"), _mirror, logs); + _bridge.claim(1, _mirror, bytes("0x1")); + } + + function test_Claim_RevertIfNoDepositsFound() public { + BridgeMintBurn.RpcLog[] memory logs = new BridgeMintBurn.RpcLog[](0); + _mockEthGetLogs(0, bytes("0x1"), _mirror, logs); + vm.expectRevert(abi.encodeWithSelector(IBridgeMintBurn.NoDepositsFound.selector)); + _bridge.claim(0, _mirror, bytes("0x1")); + } + + function test_Claim_RevertIfMultipleDepositsFound() public { + BridgeMintBurn.RpcLog[] memory logs = new BridgeMintBurn.RpcLog[](2); + logs[0] = _makeLog(0, _mirror, DEPOSIT_AMOUNT, recipient); + logs[1] = _makeLog(0, _mirror, DEPOSIT_AMOUNT, recipient); + _mockEthGetLogs(0, bytes("0x1"), _mirror, logs); + vm.expectRevert(abi.encodeWithSelector(IBridgeMintBurn.MultipleDepositsWithSameId.selector)); + _bridge.claim(0, _mirror, bytes("0x1")); + } + + function test_Claim_RevertIfMirrorTokenNotFound() public { + // Use a token not mapped in mirrorTokens + address unknownMirror = address(0xBEEF); + BridgeMintBurn.RpcLog[] memory logs = new BridgeMintBurn.RpcLog[](1); + logs[0] = _makeLog(0, unknownMirror, DEPOSIT_AMOUNT, recipient); + _mockEthGetLogs(0, bytes("0x1"), unknownMirror, logs); + + vm.expectRevert(abi.encodeWithSelector(IBridge.MirrorTokenNotFound.selector)); + _bridge.claim(0, unknownMirror, bytes("0x1")); + } + + function test_Claim_RevertIfAlreadyProcessed() public { + BridgeMintBurn.RpcLog[] memory logs = new BridgeMintBurn.RpcLog[](1); + logs[0] = _makeLog(0, _mirror, DEPOSIT_AMOUNT, recipient); + _mockEthGetLogs(0, bytes("0x1"), _mirror, logs); + _bridge.claim(0, _mirror, bytes("0x1")); + + // Mock again with same log so requestId is identical + _mockEthGetLogs(0, bytes("0x1"), _mirror, logs); + vm.expectRevert(abi.encodeWithSelector(IBridge.RequestAlreadyProcessed.selector)); + _bridge.claim(0, _mirror, bytes("0x1")); + } + + function test_Claim_RevertIfPaused() public { + vm.prank(admin); + _bridge.pause(); + vm.expectRevert(abi.encodeWithSelector(Pausable.EnforcedPause.selector)); + _bridge.claim(0, _mirror, bytes("0x1")); + } + + function test_Claim_RevertIfPrecompileCallFails() public { + BridgeMintBurn.ExternalEthGetLogsArgs memory args = _buildArgs(0, bytes("0x1"), _mirror); + podMockEthGetLogsRevert(abi.encode(args)); + + vm.expectRevert(abi.encodeWithSelector(IBridgeMintBurn.PrecompileCallFailed.selector)); + _bridge.claim(0, _mirror, bytes("0x1")); + } + + function test_Migrate_TransfersRolesToNewBridge() public { + vm.prank(admin); + _bridge.pause(); + vm.prank(admin); + _bridge.migrate(newBridge); + + // New bridge gains roles + assertTrue(_token.hasRole(_token.DEFAULT_ADMIN_ROLE(), newBridge)); + assertTrue(_token.hasRole(_token.MINTER_ROLE(), newBridge)); + assertTrue(_token.hasRole(_token.PAUSER_ROLE(), newBridge)); + // Old bridge renounces roles + assertFalse(_token.hasRole(_token.DEFAULT_ADMIN_ROLE(), address(_bridge))); + assertFalse(_token.hasRole(_token.MINTER_ROLE(), address(_bridge))); + assertFalse(_token.hasRole(_token.PAUSER_ROLE(), address(_bridge))); + } + + function test_CreateAndWhitelistMirrorToken_NewOrExisting() public { + address nonExisting = address(0x1234); + vm.prank(admin); + address created = + _bridge.createAndWhitelistMirrorToken("Token", "TKN", address(0), address(nonExisting), 18, tokenLimits); + assertTrue(created != address(0)); + } + + // ---------- Helpers for building logs ---------- + function _buildArgs(uint256 id, bytes memory fromBlock, address tokenAddr) + internal + pure + returns (BridgeMintBurn.ExternalEthGetLogsArgs memory) + { + BridgeMintBurn.EthGetLogsArgs memory inner = BridgeMintBurn.EthGetLogsArgs({ + fromBlock: fromBlock, + toBlock: hex"66696e616c697a6564", + addr: tokenAddr, + blockHash: bytes32(0), + topics: _buildTopics(id, tokenAddr) + }); + return BridgeMintBurn.ExternalEthGetLogsArgs({chainId: 1, ethGetLogsArgs: inner}); + } + + function _mockEthGetLogs(uint256 id, bytes memory fromBlock, address tokenAddr, BridgeMintBurn.RpcLog[] memory logs) + internal + { + BridgeMintBurn.ExternalEthGetLogsArgs memory args = _buildArgs(id, fromBlock, tokenAddr); + podMockEthGetLogs(abi.encode(args), abi.encode(logs)); + } + + function _buildTopics(uint256 id, address tokenAddr) internal pure returns (bytes32[] memory topics) { + topics = new bytes32[](3); + topics[0] = keccak256("Deposit(uint256,address,uint256,address)"); + topics[1] = bytes32(id); + topics[2] = bytes32(uint256(uint160(tokenAddr))); + } + + function _makeLog(uint256 id, address tokenAddr, uint256 amount, address to) + internal + pure + returns (BridgeMintBurn.RpcLog memory) + { + return BridgeMintBurn.RpcLog({ + addr: tokenAddr, + topics: _buildTopics(id, tokenAddr), + data: abi.encode(amount, to), + blockNumber: bytes(""), + transactionHash: bytes32(0), + transactionIndex: bytes(""), + blockHash: bytes32(0), + logIndex: bytes(""), + removed: false + }); + } +} diff --git a/protocol/test/abstract/Bridge.t.sol b/protocol/test/abstract/Bridge.t.sol new file mode 100644 index 00000000..52f8bea4 --- /dev/null +++ b/protocol/test/abstract/Bridge.t.sol @@ -0,0 +1,199 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +import {PodTest} from "pod-sdk/test/PodTest.sol"; +import {Bridge} from "../../src/abstract/Bridge.sol"; +import {IBridge} from "../../src/interfaces/IBridge.sol"; +import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import {Pausable} from "@openzeppelin/contracts/utils/Pausable.sol"; + +abstract contract BridgeBehaviorTest is PodTest { + address public admin = makeAddr("admin"); + address public user = makeAddr("user"); + address public recipient = makeAddr("recipient"); + address public newBridge = makeAddr("newBridge"); + + uint256 public constant INITIAL_BALANCE = 1000e18; + uint256 public constant DEPOSIT_AMOUNT = 100e18; + + IBridge.TokenLimits public tokenLimits; + + // Hooks each concrete suite must implement + function bridge() internal view virtual returns (Bridge); + function token() internal view virtual returns (IERC20); + function setUpSuite() public virtual; + + function setUp() public virtual { + tokenLimits = IBridge.TokenLimits({minAmount: 1e18, deposit: 500e18, claim: 400e18}); + setUpSuite(); + } + + // Common tests + function test_Deposit_EmitsEvent() public { + vm.prank(user); + vm.expectEmit(true, true, false, true); + emit IBridge.Deposit(0, address(token()), DEPOSIT_AMOUNT, recipient); + bridge().deposit(address(token()), DEPOSIT_AMOUNT, recipient); + } + + function test_Deposit_MinAndDailyLimit() public { + vm.prank(user); + vm.expectRevert(abi.encodeWithSelector(IBridge.InvalidTokenAmount.selector)); + bridge().deposit(address(token()), tokenLimits.minAmount - 1, recipient); + + vm.prank(user); + vm.expectRevert(abi.encodeWithSelector(IBridge.DailyLimitExhausted.selector)); + bridge().deposit(address(token()), tokenLimits.deposit + 1, recipient); + } + + function test_Deposit_ZeroRecipientAndPause() public { + vm.prank(user); + vm.expectRevert(abi.encodeWithSelector(IBridge.InvalidToAddress.selector)); + bridge().deposit(address(token()), DEPOSIT_AMOUNT, address(0)); + + vm.prank(admin); + bridge().pause(); + vm.prank(user); + vm.expectRevert(Pausable.EnforcedPause.selector); + bridge().deposit(address(token()), DEPOSIT_AMOUNT, recipient); + } + + function test_ConfigureToken() public { + IBridge.TokenLimits memory nl = IBridge.TokenLimits({minAmount: 2e18, deposit: 2000e18, claim: 2000e18}); + vm.prank(admin); + bridge().configureToken(address(token()), nl); + (IBridge.TokenLimits memory limits,,) = bridge().tokenData(address(token())); + assertEq(limits.minAmount, nl.minAmount); + assertEq(limits.deposit, nl.deposit); + assertEq(limits.claim, nl.claim); + } + + function test_ConfigureToken_RevertIfNotAdmin() public { + IBridge.TokenLimits memory nl = IBridge.TokenLimits({minAmount: 2e18, deposit: 2000e18, claim: 2000e18}); + vm.prank(user); + vm.expectRevert(); + bridge().configureToken(address(token()), nl); + } + + function test_Pause_Unpause() public { + vm.prank(admin); + bridge().pause(); + assertTrue(bridge().paused()); + vm.prank(admin); + bridge().unpause(); + assertFalse(bridge().paused()); + } + + function test_Pause_RevertIfNotPauseRole() public { + vm.prank(user); + vm.expectRevert(); + bridge().pause(); + } + + function test_Migrate_SetsMigratedContract() public { + vm.prank(admin); + bridge().pause(); + vm.prank(admin); + bridge().migrate(newBridge); + assertEq(bridge().migratedContract(), newBridge); + } + + function test_Deposit_ExactlyAtMinAndLimit() public { + vm.prank(user); + bridge().deposit(address(token()), tokenLimits.minAmount, recipient); + vm.prank(user); + bridge().deposit(address(token()), tokenLimits.deposit - tokenLimits.minAmount, recipient); + } + + function test_Deposit_MultipleSameDay_TracksConsumed() public { + vm.prank(user); + bridge().deposit(address(token()), 100e18, recipient); + vm.prank(user); + bridge().deposit(address(token()), 200e18, recipient); + (, IBridge.TokenUsage memory dep,) = bridge().tokenData(address(token())); + assertEq(dep.consumed, 300e18); + } + + function test_Deposit_DailyLimitResets_AfterOneDayOnly() public { + vm.prank(user); + bridge().deposit(address(token()), tokenLimits.deposit, recipient); + vm.warp(block.timestamp + 1 days - 1); + vm.prank(user); + vm.expectRevert(abi.encodeWithSelector(IBridge.DailyLimitExhausted.selector)); + bridge().deposit(address(token()), tokenLimits.minAmount, recipient); + vm.warp(block.timestamp + 2); + vm.prank(user); + bridge().deposit(address(token()), tokenLimits.deposit, recipient); + } + + function test_Deposit_RevertIfTokenNotWhitelisted() public { + address notWhitelisted = address(0xBEEF); + vm.prank(user); + vm.expectRevert(abi.encodeWithSelector(IBridge.InvalidTokenAmount.selector)); + bridge().deposit(notWhitelisted, 1, recipient); + } + + function test_Migrate_RevertIfAlreadyMigrated() public { + vm.startPrank(admin); + bridge().pause(); + bridge().migrate(newBridge); + vm.expectRevert(abi.encodeWithSelector(IBridge.ContractMigrated.selector)); + bridge().migrate(address(0x1234)); + vm.stopPrank(); + } + + function test_Deposit_RevertAfterMigrated() public { + vm.startPrank(admin); + bridge().pause(); + bridge().migrate(newBridge); + vm.stopPrank(); + vm.prank(user); + vm.expectRevert(Pausable.EnforcedPause.selector); + bridge().deposit(address(token()), 1, recipient); + } + + function test_Pause_RoleRequired_Unpause_AdminRequired() public { + vm.prank(user); + vm.expectRevert(); + bridge().pause(); + vm.prank(admin); + bridge().pause(); + vm.prank(user); + vm.expectRevert(); + bridge().unpause(); + } + + function test_ConfigureToken_RevertIfUpdatingUnconfiguredToken() public { + IBridge.TokenLimits memory some = IBridge.TokenLimits({minAmount: 1, deposit: 1, claim: 1}); + vm.prank(admin); + vm.expectRevert(abi.encodeWithSelector(IBridge.InvalidTokenConfig.selector)); + bridge().configureToken(address(0xCAFE), some); + } + + function test_Deposit_SkipsDailyLimit_WhenDepositCapZero() public { + IBridge.TokenLimits memory unlimited = + IBridge.TokenLimits({minAmount: tokenLimits.minAmount, deposit: 0, claim: tokenLimits.claim}); + vm.prank(admin); + bridge().configureToken(address(token()), unlimited); + + vm.prank(user); + vm.expectRevert(); + bridge().deposit(address(token()), tokenLimits.minAmount, recipient); + } + + function test_DepositIndex_IncrementsSequentially() public { + uint256 beforeIdx = bridge().depositIndex(); + vm.prank(user); + bridge().deposit(address(token()), tokenLimits.minAmount, recipient); + assertEq(bridge().depositIndex(), beforeIdx + 1); + + vm.prank(user); + bridge().deposit(address(token()), tokenLimits.minAmount, recipient); + assertEq(bridge().depositIndex(), beforeIdx + 2); + } + + function test_RoleGrants_FromConstructor() public view { + assertTrue(bridge().hasRole(bridge().DEFAULT_ADMIN_ROLE(), admin)); + assertTrue(bridge().hasRole(bridge().PAUSER_ROLE(), admin)); + } +} From 1ce3fa1266bdf368a6bc95c0b51c73ec10315489 Mon Sep 17 00:00:00 2001 From: Jakov Mitrovski Date: Thu, 4 Sep 2025 15:58:28 +0200 Subject: [PATCH 40/64] PodTest rename and add test for log --- examples/voting/contract/test/Voting.t.sol | 2 +- solidity-sdk/src/test/podTest.sol | 11 ++ solidity-sdk/src/verifier/PodECDSA.sol | 1 + src | 1 - types/src/ledger/log.rs | 118 ++++++++++++++++++++- 5 files changed, 130 insertions(+), 3 deletions(-) delete mode 120000 src diff --git a/examples/voting/contract/test/Voting.t.sol b/examples/voting/contract/test/Voting.t.sol index aad13a3b..cc5ad673 100644 --- a/examples/voting/contract/test/Voting.t.sol +++ b/examples/voting/contract/test/Voting.t.sol @@ -3,7 +3,7 @@ pragma solidity ^0.8.13; import {console} from "forge-std/console.sol"; import {Voting} from "../src/Voting.sol"; -import {PodTest} from "pod-sdk/test/podTest.sol"; +import {PodTest} from "pod-sdk/test/PodTest.sol"; import {Time} from "pod-sdk/Time.sol"; contract VotingTest is PodTest { diff --git a/solidity-sdk/src/test/podTest.sol b/solidity-sdk/src/test/podTest.sol index 5a5d063d..ebbc7c81 100644 --- a/solidity-sdk/src/test/podTest.sol +++ b/solidity-sdk/src/test/podTest.sol @@ -6,6 +6,9 @@ import {Time, POD_TIMESTAMP_PRECOMPILE} from "../Time.sol"; import {REQUIRE_QUORUM} from "../Quorum.sol"; abstract contract PodTest is Test { + address constant ETH_EXTERNAL_ETH_GET_LOGS_PRECOMPILE = + address(uint160(uint256(keccak256("ETH_EXTERNAL_ETH_GET_LOGS")))); + function podMockQuorum() public { // condition must evaluate to true and if so we mock quorum to be true vm.mockCall(REQUIRE_QUORUM, abi.encode(true), bytes("")); @@ -17,4 +20,12 @@ abstract contract PodTest is Test { function podWarp(Time.Timestamp ts) public { vm.mockCall(POD_TIMESTAMP_PRECOMPILE, bytes(""), abi.encode(Time.Timestamp.unwrap(ts))); } + + function podMockEthGetLogs(bytes memory input, bytes memory output) internal { + vm.mockCall(ETH_EXTERNAL_ETH_GET_LOGS_PRECOMPILE, input, output); + } + + function podMockEthGetLogsRevert(bytes memory input) internal { + vm.mockCallRevert(ETH_EXTERNAL_ETH_GET_LOGS_PRECOMPILE, input, bytes("")); + } } diff --git a/solidity-sdk/src/verifier/PodECDSA.sol b/solidity-sdk/src/verifier/PodECDSA.sol index 8c36e2b0..ad397c4f 100644 --- a/solidity-sdk/src/verifier/PodECDSA.sol +++ b/solidity-sdk/src/verifier/PodECDSA.sol @@ -6,6 +6,7 @@ import {MerkleTree} from "./MerkleTree.sol"; import {IPodRegistry} from "pod-protocol/interfaces/IPodRegistry.sol"; import {Strings} from "@openzeppelin/contracts/utils/Strings.sol"; import {Math} from "@openzeppelin/contracts/utils/math/Math.sol"; +import {console} from "forge-std/console.sol"; library PodECDSA { struct PodConfig { diff --git a/src b/src deleted file mode 120000 index 694967ad..00000000 --- a/src +++ /dev/null @@ -1 +0,0 @@ -solidity-sdk/src \ No newline at end of file diff --git a/types/src/ledger/log.rs b/types/src/ledger/log.rs index 892383fd..600822b3 100644 --- a/types/src/ledger/log.rs +++ b/types/src/ledger/log.rs @@ -168,7 +168,7 @@ mod test { use crate::{Hashable, Merkleizable, Transaction}; #[tokio::test] - async fn test_verifiable_log_hash_proof() { + async fn test_verifiable_log_hash_proof_single_log() { let log = Log { address: "0x217f5658c6ecc27d439922263ad9bb8e992e0373" .parse() @@ -263,4 +263,120 @@ mod test { assert!(verifiable_log.verify_proof(receipt_root, proof)); assert_eq!(verifiable_log.inner.log_index, Some(0)); } + + #[tokio::test] + async fn test_verifiable_log_hash_proof_multiple_logs() { + let log = Log { + address: "0xbea11c6707c744581a4c885424af376baa7f686c" + .parse() + .unwrap(), + data: LogData::new_unchecked( + vec![ + "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef" + .parse() + .unwrap(), + "0x00000000000000000000000013791790bef192d14712d627f13a55c4abee52a4" + .parse() + .unwrap(), + "0x0000000000000000000000000000000000000000000000000000000000000000" + .parse() + .unwrap(), + ], + "0x0000000000000000000000000000000000000000000000000de0b6b3a7640000" + .parse() + .unwrap(), + ), + }; + + let log2 = Log { + address: "0x6D9da78B6A5BEdcA287AA5d49613bA36b90c15C4" + .parse() + .unwrap(), + data: LogData::new_unchecked( + vec![ + "05e57fa62d890603d85944c963ddc7fbe77cde5ea69cad7033fc6f76b7ddd2ab" + .parse() + .unwrap(), + "0000000000000000000000000000000000000000000000000000000000000000" + .parse() + .unwrap(), + "0000000000000000000000003b1b6ffac8831f1c1c9a425bb240cd1bbf23f146" + .parse() + .unwrap(), + ], + "0x0000000000000000000000000000000000000000000000056bc75e2d63100000000000000000000000000000006217c47ffa5eb3f3c92247fffe22ad998242c5" + .parse() + .unwrap(), + ), + }; + + let to: Address = "0x12296f2D128530a834460DF6c36a2895B793F26d" + .parse() + .unwrap(); + let transaction = Transaction { + chain_id: 0x50d, + to: TxKind::Call(to.clone()), + nonce: 0, + gas_limit: 201819, + max_fee_per_gas: 1000000000, + max_priority_fee_per_gas: 1000000000, + access_list: Default::default(), + value: U256::ZERO, + input: vec![ + 244, 83, 70, 220, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 190, 161, 28, 103, 7, 199, + 68, 88, 26, 76, 136, 84, 36, 175, 55, 107, 170, 127, 104, 108, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 224, 182, 179, 167, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 121, 23, 144, 190, 241, 146, 209, 71, 18, 214, 39, + 241, 58, 85, 196, 171, 238, 82, 164, + ] + .into(), + }; + let signer = PrivateKeySigner::random(); + + let logs = vec![log.clone(), log2.clone()]; + let logs_tree = logs.to_merkle_tree(); + let logs_root = logs_tree.root(); + + let rpc_log = RPCLog { + inner: log2.clone(), + block_hash: Some(Hash::default()), + block_number: Some(0), + block_timestamp: Some(1742493092), + transaction_hash: Some(transaction.hash_custom()), + transaction_index: Some(0), + log_index: Some(1), + removed: false, + }; + + let verifiable_log = VerifiableLog { + inner: rpc_log, + pod_metadata: PodLogMetadata { + attestations: vec![], + receipt: Receipt { + status: true, + actual_gas_used: 201819, + max_fee_per_gas: transaction.max_fee_per_gas, + logs: logs.clone(), + logs_root, + tx_hash: transaction.hash_custom(), + signer: signer.address(), + to: Some(to), + contract_address: None, + }, + }, + }; + + let proof = verifiable_log.generate_proof().unwrap(); + let receipt_root = verifiable_log + .pod_metadata + .receipt + .to_merkle_tree() + .hash_custom(); + + println!("receipt_root: {:?}", receipt_root); + println!("proof: {:?}", proof.path); + + assert!(verifiable_log.verify_proof(receipt_root, proof)); + assert_eq!(verifiable_log.inner.log_index, Some(1)); + } } From 9dfd73a38a2ab2c649672b6d5e276c973b71eca0 Mon Sep 17 00:00:00 2001 From: Jakov Mitrovski Date: Thu, 4 Sep 2025 16:50:23 +0200 Subject: [PATCH 41/64] fix typo --- examples/voting/contract/test/Voting.t.sol | 2 +- protocol/test/abstract/Bridge.t.sol | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/voting/contract/test/Voting.t.sol b/examples/voting/contract/test/Voting.t.sol index cc5ad673..aad13a3b 100644 --- a/examples/voting/contract/test/Voting.t.sol +++ b/examples/voting/contract/test/Voting.t.sol @@ -3,7 +3,7 @@ pragma solidity ^0.8.13; import {console} from "forge-std/console.sol"; import {Voting} from "../src/Voting.sol"; -import {PodTest} from "pod-sdk/test/PodTest.sol"; +import {PodTest} from "pod-sdk/test/podTest.sol"; import {Time} from "pod-sdk/Time.sol"; contract VotingTest is PodTest { diff --git a/protocol/test/abstract/Bridge.t.sol b/protocol/test/abstract/Bridge.t.sol index 52f8bea4..08091b8b 100644 --- a/protocol/test/abstract/Bridge.t.sol +++ b/protocol/test/abstract/Bridge.t.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.20; -import {PodTest} from "pod-sdk/test/PodTest.sol"; +import {PodTest} from "pod-sdk/test/podTest.sol"; import {Bridge} from "../../src/abstract/Bridge.sol"; import {IBridge} from "../../src/interfaces/IBridge.sol"; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; From 0f6703129901c50f9937076170eb4c85737b608d Mon Sep 17 00:00:00 2001 From: Jakov Mitrovski Date: Fri, 5 Sep 2025 10:45:55 +0200 Subject: [PATCH 42/64] add docs --- protocol/src/BridgeDepositWithdraw.sol | 39 ++++- protocol/src/BridgeMintBurn.sol | 72 ++++++++- protocol/src/abstract/Bridge.sol | 130 +++++++++++++--- protocol/src/interfaces/IBridge.sol | 146 ++++++++++++++---- .../src/interfaces/IBridgeDepositWithdraw.sol | 25 +++ protocol/src/interfaces/IBridgeMintBurn.sol | 34 ++++ .../interfaces/IERC20MintableAndBurnable.sol | 16 ++ protocol/test/abstract/Bridge.t.sol | 23 +++ 8 files changed, 425 insertions(+), 60 deletions(-) diff --git a/protocol/src/BridgeDepositWithdraw.sol b/protocol/src/BridgeDepositWithdraw.sol index 25f98dd9..f1f51349 100644 --- a/protocol/src/BridgeDepositWithdraw.sol +++ b/protocol/src/BridgeDepositWithdraw.sol @@ -8,16 +8,38 @@ import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol import {PodECDSA} from "pod-sdk/verifier/PodECDSA.sol"; import {IPodRegistry} from "./interfaces/IPodRegistry.sol"; +/** + * @title BridgeDepositWithdraw + * @notice Implementation of the deposit-withdraw bridge. + * @dev This contract implements the IBridgeDepositWithdraw interface and provides the functionality for + * depositing and withdrawing tokens between chains. + */ contract BridgeDepositWithdraw is Bridge, IBridgeDepositWithdraw { using SafeERC20 for IERC20; + /** + * @dev The PodConfig for the bridge. The config defines the required number + * of signatures to consider a certificate valid and the PodRegistry to use. + */ PodECDSA.PodConfig public podConfig; + /** + * @dev Constructor. + * @param _podRegistry The address of the PodRegistry to use. + */ constructor(address _podRegistry) { podConfig = PodECDSA.PodConfig({thresholdNumerator: 2, thresholdDenominator: 3, registry: IPodRegistry(_podRegistry)}); } + /** + * @dev Decodes the log into the deposit details. + * @param log The log to decode. + * @return id The id of the deposit. + * @return token The token of the deposit. + * @return amount The amount of the deposit. + * @return to The address to send the tokens to. + */ function _decodeLog(PodECDSA.Log calldata log) internal pure @@ -29,10 +51,19 @@ contract BridgeDepositWithdraw is Bridge, IBridgeDepositWithdraw { (amount, to) = abi.decode(log.data, (uint256, address)); } + /** + * @dev Handles the deposit of tokens. The tokens are transferred from the msg.sender to the contract. + * @param token The token to deposit. + * @param amount The amount of tokens to deposit. + */ function handleDeposit(address token, uint256 amount) internal override { IERC20(token).safeTransferFrom(msg.sender, address(this), amount); } + /** + * @dev Handles the migration of tokens. The tokens are transferred from the contract to the new contract. + * @param _newContract The address of the new contract. + */ function handleMigrate(address _newContract) internal override { for (uint256 i = 0; i < whitelistedTokens.length; i++) { address token = whitelistedTokens[i]; @@ -43,7 +74,10 @@ contract BridgeDepositWithdraw is Bridge, IBridgeDepositWithdraw { } } - function claim(PodECDSA.CertifiedLog calldata certifiedLog) public whenNotPaused { + /** + * @inheritdoc IBridgeDepositWithdraw + */ + function claim(PodECDSA.CertifiedLog calldata certifiedLog) public override whenNotPaused { (uint256 id, address token, uint256 amount, address to) = _decodeLog(certifiedLog.log); address mirrorToken = mirrorTokens[token]; if (mirrorToken == address(0)) revert MirrorTokenNotFound(); @@ -62,6 +96,9 @@ contract BridgeDepositWithdraw is Bridge, IBridgeDepositWithdraw { emit Claim(id, mirrorToken, token, amount, to); } + /** + * @inheritdoc IBridgeDepositWithdraw + */ function whiteListToken(address token, address mirrorToken, TokenLimits calldata limits) external onlyRole(DEFAULT_ADMIN_ROLE) diff --git a/protocol/src/BridgeMintBurn.sol b/protocol/src/BridgeMintBurn.sol index 24d91d16..d03346d2 100644 --- a/protocol/src/BridgeMintBurn.sol +++ b/protocol/src/BridgeMintBurn.sol @@ -8,17 +8,45 @@ import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol import {IAccessControl} from "@openzeppelin/contracts/access/IAccessControl.sol"; import {IERC20MintableAndBurnable} from "./interfaces/IERC20MintableAndBurnable.sol"; import {WrappedToken} from "./WrappedToken.sol"; -import {console} from "forge-std/console.sol"; +/** + * @title BridgeMintBurn + * @notice Implementation of the mint-burn bridge. + * @dev This contract implements the IBridgeMintBurn interface and provides the functionality for + * minting and burning tokens between chains. + */ contract BridgeMintBurn is Bridge, IBridgeMintBurn { using SafeERC20 for IERC20; + /** + * @dev The role for the minter. + */ bytes32 constant MINTER_ROLE = keccak256("MINTER_ROLE"); + + /** + * @dev The address of the external eth get logs precompile. + */ address constant ETH_EXTERNAL_ETH_GET_LOGS_PRECOMPILE = address(uint160(uint256(keccak256("ETH_EXTERNAL_ETH_GET_LOGS")))); + + /** + * @dev The source chain id. + */ uint96 constant SOURCE_CHAIN_ID = 1; + + /** + * @dev "finalized" as bytes + */ bytes constant FINALIZED_BLOCK_BYTES = hex"66696e616c697a6564"; + /** + * @dev The arguments for the external eth get logs precompile. + * @param fromBlock The block number to start searching from. + * @param toBlock The block number to stop searching at. + * @param addr The address to search logs for. + * @param blockHash The block hash to search logs for. + * @param topics The topics to search logs for. + */ struct EthGetLogsArgs { bytes fromBlock; bytes toBlock; @@ -27,11 +55,28 @@ contract BridgeMintBurn is Bridge, IBridgeMintBurn { bytes32[] topics; } + /** + * @dev The arguments for the external eth get logs precompile. + * @param chainId The chain id to search logs for. + * @param ethGetLogsArgs The arguments for the external eth get logs precompile. + */ struct ExternalEthGetLogsArgs { uint256 chainId; EthGetLogsArgs ethGetLogsArgs; } + /** + * @dev The response from the external eth get logs precompile. + * @param addr The address of the log. + * @param topics The topics of the log. + * @param data The data of the log. + * @param blockNumber The block number of the log. + * @param transactionHash The transaction hash of the log. + * @param transactionIndex The transaction index of the log. + * @param blockHash The block hash of the log. + * @param logIndex The log index of the log. + * @param removed Whether the log was removed. + */ struct RpcLog { address addr; bytes32[] topics; @@ -44,12 +89,23 @@ contract BridgeMintBurn is Bridge, IBridgeMintBurn { bool removed; } + /** + * @dev Constructor. + */ constructor() {} + /** + * @dev Handles the deposit of tokens. The tokens are burned from the msg.sender. + * @param token The token to deposit. + * @param amount The amount of tokens to deposit. + */ function handleDeposit(address token, uint256 amount) internal override { IERC20MintableAndBurnable(token).burnFrom(msg.sender, amount); } + /** + * @inheritdoc IBridgeMintBurn + */ function claim(uint256 id, address token, bytes calldata blockNumberFrom) public whenNotPaused { bytes32[] memory topics = new bytes32[](3); topics[0] = DEPOSIT_TOPIC_0; @@ -76,13 +132,6 @@ contract BridgeMintBurn is Bridge, IBridgeMintBurn { address mirrorToken = mirrorTokens[token]; if (mirrorToken == address(0)) revert MirrorTokenNotFound(); - console.log("mirrorToken"); - console.logAddress(mirrorToken); - console.log("decodedAmount"); - console.logUint(decodedAmount); - console.log("decodedTo"); - console.logAddress(decodedTo); - if (!_isValidTokenAmount(mirrorToken, decodedAmount, false)) revert InvalidTokenAmount(); bytes32 requestId = _hashRequest(id, token, decodedAmount, decodedTo); @@ -96,6 +145,10 @@ contract BridgeMintBurn is Bridge, IBridgeMintBurn { emit Claim(id, mirrorToken, token, decodedAmount, decodedTo); } + /** + * @dev Handles the migration of tokens. The tokens and roles are transferred from the contract to the new contract. + * @param _newContract The address of the new contract. + */ function handleMigrate(address _newContract) internal override { for (uint256 i = 0; i < whitelistedTokens.length; i++) { address token = whitelistedTokens[i]; @@ -109,6 +162,9 @@ contract BridgeMintBurn is Bridge, IBridgeMintBurn { } } + /** + * @inheritdoc IBridgeMintBurn + */ function createAndWhitelistMirrorToken( string memory tokenName, string memory tokenSymbol, diff --git a/protocol/src/abstract/Bridge.sol b/protocol/src/abstract/Bridge.sol index b5a7a2c4..db097c70 100644 --- a/protocol/src/abstract/Bridge.sol +++ b/protocol/src/abstract/Bridge.sol @@ -6,44 +6,99 @@ import {AccessControl} from "@openzeppelin/contracts/access/AccessControl.sol"; import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import {Pausable} from "@openzeppelin/contracts/utils/Pausable.sol"; -import {console} from "forge-std/console.sol"; +/** + * @title Bridge + * @notice Abstract base contract for cross-chain token bridging implementations. + * @dev This contract implements the IBridge interface and provides common functionality + * for bridging tokens between chains. It serves as a base contract for both + * BridgeMintBurn and BridgeDepositWithdraw concrete implementations. + * + * The contract uses the Template Method design pattern (https://refactoring.guru/design-patterns/template-method) + * where the core deposit and migrate functions are implemented here, but delegate specific token handling logic to + * the callback functions (handleDeposit and handleMigrate) that must be implemented by concrete contracts. + * + * Key features: + * - Token whitelisting and configuration with daily limits + * - Access control with admin and pauser roles + * - Pausable functionality for emergency stops + * - Migration support for contract upgrades + * - Request deduplication to prevent double-processing + * + */ abstract contract Bridge is IBridge, AccessControl, Pausable { using SafeERC20 for IERC20; - /// @dev The role ID for addresses that can pause the contract. + /** + * @dev The role ID for addresses that can pause the contract. + */ bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE"); - /// @dev The topic 0 (event signature) of the deposit event. + + /** + * @dev The topic 0 (event signature) of the deposit event. + */ bytes32 constant DEPOSIT_TOPIC_0 = keccak256("Deposit(uint256,address,uint256,address)"); - /// @dev Map token address to token info. + /** + * @dev Map token address to token data. + */ mapping(address => TokenData) public tokenData; - /// @dev Map mirror token address to token address. + /** + * @dev Map source chain token address to destination chain token address. + */ mapping(address => address) public mirrorTokens; - /// @dev Map request hash to processed requests. + /** + * @dev Map request hash to processed requests. + */ mapping(bytes32 => bool) public processedRequests; - /// @dev Array of all the whitelisted tokens. - /// @notice A token in the list might not be active. + /** + * @dev Array of all the whitelisted tokens. + * @notice A token in the list can be disabled. + */ address[] public whitelistedTokens; - /// @dev The number of deposits. + /** + * @dev A counter tracking the number of deposits. + * @notice Id of the current deposit. + */ uint256 public depositIndex; - /// @dev Address of the migrated contract. + /** + * @dev Address of the migrated contract. + */ address public migratedContract; + /** + * @dev Constructor. + * @notice Grants the DEFAULT_ADMIN_ROLE and PAUSER_ROLE to the msg.sender. + */ constructor() { _grantRole(DEFAULT_ADMIN_ROLE, msg.sender); _grantRole(PAUSER_ROLE, msg.sender); } + /** + * @dev Internal function to handle the deposit of tokens. + * This is a callback defining the different token handling logic for the different bridge contracts. + * @param token The token to deposit. + * @param amount The amount of tokens to deposit. + */ function handleDeposit(address token, uint256 amount) internal virtual; + + /** + * @dev Internal function to handle the migration of tokens. + * This is a callback defining the different token handling logic for the different bridge contracts. + * @param _newContract The address of the new contract. + */ function handleMigrate(address _newContract) internal virtual; - /// @dev Modifier to check that contract is not already migrated. + /** + * @dev Modifier to check that contract has not been migrated. + * @dev Reverts with ContractMigrated if the contract has already been migrated. + */ modifier notMigrated() { if (migratedContract != address(0)) { revert ContractMigrated(); @@ -51,6 +106,14 @@ abstract contract Bridge is IBridge, AccessControl, Pausable { _; } + /** + * @dev Internal function to check if the token amount is valid. + * @param token The token to check. + * @param amount The amount of tokens to check. + * @param isDeposit Whether the amount is for a deposit or a claim. + * @return True if the token amount is valid, false otherwise. + * @dev Reverts with DailyLimitExhausted if the daily token deposit or claim limit is exhausted. + */ function _isValidTokenAmount(address token, uint256 amount, bool isDeposit) internal returns (bool) { TokenData storage t = tokenData[token]; @@ -82,6 +145,9 @@ abstract contract Bridge is IBridge, AccessControl, Pausable { return true; } + /** + * @inheritdoc IBridge + */ function deposit(address token, uint256 amount, address to) external whenNotPaused returns (uint256 id) { if (!_isValidTokenAmount(token, amount, true)) revert InvalidTokenAmount(); if (to == address(0)) revert InvalidToAddress(); @@ -90,6 +156,14 @@ abstract contract Bridge is IBridge, AccessControl, Pausable { emit Deposit(id, token, amount, to); } + /** + * @dev Internal function to hash a request. + * @param id The request index. + * @param token The token to hash. + * @param amount The amount of tokens to hash. + * @param to The address to hash. + * @return The hash of the request used for uniquely identifying a bridging request. + */ function _hashRequest(uint256 id, address token, uint256 amount, address to) internal pure returns (bytes32 hash) { assembly { let ptr := mload(0x40) @@ -101,6 +175,12 @@ abstract contract Bridge is IBridge, AccessControl, Pausable { } } + /** + * @dev Internal function to configure the token data. + * @param token The token to configure. + * @param limits The token limits to configure. + * @param newToken Whether the token is new. + */ function _configureTokenData(address token, TokenLimits calldata limits, bool newToken) internal { uint256 currMinAmount = tokenData[token].limits.minAmount; if (limits.minAmount == 0 || (newToken ? currMinAmount != 0 : currMinAmount == 0)) { @@ -109,20 +189,24 @@ abstract contract Bridge is IBridge, AccessControl, Pausable { TokenUsage memory depositUsage = TokenUsage(0, block.timestamp); TokenUsage memory claimUsage = TokenUsage(0, block.timestamp); - // configuring token also resets the daily volume limit + TokenData memory data = TokenData(limits, depositUsage, claimUsage); tokenData[token] = data; } - /// @inheritdoc IBridge + /** + * @inheritdoc IBridge + */ function configureToken(address token, TokenLimits calldata limits) external onlyRole(DEFAULT_ADMIN_ROLE) { _configureTokenData(token, limits, false); } - /// @dev Internal function to whitelist a new token. - /// @param token Token that will be deposited in the contract. - /// @param mirrorToken Token that will be deposited in the mirror contract. - /// @param limits Token limits associated with the token. + /** + * @dev Internal function to whitelist a new token. + * @param token Token that will be deposited in the contract. + * @param mirrorToken Token that will be deposited in the mirror contract. + * @param limits Token limits associated with the token. + */ function _whitelistToken(address token, address mirrorToken, TokenLimits calldata limits) internal { if (mirrorTokens[mirrorToken] != address(0)) { revert InvalidTokenConfig(); @@ -133,17 +217,23 @@ abstract contract Bridge is IBridge, AccessControl, Pausable { mirrorTokens[mirrorToken] = token; } - /// @inheritdoc IBridge + /** + * @inheritdoc IBridge + */ function pause() external onlyRole(PAUSER_ROLE) { _pause(); } - /// @inheritdoc IBridge + /** + * @inheritdoc IBridge + */ function unpause() external notMigrated onlyRole(DEFAULT_ADMIN_ROLE) { _unpause(); } - /// @inheritdoc IBridge + /** + * @inheritdoc IBridge + */ function migrate(address _newContract) public whenPaused notMigrated onlyRole(DEFAULT_ADMIN_ROLE) { handleMigrate(_newContract); migratedContract = _newContract; diff --git a/protocol/src/interfaces/IBridge.sol b/protocol/src/interfaces/IBridge.sol index 3e8d2eae..3af80d47 100644 --- a/protocol/src/interfaces/IBridge.sol +++ b/protocol/src/interfaces/IBridge.sol @@ -3,42 +3,114 @@ pragma solidity ^0.8.20; /** * @title IBridge - * @notice Interface for the Bridge contracts that allow for cross-chain communication. + * @notice Interface for cross-chain token bridging contracts. + * @dev This interface defines the standard contract for bridging tokens between chains. + * It is implemented by the Bridge abstract contract and it standardizes an API + * for the shared bridge functionality. + * + * The interface includes: + * - Token deposit functionality with daily limits and validation + * - Token configuration and whitelisting + * - Access control for administrative operations + * - Pausable functionality for emergency stops + * - Migration support */ interface IBridge { + /** + * @dev Error thrown when attempting to perform operations on an already migrated contract. + */ error ContractMigrated(); + + /** + * @dev Error thrown when the provided token amount is invalid (below minimum or exceeds limits). + */ error InvalidTokenAmount(); + + /** + * @dev Error thrown when the destination address is zero or invalid. + */ error InvalidToAddress(); + + /** + * @dev Error thrown when the token configuration is invalid. + */ error InvalidTokenConfig(); + + /** + * @dev Error thrown when the daily deposit or claim limit for a token has been exceeded. + */ error DailyLimitExhausted(); + + /** + * @dev Error thrown when attempting to process a claim for a token that has no mirror token mapping. + */ error MirrorTokenNotFound(); + + /** + * @dev Error thrown when attempting to process a request that has already been processed. + */ error RequestAlreadyProcessed(); + /** + * @dev Event emitted when a deposit is made. + * @param id The request index. + * @param token The token to bridge. + * @param amount The amount of tokens to bridge. + * @param to The address to send the tokens to. + */ event Deposit(uint256 indexed id, address indexed token, uint256 amount, address to); + + /** + * @dev Event emitted when a claim is made. + * @param id The request index. + * @param mirrorToken The token on the source chain. + * @param token The token on the destination chain. + * @param amount The amount of tokens to bridge. + * @param to The address to send the tokens to. + */ event Claim(uint256 indexed id, address indexed mirrorToken, address indexed token, uint256 amount, address to); + /** + * @dev Token limits. + * @param minAmount The minimum amount of tokens that can be deposited. + * @param deposit The daily deposit limit for the token. + * @param claim The daily claim limit for the token. + */ struct TokenLimits { - uint256 minAmount; // The minimum amount of tokens that can be deposited. - uint256 deposit; // The daily deposit limit for the token. - uint256 claim; // The daily claim limit for the token. + uint256 minAmount; + uint256 deposit; + uint256 claim; } + /** + * @dev Token usage. + * @param consumed The amount of tokens that have been used. + * @param lastUpdated The timestamp when the consumed limits were last updated. + */ struct TokenUsage { - uint256 consumed; // The amount of tokens that have been used. - uint256 lastUpdated; // The timestamp when the consumed limits were last updated. + uint256 consumed; + uint256 lastUpdated; } + /** + * @dev Token data. + * @param limits The token limits. + * @param deposit The token usage for deposits. + * @param claim The token usage for claims. + */ struct TokenData { TokenLimits limits; TokenUsage deposit; TokenUsage claim; } - /// @dev Request information. - /// @param id ID associated with the request. - /// @param token Token requested. - /// @param amount Amount of tokens requested. - /// @param to Address to release the funds to. + /** + * @dev Request information. + * @param id The request index. + * @param token The token to bridge. + * @param amount The amount of tokens to bridge. + * @param to The address to send the tokens to. + */ struct RequestInfo { uint256 id; address token; @@ -46,35 +118,47 @@ interface IBridge { address to; } - /// @dev Returns the number of deposits. + /** + * @return The number of deposits. + */ function depositIndex() external view returns (uint256); - /// @dev Update a token's configuration information. - /// @param limits The token's new configuration limits. - /// @notice Set maxAmount to zero to disable the token. - /// @notice Can only be called by the weak-admin. + /** + * @dev Update a token's configuration information. + * @notice Token can be disabled by setting deposit and claim limits to zero. + * @notice Access is restricted to the admin. + * @param token The token to configure. + * @param limits The token's new configuration limits. + */ function configureToken(address token, TokenLimits calldata limits) external; - /// @dev Deposit tokens to bridge to the other side. - /// @param token Token being deposited. - /// @param amount Amount of tokens being deposited. - /// @param to Address to release the tokens to on the other side. - /// @return The ID associated to the request. + /** + * @dev Deposit tokens to bridge to the destination chain. + * @notice Function used to bridge tokens to the destination chain. + * @param token The token to bridge. + * @param amount The amount of tokens to bridge. + * @param to The address to send the tokens to on the destination chain. + * @return The ID (request index) associated to the request. + */ function deposit(address token, uint256 amount, address to) external returns (uint256); - /// @dev Pauses the contract. - /// @notice The contract can be paused by all addresses - /// with pause role but can only be unpaused by the weak-admin. + /** + * @dev Pauses the contract. + * @notice Access control is restricted to the pause role. + */ function pause() external; - /// @dev Unpauses the contract. - /// @notice The contract can be paused by all addresses - /// with pause role but can only be unpaused by the weak-admin. + /** + * @dev Unpauses the contract. + * @notice Access control is restricted to the admin. + */ function unpause() external; - /// @dev Migrates the contract to a new address. - /// @param _newContract Address of the new contract. - /// @notice This function can only be called once in the lifetime of this - /// contract by the admin. + /** + * @dev Migrates the contract to a new address. + * @param _newContract Address of the new contract. + * @notice Access control is restricted to the admin. + * @notice Migration can only be done once on this contract + */ function migrate(address _newContract) external; } diff --git a/protocol/src/interfaces/IBridgeDepositWithdraw.sol b/protocol/src/interfaces/IBridgeDepositWithdraw.sol index cc3a5567..ed593eeb 100644 --- a/protocol/src/interfaces/IBridgeDepositWithdraw.sol +++ b/protocol/src/interfaces/IBridgeDepositWithdraw.sol @@ -2,10 +2,35 @@ pragma solidity ^0.8.20; import {IBridge} from "./IBridge.sol"; +import {PodECDSA} from "pod-sdk/verifier/PodECDSA.sol"; +/** + * @title IBridgeDepositWithdraw + * @notice Interface for deposit-withdraw bridge implementation. + * @dev Extends IBridge to add token whitelisting and claiming through certified log verification. + */ interface IBridgeDepositWithdraw is IBridge { + /** + * @notice Whitelist a token for bridging. + * @param token Source chain token address. + * @param mirrorToken Destination chain token address. + * @param limits Daily limits for deposits and claims. + */ function whiteListToken(address token, address mirrorToken, TokenLimits calldata limits) external; + /** + * @notice Claim bridged tokens using a certified log proof. + * @param certifiedLog The proof of the deposit represented as a pod certified log. + */ + function claim(PodECDSA.CertifiedLog calldata certifiedLog) external; + + /** + * @dev Error thrown when the deposit log is invalid. + */ error InvalidDepositLog(); + + /** + * @dev Error thrown when the certificate verification fails. + */ error InvalidCertificate(); } diff --git a/protocol/src/interfaces/IBridgeMintBurn.sol b/protocol/src/interfaces/IBridgeMintBurn.sol index f0392f1d..ccb35f0a 100644 --- a/protocol/src/interfaces/IBridgeMintBurn.sol +++ b/protocol/src/interfaces/IBridgeMintBurn.sol @@ -3,7 +3,22 @@ pragma solidity ^0.8.20; import {IBridge} from "./IBridge.sol"; +/** + * @title IBridgeMintBurn + * @notice Interface for mint-burn bridge implementation. + * @dev Extends IBridge to add token creation and claiming through external precompile verification. + */ interface IBridgeMintBurn is IBridge { + /** + * @notice Create and whitelist a mirror token for bridging. + * @param tokenName Name of the token to create. + * @param tokenSymbol Symbol of the token to create. + * @param existingToken Address of existing token (0 to create new). + * @param mirrorToken Source chain token address. + * @param mirrorTokenDecimals Decimals of the mirror token. + * @param limits Daily limits for deposits and claims. + * @return Address of the created or existing token. + */ function createAndWhitelistMirrorToken( string memory tokenName, string memory tokenSymbol, @@ -13,7 +28,26 @@ interface IBridgeMintBurn is IBridge { TokenLimits calldata limits ) external returns (address); + /** + * @notice Claim bridged tokens using external precompile verification. + * @param id Deposit ID to claim. + * @param token Source chain token address. + * @param blockNumberFrom Starting block number for log search. + */ + function claim(uint256 id, address token, bytes calldata blockNumberFrom) external; + + /** + * @dev Error thrown when multiple deposits are found with the same ID. + */ error MultipleDepositsWithSameId(); + + /** + * @dev Error thrown when no deposits are found for the given parameters. + */ error NoDepositsFound(); + + /** + * @dev Error thrown when the external precompile call fails. + */ error PrecompileCallFailed(); } diff --git a/protocol/src/interfaces/IERC20MintableAndBurnable.sol b/protocol/src/interfaces/IERC20MintableAndBurnable.sol index 701738ef..31358659 100644 --- a/protocol/src/interfaces/IERC20MintableAndBurnable.sol +++ b/protocol/src/interfaces/IERC20MintableAndBurnable.sol @@ -3,7 +3,23 @@ pragma solidity ^0.8.20; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +/** + * @title IERC20MintableAndBurnable + * @notice Interface for ERC20 tokens that can be minted and burned. + * @dev This interface extends the IERC20 interface and adds mint and burn functionality. + */ interface IERC20MintableAndBurnable is IERC20 { + /** + * @notice Mints tokens to an address. + * @param to The address to mint tokens to. + * @param amount The amount of tokens to mint. + */ function mint(address to, uint256 amount) external; + + /** + * @notice Burns tokens from an address. + * @param account The address to burn tokens from. + * @param amount The amount of tokens to burn. + */ function burnFrom(address account, uint256 amount) external; } diff --git a/protocol/test/abstract/Bridge.t.sol b/protocol/test/abstract/Bridge.t.sol index 08091b8b..6b852306 100644 --- a/protocol/test/abstract/Bridge.t.sol +++ b/protocol/test/abstract/Bridge.t.sol @@ -196,4 +196,27 @@ abstract contract BridgeBehaviorTest is PodTest { assertTrue(bridge().hasRole(bridge().DEFAULT_ADMIN_ROLE(), admin)); assertTrue(bridge().hasRole(bridge().PAUSER_ROLE(), admin)); } + + function test_ConfigureToken_ResetsDailyLimits() public { + vm.prank(user); + bridge().deposit(address(token()), tokenLimits.minAmount, recipient); + (, IBridge.TokenUsage memory dep,) = bridge().tokenData(address(token())); + assertEq(dep.consumed, tokenLimits.minAmount); + vm.prank(admin); + bridge().configureToken(address(token()), tokenLimits); + (, IBridge.TokenUsage memory dep2,) = bridge().tokenData(address(token())); + assertEq(dep2.consumed, 0); + vm.prank(user); + bridge().deposit(address(token()), tokenLimits.minAmount, recipient); + } + + function test_ConfigureToken_DisableToken() public { + vm.prank(user); + bridge().deposit(address(token()), tokenLimits.minAmount, recipient); + vm.prank(admin); + bridge().configureToken(address(token()), IBridge.TokenLimits({minAmount: 1e18, deposit: 0, claim: 0})); + vm.prank(user); + vm.expectRevert(abi.encodeWithSelector(IBridge.DailyLimitExhausted.selector)); + bridge().deposit(address(token()), tokenLimits.minAmount, recipient); + } } From a9552ddb2e3350d770b5e869a50b0340c0fbf4ff Mon Sep 17 00:00:00 2001 From: Jakov Mitrovski Date: Fri, 5 Sep 2025 10:47:44 +0200 Subject: [PATCH 43/64] fix err --- protocol/src/abstract/Bridge.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/protocol/src/abstract/Bridge.sol b/protocol/src/abstract/Bridge.sol index db097c70..686651dd 100644 --- a/protocol/src/abstract/Bridge.sol +++ b/protocol/src/abstract/Bridge.sol @@ -162,7 +162,7 @@ abstract contract Bridge is IBridge, AccessControl, Pausable { * @param token The token to hash. * @param amount The amount of tokens to hash. * @param to The address to hash. - * @return The hash of the request used for uniquely identifying a bridging request. + * @return hash The hash of the request used for uniquely identifying a bridging request. */ function _hashRequest(uint256 id, address token, uint256 amount, address to) internal pure returns (bytes32 hash) { assembly { From 9103d9f0d9ea70182a2f38ab41d4ea8ae7baf496 Mon Sep 17 00:00:00 2001 From: Jakov Mitrovski Date: Fri, 5 Sep 2025 11:06:18 +0200 Subject: [PATCH 44/64] upd doc --- protocol/src/WrappedToken.sol | 42 +++++++++++++++++++++++++++++ protocol/src/abstract/Bridge.sol | 8 ------ protocol/src/interfaces/IBridge.sol | 7 ----- 3 files changed, 42 insertions(+), 15 deletions(-) diff --git a/protocol/src/WrappedToken.sol b/protocol/src/WrappedToken.sol index 6ac736b4..f89f5e5c 100644 --- a/protocol/src/WrappedToken.sol +++ b/protocol/src/WrappedToken.sol @@ -6,11 +6,33 @@ import {ERC20Pausable} from "@openzeppelin/contracts/token/ERC20/extensions/ERC2 import {AccessControl} from "@openzeppelin/contracts/access/AccessControl.sol"; import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; +/** + * @title WrappedToken + * @notice A contract for wrapping and unwrapping tokens. + * @dev This contract is used to wrap and unwrap tokens between chains. + */ contract WrappedToken is ERC20Burnable, ERC20Pausable, AccessControl { + /** + * @dev The role for the minter. + */ bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE"); + + /** + * @dev The role for the pauser. + */ bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE"); + + /** + * @dev The number of decimals of the token. + */ uint8 private immutable DECIMALS; + /** + * @dev Constructor. + * @param name_ The name of the token. + * @param symbol_ The symbol of the token. + * @param decimals_ The number of decimals of the token. + */ constructor(string memory name_, string memory symbol_, uint8 decimals_) ERC20(name_, symbol_) { DECIMALS = decimals_; _grantRole(DEFAULT_ADMIN_ROLE, msg.sender); @@ -18,22 +40,42 @@ contract WrappedToken is ERC20Burnable, ERC20Pausable, AccessControl { _grantRole(MINTER_ROLE, msg.sender); } + /** + * @inheritdoc ERC20 + */ function decimals() public view override returns (uint8) { return DECIMALS; } + /** + * @dev Mints tokens to an address. + * @notice Access is restricted to the minter role. + * @param to The address to mint tokens to. + * @param amount The amount of tokens to mint. + */ function mint(address to, uint256 amount) external onlyRole(MINTER_ROLE) { _mint(to, amount); // will revert when paused because ERC20Pausable guards _update } + /** + * @inheritdoc ERC20Pausable + * @notice Access is restricted to the pauser role. + */ function pause() external onlyRole(PAUSER_ROLE) { _pause(); } + /** + * @inheritdoc ERC20Pausable + * @notice Access is restricted to the admin role. + */ function unpause() external onlyRole(DEFAULT_ADMIN_ROLE) { _unpause(); } + /** + * @inheritdoc ERC20Pausable + */ function _update(address from, address to, uint256 value) internal override(ERC20, ERC20Pausable) whenNotPaused { super._update(from, to, value); } diff --git a/protocol/src/abstract/Bridge.sol b/protocol/src/abstract/Bridge.sol index 686651dd..90d8ef64 100644 --- a/protocol/src/abstract/Bridge.sol +++ b/protocol/src/abstract/Bridge.sol @@ -17,14 +17,6 @@ import {Pausable} from "@openzeppelin/contracts/utils/Pausable.sol"; * The contract uses the Template Method design pattern (https://refactoring.guru/design-patterns/template-method) * where the core deposit and migrate functions are implemented here, but delegate specific token handling logic to * the callback functions (handleDeposit and handleMigrate) that must be implemented by concrete contracts. - * - * Key features: - * - Token whitelisting and configuration with daily limits - * - Access control with admin and pauser roles - * - Pausable functionality for emergency stops - * - Migration support for contract upgrades - * - Request deduplication to prevent double-processing - * */ abstract contract Bridge is IBridge, AccessControl, Pausable { using SafeERC20 for IERC20; diff --git a/protocol/src/interfaces/IBridge.sol b/protocol/src/interfaces/IBridge.sol index 3af80d47..fb50533a 100644 --- a/protocol/src/interfaces/IBridge.sol +++ b/protocol/src/interfaces/IBridge.sol @@ -7,13 +7,6 @@ pragma solidity ^0.8.20; * @dev This interface defines the standard contract for bridging tokens between chains. * It is implemented by the Bridge abstract contract and it standardizes an API * for the shared bridge functionality. - * - * The interface includes: - * - Token deposit functionality with daily limits and validation - * - Token configuration and whitelisting - * - Access control for administrative operations - * - Pausable functionality for emergency stops - * - Migration support */ interface IBridge { /** From 0fbdce5ac5b6cf49a7303b270ce5f9b0672f124f Mon Sep 17 00:00:00 2001 From: Jakov Mitrovski Date: Fri, 5 Sep 2025 11:10:30 +0200 Subject: [PATCH 45/64] update WrappedToken doc --- protocol/src/WrappedToken.sol | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/protocol/src/WrappedToken.sol b/protocol/src/WrappedToken.sol index f89f5e5c..3b4bb513 100644 --- a/protocol/src/WrappedToken.sol +++ b/protocol/src/WrappedToken.sol @@ -49,16 +49,17 @@ contract WrappedToken is ERC20Burnable, ERC20Pausable, AccessControl { /** * @dev Mints tokens to an address. + * @dev Will revert when paused because ERC20Pausable guards _update * @notice Access is restricted to the minter role. * @param to The address to mint tokens to. * @param amount The amount of tokens to mint. */ function mint(address to, uint256 amount) external onlyRole(MINTER_ROLE) { - _mint(to, amount); // will revert when paused because ERC20Pausable guards _update + _mint(to, amount); } /** - * @inheritdoc ERC20Pausable + * @dev Pauses the contract * @notice Access is restricted to the pauser role. */ function pause() external onlyRole(PAUSER_ROLE) { @@ -66,7 +67,7 @@ contract WrappedToken is ERC20Burnable, ERC20Pausable, AccessControl { } /** - * @inheritdoc ERC20Pausable + * @dev Unpauses the contract * @notice Access is restricted to the admin role. */ function unpause() external onlyRole(DEFAULT_ADMIN_ROLE) { @@ -74,7 +75,10 @@ contract WrappedToken is ERC20Burnable, ERC20Pausable, AccessControl { } /** - * @inheritdoc ERC20Pausable + * @dev Updates the token balance of an address. + * @param from The address to update the balance from. + * @param to The address to update the balance to. + * @param value The amount of tokens to update the balance by. */ function _update(address from, address to, uint256 value) internal override(ERC20, ERC20Pausable) whenNotPaused { super._update(from, to, value); From 6f7badbb2e5e8de927a22a8ff9529ef61a3aa73d Mon Sep 17 00:00:00 2001 From: Jakov Mitrovski Date: Fri, 5 Sep 2025 12:50:04 +0200 Subject: [PATCH 46/64] Add eth get logs precompile specific types --- .github/workflows/test.yml | 1 + protocol/src/BridgeMintBurn.sol | 68 +----- protocol/test/BridgeMintBurn.t.sol | 39 +-- .../bindings/src/mockrequirequorum.rs | 231 ------------------ solidity-sdk/src/test/podTest.sol | 8 +- .../types/EthGetLogsPrecompileHelperTypes.sol | 59 +++++ 6 files changed, 92 insertions(+), 314 deletions(-) delete mode 100644 solidity-sdk/bindings/src/mockrequirequorum.rs create mode 100644 solidity-sdk/src/types/EthGetLogsPrecompileHelperTypes.sol diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 349a8c64..b2c595c5 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -128,6 +128,7 @@ jobs: forge test -vvv id: test working-directory: solidity-sdk + optimistic-auction: name: optimistic-auction diff --git a/protocol/src/BridgeMintBurn.sol b/protocol/src/BridgeMintBurn.sol index d03346d2..1a367841 100644 --- a/protocol/src/BridgeMintBurn.sol +++ b/protocol/src/BridgeMintBurn.sol @@ -8,6 +8,7 @@ import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol import {IAccessControl} from "@openzeppelin/contracts/access/IAccessControl.sol"; import {IERC20MintableAndBurnable} from "./interfaces/IERC20MintableAndBurnable.sol"; import {WrappedToken} from "./WrappedToken.sol"; +import {EthGetLogsPrecompileHelperTypes} from "pod-sdk/types/EthGetLogsPrecompileHelperTypes.sol"; /** * @title BridgeMintBurn @@ -23,12 +24,6 @@ contract BridgeMintBurn is Bridge, IBridgeMintBurn { */ bytes32 constant MINTER_ROLE = keccak256("MINTER_ROLE"); - /** - * @dev The address of the external eth get logs precompile. - */ - address constant ETH_EXTERNAL_ETH_GET_LOGS_PRECOMPILE = - address(uint160(uint256(keccak256("ETH_EXTERNAL_ETH_GET_LOGS")))); - /** * @dev The source chain id. */ @@ -39,56 +34,6 @@ contract BridgeMintBurn is Bridge, IBridgeMintBurn { */ bytes constant FINALIZED_BLOCK_BYTES = hex"66696e616c697a6564"; - /** - * @dev The arguments for the external eth get logs precompile. - * @param fromBlock The block number to start searching from. - * @param toBlock The block number to stop searching at. - * @param addr The address to search logs for. - * @param blockHash The block hash to search logs for. - * @param topics The topics to search logs for. - */ - struct EthGetLogsArgs { - bytes fromBlock; - bytes toBlock; - address addr; - bytes32 blockHash; - bytes32[] topics; - } - - /** - * @dev The arguments for the external eth get logs precompile. - * @param chainId The chain id to search logs for. - * @param ethGetLogsArgs The arguments for the external eth get logs precompile. - */ - struct ExternalEthGetLogsArgs { - uint256 chainId; - EthGetLogsArgs ethGetLogsArgs; - } - - /** - * @dev The response from the external eth get logs precompile. - * @param addr The address of the log. - * @param topics The topics of the log. - * @param data The data of the log. - * @param blockNumber The block number of the log. - * @param transactionHash The transaction hash of the log. - * @param transactionIndex The transaction index of the log. - * @param blockHash The block hash of the log. - * @param logIndex The log index of the log. - * @param removed Whether the log was removed. - */ - struct RpcLog { - address addr; - bytes32[] topics; - bytes data; - bytes blockNumber; - bytes32 transactionHash; - bytes transactionIndex; - bytes32 blockHash; - bytes logIndex; - bool removed; - } - /** * @dev Constructor. */ @@ -112,17 +57,20 @@ contract BridgeMintBurn is Bridge, IBridgeMintBurn { topics[1] = bytes32(id); topics[2] = bytes32(uint256(uint160(token))); - (bool success, bytes memory output) = ETH_EXTERNAL_ETH_GET_LOGS_PRECOMPILE.staticcall( + (bool success, bytes memory output) = EthGetLogsPrecompileHelperTypes.PRECOMPILE_ADDRESS.staticcall( abi.encode( - ExternalEthGetLogsArgs( + EthGetLogsPrecompileHelperTypes.PrecompileArgs( SOURCE_CHAIN_ID, - EthGetLogsArgs(blockNumberFrom, FINALIZED_BLOCK_BYTES, address(token), bytes32(0), topics) + EthGetLogsPrecompileHelperTypes.RpcArgs( + blockNumberFrom, FINALIZED_BLOCK_BYTES, address(token), bytes32(0), topics + ) ) ) ); if (!success) revert PrecompileCallFailed(); - RpcLog[] memory logs = abi.decode(output, (RpcLog[])); + EthGetLogsPrecompileHelperTypes.RpcLog[] memory logs = + abi.decode(output, (EthGetLogsPrecompileHelperTypes.RpcLog[])); if (logs.length == 0) revert NoDepositsFound(); if (logs.length > 1) revert MultipleDepositsWithSameId(); diff --git a/protocol/test/BridgeMintBurn.t.sol b/protocol/test/BridgeMintBurn.t.sol index aeeb499c..ca780b8d 100644 --- a/protocol/test/BridgeMintBurn.t.sol +++ b/protocol/test/BridgeMintBurn.t.sol @@ -8,8 +8,8 @@ import {IBridge} from "../src/interfaces/IBridge.sol"; import {Bridge} from "../src/abstract/Bridge.sol"; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import {WrappedToken} from "../src/WrappedToken.sol"; -import {MerkleTree} from "pod-sdk/verifier/MerkleTree.sol"; import {Pausable} from "@openzeppelin/contracts/utils/Pausable.sol"; +import {EthGetLogsPrecompileHelperTypes} from "pod-sdk/types/EthGetLogsPrecompileHelperTypes.sol"; contract BridgeMintBurnTest is BridgeBehaviorTest { BridgeMintBurn private _bridge; @@ -50,7 +50,7 @@ contract BridgeMintBurnTest is BridgeBehaviorTest { } function test_Claim_SingleLog_MintsToRecipient() public { - BridgeMintBurn.RpcLog[] memory logs = new BridgeMintBurn.RpcLog[](1); + EthGetLogsPrecompileHelperTypes.RpcLog[] memory logs = new EthGetLogsPrecompileHelperTypes.RpcLog[](1); logs[0] = _makeLog(0, _mirror, DEPOSIT_AMOUNT, recipient); _mockEthGetLogs(0, bytes("0x1"), _mirror, logs); assertEq(_token.balanceOf(recipient), 0); @@ -69,7 +69,7 @@ contract BridgeMintBurnTest is BridgeBehaviorTest { } function test_Claim_RevertIfDailyLimitExhausted() public { - BridgeMintBurn.RpcLog[] memory logs = new BridgeMintBurn.RpcLog[](1); + EthGetLogsPrecompileHelperTypes.RpcLog[] memory logs = new EthGetLogsPrecompileHelperTypes.RpcLog[](1); logs[0] = _makeLog(0, _mirror, tokenLimits.claim + 1, recipient); _mockEthGetLogs(0, bytes("0x1"), _mirror, logs); vm.expectRevert(abi.encodeWithSelector(IBridge.DailyLimitExhausted.selector)); @@ -77,7 +77,7 @@ contract BridgeMintBurnTest is BridgeBehaviorTest { } function test_Claim_RevertIfDailyLimitExhausted_ButSucceedAfterOneDay() public { - BridgeMintBurn.RpcLog[] memory logs = new BridgeMintBurn.RpcLog[](1); + EthGetLogsPrecompileHelperTypes.RpcLog[] memory logs = new EthGetLogsPrecompileHelperTypes.RpcLog[](1); logs[0] = _makeLog(0, _mirror, DEPOSIT_AMOUNT, recipient); _mockEthGetLogs(0, bytes("0x1"), _mirror, logs); _bridge.claim(0, _mirror, bytes("0x1")); @@ -91,14 +91,14 @@ contract BridgeMintBurnTest is BridgeBehaviorTest { } function test_Claim_RevertIfNoDepositsFound() public { - BridgeMintBurn.RpcLog[] memory logs = new BridgeMintBurn.RpcLog[](0); + EthGetLogsPrecompileHelperTypes.RpcLog[] memory logs = new EthGetLogsPrecompileHelperTypes.RpcLog[](0); _mockEthGetLogs(0, bytes("0x1"), _mirror, logs); vm.expectRevert(abi.encodeWithSelector(IBridgeMintBurn.NoDepositsFound.selector)); _bridge.claim(0, _mirror, bytes("0x1")); } function test_Claim_RevertIfMultipleDepositsFound() public { - BridgeMintBurn.RpcLog[] memory logs = new BridgeMintBurn.RpcLog[](2); + EthGetLogsPrecompileHelperTypes.RpcLog[] memory logs = new EthGetLogsPrecompileHelperTypes.RpcLog[](2); logs[0] = _makeLog(0, _mirror, DEPOSIT_AMOUNT, recipient); logs[1] = _makeLog(0, _mirror, DEPOSIT_AMOUNT, recipient); _mockEthGetLogs(0, bytes("0x1"), _mirror, logs); @@ -109,7 +109,7 @@ contract BridgeMintBurnTest is BridgeBehaviorTest { function test_Claim_RevertIfMirrorTokenNotFound() public { // Use a token not mapped in mirrorTokens address unknownMirror = address(0xBEEF); - BridgeMintBurn.RpcLog[] memory logs = new BridgeMintBurn.RpcLog[](1); + EthGetLogsPrecompileHelperTypes.RpcLog[] memory logs = new EthGetLogsPrecompileHelperTypes.RpcLog[](1); logs[0] = _makeLog(0, unknownMirror, DEPOSIT_AMOUNT, recipient); _mockEthGetLogs(0, bytes("0x1"), unknownMirror, logs); @@ -118,7 +118,7 @@ contract BridgeMintBurnTest is BridgeBehaviorTest { } function test_Claim_RevertIfAlreadyProcessed() public { - BridgeMintBurn.RpcLog[] memory logs = new BridgeMintBurn.RpcLog[](1); + EthGetLogsPrecompileHelperTypes.RpcLog[] memory logs = new EthGetLogsPrecompileHelperTypes.RpcLog[](1); logs[0] = _makeLog(0, _mirror, DEPOSIT_AMOUNT, recipient); _mockEthGetLogs(0, bytes("0x1"), _mirror, logs); _bridge.claim(0, _mirror, bytes("0x1")); @@ -137,7 +137,7 @@ contract BridgeMintBurnTest is BridgeBehaviorTest { } function test_Claim_RevertIfPrecompileCallFails() public { - BridgeMintBurn.ExternalEthGetLogsArgs memory args = _buildArgs(0, bytes("0x1"), _mirror); + EthGetLogsPrecompileHelperTypes.PrecompileArgs memory args = _buildArgs(0, bytes("0x1"), _mirror); podMockEthGetLogsRevert(abi.encode(args)); vm.expectRevert(abi.encodeWithSelector(IBridgeMintBurn.PrecompileCallFailed.selector)); @@ -172,22 +172,25 @@ contract BridgeMintBurnTest is BridgeBehaviorTest { function _buildArgs(uint256 id, bytes memory fromBlock, address tokenAddr) internal pure - returns (BridgeMintBurn.ExternalEthGetLogsArgs memory) + returns (EthGetLogsPrecompileHelperTypes.PrecompileArgs memory) { - BridgeMintBurn.EthGetLogsArgs memory inner = BridgeMintBurn.EthGetLogsArgs({ + EthGetLogsPrecompileHelperTypes.RpcArgs memory inner = EthGetLogsPrecompileHelperTypes.RpcArgs({ fromBlock: fromBlock, toBlock: hex"66696e616c697a6564", addr: tokenAddr, blockHash: bytes32(0), topics: _buildTopics(id, tokenAddr) }); - return BridgeMintBurn.ExternalEthGetLogsArgs({chainId: 1, ethGetLogsArgs: inner}); + return EthGetLogsPrecompileHelperTypes.PrecompileArgs({chainId: 1, ethGetLogsArgs: inner}); } - function _mockEthGetLogs(uint256 id, bytes memory fromBlock, address tokenAddr, BridgeMintBurn.RpcLog[] memory logs) - internal - { - BridgeMintBurn.ExternalEthGetLogsArgs memory args = _buildArgs(id, fromBlock, tokenAddr); + function _mockEthGetLogs( + uint256 id, + bytes memory fromBlock, + address tokenAddr, + EthGetLogsPrecompileHelperTypes.RpcLog[] memory logs + ) internal { + EthGetLogsPrecompileHelperTypes.PrecompileArgs memory args = _buildArgs(id, fromBlock, tokenAddr); podMockEthGetLogs(abi.encode(args), abi.encode(logs)); } @@ -201,9 +204,9 @@ contract BridgeMintBurnTest is BridgeBehaviorTest { function _makeLog(uint256 id, address tokenAddr, uint256 amount, address to) internal pure - returns (BridgeMintBurn.RpcLog memory) + returns (EthGetLogsPrecompileHelperTypes.RpcLog memory) { - return BridgeMintBurn.RpcLog({ + return EthGetLogsPrecompileHelperTypes.RpcLog({ addr: tokenAddr, topics: _buildTopics(id, tokenAddr), data: abi.encode(amount, to), diff --git a/solidity-sdk/bindings/src/mockrequirequorum.rs b/solidity-sdk/bindings/src/mockrequirequorum.rs deleted file mode 100644 index 4e1467d3..00000000 --- a/solidity-sdk/bindings/src/mockrequirequorum.rs +++ /dev/null @@ -1,231 +0,0 @@ -/** - -Generated by the following Solidity interface... -```solidity -interface MockRequireQuorum { - fallback() external; -} -``` - -...which was generated by the following JSON ABI: -```json -[ - { - "type": "fallback", - "stateMutability": "nonpayable" - } -] -```*/ -#[allow( - non_camel_case_types, - non_snake_case, - clippy::pub_underscore_fields, - clippy::style, - clippy::empty_structs_with_brackets -)] -pub mod MockRequireQuorum { - use super::*; - use alloy::sol_types as alloy_sol_types; - /// The creation / init bytecode of the contract. - /// - /// ```text - ///0x6080604052348015600f57600080fd5b506103748061001f6000396000f3fe608060405234801561001057600080fd5b5060003660606000838381019061002791906101dd565b90506100686040518060400160405280600a81526020017f636f6e646974696f6e3a00000000000000000000000000000000000000000000815250826100b4565b806100a8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161009f90610267565b60405180910390fd5b50915050805190602001f35b61014c82826040516024016100ca929190610315565b6040516020818303038152906040527fc3b55635000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050610150565b5050565b6101678161015f61016a61018b565b63ffffffff16565b50565b60006a636f6e736f6c652e6c6f679050600080835160208501845afa505050565b610196819050919050565b61019e610345565b565b600080fd5b60008115159050919050565b6101ba816101a5565b81146101c557600080fd5b50565b6000813590506101d7816101b1565b92915050565b6000602082840312156101f3576101f26101a0565b5b6000610201848285016101c8565b91505092915050565b600082825260208201905092915050565b7f51756f72756d20726571756972656d656e74206e6f74206d6574000000000000600082015250565b6000610251601a8361020a565b915061025c8261021b565b602082019050919050565b6000602082019050818103600083015261028081610244565b9050919050565b600081519050919050565b60005b838110156102b0578082015181840152602081019050610295565b60008484015250505050565b6000601f19601f8301169050919050565b60006102d882610287565b6102e2818561020a565b93506102f2818560208601610292565b6102fb816102bc565b840191505092915050565b61030f816101a5565b82525050565b6000604082019050818103600083015261032f81856102cd565b905061033e6020830184610306565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052605160045260246000fd - /// ``` - #[rustfmt::skip] - #[allow(clippy::all)] - pub static BYTECODE: alloy_sol_types::private::Bytes = alloy_sol_types::private::Bytes::from_static( - b"`\x80`@R4\x80\x15`\x0FW`\0\x80\xFD[Pa\x03t\x80a\0\x1F`\09`\0\xF3\xFE`\x80`@R4\x80\x15a\0\x10W`\0\x80\xFD[P`\x006```\0\x83\x83\x81\x01\x90a\0'\x91\x90a\x01\xDDV[\x90Pa\0h`@Q\x80`@\x01`@R\x80`\n\x81R` \x01\x7Fcondition:\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81RP\x82a\0\xB4V[\x80a\0\xA8W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\0\x9F\x90a\x02gV[`@Q\x80\x91\x03\x90\xFD[P\x91PP\x80Q\x90` \x01\xF3[a\x01L\x82\x82`@Q`$\x01a\0\xCA\x92\x91\x90a\x03\x15V[`@Q` \x81\x83\x03\x03\x81R\x90`@R\x7F\xC3\xB5V5\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0{\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x19\x16` \x82\x01\x80Q{\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x83\x81\x83\x16\x17\x83RPPPPa\x01PV[PPV[a\x01g\x81a\x01_a\x01ja\x01\x8BV[c\xFF\xFF\xFF\xFF\x16V[PV[`\0jconsole.log\x90P`\0\x80\x83Q` \x85\x01\x84Z\xFAPPPV[a\x01\x96\x81\x90P\x91\x90PV[a\x01\x9Ea\x03EV[V[`\0\x80\xFD[`\0\x81\x15\x15\x90P\x91\x90PV[a\x01\xBA\x81a\x01\xA5V[\x81\x14a\x01\xC5W`\0\x80\xFD[PV[`\0\x815\x90Pa\x01\xD7\x81a\x01\xB1V[\x92\x91PPV[`\0` \x82\x84\x03\x12\x15a\x01\xF3Wa\x01\xF2a\x01\xA0V[[`\0a\x02\x01\x84\x82\x85\x01a\x01\xC8V[\x91PP\x92\x91PPV[`\0\x82\x82R` \x82\x01\x90P\x92\x91PPV[\x7FQuorum requirement not met\0\0\0\0\0\0`\0\x82\x01RPV[`\0a\x02Q`\x1A\x83a\x02\nV[\x91Pa\x02\\\x82a\x02\x1BV[` \x82\x01\x90P\x91\x90PV[`\0` \x82\x01\x90P\x81\x81\x03`\0\x83\x01Ra\x02\x80\x81a\x02DV[\x90P\x91\x90PV[`\0\x81Q\x90P\x91\x90PV[`\0[\x83\x81\x10\x15a\x02\xB0W\x80\x82\x01Q\x81\x84\x01R` \x81\x01\x90Pa\x02\x95V[`\0\x84\x84\x01RPPPPV[`\0`\x1F\x19`\x1F\x83\x01\x16\x90P\x91\x90PV[`\0a\x02\xD8\x82a\x02\x87V[a\x02\xE2\x81\x85a\x02\nV[\x93Pa\x02\xF2\x81\x85` \x86\x01a\x02\x92V[a\x02\xFB\x81a\x02\xBCV[\x84\x01\x91PP\x92\x91PPV[a\x03\x0F\x81a\x01\xA5V[\x82RPPV[`\0`@\x82\x01\x90P\x81\x81\x03`\0\x83\x01Ra\x03/\x81\x85a\x02\xCDV[\x90Pa\x03>` \x83\x01\x84a\x03\x06V[\x93\x92PPPV[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0`\0R`Q`\x04R`$`\0\xFD", - ); - /// The runtime bytecode of the contract, as deployed on the network. - /// - /// ```text - ///0x608060405234801561001057600080fd5b5060003660606000838381019061002791906101dd565b90506100686040518060400160405280600a81526020017f636f6e646974696f6e3a00000000000000000000000000000000000000000000815250826100b4565b806100a8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161009f90610267565b60405180910390fd5b50915050805190602001f35b61014c82826040516024016100ca929190610315565b6040516020818303038152906040527fc3b55635000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050610150565b5050565b6101678161015f61016a61018b565b63ffffffff16565b50565b60006a636f6e736f6c652e6c6f679050600080835160208501845afa505050565b610196819050919050565b61019e610345565b565b600080fd5b60008115159050919050565b6101ba816101a5565b81146101c557600080fd5b50565b6000813590506101d7816101b1565b92915050565b6000602082840312156101f3576101f26101a0565b5b6000610201848285016101c8565b91505092915050565b600082825260208201905092915050565b7f51756f72756d20726571756972656d656e74206e6f74206d6574000000000000600082015250565b6000610251601a8361020a565b915061025c8261021b565b602082019050919050565b6000602082019050818103600083015261028081610244565b9050919050565b600081519050919050565b60005b838110156102b0578082015181840152602081019050610295565b60008484015250505050565b6000601f19601f8301169050919050565b60006102d882610287565b6102e2818561020a565b93506102f2818560208601610292565b6102fb816102bc565b840191505092915050565b61030f816101a5565b82525050565b6000604082019050818103600083015261032f81856102cd565b905061033e6020830184610306565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052605160045260246000fd - /// ``` - #[rustfmt::skip] - #[allow(clippy::all)] - pub static DEPLOYED_BYTECODE: alloy_sol_types::private::Bytes = alloy_sol_types::private::Bytes::from_static( - b"`\x80`@R4\x80\x15a\0\x10W`\0\x80\xFD[P`\x006```\0\x83\x83\x81\x01\x90a\0'\x91\x90a\x01\xDDV[\x90Pa\0h`@Q\x80`@\x01`@R\x80`\n\x81R` \x01\x7Fcondition:\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81RP\x82a\0\xB4V[\x80a\0\xA8W`@Q\x7F\x08\xC3y\xA0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\0\x9F\x90a\x02gV[`@Q\x80\x91\x03\x90\xFD[P\x91PP\x80Q\x90` \x01\xF3[a\x01L\x82\x82`@Q`$\x01a\0\xCA\x92\x91\x90a\x03\x15V[`@Q` \x81\x83\x03\x03\x81R\x90`@R\x7F\xC3\xB5V5\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0{\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x19\x16` \x82\x01\x80Q{\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x83\x81\x83\x16\x17\x83RPPPPa\x01PV[PPV[a\x01g\x81a\x01_a\x01ja\x01\x8BV[c\xFF\xFF\xFF\xFF\x16V[PV[`\0jconsole.log\x90P`\0\x80\x83Q` \x85\x01\x84Z\xFAPPPV[a\x01\x96\x81\x90P\x91\x90PV[a\x01\x9Ea\x03EV[V[`\0\x80\xFD[`\0\x81\x15\x15\x90P\x91\x90PV[a\x01\xBA\x81a\x01\xA5V[\x81\x14a\x01\xC5W`\0\x80\xFD[PV[`\0\x815\x90Pa\x01\xD7\x81a\x01\xB1V[\x92\x91PPV[`\0` \x82\x84\x03\x12\x15a\x01\xF3Wa\x01\xF2a\x01\xA0V[[`\0a\x02\x01\x84\x82\x85\x01a\x01\xC8V[\x91PP\x92\x91PPV[`\0\x82\x82R` \x82\x01\x90P\x92\x91PPV[\x7FQuorum requirement not met\0\0\0\0\0\0`\0\x82\x01RPV[`\0a\x02Q`\x1A\x83a\x02\nV[\x91Pa\x02\\\x82a\x02\x1BV[` \x82\x01\x90P\x91\x90PV[`\0` \x82\x01\x90P\x81\x81\x03`\0\x83\x01Ra\x02\x80\x81a\x02DV[\x90P\x91\x90PV[`\0\x81Q\x90P\x91\x90PV[`\0[\x83\x81\x10\x15a\x02\xB0W\x80\x82\x01Q\x81\x84\x01R` \x81\x01\x90Pa\x02\x95V[`\0\x84\x84\x01RPPPPV[`\0`\x1F\x19`\x1F\x83\x01\x16\x90P\x91\x90PV[`\0a\x02\xD8\x82a\x02\x87V[a\x02\xE2\x81\x85a\x02\nV[\x93Pa\x02\xF2\x81\x85` \x86\x01a\x02\x92V[a\x02\xFB\x81a\x02\xBCV[\x84\x01\x91PP\x92\x91PPV[a\x03\x0F\x81a\x01\xA5V[\x82RPPV[`\0`@\x82\x01\x90P\x81\x81\x03`\0\x83\x01Ra\x03/\x81\x85a\x02\xCDV[\x90Pa\x03>` \x83\x01\x84a\x03\x06V[\x93\x92PPPV[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0`\0R`Q`\x04R`$`\0\xFD", - ); - use alloy::contract as alloy_contract; - /**Creates a new wrapper around an on-chain [`MockRequireQuorum`](self) contract instance. - -See the [wrapper's documentation](`MockRequireQuorumInstance`) for more details.*/ - #[inline] - pub const fn new< - T: alloy_contract::private::Transport + ::core::clone::Clone, - P: alloy_contract::private::Provider, - N: alloy_contract::private::Network, - >( - address: alloy_sol_types::private::Address, - provider: P, - ) -> MockRequireQuorumInstance { - MockRequireQuorumInstance::::new(address, provider) - } - /**Deploys this contract using the given `provider` and constructor arguments, if any. - -Returns a new instance of the contract, if the deployment was successful. - -For more fine-grained control over the deployment process, use [`deploy_builder`] instead.*/ - #[inline] - pub fn deploy< - T: alloy_contract::private::Transport + ::core::clone::Clone, - P: alloy_contract::private::Provider, - N: alloy_contract::private::Network, - >( - provider: P, - ) -> impl ::core::future::Future< - Output = alloy_contract::Result>, - > { - MockRequireQuorumInstance::::deploy(provider) - } - /**Creates a `RawCallBuilder` for deploying this contract using the given `provider` -and constructor arguments, if any. - -This is a simple wrapper around creating a `RawCallBuilder` with the data set to -the bytecode concatenated with the constructor's ABI-encoded arguments.*/ - #[inline] - pub fn deploy_builder< - T: alloy_contract::private::Transport + ::core::clone::Clone, - P: alloy_contract::private::Provider, - N: alloy_contract::private::Network, - >(provider: P) -> alloy_contract::RawCallBuilder { - MockRequireQuorumInstance::::deploy_builder(provider) - } - /**A [`MockRequireQuorum`](self) instance. - -Contains type-safe methods for interacting with an on-chain instance of the -[`MockRequireQuorum`](self) contract located at a given `address`, using a given -provider `P`. - -If the contract bytecode is available (see the [`sol!`](alloy_sol_types::sol!) -documentation on how to provide it), the `deploy` and `deploy_builder` methods can -be used to deploy a new instance of the contract. - -See the [module-level documentation](self) for all the available methods.*/ - #[derive(Clone)] - pub struct MockRequireQuorumInstance { - address: alloy_sol_types::private::Address, - provider: P, - _network_transport: ::core::marker::PhantomData<(N, T)>, - } - #[automatically_derived] - impl ::core::fmt::Debug for MockRequireQuorumInstance { - #[inline] - fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { - f.debug_tuple("MockRequireQuorumInstance").field(&self.address).finish() - } - } - /// Instantiation and getters/setters. - #[automatically_derived] - impl< - T: alloy_contract::private::Transport + ::core::clone::Clone, - P: alloy_contract::private::Provider, - N: alloy_contract::private::Network, - > MockRequireQuorumInstance { - /**Creates a new wrapper around an on-chain [`MockRequireQuorum`](self) contract instance. - -See the [wrapper's documentation](`MockRequireQuorumInstance`) for more details.*/ - #[inline] - pub const fn new( - address: alloy_sol_types::private::Address, - provider: P, - ) -> Self { - Self { - address, - provider, - _network_transport: ::core::marker::PhantomData, - } - } - /**Deploys this contract using the given `provider` and constructor arguments, if any. - -Returns a new instance of the contract, if the deployment was successful. - -For more fine-grained control over the deployment process, use [`deploy_builder`] instead.*/ - #[inline] - pub async fn deploy( - provider: P, - ) -> alloy_contract::Result> { - let call_builder = Self::deploy_builder(provider); - let contract_address = call_builder.deploy().await?; - Ok(Self::new(contract_address, call_builder.provider)) - } - /**Creates a `RawCallBuilder` for deploying this contract using the given `provider` -and constructor arguments, if any. - -This is a simple wrapper around creating a `RawCallBuilder` with the data set to -the bytecode concatenated with the constructor's ABI-encoded arguments.*/ - #[inline] - pub fn deploy_builder(provider: P) -> alloy_contract::RawCallBuilder { - alloy_contract::RawCallBuilder::new_raw_deploy( - provider, - ::core::clone::Clone::clone(&BYTECODE), - ) - } - /// Returns a reference to the address. - #[inline] - pub const fn address(&self) -> &alloy_sol_types::private::Address { - &self.address - } - /// Sets the address. - #[inline] - pub fn set_address(&mut self, address: alloy_sol_types::private::Address) { - self.address = address; - } - /// Sets the address and returns `self`. - pub fn at(mut self, address: alloy_sol_types::private::Address) -> Self { - self.set_address(address); - self - } - /// Returns a reference to the provider. - #[inline] - pub const fn provider(&self) -> &P { - &self.provider - } - } - impl MockRequireQuorumInstance { - /// Clones the provider and returns a new instance with the cloned provider. - #[inline] - pub fn with_cloned_provider(self) -> MockRequireQuorumInstance { - MockRequireQuorumInstance { - address: self.address, - provider: ::core::clone::Clone::clone(&self.provider), - _network_transport: ::core::marker::PhantomData, - } - } - } - /// Function calls. - #[automatically_derived] - impl< - T: alloy_contract::private::Transport + ::core::clone::Clone, - P: alloy_contract::private::Provider, - N: alloy_contract::private::Network, - > MockRequireQuorumInstance { - /// Creates a new call builder using this contract instance's provider and address. - /// - /// Note that the call can be any function call, not just those defined in this - /// contract. Prefer using the other methods for building type-safe contract calls. - pub fn call_builder( - &self, - call: &C, - ) -> alloy_contract::SolCallBuilder { - alloy_contract::SolCallBuilder::new_sol(&self.provider, &self.address, call) - } - } - /// Event filters. - #[automatically_derived] - impl< - T: alloy_contract::private::Transport + ::core::clone::Clone, - P: alloy_contract::private::Provider, - N: alloy_contract::private::Network, - > MockRequireQuorumInstance { - /// Creates a new event filter using this contract instance's provider and address. - /// - /// Note that the type can be any event, not just those defined in this contract. - /// Prefer using the other methods for building type-safe event filters. - pub fn event_filter( - &self, - ) -> alloy_contract::Event { - alloy_contract::Event::new_sol(&self.provider, &self.address) - } - } -} diff --git a/solidity-sdk/src/test/podTest.sol b/solidity-sdk/src/test/podTest.sol index ebbc7c81..9c1c5497 100644 --- a/solidity-sdk/src/test/podTest.sol +++ b/solidity-sdk/src/test/podTest.sol @@ -4,11 +4,9 @@ pragma solidity ^0.8.0; import {Test} from "forge-std/Test.sol"; import {Time, POD_TIMESTAMP_PRECOMPILE} from "../Time.sol"; import {REQUIRE_QUORUM} from "../Quorum.sol"; +import {EthGetLogsPrecompileHelperTypes} from "../types/EthGetLogsPrecompileHelperTypes.sol"; abstract contract PodTest is Test { - address constant ETH_EXTERNAL_ETH_GET_LOGS_PRECOMPILE = - address(uint160(uint256(keccak256("ETH_EXTERNAL_ETH_GET_LOGS")))); - function podMockQuorum() public { // condition must evaluate to true and if so we mock quorum to be true vm.mockCall(REQUIRE_QUORUM, abi.encode(true), bytes("")); @@ -22,10 +20,10 @@ abstract contract PodTest is Test { } function podMockEthGetLogs(bytes memory input, bytes memory output) internal { - vm.mockCall(ETH_EXTERNAL_ETH_GET_LOGS_PRECOMPILE, input, output); + vm.mockCall(EthGetLogsPrecompileHelperTypes.PRECOMPILE_ADDRESS, input, output); } function podMockEthGetLogsRevert(bytes memory input) internal { - vm.mockCallRevert(ETH_EXTERNAL_ETH_GET_LOGS_PRECOMPILE, input, bytes("")); + vm.mockCallRevert(EthGetLogsPrecompileHelperTypes.PRECOMPILE_ADDRESS, input, bytes("")); } } diff --git a/solidity-sdk/src/types/EthGetLogsPrecompileHelperTypes.sol b/solidity-sdk/src/types/EthGetLogsPrecompileHelperTypes.sol new file mode 100644 index 00000000..a7872fff --- /dev/null +++ b/solidity-sdk/src/types/EthGetLogsPrecompileHelperTypes.sol @@ -0,0 +1,59 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.28; + +library EthGetLogsPrecompileHelperTypes { + /** + * @dev The address of the external eth get logs precompile. + */ + address constant PRECOMPILE_ADDRESS = address(uint160(uint256(keccak256("ETH_EXTERNAL_ETH_GET_LOGS")))); + + /** + * @dev The arguments for the external eth get logs precompile. + * @param fromBlock The block number to start searching from. + * @param toBlock The block number to stop searching at. + * @param addr The address to search logs for. + * @param blockHash The block hash to search logs for. + * @param topics The topics to search logs for. + */ + struct RpcArgs { + bytes fromBlock; + bytes toBlock; + address addr; + bytes32 blockHash; + bytes32[] topics; + } + + /** + * @dev The arguments for the external eth get logs precompile. + * @param chainId The chain id to search logs for. + * @param ethGetLogsArgs The arguments for the external eth get logs precompile. + */ + struct PrecompileArgs { + uint256 chainId; + RpcArgs ethGetLogsArgs; + } + + /** + * @dev The response from the external eth get logs precompile. + * @param addr The address of the log. + * @param topics The topics of the log. + * @param data The data of the log. + * @param blockNumber The block number of the log. + * @param transactionHash The transaction hash of the log. + * @param transactionIndex The transaction index of the log. + * @param blockHash The block hash of the log. + * @param logIndex The log index of the log. + * @param removed Whether the log was removed. + */ + struct RpcLog { + address addr; + bytes32[] topics; + bytes data; + bytes blockNumber; + bytes32 transactionHash; + bytes transactionIndex; + bytes32 blockHash; + bytes logIndex; + bool removed; + } +} From 1b1cc01b0f12a17b191a5f30fe63c878a075e72e Mon Sep 17 00:00:00 2001 From: Jakov Mitrovski Date: Thu, 18 Sep 2025 18:12:35 +0200 Subject: [PATCH 47/64] Address comments, resolve bugs, introduce native bridging, implement test suite --- protocol/script/DeployDepositWithdraw.s.sol | 4 +- protocol/script/DeployMintBurn.s.sol | 4 +- protocol/src/BridgeDepositWithdraw.sol | 67 +++- protocol/src/BridgeMintBurn.sol | 110 ++++++- protocol/src/abstract/Bridge.sol | 39 ++- protocol/src/interfaces/IBridge.sol | 56 +++- .../src/interfaces/IBridgeDepositWithdraw.sol | 5 +- protocol/src/interfaces/IBridgeMintBurn.sol | 18 +- protocol/src/libraries/HexUtils.sol | 41 +++ protocol/src/libraries/PodMintBalance.sol | 19 ++ protocol/test/BridgeDepositWithdraw.t.sol | 179 +++++++++- protocol/test/BridgeMintBurn.t.sol | 310 +++++++++++++++--- protocol/test/HexUtils.t.sol | 15 + protocol/test/abstract/Bridge.t.sol | 46 ++- solidity-sdk/src/test/podTest.sol | 27 +- .../src/types/EthGetBlockByNumberTypes.sol | 73 +++++ ...ileHelperTypes.sol => EthGetLogsTypes.sol} | 4 +- types/src/ledger/log.rs | 5 +- 18 files changed, 890 insertions(+), 132 deletions(-) create mode 100644 protocol/src/libraries/HexUtils.sol create mode 100644 protocol/src/libraries/PodMintBalance.sol create mode 100644 protocol/test/HexUtils.t.sol create mode 100644 solidity-sdk/src/types/EthGetBlockByNumberTypes.sol rename solidity-sdk/src/types/{EthGetLogsPrecompileHelperTypes.sol => EthGetLogsTypes.sol} (95%) diff --git a/protocol/script/DeployDepositWithdraw.s.sol b/protocol/script/DeployDepositWithdraw.s.sol index 53ed9461..9dc82dec 100644 --- a/protocol/script/DeployDepositWithdraw.s.sol +++ b/protocol/script/DeployDepositWithdraw.s.sol @@ -12,6 +12,7 @@ import {BaseDeployer} from "./BaseDeployer.s.sol"; contract DeployDepositWithdraw is BaseDeployer { uint256 constant CHAIN_ID = 31337; string constant RPC_URL = "http://localhost:8546"; + address constant OTHER_BRIDGE_CONTRACT = 0x12296f2D128530a834460DF6c36a2895B793F26d; function run() external { console.log("=== Deploying BridgeDepositWithdraw to localhost:8546 (chainId 31337) ==="); @@ -26,7 +27,8 @@ contract DeployDepositWithdraw is BaseDeployer { PodRegistry podRegistry = new PodRegistry(initialValidators); console.log("PodRegistry deployed at:", address(podRegistry)); - BridgeDepositWithdraw bridgeDepositWithdraw = new BridgeDepositWithdraw(address(podRegistry)); + BridgeDepositWithdraw bridgeDepositWithdraw = + new BridgeDepositWithdraw(address(podRegistry), OTHER_BRIDGE_CONTRACT); console.log("BridgeDepositWithdraw deployed at:", address(bridgeDepositWithdraw)); // Deploy some test tokens diff --git a/protocol/script/DeployMintBurn.s.sol b/protocol/script/DeployMintBurn.s.sol index 94793627..02b2c274 100644 --- a/protocol/script/DeployMintBurn.s.sol +++ b/protocol/script/DeployMintBurn.s.sol @@ -7,12 +7,14 @@ import {BridgeMintBurn} from "../src/BridgeMintBurn.sol"; import {PodRegistry} from "../src/PodRegistry.sol"; contract DeployMintBurn is Script { + address constant OTHER_BRIDGE_CONTRACT = 0x12296f2D128530a834460DF6c36a2895B793F26d; + function run() external { console.log("=== Deploying BridgeMintBurn to localhost:8545 (chainId 1293) ==="); vm.startBroadcast(); - BridgeMintBurn bridgeMintBurn = new BridgeMintBurn(); + BridgeMintBurn bridgeMintBurn = new BridgeMintBurn(OTHER_BRIDGE_CONTRACT); console.log("BridgeMintBurn deployed at:", address(bridgeMintBurn)); vm.stopBroadcast(); diff --git a/protocol/src/BridgeDepositWithdraw.sol b/protocol/src/BridgeDepositWithdraw.sol index f1f51349..851f3f65 100644 --- a/protocol/src/BridgeDepositWithdraw.sol +++ b/protocol/src/BridgeDepositWithdraw.sol @@ -7,6 +7,7 @@ import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import {PodECDSA} from "pod-sdk/verifier/PodECDSA.sol"; import {IPodRegistry} from "./interfaces/IPodRegistry.sol"; +import {console} from "forge-std/console.sol"; /** * @title BridgeDepositWithdraw @@ -23,11 +24,16 @@ contract BridgeDepositWithdraw is Bridge, IBridgeDepositWithdraw { */ PodECDSA.PodConfig public podConfig; + /** + * @dev The index of the next deposit. + */ + uint256 public depositIndex; + /** * @dev Constructor. * @param _podRegistry The address of the PodRegistry to use. */ - constructor(address _podRegistry) { + constructor(address _podRegistry, address _bridgeContract) Bridge(_bridgeContract) { podConfig = PodECDSA.PodConfig({thresholdNumerator: 2, thresholdDenominator: 3, registry: IPodRegistry(_podRegistry)}); } @@ -40,17 +46,38 @@ contract BridgeDepositWithdraw is Bridge, IBridgeDepositWithdraw { * @return amount The amount of the deposit. * @return to The address to send the tokens to. */ - function _decodeLog(PodECDSA.Log calldata log) + function _decodeDepositLog(PodECDSA.Log calldata log) internal pure returns (uint256 id, address token, uint256 amount, address to) { - if (log.topics.length != 3 || log.topics[0] != DEPOSIT_TOPIC_0) revert InvalidDepositLog(); + if (log.topics[0] != DEPOSIT_TOPIC_0 || log.topics.length != 3) { + revert InvalidDepositLog(); + } id = uint256(log.topics[1]); token = address(uint160(uint256(log.topics[2]))); (amount, to) = abi.decode(log.data, (uint256, address)); } + /** + * @dev Decodes the log into native deposit details. + * @param log The log to decode. + * @return id The id of the deposit. + * @return amount The amount of the deposit. + * @return to The address to send the tokens to. + */ + function _decodeDepositNativeLog(PodECDSA.Log calldata log) + internal + pure + returns (uint256 id, uint256 amount, address to) + { + if (log.topics[0] != DEPOSIT_NATIVE_TOPIC_0 || log.topics.length != 2) { + revert InvalidDepositLog(); + } + id = uint256(log.topics[1]); + (amount, to) = abi.decode(log.data, (uint256, address)); + } + /** * @dev Handles the deposit of tokens. The tokens are transferred from the msg.sender to the contract. * @param token The token to deposit. @@ -60,6 +87,14 @@ contract BridgeDepositWithdraw is Bridge, IBridgeDepositWithdraw { IERC20(token).safeTransferFrom(msg.sender, address(this), amount); } + /** + * @dev Internal function to get the deposit ID. + * @return id The request ID of the deposit. + */ + function _getDepositId() internal override returns (uint256) { + return depositIndex++; + } + /** * @dev Handles the migration of tokens. The tokens are transferred from the contract to the new contract. * @param _newContract The address of the new contract. @@ -78,7 +113,7 @@ contract BridgeDepositWithdraw is Bridge, IBridgeDepositWithdraw { * @inheritdoc IBridgeDepositWithdraw */ function claim(PodECDSA.CertifiedLog calldata certifiedLog) public override whenNotPaused { - (uint256 id, address token, uint256 amount, address to) = _decodeLog(certifiedLog.log); + (uint256 id, address token, uint256 amount, address to) = _decodeDepositLog(certifiedLog.log); address mirrorToken = mirrorTokens[token]; if (mirrorToken == address(0)) revert MirrorTokenNotFound(); @@ -87,6 +122,8 @@ contract BridgeDepositWithdraw is Bridge, IBridgeDepositWithdraw { bytes32 requestId = _hashRequest(id, token, amount, to); if (processedRequests[requestId]) revert RequestAlreadyProcessed(); + if (certifiedLog.log.addr != bridgeContract) revert InvalidBridgeContract(); + bool verified = PodECDSA.verifyCertifiedLog(podConfig, certifiedLog); if (!verified) revert InvalidCertificate(); @@ -96,6 +133,28 @@ contract BridgeDepositWithdraw is Bridge, IBridgeDepositWithdraw { emit Claim(id, mirrorToken, token, amount, to); } + /** + * @inheritdoc IBridgeDepositWithdraw + */ + function claimNative(PodECDSA.CertifiedLog calldata certifiedLog) public override whenNotPaused { + (uint256 id, uint256 amount, address to) = _decodeDepositNativeLog(certifiedLog.log); + + if (amount < 0.01 ether) revert InvalidAmount(); + + bytes32 requestId = _hashRequest(id, address(0), amount, to); + if (processedRequests[requestId]) revert RequestAlreadyProcessed(); + + if (certifiedLog.log.addr != bridgeContract) revert InvalidBridgeContract(); + + bool verified = PodECDSA.verifyCertifiedLog(podConfig, certifiedLog); + if (!verified) revert InvalidCertificate(); + + processedRequests[requestId] = true; + + payable(to).transfer(amount); + emit ClaimNative(id, amount, to); + } + /** * @inheritdoc IBridgeDepositWithdraw */ diff --git a/protocol/src/BridgeMintBurn.sol b/protocol/src/BridgeMintBurn.sol index 1a367841..9052b87d 100644 --- a/protocol/src/BridgeMintBurn.sol +++ b/protocol/src/BridgeMintBurn.sol @@ -8,7 +8,11 @@ import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol import {IAccessControl} from "@openzeppelin/contracts/access/IAccessControl.sol"; import {IERC20MintableAndBurnable} from "./interfaces/IERC20MintableAndBurnable.sol"; import {WrappedToken} from "./WrappedToken.sol"; -import {EthGetLogsPrecompileHelperTypes} from "pod-sdk/types/EthGetLogsPrecompileHelperTypes.sol"; +import {EthGetLogsTypes} from "pod-sdk/types/EthGetLogsTypes.sol"; +import {EthGetBlockByNumberTypes} from "pod-sdk/types/EthGetBlockByNumberTypes.sol"; +import {PodMintBalance} from "./libraries/PodMintBalance.sol"; +import {TxInfo, getTxInfo} from "pod-sdk/Context.sol"; +import {HexUtils} from "./libraries/HexUtils.sol"; /** * @title BridgeMintBurn @@ -37,7 +41,7 @@ contract BridgeMintBurn is Bridge, IBridgeMintBurn { /** * @dev Constructor. */ - constructor() {} + constructor(address _bridgeContract) Bridge(_bridgeContract) {} /** * @dev Handles the deposit of tokens. The tokens are burned from the msg.sender. @@ -49,31 +53,68 @@ contract BridgeMintBurn is Bridge, IBridgeMintBurn { } /** - * @inheritdoc IBridgeMintBurn + * @dev Internal function to get the deposit ID. + * @return id The request ID of the deposit. */ - function claim(uint256 id, address token, bytes calldata blockNumberFrom) public whenNotPaused { - bytes32[] memory topics = new bytes32[](3); - topics[0] = DEPOSIT_TOPIC_0; - topics[1] = bytes32(id); - topics[2] = bytes32(uint256(uint160(token))); + function _getDepositId() internal view override returns (uint256) { + TxInfo memory txInfo = getTxInfo(); + return uint256(txInfo.txHash); + } - (bool success, bytes memory output) = EthGetLogsPrecompileHelperTypes.PRECOMPILE_ADDRESS.staticcall( + function _getFinalizedBlockNumber() internal view returns (uint256) { + (bool success, bytes memory output) = EthGetBlockByNumberTypes.PRECOMPILE_ADDRESS.staticcall( abi.encode( - EthGetLogsPrecompileHelperTypes.PrecompileArgs( - SOURCE_CHAIN_ID, - EthGetLogsPrecompileHelperTypes.RpcArgs( - blockNumberFrom, FINALIZED_BLOCK_BYTES, address(token), bytes32(0), topics - ) + EthGetBlockByNumberTypes.PrecompileArgs( + SOURCE_CHAIN_ID, EthGetBlockByNumberTypes.RpcArgs(FINALIZED_BLOCK_BYTES, false) ) ) ); if (!success) revert PrecompileCallFailed(); - EthGetLogsPrecompileHelperTypes.RpcLog[] memory logs = - abi.decode(output, (EthGetLogsPrecompileHelperTypes.RpcLog[])); + EthGetBlockByNumberTypes.RpcBlock memory rpcBlock = abi.decode(output, (EthGetBlockByNumberTypes.RpcBlock)); + + return HexUtils.uintFromBigEndian(rpcBlock.number); + } + + function _getLogs(uint256 blockNumber, bytes32[] memory topics) + internal + view + returns (EthGetLogsTypes.RpcLog[] memory) + { + bytes memory precompileArgs; + bytes memory blockNumberBytes = HexUtils.toBytesMinimal(blockNumber); + precompileArgs = abi.encode( + EthGetLogsTypes.PrecompileArgs( + SOURCE_CHAIN_ID, + EthGetLogsTypes.RpcArgs(blockNumberBytes, blockNumberBytes, address(bridgeContract), bytes32(0), topics) + ) + ); + (bool success, bytes memory output) = EthGetLogsTypes.PRECOMPILE_ADDRESS.staticcall(precompileArgs); + if (!success) revert PrecompileCallFailed(); + EthGetLogsTypes.RpcLog[] memory logs = abi.decode(output, (EthGetLogsTypes.RpcLog[])); + + if (logs.length != 1) revert InvalidDepositLog(); + if (logs[0].addr != bridgeContract) revert InvalidBridgeContract(); + + return logs; + } + + /** + * @inheritdoc IBridgeMintBurn + */ + function claim(uint256 id, address token, uint256 blockNumber) external override whenNotPaused { + bytes32[] memory topics = new bytes32[](3); + topics[0] = DEPOSIT_TOPIC_0; + topics[1] = bytes32(id); + topics[2] = bytes32(uint256(uint160(token))); + + uint256 finalizedBlockNumber = _getFinalizedBlockNumber(); + + if (blockNumber > finalizedBlockNumber) { + revert BlockNotFinalized(); + } - if (logs.length == 0) revert NoDepositsFound(); - if (logs.length > 1) revert MultipleDepositsWithSameId(); + EthGetLogsTypes.RpcLog[] memory logs = _getLogs(blockNumber, topics); (uint256 decodedAmount, address decodedTo) = abi.decode(logs[0].data, (uint256, address)); @@ -93,6 +134,39 @@ contract BridgeMintBurn is Bridge, IBridgeMintBurn { emit Claim(id, mirrorToken, token, decodedAmount, decodedTo); } + /** + * @inheritdoc IBridgeMintBurn + */ + function claimNative(uint256 id, uint256 blockNumber) external override whenNotPaused { + bytes32[] memory topics = new bytes32[](2); + topics[0] = DEPOSIT_NATIVE_TOPIC_0; + topics[1] = bytes32(id); + + uint256 finalizedBlockNumber = _getFinalizedBlockNumber(); + + if (blockNumber > finalizedBlockNumber) { + revert BlockNotFinalized(); + } + + EthGetLogsTypes.RpcLog[] memory logs = _getLogs(blockNumber, topics); + + (uint256 decodedAmount, address decodedTo) = abi.decode(logs[0].data, (uint256, address)); + + if (decodedAmount < 0.01 ether) revert InvalidAmount(); + + bytes32 requestId = _hashRequest(id, address(0), decodedAmount, decodedTo); + if (processedRequests[requestId]) revert RequestAlreadyProcessed(); + + if (decodedTo != msg.sender) revert InvalidToAddress(); + + processedRequests[requestId] = true; + + // mint the native tokens to msg.sender + if (!PodMintBalance.mint(decodedAmount)) revert PrecompileCallFailed(); + + emit ClaimNative(id, decodedAmount, decodedTo); + } + /** * @dev Handles the migration of tokens. The tokens and roles are transferred from the contract to the new contract. * @param _newContract The address of the new contract. diff --git a/protocol/src/abstract/Bridge.sol b/protocol/src/abstract/Bridge.sol index 90d8ef64..e3508958 100644 --- a/protocol/src/abstract/Bridge.sol +++ b/protocol/src/abstract/Bridge.sol @@ -31,6 +31,11 @@ abstract contract Bridge is IBridge, AccessControl, Pausable { */ bytes32 constant DEPOSIT_TOPIC_0 = keccak256("Deposit(uint256,address,uint256,address)"); + /** + * @dev The topic 0 (event signature) of the deposit native event. + */ + bytes32 constant DEPOSIT_NATIVE_TOPIC_0 = keccak256("DepositNative(uint256,uint256,address)"); + /** * @dev Map token address to token data. */ @@ -53,23 +58,29 @@ abstract contract Bridge is IBridge, AccessControl, Pausable { address[] public whitelistedTokens; /** - * @dev A counter tracking the number of deposits. - * @notice Id of the current deposit. + * @dev Map nonce to used nonces. */ - uint256 public depositIndex; + mapping(uint256 => bool) public usedNonces; /** * @dev Address of the migrated contract. */ address public migratedContract; + /** + * @dev The address of the bridge contract on the other chain. + */ + address public bridgeContract; + /** * @dev Constructor. * @notice Grants the DEFAULT_ADMIN_ROLE and PAUSER_ROLE to the msg.sender. */ - constructor() { + constructor(address _bridgeContract) { + if (_bridgeContract == address(0)) revert InvalidBridgeContract(); _grantRole(DEFAULT_ADMIN_ROLE, msg.sender); _grantRole(PAUSER_ROLE, msg.sender); + bridgeContract = _bridgeContract; } /** @@ -80,6 +91,13 @@ abstract contract Bridge is IBridge, AccessControl, Pausable { */ function handleDeposit(address token, uint256 amount) internal virtual; + /** + * @dev Internal function to get the deposit ID. + * This is a callback defining the different deposit ID logic for the different bridge contracts. + * @return id The request ID of the deposit. + */ + function _getDepositId() internal virtual returns (uint256); + /** * @dev Internal function to handle the migration of tokens. * This is a callback defining the different token handling logic for the different bridge contracts. @@ -140,14 +158,23 @@ abstract contract Bridge is IBridge, AccessControl, Pausable { /** * @inheritdoc IBridge */ - function deposit(address token, uint256 amount, address to) external whenNotPaused returns (uint256 id) { + function deposit(address token, uint256 amount, address to) external override whenNotPaused { if (!_isValidTokenAmount(token, amount, true)) revert InvalidTokenAmount(); if (to == address(0)) revert InvalidToAddress(); - id = depositIndex++; + uint256 id = _getDepositId(); handleDeposit(token, amount); emit Deposit(id, token, amount, to); } + /** + * @inheritdoc IBridge + */ + function depositNative(address to) external payable override whenNotPaused { + if (msg.value < 0.01 ether) revert InvalidAmount(); + uint256 id = _getDepositId(); + emit DepositNative(id, msg.value, to); + } + /** * @dev Internal function to hash a request. * @param id The request index. diff --git a/protocol/src/interfaces/IBridge.sol b/protocol/src/interfaces/IBridge.sol index fb50533a..cd10e67e 100644 --- a/protocol/src/interfaces/IBridge.sol +++ b/protocol/src/interfaces/IBridge.sol @@ -19,6 +19,11 @@ interface IBridge { */ error InvalidTokenAmount(); + /** + * @dev Error thrown when the provided amount is invalid. + */ + error InvalidAmount(); + /** * @dev Error thrown when the destination address is zero or invalid. */ @@ -44,6 +49,21 @@ interface IBridge { */ error RequestAlreadyProcessed(); + /** + * @dev Error thrown when the bridge contract is invalid. + */ + error InvalidBridgeContract(); + + /** + * @dev Error thrown when the deposit log is invalid. + */ + error InvalidDepositLog(); + + /** + * @dev Error thrown when the nonce is invalid. + */ + error InvalidNonce(); + /** * @dev Event emitted when a deposit is made. * @param id The request index. @@ -53,6 +73,14 @@ interface IBridge { */ event Deposit(uint256 indexed id, address indexed token, uint256 amount, address to); + /** + * @dev Event emitted when a native deposit is made. + * @param id The request index. + * @param amount The amount of native tokens to bridge. + * @param to The address to send the native tokens to. + */ + event DepositNative(uint256 indexed id, uint256 amount, address to); + /** * @dev Event emitted when a claim is made. * @param id The request index. @@ -63,6 +91,14 @@ interface IBridge { */ event Claim(uint256 indexed id, address indexed mirrorToken, address indexed token, uint256 amount, address to); + /** + * @dev Event emitted when a native claim is made. + * @param id The request index. + * @param amount The amount of native tokens to bridge. + * @param to The address to send the native tokens to. + */ + event ClaimNative(uint256 indexed id, uint256 amount, address to); + /** * @dev Token limits. * @param minAmount The minimum amount of tokens that can be deposited. @@ -111,13 +147,13 @@ interface IBridge { address to; } - /** - * @return The number of deposits. - */ - function depositIndex() external view returns (uint256); - /** * @dev Update a token's configuration information. + * Token limits need to be set to half the desired value, due to users being able to deposit and claim at the boundry condition. + * If the desired deposit limit is 1000 tokens, the limit should be set to 500 tokens. + * For example, the limits are over the course of 1 day, and the limit reset at 12:00 AM UTC and suppose there are no bridging transactions + * for that day until 11:58 PM UTC. Then a user can deposit the limit amount at 11:59 PM UTC, and then immediately + * deposit the limit amount again at 12:00 AM UTC. * @notice Token can be disabled by setting deposit and claim limits to zero. * @notice Access is restricted to the admin. * @param token The token to configure. @@ -131,9 +167,15 @@ interface IBridge { * @param token The token to bridge. * @param amount The amount of tokens to bridge. * @param to The address to send the tokens to on the destination chain. - * @return The ID (request index) associated to the request. */ - function deposit(address token, uint256 amount, address to) external returns (uint256); + function deposit(address token, uint256 amount, address to) external; + + /** + * @dev Deposit native tokens to bridge to the destination chain. + * @notice Function used to bridge native tokens to the destination chain. + * @param to The address to send the native tokens to on the destination chain. + */ + function depositNative(address to) external payable; /** * @dev Pauses the contract. diff --git a/protocol/src/interfaces/IBridgeDepositWithdraw.sol b/protocol/src/interfaces/IBridgeDepositWithdraw.sol index ed593eeb..a8bdb475 100644 --- a/protocol/src/interfaces/IBridgeDepositWithdraw.sol +++ b/protocol/src/interfaces/IBridgeDepositWithdraw.sol @@ -25,9 +25,10 @@ interface IBridgeDepositWithdraw is IBridge { function claim(PodECDSA.CertifiedLog calldata certifiedLog) external; /** - * @dev Error thrown when the deposit log is invalid. + * @notice Claim native tokens using a certified log proof. + * @param certifiedLog The proof of the deposit represented as a pod certified log. */ - error InvalidDepositLog(); + function claimNative(PodECDSA.CertifiedLog calldata certifiedLog) external; /** * @dev Error thrown when the certificate verification fails. diff --git a/protocol/src/interfaces/IBridgeMintBurn.sol b/protocol/src/interfaces/IBridgeMintBurn.sol index ccb35f0a..c88cb7a6 100644 --- a/protocol/src/interfaces/IBridgeMintBurn.sol +++ b/protocol/src/interfaces/IBridgeMintBurn.sol @@ -32,22 +32,24 @@ interface IBridgeMintBurn is IBridge { * @notice Claim bridged tokens using external precompile verification. * @param id Deposit ID to claim. * @param token Source chain token address. - * @param blockNumberFrom Starting block number for log search. + * @param blockNumber The block number that contains the log to of the deposit. */ - function claim(uint256 id, address token, bytes calldata blockNumberFrom) external; + function claim(uint256 id, address token, uint256 blockNumber) external; /** - * @dev Error thrown when multiple deposits are found with the same ID. + * @notice Claim native tokens using external precompile verification. + * @param id Deposit ID to claim. + * @param blockNumber The block number that contains the log to of the native deposit. */ - error MultipleDepositsWithSameId(); + function claimNative(uint256 id, uint256 blockNumber) external; /** - * @dev Error thrown when no deposits are found for the given parameters. + * @dev Error thrown when the external precompile call fails. */ - error NoDepositsFound(); + error PrecompileCallFailed(); /** - * @dev Error thrown when the external precompile call fails. + * @dev Error thrown when the block is not finalized. */ - error PrecompileCallFailed(); + error BlockNotFinalized(); } diff --git a/protocol/src/libraries/HexUtils.sol b/protocol/src/libraries/HexUtils.sol new file mode 100644 index 00000000..18e79e42 --- /dev/null +++ b/protocol/src/libraries/HexUtils.sol @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +library HexUtils { + error Empty(); + error InvalidHexChar(uint8 ch, uint256 pos); + error Overflow256(); + + bytes16 private constant _HEX = "0123456789abcdef"; + + /// @notice Parse raw big-endian bytes into uint256 (e.g. 0x01 0x56). + /// @param b The bytes to parse. + /// @return v The parsed uint256. + function uintFromBigEndian(bytes memory b) internal pure returns (uint256 v) { + uint256 len = b.length; + if (len == 0) revert Empty(); + if (len > 32) revert Overflow256(); + for (uint256 i = 0; i < len; ++i) { + v = (v << 8) | uint8(b[i]); + } + } + + /// @notice Minimal big-endian BINARY bytes: 1 -> 0x01, 0 -> 0x00. + /// @param value The value to convert. + /// @return out The converted bytes. + function toBytesMinimal(uint256 value) internal pure returns (bytes memory out) { + if (value == 0) return hex"00"; + uint256 v = value; + uint256 len; + while (v != 0) { + len++; + v >>= 8; + } + out = new bytes(len); + v = value; + for (uint256 i = len; i > 0;) { + out[--i] = bytes1(uint8(v)); + v >>= 8; + } + } +} diff --git a/protocol/src/libraries/PodMintBalance.sol b/protocol/src/libraries/PodMintBalance.sol new file mode 100644 index 00000000..16703b7c --- /dev/null +++ b/protocol/src/libraries/PodMintBalance.sol @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.28; + +library PodMintBalance { + /** + * @dev The address of the external pod mint balance precompile. + */ + address constant PRECOMPILE_ADDRESS = address(uint160(uint256(keccak256("POD_MINT_BALANCE")))); + + /** + * @dev Mints tokens to the caller. + * @param amount The amount of tokens to mint. + * @return success Whether the minting was successful. + */ + function mint(uint256 amount) external view returns (bool) { + (bool success,) = PRECOMPILE_ADDRESS.staticcall(abi.encode(amount)); + return success; + } +} diff --git a/protocol/test/BridgeDepositWithdraw.t.sol b/protocol/test/BridgeDepositWithdraw.t.sol index b6bc241a..326880fa 100644 --- a/protocol/test/BridgeDepositWithdraw.t.sol +++ b/protocol/test/BridgeDepositWithdraw.t.sol @@ -22,6 +22,7 @@ contract BridgeDepositWithdrawTest is BridgeBehaviorTest { uint256[] validatorPrivateKeys; uint256 constant NUMBER_OF_VALIDATORS = 4; address immutable MIRROR_TOKEN = makeAddr("mirrorToken"); + address immutable OTHER_BRIDGE_CONTRACT = makeAddr("otherBridgeContract"); function bridge() internal view override returns (Bridge) { return _bridge; @@ -43,7 +44,8 @@ contract BridgeDepositWithdrawTest is BridgeBehaviorTest { } podRegistry = new PodRegistry(initialValidators); - _bridge = new BridgeDepositWithdraw(address(podRegistry)); + _bridge = new BridgeDepositWithdraw(address(podRegistry), OTHER_BRIDGE_CONTRACT); + _token = new WrappedToken("InitialToken", "ITKN", 18); _token.mint(user, INITIAL_BALANCE); _token.mint(admin, INITIAL_BALANCE); @@ -56,6 +58,17 @@ contract BridgeDepositWithdrawTest is BridgeBehaviorTest { _token.approve(address(_bridge), type(uint256).max); } + function test_DepositIndex_IncrementsSequentially() public { + uint256 beforeIdx = _bridge.depositIndex(); + vm.prank(user); + bridge().deposit(address(token()), tokenLimits.minAmount, recipient); + assertEq(_bridge.depositIndex(), beforeIdx + 1); + + vm.prank(user); + bridge().deposit(address(token()), tokenLimits.minAmount, recipient); + assertEq(_bridge.depositIndex(), beforeIdx + 2); + } + function test_Deposit_TransfersIntoBridge() public { uint256 ub = _token.balanceOf(user); uint256 bb = _token.balanceOf(address(_bridge)); @@ -104,6 +117,13 @@ contract BridgeDepositWithdrawTest is BridgeBehaviorTest { _bridge.claim(certifiedLog); } + function test_Claim_RevertIfInvalidBridgeContract() public { + PodECDSA.CertifiedLog memory certifiedLog = createCertifiedLog(3); + certifiedLog.log.addr = address(0xBEEF); + vm.expectRevert(abi.encodeWithSelector(IBridge.InvalidBridgeContract.selector)); + _bridge.claim(certifiedLog); + } + function test_Claim_RevertIfAlreadyClaimed() public { vm.prank(admin); _bridge.deposit(address(_token), DEPOSIT_AMOUNT, recipient); @@ -113,16 +133,96 @@ contract BridgeDepositWithdrawTest is BridgeBehaviorTest { _bridge.claim(certifiedLog); } + function test_ClaimNative() public { + vm.deal(admin, DEPOSIT_AMOUNT); + vm.prank(admin); + _bridge.depositNative{value: DEPOSIT_AMOUNT}(recipient); + assertEq(address(bridge()).balance, DEPOSIT_AMOUNT); + assertEq(recipient.balance, 0); + PodECDSA.CertifiedLog memory certifiedLog = createNativeCertifiedLog(3); + vm.expectEmit(true, false, false, true); + emit IBridge.ClaimNative(0, DEPOSIT_AMOUNT, recipient); + _bridge.claimNative(certifiedLog); + assertEq(address(bridge()).balance, 0); + assertEq(recipient.balance, DEPOSIT_AMOUNT); + } + + function test_ClaimNative_RevertIfPaused() public { + vm.prank(admin); + _bridge.pause(); + PodECDSA.CertifiedLog memory certifiedLog = createNativeCertifiedLog(3); + vm.expectRevert(abi.encodeWithSelector(Pausable.EnforcedPause.selector)); + _bridge.claimNative(certifiedLog); + } + + function test_ClaimNative_RevertIfInvalidLog() public { + PodECDSA.CertifiedLog memory certifiedLog = createNativeCertifiedLog(3); + certifiedLog.log.topics[0] = bytes32(uint256(1232)); + vm.expectRevert(abi.encodeWithSelector(IBridge.InvalidDepositLog.selector)); + _bridge.claimNative(certifiedLog); + } + + function test_ClaimNative_RevertIfInvalidBridgeContract() public { + PodECDSA.CertifiedLog memory certifiedLog = createNativeCertifiedLog(3); + certifiedLog.log.addr = address(0xBEEF); + vm.expectRevert(abi.encodeWithSelector(IBridge.InvalidBridgeContract.selector)); + _bridge.claimNative(certifiedLog); + } + + function test_ClaimNative_RevertIfInvalidAmount() public { + vm.deal(admin, DEPOSIT_AMOUNT); + vm.prank(admin); + _bridge.depositNative{value: DEPOSIT_AMOUNT}(recipient); + PodECDSA.CertifiedLog memory certifiedLog = createNativeCertifiedLog(3); + certifiedLog.log.data = abi.encode(uint256(0.001 ether), recipient); + vm.expectRevert(abi.encodeWithSelector(IBridge.InvalidAmount.selector)); + _bridge.claimNative(certifiedLog); + assertEq(address(bridge()).balance, DEPOSIT_AMOUNT); + assertEq(recipient.balance, 0); + } + + function test_ClaimNative_RevertIfInvalidCertificate() public { + // invalid leaf + vm.deal(admin, DEPOSIT_AMOUNT); + vm.prank(admin); + _bridge.depositNative{value: DEPOSIT_AMOUNT}(recipient); + PodECDSA.CertifiedLog memory certifiedLog = createNativeCertifiedLog(3); + certifiedLog.certificate.leaf = bytes32(0); + vm.expectRevert(abi.encodeWithSelector(IBridgeDepositWithdraw.InvalidCertificate.selector)); + _bridge.claimNative(certifiedLog); + + // tampered proof + certifiedLog = createNativeCertifiedLog(3); + certifiedLog.certificate.proof.path[0] = bytes32(uint256(1232)); + vm.expectRevert(abi.encodeWithSelector(IBridgeDepositWithdraw.InvalidCertificate.selector)); + _bridge.claimNative(certifiedLog); + + // not enough signatures + certifiedLog = createNativeCertifiedLog(2); + vm.expectRevert(abi.encodeWithSelector(IBridgeDepositWithdraw.InvalidCertificate.selector)); + _bridge.claimNative(certifiedLog); + } + + function test_ClaimNative_RevertIfAlreadyClaimed() public { + vm.deal(admin, DEPOSIT_AMOUNT); + vm.prank(admin); + _bridge.depositNative{value: DEPOSIT_AMOUNT}(recipient); + PodECDSA.CertifiedLog memory certifiedLog = createNativeCertifiedLog(3); + _bridge.claimNative(certifiedLog); + vm.expectRevert(abi.encodeWithSelector(IBridge.RequestAlreadyProcessed.selector)); + _bridge.claimNative(certifiedLog); + } + function test_Claim_RevertIfInvalidDepositLog() public { PodECDSA.CertifiedLog memory certifiedLog = createCertifiedLog(3); certifiedLog.log.topics[0] = bytes32(uint256(1232)); - vm.expectRevert(abi.encodeWithSelector(IBridgeDepositWithdraw.InvalidDepositLog.selector)); + vm.expectRevert(abi.encodeWithSelector(IBridge.InvalidDepositLog.selector)); _bridge.claim(certifiedLog); certifiedLog = createCertifiedLog(3); certifiedLog.log.topics = new bytes32[](1); certifiedLog.log.topics[0] = bytes32(uint256(1232)); - vm.expectRevert(abi.encodeWithSelector(IBridgeDepositWithdraw.InvalidDepositLog.selector)); + vm.expectRevert(abi.encodeWithSelector(IBridge.InvalidDepositLog.selector)); _bridge.claim(certifiedLog); } @@ -169,9 +269,19 @@ contract BridgeDepositWithdrawTest is BridgeBehaviorTest { _bridge.deposit(address(_token), DEPOSIT_AMOUNT, recipient); } + function test_DepositNative_IncrementsIndexSequentially() public { + vm.deal(user, 2 * DEPOSIT_AMOUNT); + vm.prank(user); + _bridge.depositNative{value: DEPOSIT_AMOUNT}(recipient); + assertEq(_bridge.depositIndex(), 1); + vm.prank(user); + _bridge.depositNative{value: DEPOSIT_AMOUNT}(recipient); + assertEq(_bridge.depositIndex(), 2); + } + function test_Migrate_NoWhitelistedTokens() public { vm.prank(admin); - BridgeDepositWithdraw fresh = new BridgeDepositWithdraw(address(podRegistry)); + BridgeDepositWithdraw fresh = new BridgeDepositWithdraw(address(podRegistry), OTHER_BRIDGE_CONTRACT); vm.prank(admin); fresh.pause(); vm.prank(admin); @@ -233,7 +343,7 @@ contract BridgeDepositWithdrawTest is BridgeBehaviorTest { view returns (PodECDSA.CertifiedLog memory) { - bytes32 receiptRoot = 0xca35a1783abe48ca23da757fb7253a1315777b4e8820262c67e85e6f87eb340f; + bytes32 receiptRoot = 0xb971e2eaeaab46dbad2fa4ed54edbaac586939dbc33c73315903a80bcc931b39; bytes32[] memory topics = new bytes32[](3); topics[0] = keccak256("Deposit(uint256,address,uint256,address)"); topics[1] = bytes32(uint256(0)); @@ -243,10 +353,59 @@ contract BridgeDepositWithdrawTest is BridgeBehaviorTest { bytes32[] memory merklePath = new bytes32[](4); - merklePath[0] = 0x8a998be39bd3962defce6fb56ba8a10da89ae208743fa4147503adebfb32005d; - merklePath[1] = 0x2498e05df11f1325b6f78c1d181cb7db187233732812af1f16efe9a129abe618; - merklePath[2] = 0xaae4eb6d4b3989ffc690c918484b530f4d853427b635b39e8f70975dd7cbff1b; - merklePath[3] = 0x996db2475c7d59b0652b50c24aeca2454967b3e7101a667e2ce9d03567202483; + merklePath[0] = 0x42ee24b8bf1831e9a79284d4f5719840477450d02681315d2d2ae29a4c2c829b; + merklePath[1] = 0x05ad2355f20950fa862daf53cc8ac0b82c0106289c3e1e4c8602aa13792d0831; + merklePath[2] = 0x0eb6eaabad615528bc24c8c5786a4ceff0c07481daac20e40a7f009c47b1868e; + merklePath[3] = 0xa570326bbbc2e5afb293034a35a7a074d76d2ec3af3695beb2da2b870da524b5; + + bytes[] memory signatures = new bytes[](numberOfRequiredSignatures); + uint256[] memory sortedAttestationTimestamps = new uint256[](numberOfRequiredSignatures); + for (uint256 i = 0; i < numberOfRequiredSignatures; i++) { + (uint8 v, bytes32 r, bytes32 s) = vm.sign(validatorPrivateKeys[i], receiptRoot); + signatures[i] = ECDSA._serialize_signature(v, r, s); + sortedAttestationTimestamps[i] = i + 1; + } + + bytes memory aggregateSignature = ECDSA.aggregate_signatures(signatures); + + PodECDSA.CertifiedReceipt memory certifiedReceipt = PodECDSA.CertifiedReceipt({ + receiptRoot: receiptRoot, + aggregateSignature: aggregateSignature, + sortedAttestationTimestamps: sortedAttestationTimestamps + }); + + PodECDSA.Log memory log = PodECDSA.Log({addr: address(OTHER_BRIDGE_CONTRACT), topics: topics, data: data}); + + bytes32 logHash = PodECDSA.hashLog(log); + bytes32 leaf = MerkleTree.hashLeaf(bytes("log_hashes[1]"), logHash); + MerkleTree.Proof memory proof = MerkleTree.Proof({path: merklePath}); + + PodECDSA.CertifiedLog memory certifiedLog = PodECDSA.CertifiedLog({ + log: log, + logIndex: 1, + certificate: PodECDSA.Certificate({leaf: leaf, certifiedReceipt: certifiedReceipt, proof: proof}) + }); + + return certifiedLog; + } + + function createNativeCertifiedLog(uint256 numberOfRequiredSignatures) + internal + view + returns (PodECDSA.CertifiedLog memory) + { + bytes32 receiptRoot = 0x53530f2085bae5343304dc02eba7f347453fe00ad74f5acf9f0aced719fe4a03; + bytes32[] memory topics = new bytes32[](2); + topics[0] = keccak256("DepositNative(uint256,uint256,address)"); + topics[1] = bytes32(uint256(0)); + + bytes memory data = abi.encode(DEPOSIT_AMOUNT, recipient); + + bytes32[] memory merklePath = new bytes32[](3); + + merklePath[0] = 0x05ad2355f20950fa862daf53cc8ac0b82c0106289c3e1e4c8602aa13792d0831; + merklePath[1] = 0x801cf30b996f0126b23e8bb5b0833b4253c4c752a64cefd31adbc887f04397c1; + merklePath[2] = 0xa12e4e7415c5592a840a2fd2d4b0786526eb78284f1f8f8ecd7d10fd113f4a14; bytes[] memory signatures = new bytes[](numberOfRequiredSignatures); uint256[] memory sortedAttestationTimestamps = new uint256[](numberOfRequiredSignatures); @@ -264,7 +423,7 @@ contract BridgeDepositWithdrawTest is BridgeBehaviorTest { sortedAttestationTimestamps: sortedAttestationTimestamps }); - PodECDSA.Log memory log = PodECDSA.Log({addr: address(_bridge), topics: topics, data: data}); + PodECDSA.Log memory log = PodECDSA.Log({addr: address(OTHER_BRIDGE_CONTRACT), topics: topics, data: data}); bytes32 logHash = PodECDSA.hashLog(log); bytes32 leaf = MerkleTree.hashLeaf(bytes("log_hashes[1]"), logHash); diff --git a/protocol/test/BridgeMintBurn.t.sol b/protocol/test/BridgeMintBurn.t.sol index ca780b8d..10bfd272 100644 --- a/protocol/test/BridgeMintBurn.t.sol +++ b/protocol/test/BridgeMintBurn.t.sol @@ -9,12 +9,16 @@ import {Bridge} from "../src/abstract/Bridge.sol"; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import {WrappedToken} from "../src/WrappedToken.sol"; import {Pausable} from "@openzeppelin/contracts/utils/Pausable.sol"; -import {EthGetLogsPrecompileHelperTypes} from "pod-sdk/types/EthGetLogsPrecompileHelperTypes.sol"; +import {EthGetLogsTypes} from "pod-sdk/types/EthGetLogsTypes.sol"; +import {EthGetBlockByNumberTypes} from "pod-sdk/types/EthGetBlockByNumberTypes.sol"; +import {HexUtils} from "../src/libraries/HexUtils.sol"; +import {TxInfo} from "pod-sdk/Context.sol"; contract BridgeMintBurnTest is BridgeBehaviorTest { BridgeMintBurn private _bridge; WrappedToken private _token; address immutable _mirror = makeAddr("mirrorToken"); + address immutable OTHER_BRIDGE_CONTRACT = makeAddr("otherBridgeContract"); function bridge() internal view override returns (Bridge) { return _bridge; @@ -26,7 +30,7 @@ contract BridgeMintBurnTest is BridgeBehaviorTest { function setUpSuite() public override { vm.startPrank(admin); - _bridge = new BridgeMintBurn(); + _bridge = new BridgeMintBurn(OTHER_BRIDGE_CONTRACT); _token = WrappedToken( _bridge.createAndWhitelistMirrorToken("Token", "TKN", address(0), address(_mirror), 18, tokenLimits) @@ -38,26 +42,31 @@ contract BridgeMintBurnTest is BridgeBehaviorTest { vm.prank(user); _token.approve(address(_bridge), type(uint256).max); + + _mockTxInfo(TxInfo({txHash: bytes32(0), nonce: 0})); } function test_Deposit_BurnsFromUser() public { uint256 ub = _token.balanceOf(user); uint256 ts = _token.totalSupply(); vm.prank(user); + _mockTxInfo(TxInfo({txHash: bytes32(0), nonce: 0})); bridge().deposit(address(_token), DEPOSIT_AMOUNT, recipient); assertEq(_token.balanceOf(user), ub - DEPOSIT_AMOUNT); assertEq(_token.totalSupply(), ts - DEPOSIT_AMOUNT); } function test_Claim_SingleLog_MintsToRecipient() public { - EthGetLogsPrecompileHelperTypes.RpcLog[] memory logs = new EthGetLogsPrecompileHelperTypes.RpcLog[](1); + EthGetLogsTypes.RpcLog[] memory logs = new EthGetLogsTypes.RpcLog[](1); logs[0] = _makeLog(0, _mirror, DEPOSIT_AMOUNT, recipient); - _mockEthGetLogs(0, bytes("0x1"), _mirror, logs); + _mockEthGetLogs(0, 1, 1, _mirror, logs); + _mockEthGetBlockByNumber(2); + _mockTxInfo(TxInfo({txHash: bytes32(0), nonce: 0})); assertEq(_token.balanceOf(recipient), 0); - vm.expectEmit(true, true, true, true); + // vm.expectEmit(true, true, true, true); emit IBridge.Claim(0, address(_token), _mirror, DEPOSIT_AMOUNT, recipient); - _bridge.claim(0, _mirror, bytes("0x1")); + _bridge.claim(0, _mirror, 1); assertEq(_token.balanceOf(recipient), DEPOSIT_AMOUNT); @@ -69,79 +78,217 @@ contract BridgeMintBurnTest is BridgeBehaviorTest { } function test_Claim_RevertIfDailyLimitExhausted() public { - EthGetLogsPrecompileHelperTypes.RpcLog[] memory logs = new EthGetLogsPrecompileHelperTypes.RpcLog[](1); + EthGetLogsTypes.RpcLog[] memory logs = new EthGetLogsTypes.RpcLog[](1); logs[0] = _makeLog(0, _mirror, tokenLimits.claim + 1, recipient); - _mockEthGetLogs(0, bytes("0x1"), _mirror, logs); + _mockEthGetBlockByNumber(1); + _mockEthGetLogs(0, 1, 1, _mirror, logs); vm.expectRevert(abi.encodeWithSelector(IBridge.DailyLimitExhausted.selector)); - _bridge.claim(0, _mirror, bytes("0x1")); + _bridge.claim(0, _mirror, 1); + } + + function test_Claim_RevertIfInvalidBridgeContract() public { + EthGetLogsTypes.RpcLog[] memory logs = new EthGetLogsTypes.RpcLog[](1); + logs[0] = _makeLog(0, _mirror, DEPOSIT_AMOUNT, recipient); + logs[0].addr = address(0xBEEF); + _mockEthGetBlockByNumber(1); + _mockEthGetLogs(0, 1, 1, _mirror, logs); + vm.expectRevert(abi.encodeWithSelector(IBridge.InvalidBridgeContract.selector)); + _bridge.claim(0, _mirror, 1); } function test_Claim_RevertIfDailyLimitExhausted_ButSucceedAfterOneDay() public { - EthGetLogsPrecompileHelperTypes.RpcLog[] memory logs = new EthGetLogsPrecompileHelperTypes.RpcLog[](1); + EthGetLogsTypes.RpcLog[] memory logs = new EthGetLogsTypes.RpcLog[](1); logs[0] = _makeLog(0, _mirror, DEPOSIT_AMOUNT, recipient); - _mockEthGetLogs(0, bytes("0x1"), _mirror, logs); - _bridge.claim(0, _mirror, bytes("0x1")); + _mockEthGetBlockByNumber(1); + _mockEthGetLogs(0, 1, 1, _mirror, logs); + _bridge.claim(0, _mirror, 1); logs[0] = _makeLog(1, _mirror, tokenLimits.claim, recipient); - _mockEthGetLogs(1, bytes("0x1"), _mirror, logs); + _mockEthGetBlockByNumber(1); + _mockEthGetLogs(1, 1, 1, _mirror, logs); vm.expectRevert(abi.encodeWithSelector(IBridge.DailyLimitExhausted.selector)); - _bridge.claim(1, _mirror, bytes("0x1")); + _bridge.claim(1, _mirror, 1); vm.warp(block.timestamp + 1 days + 1); - _mockEthGetLogs(1, bytes("0x1"), _mirror, logs); - _bridge.claim(1, _mirror, bytes("0x1")); + _mockEthGetBlockByNumber(1); + _mockEthGetLogs(1, 1, 1, _mirror, logs); + _bridge.claim(1, _mirror, 1); } function test_Claim_RevertIfNoDepositsFound() public { - EthGetLogsPrecompileHelperTypes.RpcLog[] memory logs = new EthGetLogsPrecompileHelperTypes.RpcLog[](0); - _mockEthGetLogs(0, bytes("0x1"), _mirror, logs); - vm.expectRevert(abi.encodeWithSelector(IBridgeMintBurn.NoDepositsFound.selector)); - _bridge.claim(0, _mirror, bytes("0x1")); + EthGetLogsTypes.RpcLog[] memory logs = new EthGetLogsTypes.RpcLog[](0); + _mockEthGetBlockByNumber(1); + _mockEthGetLogs(0, 1, 1, _mirror, logs); + vm.expectRevert(abi.encodeWithSelector(IBridge.InvalidDepositLog.selector)); + _bridge.claim(0, _mirror, 1); } function test_Claim_RevertIfMultipleDepositsFound() public { - EthGetLogsPrecompileHelperTypes.RpcLog[] memory logs = new EthGetLogsPrecompileHelperTypes.RpcLog[](2); + EthGetLogsTypes.RpcLog[] memory logs = new EthGetLogsTypes.RpcLog[](2); logs[0] = _makeLog(0, _mirror, DEPOSIT_AMOUNT, recipient); logs[1] = _makeLog(0, _mirror, DEPOSIT_AMOUNT, recipient); - _mockEthGetLogs(0, bytes("0x1"), _mirror, logs); - vm.expectRevert(abi.encodeWithSelector(IBridgeMintBurn.MultipleDepositsWithSameId.selector)); - _bridge.claim(0, _mirror, bytes("0x1")); + _mockEthGetBlockByNumber(1); + _mockEthGetLogs(0, 1, 1, _mirror, logs); + vm.expectRevert(abi.encodeWithSelector(IBridge.InvalidDepositLog.selector)); + _bridge.claim(0, _mirror, 1); } function test_Claim_RevertIfMirrorTokenNotFound() public { // Use a token not mapped in mirrorTokens address unknownMirror = address(0xBEEF); - EthGetLogsPrecompileHelperTypes.RpcLog[] memory logs = new EthGetLogsPrecompileHelperTypes.RpcLog[](1); + EthGetLogsTypes.RpcLog[] memory logs = new EthGetLogsTypes.RpcLog[](1); logs[0] = _makeLog(0, unknownMirror, DEPOSIT_AMOUNT, recipient); - _mockEthGetLogs(0, bytes("0x1"), unknownMirror, logs); + _mockEthGetBlockByNumber(1); + _mockEthGetLogs(0, 1, 1, unknownMirror, logs); vm.expectRevert(abi.encodeWithSelector(IBridge.MirrorTokenNotFound.selector)); - _bridge.claim(0, unknownMirror, bytes("0x1")); + _bridge.claim(0, unknownMirror, 1); + } + + function test_Claim_RevertIfBlockNotFinalized() public { + EthGetLogsTypes.RpcLog[] memory logs = new EthGetLogsTypes.RpcLog[](1); + logs[0] = _makeLog(0, _mirror, DEPOSIT_AMOUNT, recipient); + _mockEthGetBlockByNumber(1); + _mockEthGetLogs(0, 1, 1, _mirror, logs); + vm.expectRevert(abi.encodeWithSelector(IBridgeMintBurn.BlockNotFinalized.selector)); + _bridge.claim(0, _mirror, 10); } function test_Claim_RevertIfAlreadyProcessed() public { - EthGetLogsPrecompileHelperTypes.RpcLog[] memory logs = new EthGetLogsPrecompileHelperTypes.RpcLog[](1); + EthGetLogsTypes.RpcLog[] memory logs = new EthGetLogsTypes.RpcLog[](1); logs[0] = _makeLog(0, _mirror, DEPOSIT_AMOUNT, recipient); - _mockEthGetLogs(0, bytes("0x1"), _mirror, logs); - _bridge.claim(0, _mirror, bytes("0x1")); + _mockEthGetBlockByNumber(1); + _mockEthGetLogs(0, 1, 1, _mirror, logs); + _bridge.claim(0, _mirror, 1); // Mock again with same log so requestId is identical - _mockEthGetLogs(0, bytes("0x1"), _mirror, logs); + _mockEthGetBlockByNumber(1); + _mockEthGetLogs(0, 1, 1, _mirror, logs); vm.expectRevert(abi.encodeWithSelector(IBridge.RequestAlreadyProcessed.selector)); - _bridge.claim(0, _mirror, bytes("0x1")); + _bridge.claim(0, _mirror, 1); } function test_Claim_RevertIfPaused() public { vm.prank(admin); _bridge.pause(); vm.expectRevert(abi.encodeWithSelector(Pausable.EnforcedPause.selector)); - _bridge.claim(0, _mirror, bytes("0x1")); + _bridge.claim(0, _mirror, 1); + } + + function test_Claim_RevertIfInvalidLog() public { + EthGetLogsTypes.RpcLog[] memory logs = new EthGetLogsTypes.RpcLog[](2); + logs[0] = _makeLog(0, _mirror, DEPOSIT_AMOUNT, recipient); + logs[1] = _makeLog(1, _mirror, DEPOSIT_AMOUNT, recipient); + _mockEthGetBlockByNumber(1); + _mockEthGetLogs(0, 1, 1, _mirror, logs); + vm.expectRevert(abi.encodeWithSelector(IBridge.InvalidDepositLog.selector)); + _bridge.claim(0, _mirror, 1); + + logs = new EthGetLogsTypes.RpcLog[](0); + _mockEthGetBlockByNumber(1); + _mockEthGetLogs(0, 1, 1, _mirror, logs); + vm.expectRevert(abi.encodeWithSelector(IBridge.InvalidDepositLog.selector)); + _bridge.claim(0, _mirror, 1); } function test_Claim_RevertIfPrecompileCallFails() public { - EthGetLogsPrecompileHelperTypes.PrecompileArgs memory args = _buildArgs(0, bytes("0x1"), _mirror); + _mockEthGetBlockByNumber(1); + EthGetLogsTypes.PrecompileArgs memory args = _buildArgs(0, 1, 1, _mirror); podMockEthGetLogsRevert(abi.encode(args)); vm.expectRevert(abi.encodeWithSelector(IBridgeMintBurn.PrecompileCallFailed.selector)); - _bridge.claim(0, _mirror, bytes("0x1")); + _bridge.claim(0, _mirror, 1); + } + + function test_ClaimNative() public { + EthGetLogsTypes.RpcLog[] memory logs = new EthGetLogsTypes.RpcLog[](1); + logs[0] = _makeLog(0, address(0), DEPOSIT_AMOUNT, recipient); + _mockEthGetBlockByNumber(1); + _mockEthGetLogs(0, 1, 1, address(0), logs); + _mockMintBalance(recipient, DEPOSIT_AMOUNT); + + vm.expectEmit(true, false, false, true); + emit IBridge.ClaimNative(0, DEPOSIT_AMOUNT, recipient); + vm.prank(recipient); + _bridge.claimNative(0, 1); + // should be done by precompile + assertEq(recipient.balance, DEPOSIT_AMOUNT); + } + + function test_ClaimNative_RevertIfPaused() public { + vm.prank(admin); + _bridge.pause(); + vm.expectRevert(abi.encodeWithSelector(Pausable.EnforcedPause.selector)); + _bridge.claimNative(0, 1); + } + + function test_ClaimNative_RevertIfInvalidLog() public { + EthGetLogsTypes.RpcLog[] memory logs = new EthGetLogsTypes.RpcLog[](2); + logs[0] = _makeLog(0, address(0), DEPOSIT_AMOUNT, recipient); + logs[1] = _makeLog(1, address(0), DEPOSIT_AMOUNT, recipient); + _mockEthGetBlockByNumber(1); + _mockEthGetLogs(0, 1, 1, address(0), logs); + vm.expectRevert(abi.encodeWithSelector(IBridge.InvalidDepositLog.selector)); + vm.prank(recipient); + _bridge.claimNative(0, 1); + + logs = new EthGetLogsTypes.RpcLog[](0); + _mockEthGetBlockByNumber(1); + _mockEthGetLogs(0, 1, 1, address(0), logs); + vm.expectRevert(abi.encodeWithSelector(IBridge.InvalidDepositLog.selector)); + vm.prank(recipient); + _bridge.claimNative(0, 1); + } + + function test_ClaimNative_RevertIfInvalidAmount() public { + EthGetLogsTypes.RpcLog[] memory logs = new EthGetLogsTypes.RpcLog[](1); + logs[0] = _makeLog(0, address(0), 0.001 ether, recipient); + _mockEthGetBlockByNumber(1); + _mockEthGetLogs(0, 1, 1, address(0), logs); + vm.expectRevert(abi.encodeWithSelector(IBridge.InvalidAmount.selector)); + _bridge.claimNative(0, 1); + } + + function test_ClaimNative_RevertIfBlockNotFinalized() public { + EthGetLogsTypes.RpcLog[] memory logs = new EthGetLogsTypes.RpcLog[](1); + logs[0] = _makeLog(0, address(0), DEPOSIT_AMOUNT, recipient); + _mockEthGetBlockByNumber(1); + _mockEthGetLogs(0, 1, 1, address(0), logs); + vm.expectRevert(abi.encodeWithSelector(IBridgeMintBurn.BlockNotFinalized.selector)); + _bridge.claimNative(0, 10); + } + + function test_ClaimNative_RevertIfInvalidBridgeContract() public { + EthGetLogsTypes.RpcLog[] memory logs = new EthGetLogsTypes.RpcLog[](1); + logs[0] = _makeLog(0, address(0), DEPOSIT_AMOUNT, recipient); + logs[0].addr = address(0xBEEF); + _mockEthGetBlockByNumber(1); + _mockEthGetLogs(0, 1, 1, address(0), logs); + vm.expectRevert(abi.encodeWithSelector(IBridge.InvalidBridgeContract.selector)); + _bridge.claimNative(0, 1); + } + + function test_ClaimNative_RevertIfRequestAlreadyProcessed() public { + EthGetLogsTypes.RpcLog[] memory logs = new EthGetLogsTypes.RpcLog[](1); + logs[0] = _makeLog(0, address(0), DEPOSIT_AMOUNT, recipient); + _mockEthGetBlockByNumber(1); + _mockEthGetLogs(0, 1, 1, address(0), logs); + vm.prank(recipient); + _bridge.claimNative(0, 1); + + _mockEthGetBlockByNumber(1); + _mockEthGetLogs(0, 1, 1, address(0), logs); + vm.expectRevert(abi.encodeWithSelector(IBridge.RequestAlreadyProcessed.selector)); + vm.prank(recipient); + _bridge.claimNative(0, 1); + } + + function test_ClaimNative_RevertIfInvalidToAddress() public { + EthGetLogsTypes.RpcLog[] memory logs = new EthGetLogsTypes.RpcLog[](1); + logs[0] = _makeLog(0, address(0), DEPOSIT_AMOUNT, address(0xBEEF)); + _mockEthGetBlockByNumber(1); + _mockEthGetLogs(0, 1, 1, address(0), logs); + vm.prank(recipient); + vm.expectRevert(abi.encodeWithSelector(IBridge.InvalidToAddress.selector)); + _bridge.claimNative(0, 1); } function test_Migrate_TransfersRolesToNewBridge() public { @@ -169,45 +316,54 @@ contract BridgeMintBurnTest is BridgeBehaviorTest { } // ---------- Helpers for building logs ---------- - function _buildArgs(uint256 id, bytes memory fromBlock, address tokenAddr) + function _buildArgs(uint256 id, uint256 fromBlock, uint256 toBlock, address tokenAddr) internal - pure - returns (EthGetLogsPrecompileHelperTypes.PrecompileArgs memory) + view + returns (EthGetLogsTypes.PrecompileArgs memory) { - EthGetLogsPrecompileHelperTypes.RpcArgs memory inner = EthGetLogsPrecompileHelperTypes.RpcArgs({ - fromBlock: fromBlock, - toBlock: hex"66696e616c697a6564", - addr: tokenAddr, + bytes memory fromBlockBytes = HexUtils.toBytesMinimal(fromBlock); + bytes memory toBlockBytes = HexUtils.toBytesMinimal(toBlock); + EthGetLogsTypes.RpcArgs memory inner = EthGetLogsTypes.RpcArgs({ + fromBlock: fromBlockBytes, + toBlock: toBlockBytes, + addr: address(OTHER_BRIDGE_CONTRACT), blockHash: bytes32(0), topics: _buildTopics(id, tokenAddr) }); - return EthGetLogsPrecompileHelperTypes.PrecompileArgs({chainId: 1, ethGetLogsArgs: inner}); + return EthGetLogsTypes.PrecompileArgs({chainId: 1, ethGetLogsArgs: inner}); } function _mockEthGetLogs( uint256 id, - bytes memory fromBlock, + uint256 fromBlock, + uint256 toBlock, address tokenAddr, - EthGetLogsPrecompileHelperTypes.RpcLog[] memory logs + EthGetLogsTypes.RpcLog[] memory logs ) internal { - EthGetLogsPrecompileHelperTypes.PrecompileArgs memory args = _buildArgs(id, fromBlock, tokenAddr); + EthGetLogsTypes.PrecompileArgs memory args = _buildArgs(id, fromBlock, toBlock, tokenAddr); podMockEthGetLogs(abi.encode(args), abi.encode(logs)); } function _buildTopics(uint256 id, address tokenAddr) internal pure returns (bytes32[] memory topics) { - topics = new bytes32[](3); - topics[0] = keccak256("Deposit(uint256,address,uint256,address)"); - topics[1] = bytes32(id); - topics[2] = bytes32(uint256(uint160(tokenAddr))); + if (tokenAddr == address(0)) { + topics = new bytes32[](2); + topics[0] = keccak256("DepositNative(uint256,uint256,address)"); + topics[1] = bytes32(id); + } else { + topics = new bytes32[](3); + topics[0] = keccak256("Deposit(uint256,address,uint256,address)"); + topics[1] = bytes32(id); + topics[2] = bytes32(uint256(uint160(tokenAddr))); + } } function _makeLog(uint256 id, address tokenAddr, uint256 amount, address to) internal - pure - returns (EthGetLogsPrecompileHelperTypes.RpcLog memory) + view + returns (EthGetLogsTypes.RpcLog memory) { - return EthGetLogsPrecompileHelperTypes.RpcLog({ - addr: tokenAddr, + return EthGetLogsTypes.RpcLog({ + addr: address(OTHER_BRIDGE_CONTRACT), topics: _buildTopics(id, tokenAddr), data: abi.encode(amount, to), blockNumber: bytes(""), @@ -218,4 +374,50 @@ contract BridgeMintBurnTest is BridgeBehaviorTest { removed: false }); } + + function _buildEthGetBlockByNumberArgs() internal pure returns (bytes memory) { + return abi.encode( + EthGetBlockByNumberTypes.PrecompileArgs(1, EthGetBlockByNumberTypes.RpcArgs(hex"66696e616c697a6564", false)) + ); + } + + function _buildEthGetBlockByNumberRpcBlock(uint256 blockNumber) internal pure returns (bytes memory) { + return abi.encode( + EthGetBlockByNumberTypes.RpcBlock({ + number: HexUtils.toBytesMinimal(blockNumber), + difficulty: bytes(""), + extraData: bytes(""), + gasLimit: bytes(""), + gasUsed: bytes(""), + hash: bytes32(0), + logsBloom: bytes(""), + miner: address(0), + mixHash: bytes32(0), + nonce: bytes(""), + parentHash: bytes32(0), + receiptsRoot: bytes32(0), + sha3Uncles: bytes32(0), + size: bytes(""), + stateRoot: bytes32(0), + timestamp: bytes(""), + transactions: new bytes32[](0), + transactionsRoot: bytes32(0), + uncles: new bytes32[](0) + }) + ); + } + + function _mockEthGetBlockByNumber(uint256 blockNumber) internal { + bytes memory args = _buildEthGetBlockByNumberArgs(); + bytes memory rpcBlock = _buildEthGetBlockByNumberRpcBlock(blockNumber); + podMockEthGetBlockByNumber(args, rpcBlock); + } + + function _mockTxInfo(TxInfo memory txInfo) internal { + podMockTxInfo(abi.encode(txInfo)); + } + + function _mockMintBalance(address recipient, uint256 amount) internal { + podMockMintBalance(recipient, abi.encode(amount)); + } } diff --git a/protocol/test/HexUtils.t.sol b/protocol/test/HexUtils.t.sol new file mode 100644 index 00000000..cb4f0eb7 --- /dev/null +++ b/protocol/test/HexUtils.t.sol @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +import {Test} from "forge-std/Test.sol"; +import {HexUtils} from "../src/libraries/HexUtils.sol"; + +contract HexUtilsTest is Test { + function test_uintFromBigEndian() public pure { + assertEq(HexUtils.uintFromBigEndian(hex"0156"), 342); + } + + function test_toBytesMinimal() public pure { + assertEq(HexUtils.toBytesMinimal(342), hex"0156"); + } +} diff --git a/protocol/test/abstract/Bridge.t.sol b/protocol/test/abstract/Bridge.t.sol index 6b852306..80cc3372 100644 --- a/protocol/test/abstract/Bridge.t.sol +++ b/protocol/test/abstract/Bridge.t.sol @@ -31,11 +31,19 @@ abstract contract BridgeBehaviorTest is PodTest { // Common tests function test_Deposit_EmitsEvent() public { vm.prank(user); - vm.expectEmit(true, true, false, true); + vm.expectEmit(true, true, true, true); emit IBridge.Deposit(0, address(token()), DEPOSIT_AMOUNT, recipient); bridge().deposit(address(token()), DEPOSIT_AMOUNT, recipient); } + function test_Deposit_RevertIfPaused() public { + vm.prank(admin); + bridge().pause(); + vm.expectRevert(Pausable.EnforcedPause.selector); + vm.prank(user); + bridge().deposit(address(token()), DEPOSIT_AMOUNT, recipient); + } + function test_Deposit_MinAndDailyLimit() public { vm.prank(user); vm.expectRevert(abi.encodeWithSelector(IBridge.InvalidTokenAmount.selector)); @@ -46,6 +54,31 @@ abstract contract BridgeBehaviorTest is PodTest { bridge().deposit(address(token()), tokenLimits.deposit + 1, recipient); } + function test_DepositNative_EmitsEvent() public { + vm.deal(user, DEPOSIT_AMOUNT); + vm.expectEmit(true, true, true, true); + emit IBridge.DepositNative(0, DEPOSIT_AMOUNT, recipient); + vm.prank(user); + bridge().depositNative{value: DEPOSIT_AMOUNT}(recipient); + assertEq(address(bridge()).balance, DEPOSIT_AMOUNT); + } + + function test_DepositNative_RevertIfPaused() public { + vm.deal(user, DEPOSIT_AMOUNT); + vm.prank(admin); + bridge().pause(); + vm.expectRevert(Pausable.EnforcedPause.selector); + vm.prank(user); + bridge().depositNative{value: DEPOSIT_AMOUNT}(recipient); + } + + function test_DepositNative_RevertIfInvalidAmount() public { + vm.deal(user, DEPOSIT_AMOUNT); + vm.expectRevert(abi.encodeWithSelector(IBridge.InvalidAmount.selector)); + vm.prank(user); + bridge().depositNative{value: 0.001 ether}(recipient); + } + function test_Deposit_ZeroRecipientAndPause() public { vm.prank(user); vm.expectRevert(abi.encodeWithSelector(IBridge.InvalidToAddress.selector)); @@ -181,17 +214,6 @@ abstract contract BridgeBehaviorTest is PodTest { bridge().deposit(address(token()), tokenLimits.minAmount, recipient); } - function test_DepositIndex_IncrementsSequentially() public { - uint256 beforeIdx = bridge().depositIndex(); - vm.prank(user); - bridge().deposit(address(token()), tokenLimits.minAmount, recipient); - assertEq(bridge().depositIndex(), beforeIdx + 1); - - vm.prank(user); - bridge().deposit(address(token()), tokenLimits.minAmount, recipient); - assertEq(bridge().depositIndex(), beforeIdx + 2); - } - function test_RoleGrants_FromConstructor() public view { assertTrue(bridge().hasRole(bridge().DEFAULT_ADMIN_ROLE(), admin)); assertTrue(bridge().hasRole(bridge().PAUSER_ROLE(), admin)); diff --git a/solidity-sdk/src/test/podTest.sol b/solidity-sdk/src/test/podTest.sol index 9c1c5497..a46ab1c8 100644 --- a/solidity-sdk/src/test/podTest.sol +++ b/solidity-sdk/src/test/podTest.sol @@ -4,7 +4,10 @@ pragma solidity ^0.8.0; import {Test} from "forge-std/Test.sol"; import {Time, POD_TIMESTAMP_PRECOMPILE} from "../Time.sol"; import {REQUIRE_QUORUM} from "../Quorum.sol"; -import {EthGetLogsPrecompileHelperTypes} from "../types/EthGetLogsPrecompileHelperTypes.sol"; +import {EthGetLogsTypes} from "../types/EthGetLogsTypes.sol"; +import {EthGetBlockByNumberTypes} from "../types/EthGetBlockByNumberTypes.sol"; +import {PodMintBalance} from "pod-protocol/libraries/PodMintBalance.sol"; +import {POD_TX_INFO} from "../Context.sol"; abstract contract PodTest is Test { function podMockQuorum() public { @@ -20,10 +23,28 @@ abstract contract PodTest is Test { } function podMockEthGetLogs(bytes memory input, bytes memory output) internal { - vm.mockCall(EthGetLogsPrecompileHelperTypes.PRECOMPILE_ADDRESS, input, output); + vm.mockCall(EthGetLogsTypes.PRECOMPILE_ADDRESS, input, output); } function podMockEthGetLogsRevert(bytes memory input) internal { - vm.mockCallRevert(EthGetLogsPrecompileHelperTypes.PRECOMPILE_ADDRESS, input, bytes("")); + vm.mockCallRevert(EthGetLogsTypes.PRECOMPILE_ADDRESS, input, bytes("")); + } + + function podMockEthGetBlockByNumber(bytes memory input, bytes memory output) internal { + vm.mockCall(EthGetBlockByNumberTypes.PRECOMPILE_ADDRESS, input, output); + } + + function podMockEthGetBlockByNumberRevert(bytes memory input) internal { + vm.mockCallRevert(EthGetBlockByNumberTypes.PRECOMPILE_ADDRESS, input, bytes("")); + } + + function podMockTxInfo(bytes memory output) internal { + vm.mockCall(POD_TX_INFO, bytes(""), output); + } + + function podMockMintBalance(address recipient, bytes memory input) internal { + vm.mockCall(PodMintBalance.PRECOMPILE_ADDRESS, input, bytes("")); + uint256 amount = abi.decode(input, (uint256)); + vm.deal(recipient, amount); } } diff --git a/solidity-sdk/src/types/EthGetBlockByNumberTypes.sol b/solidity-sdk/src/types/EthGetBlockByNumberTypes.sol new file mode 100644 index 00000000..d740f2ac --- /dev/null +++ b/solidity-sdk/src/types/EthGetBlockByNumberTypes.sol @@ -0,0 +1,73 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.28; + +library EthGetBlockByNumberTypes { + /** + * @dev The address of the external eth get block by number precompile. + */ + address constant PRECOMPILE_ADDRESS = address(uint160(uint256(keccak256("POD_EXTERNAL_ETH_GET_BLOCK_BY_NUMBER")))); + + /** + * @dev The arguments for the external eth get block by number precompile. + * @param blockNumber The block number to get. + * @param transactionDetailFlag Whether to return full transaction details. + */ + struct RpcArgs { + bytes blockNumber; + bool transactionDetailFlag; + } + + /** + * @dev The arguments for the external eth get block by number precompile. + * @param chainId The chain id to search block by number for. + * @param ethGetBlockByNumberArgs The arguments for the external eth get block by number precompile. + */ + struct PrecompileArgs { + uint256 chainId; + RpcArgs ethGetBlockByNumberArgs; + } + + /** + * @dev The response from the external eth get block by number precompile. + * @param difficulty The difficulty of the block. + * @param extraData The extra data of the block. + * @param gasLimit The gas limit of the block. + * @param gasUsed The gas used of the block. + * @param hash The hash of the block. + * @param logsBloom The logs bloom of the block. + * @param miner The miner of the block. + * @param mixHash The mix hash of the block. + * @param nonce The nonce of the block. + * @param number The number of the block. + * @param parentHash The parent hash of the block. + * @param receiptsRoot The receipts root of the block. + * @param sha3Uncles The sha3 uncles of the block. + * @param size The size of the block. + * @param stateRoot The state root of the block. + * @param timestamp The timestamp of the block. + * @param transactions The transactions of the block. + * @param transactionsRoot The transactions root of the block. + * @param uncles The uncles of the block. + */ + struct RpcBlock { + bytes difficulty; + bytes extraData; + bytes gasLimit; + bytes gasUsed; + bytes32 hash; + bytes logsBloom; + address miner; + bytes32 mixHash; + bytes nonce; + bytes number; + bytes32 parentHash; + bytes32 receiptsRoot; + bytes32 sha3Uncles; + bytes size; + bytes32 stateRoot; + bytes timestamp; + bytes32[] transactions; + bytes32 transactionsRoot; + bytes32[] uncles; + } +} diff --git a/solidity-sdk/src/types/EthGetLogsPrecompileHelperTypes.sol b/solidity-sdk/src/types/EthGetLogsTypes.sol similarity index 95% rename from solidity-sdk/src/types/EthGetLogsPrecompileHelperTypes.sol rename to solidity-sdk/src/types/EthGetLogsTypes.sol index a7872fff..2f7a0a99 100644 --- a/solidity-sdk/src/types/EthGetLogsPrecompileHelperTypes.sol +++ b/solidity-sdk/src/types/EthGetLogsTypes.sol @@ -1,11 +1,11 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.28; -library EthGetLogsPrecompileHelperTypes { +library EthGetLogsTypes { /** * @dev The address of the external eth get logs precompile. */ - address constant PRECOMPILE_ADDRESS = address(uint160(uint256(keccak256("ETH_EXTERNAL_ETH_GET_LOGS")))); + address constant PRECOMPILE_ADDRESS = address(uint160(uint256(keccak256("POD_EXTERNAL_ETH_GET_LOGS")))); /** * @dev The arguments for the external eth get logs precompile. diff --git a/types/src/ledger/log.rs b/types/src/ledger/log.rs index 600822b3..c775d4de 100644 --- a/types/src/ledger/log.rs +++ b/types/src/ledger/log.rs @@ -289,7 +289,7 @@ mod test { }; let log2 = Log { - address: "0x6D9da78B6A5BEdcA287AA5d49613bA36b90c15C4" + address: "0x7eE47822C517C29d49744890f52c624d3AcfdBfc" .parse() .unwrap(), data: LogData::new_unchecked( @@ -373,9 +373,6 @@ mod test { .to_merkle_tree() .hash_custom(); - println!("receipt_root: {:?}", receipt_root); - println!("proof: {:?}", proof.path); - assert!(verifiable_log.verify_proof(receipt_root, proof)); assert_eq!(verifiable_log.inner.log_index, Some(1)); } From d4706ded53c8588a8017c5a9efbb5fd20d49d0ac Mon Sep 17 00:00:00 2001 From: Jakov Mitrovski Date: Thu, 18 Sep 2025 18:17:32 +0200 Subject: [PATCH 48/64] rm protocl dependency --- solidity-sdk/src/test/podTest.sol | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/solidity-sdk/src/test/podTest.sol b/solidity-sdk/src/test/podTest.sol index a46ab1c8..20a8a254 100644 --- a/solidity-sdk/src/test/podTest.sol +++ b/solidity-sdk/src/test/podTest.sol @@ -6,7 +6,6 @@ import {Time, POD_TIMESTAMP_PRECOMPILE} from "../Time.sol"; import {REQUIRE_QUORUM} from "../Quorum.sol"; import {EthGetLogsTypes} from "../types/EthGetLogsTypes.sol"; import {EthGetBlockByNumberTypes} from "../types/EthGetBlockByNumberTypes.sol"; -import {PodMintBalance} from "pod-protocol/libraries/PodMintBalance.sol"; import {POD_TX_INFO} from "../Context.sol"; abstract contract PodTest is Test { @@ -43,7 +42,7 @@ abstract contract PodTest is Test { } function podMockMintBalance(address recipient, bytes memory input) internal { - vm.mockCall(PodMintBalance.PRECOMPILE_ADDRESS, input, bytes("")); + vm.mockCall(address(uint160(uint256(keccak256("POD_MINT_BALANCE")))), input, bytes("")); uint256 amount = abi.decode(input, (uint256)); vm.deal(recipient, amount); } From 91518c725182e88ef9981cc050c658f0cf494ed9 Mon Sep 17 00:00:00 2001 From: Jakov Mitrovski Date: Thu, 18 Sep 2025 18:26:00 +0200 Subject: [PATCH 49/64] fix error in log --- types/src/ledger/log.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/types/src/ledger/log.rs b/types/src/ledger/log.rs index 0461dc9d..bd9bdf90 100644 --- a/types/src/ledger/log.rs +++ b/types/src/ledger/log.rs @@ -354,11 +354,11 @@ mod test { attestations: vec![], receipt: Receipt { status: true, - actual_gas_used: 201819, + actual_gas_used: 21784, max_fee_per_gas: transaction.max_fee_per_gas, logs: logs.clone(), logs_root, - tx_hash: transaction.hash_custom(), + attested_tx: AttestedTx::success(transaction.hash_custom(), 0), signer: signer.address(), to: Some(to), contract_address: None, From 2bb21c95233b0103e6a7016ac9d633bc807c9168 Mon Sep 17 00:00:00 2001 From: Jakov Mitrovski Date: Thu, 18 Sep 2025 18:33:47 +0200 Subject: [PATCH 50/64] reduce contract size --- protocol/src/BridgeMintBurn.sol | 2 -- protocol/src/abstract/Bridge.sol | 2 -- 2 files changed, 4 deletions(-) diff --git a/protocol/src/BridgeMintBurn.sol b/protocol/src/BridgeMintBurn.sol index 9052b87d..913c441f 100644 --- a/protocol/src/BridgeMintBurn.sol +++ b/protocol/src/BridgeMintBurn.sol @@ -21,8 +21,6 @@ import {HexUtils} from "./libraries/HexUtils.sol"; * minting and burning tokens between chains. */ contract BridgeMintBurn is Bridge, IBridgeMintBurn { - using SafeERC20 for IERC20; - /** * @dev The role for the minter. */ diff --git a/protocol/src/abstract/Bridge.sol b/protocol/src/abstract/Bridge.sol index e3508958..91bbbafb 100644 --- a/protocol/src/abstract/Bridge.sol +++ b/protocol/src/abstract/Bridge.sol @@ -19,8 +19,6 @@ import {Pausable} from "@openzeppelin/contracts/utils/Pausable.sol"; * the callback functions (handleDeposit and handleMigrate) that must be implemented by concrete contracts. */ abstract contract Bridge is IBridge, AccessControl, Pausable { - using SafeERC20 for IERC20; - /** * @dev The role ID for addresses that can pause the contract. */ From 775f9c46db2ebd6725a09f18d89502caea684d11 Mon Sep 17 00:00:00 2001 From: Jakov Mitrovski Date: Thu, 18 Sep 2025 19:51:08 +0200 Subject: [PATCH 51/64] add configurable native token limits, contract size reduction, library refactor --- protocol/script/CreateAndWhitelistToken.s.sol | 2 + protocol/script/DeployDepositWithdraw.s.sol | 4 +- protocol/script/DeployMintBurn.s.sol | 5 +- protocol/script/Deposit.s.sol | 1 - protocol/src/BridgeDepositWithdraw.sol | 5 +- protocol/src/BridgeMintBurn.sol | 99 ++++-------- protocol/src/abstract/Bridge.sol | 17 +- protocol/src/libraries/PodMintBalance.sol | 34 ++-- .../src/libraries/PodPrecompileHelper.sol | 74 +++++++++ protocol/test/BridgeDepositWithdraw.t.sol | 5 +- protocol/test/BridgeMintBurn.t.sol | 147 +++++++++--------- protocol/test/abstract/Bridge.t.sol | 4 +- 12 files changed, 227 insertions(+), 170 deletions(-) create mode 100644 protocol/src/libraries/PodPrecompileHelper.sol diff --git a/protocol/script/CreateAndWhitelistToken.s.sol b/protocol/script/CreateAndWhitelistToken.s.sol index 984c63fb..76a2549f 100644 --- a/protocol/script/CreateAndWhitelistToken.s.sol +++ b/protocol/script/CreateAndWhitelistToken.s.sol @@ -25,6 +25,8 @@ contract CreateAndWhitelistToken is Script { IBridge.TokenLimits({minAmount: 1e18, deposit: 10000e18, claim: 10000e18}) ); + console.log("Token created and whitelisted"); + vm.stopBroadcast(); } } diff --git a/protocol/script/DeployDepositWithdraw.s.sol b/protocol/script/DeployDepositWithdraw.s.sol index 9dc82dec..16092e03 100644 --- a/protocol/script/DeployDepositWithdraw.s.sol +++ b/protocol/script/DeployDepositWithdraw.s.sol @@ -1,7 +1,6 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.20; -import {Script} from "forge-std/Script.sol"; import {console} from "forge-std/console.sol"; import {BridgeDepositWithdraw} from "../src/BridgeDepositWithdraw.sol"; import {PodRegistry} from "../src/PodRegistry.sol"; @@ -13,6 +12,7 @@ contract DeployDepositWithdraw is BaseDeployer { uint256 constant CHAIN_ID = 31337; string constant RPC_URL = "http://localhost:8546"; address constant OTHER_BRIDGE_CONTRACT = 0x12296f2D128530a834460DF6c36a2895B793F26d; + IBridge.TokenLimits nativeTokenLimits = IBridge.TokenLimits({minAmount: 0.01 ether, deposit: 500e18, claim: 400e18}); function run() external { console.log("=== Deploying BridgeDepositWithdraw to localhost:8546 (chainId 31337) ==="); @@ -28,7 +28,7 @@ contract DeployDepositWithdraw is BaseDeployer { console.log("PodRegistry deployed at:", address(podRegistry)); BridgeDepositWithdraw bridgeDepositWithdraw = - new BridgeDepositWithdraw(address(podRegistry), OTHER_BRIDGE_CONTRACT); + new BridgeDepositWithdraw(address(podRegistry), OTHER_BRIDGE_CONTRACT, nativeTokenLimits); console.log("BridgeDepositWithdraw deployed at:", address(bridgeDepositWithdraw)); // Deploy some test tokens diff --git a/protocol/script/DeployMintBurn.s.sol b/protocol/script/DeployMintBurn.s.sol index 02b2c274..3497babd 100644 --- a/protocol/script/DeployMintBurn.s.sol +++ b/protocol/script/DeployMintBurn.s.sol @@ -4,17 +4,18 @@ pragma solidity ^0.8.20; import {Script} from "forge-std/Script.sol"; import {console} from "forge-std/console.sol"; import {BridgeMintBurn} from "../src/BridgeMintBurn.sol"; -import {PodRegistry} from "../src/PodRegistry.sol"; +import {IBridge} from "../src/interfaces/IBridge.sol"; contract DeployMintBurn is Script { address constant OTHER_BRIDGE_CONTRACT = 0x12296f2D128530a834460DF6c36a2895B793F26d; + IBridge.TokenLimits nativeTokenLimits = IBridge.TokenLimits({minAmount: 0.01 ether, deposit: 500e18, claim: 400e18}); function run() external { console.log("=== Deploying BridgeMintBurn to localhost:8545 (chainId 1293) ==="); vm.startBroadcast(); - BridgeMintBurn bridgeMintBurn = new BridgeMintBurn(OTHER_BRIDGE_CONTRACT); + BridgeMintBurn bridgeMintBurn = new BridgeMintBurn(OTHER_BRIDGE_CONTRACT, nativeTokenLimits); console.log("BridgeMintBurn deployed at:", address(bridgeMintBurn)); vm.stopBroadcast(); diff --git a/protocol/script/Deposit.s.sol b/protocol/script/Deposit.s.sol index 5ea25d8f..88dfcd2a 100644 --- a/protocol/script/Deposit.s.sol +++ b/protocol/script/Deposit.s.sol @@ -4,7 +4,6 @@ pragma solidity ^0.8.20; import {Script} from "forge-std/Script.sol"; import {console} from "forge-std/console.sol"; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import {IBridge} from "../src/interfaces/IBridge.sol"; import {Bridge} from "../src/abstract/Bridge.sol"; contract Deposit is Script { diff --git a/protocol/src/BridgeDepositWithdraw.sol b/protocol/src/BridgeDepositWithdraw.sol index 851f3f65..40df63a4 100644 --- a/protocol/src/BridgeDepositWithdraw.sol +++ b/protocol/src/BridgeDepositWithdraw.sol @@ -7,7 +7,6 @@ import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import {PodECDSA} from "pod-sdk/verifier/PodECDSA.sol"; import {IPodRegistry} from "./interfaces/IPodRegistry.sol"; -import {console} from "forge-std/console.sol"; /** * @title BridgeDepositWithdraw @@ -33,7 +32,9 @@ contract BridgeDepositWithdraw is Bridge, IBridgeDepositWithdraw { * @dev Constructor. * @param _podRegistry The address of the PodRegistry to use. */ - constructor(address _podRegistry, address _bridgeContract) Bridge(_bridgeContract) { + constructor(address _podRegistry, address _bridgeContract, TokenLimits memory nativeTokenLimits) + Bridge(_bridgeContract, nativeTokenLimits) + { podConfig = PodECDSA.PodConfig({thresholdNumerator: 2, thresholdDenominator: 3, registry: IPodRegistry(_podRegistry)}); } diff --git a/protocol/src/BridgeMintBurn.sol b/protocol/src/BridgeMintBurn.sol index 913c441f..5849b313 100644 --- a/protocol/src/BridgeMintBurn.sol +++ b/protocol/src/BridgeMintBurn.sol @@ -3,16 +3,11 @@ pragma solidity ^0.8.20; import {IBridgeMintBurn} from "./interfaces/IBridgeMintBurn.sol"; import {Bridge} from "./abstract/Bridge.sol"; -import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import {IAccessControl} from "@openzeppelin/contracts/access/IAccessControl.sol"; import {IERC20MintableAndBurnable} from "./interfaces/IERC20MintableAndBurnable.sol"; import {WrappedToken} from "./WrappedToken.sol"; import {EthGetLogsTypes} from "pod-sdk/types/EthGetLogsTypes.sol"; -import {EthGetBlockByNumberTypes} from "pod-sdk/types/EthGetBlockByNumberTypes.sol"; -import {PodMintBalance} from "./libraries/PodMintBalance.sol"; -import {TxInfo, getTxInfo} from "pod-sdk/Context.sol"; -import {HexUtils} from "./libraries/HexUtils.sol"; +import {PodPrecompileHelper} from "./libraries/PodPrecompileHelper.sol"; /** * @title BridgeMintBurn @@ -39,7 +34,9 @@ contract BridgeMintBurn is Bridge, IBridgeMintBurn { /** * @dev Constructor. */ - constructor(address _bridgeContract) Bridge(_bridgeContract) {} + constructor(address _bridgeContract, TokenLimits memory nativeTokenLimits) + Bridge(_bridgeContract, nativeTokenLimits) + {} /** * @dev Handles the deposit of tokens. The tokens are burned from the msg.sender. @@ -55,46 +52,7 @@ contract BridgeMintBurn is Bridge, IBridgeMintBurn { * @return id The request ID of the deposit. */ function _getDepositId() internal view override returns (uint256) { - TxInfo memory txInfo = getTxInfo(); - return uint256(txInfo.txHash); - } - - function _getFinalizedBlockNumber() internal view returns (uint256) { - (bool success, bytes memory output) = EthGetBlockByNumberTypes.PRECOMPILE_ADDRESS.staticcall( - abi.encode( - EthGetBlockByNumberTypes.PrecompileArgs( - SOURCE_CHAIN_ID, EthGetBlockByNumberTypes.RpcArgs(FINALIZED_BLOCK_BYTES, false) - ) - ) - ); - if (!success) revert PrecompileCallFailed(); - - EthGetBlockByNumberTypes.RpcBlock memory rpcBlock = abi.decode(output, (EthGetBlockByNumberTypes.RpcBlock)); - - return HexUtils.uintFromBigEndian(rpcBlock.number); - } - - function _getLogs(uint256 blockNumber, bytes32[] memory topics) - internal - view - returns (EthGetLogsTypes.RpcLog[] memory) - { - bytes memory precompileArgs; - bytes memory blockNumberBytes = HexUtils.toBytesMinimal(blockNumber); - precompileArgs = abi.encode( - EthGetLogsTypes.PrecompileArgs( - SOURCE_CHAIN_ID, - EthGetLogsTypes.RpcArgs(blockNumberBytes, blockNumberBytes, address(bridgeContract), bytes32(0), topics) - ) - ); - (bool success, bytes memory output) = EthGetLogsTypes.PRECOMPILE_ADDRESS.staticcall(precompileArgs); - if (!success) revert PrecompileCallFailed(); - EthGetLogsTypes.RpcLog[] memory logs = abi.decode(output, (EthGetLogsTypes.RpcLog[])); - - if (logs.length != 1) revert InvalidDepositLog(); - if (logs[0].addr != bridgeContract) revert InvalidBridgeContract(); - - return logs; + return PodPrecompileHelper.getTxHash(); } /** @@ -106,22 +64,18 @@ contract BridgeMintBurn is Bridge, IBridgeMintBurn { topics[1] = bytes32(id); topics[2] = bytes32(uint256(uint160(token))); - uint256 finalizedBlockNumber = _getFinalizedBlockNumber(); + uint256 finalizedBlockNumber = PodPrecompileHelper.getFinalizedBlockNumber(); if (blockNumber > finalizedBlockNumber) { revert BlockNotFinalized(); } - EthGetLogsTypes.RpcLog[] memory logs = _getLogs(blockNumber, topics); - - (uint256 decodedAmount, address decodedTo) = abi.decode(logs[0].data, (uint256, address)); - address mirrorToken = mirrorTokens[token]; if (mirrorToken == address(0)) revert MirrorTokenNotFound(); - if (!_isValidTokenAmount(mirrorToken, decodedAmount, false)) revert InvalidTokenAmount(); + (uint256 decodedAmount, address decodedTo, bytes32 requestId) = _claim(id, token, blockNumber, topics); - bytes32 requestId = _hashRequest(id, token, decodedAmount, decodedTo); + if (!_isValidTokenAmount(mirrorToken, decodedAmount, false)) revert InvalidTokenAmount(); if (processedRequests[requestId]) revert RequestAlreadyProcessed(); @@ -132,6 +86,23 @@ contract BridgeMintBurn is Bridge, IBridgeMintBurn { emit Claim(id, mirrorToken, token, decodedAmount, decodedTo); } + function _claim(uint256 id, address token, uint256 blockNumber, bytes32[] memory topics) + internal + view + returns (uint256 decodedAmount, address decodedTo, bytes32 requestId) + { + EthGetLogsTypes.RpcLog[] memory logs = + PodPrecompileHelper.getLogs(SOURCE_CHAIN_ID, blockNumber, topics, bridgeContract); + + if (logs.length != 1) revert InvalidDepositLog(); + + // TODO: redunatnt check for extra security, removing because of gas, add it if gas limit permits. + // if (logs[0].addr != bridgeContract) revert InvalidBridgeContract(); + + (decodedAmount, decodedTo) = abi.decode(logs[0].data, (uint256, address)); + requestId = _hashRequest(id, token, decodedAmount, decodedTo); + } + /** * @inheritdoc IBridgeMintBurn */ @@ -140,29 +111,27 @@ contract BridgeMintBurn is Bridge, IBridgeMintBurn { topics[0] = DEPOSIT_NATIVE_TOPIC_0; topics[1] = bytes32(id); - uint256 finalizedBlockNumber = _getFinalizedBlockNumber(); + uint256 finalizedBlockNumber = PodPrecompileHelper.getFinalizedBlockNumber(); if (blockNumber > finalizedBlockNumber) { revert BlockNotFinalized(); } - EthGetLogsTypes.RpcLog[] memory logs = _getLogs(blockNumber, topics); + (uint256 decodedAmount, address decodedTo, bytes32 requestId) = _claim(id, address(0), blockNumber, topics); - (uint256 decodedAmount, address decodedTo) = abi.decode(logs[0].data, (uint256, address)); + if (!_isValidTokenAmount(MOCK_ADDRESS_FOR_NATIVE_DEPOSIT, decodedAmount, false)) revert InvalidAmount(); - if (decodedAmount < 0.01 ether) revert InvalidAmount(); - - bytes32 requestId = _hashRequest(id, address(0), decodedAmount, decodedTo); - if (processedRequests[requestId]) revert RequestAlreadyProcessed(); - - if (decodedTo != msg.sender) revert InvalidToAddress(); + bool isProcessed = processedRequests[requestId]; processedRequests[requestId] = true; // mint the native tokens to msg.sender - if (!PodMintBalance.mint(decodedAmount)) revert PrecompileCallFailed(); + if (!isProcessed) { + // TODO: need to modify this to mint to decodedTo instead of msg.sender + if (!PodPrecompileHelper.mint(decodedAmount)) revert PrecompileCallFailed(); - emit ClaimNative(id, decodedAmount, decodedTo); + emit ClaimNative(id, decodedAmount, decodedTo); + } } /** diff --git a/protocol/src/abstract/Bridge.sol b/protocol/src/abstract/Bridge.sol index 91bbbafb..3d94ab5a 100644 --- a/protocol/src/abstract/Bridge.sol +++ b/protocol/src/abstract/Bridge.sol @@ -3,8 +3,6 @@ pragma solidity ^0.8.20; import {IBridge} from "../interfaces/IBridge.sol"; import {AccessControl} from "@openzeppelin/contracts/access/AccessControl.sol"; -import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; -import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import {Pausable} from "@openzeppelin/contracts/utils/Pausable.sol"; /** @@ -34,6 +32,12 @@ abstract contract Bridge is IBridge, AccessControl, Pausable { */ bytes32 constant DEPOSIT_NATIVE_TOPIC_0 = keccak256("DepositNative(uint256,uint256,address)"); + /** + * @dev The topic 0 (event signature) of the address for native deposit event. + */ + address constant MOCK_ADDRESS_FOR_NATIVE_DEPOSIT = + address(uint160(uint256(keccak256("MOCK_ADDRESS_FOR_NATIVE_DEPOSIT")))); + /** * @dev Map token address to token data. */ @@ -74,11 +78,12 @@ abstract contract Bridge is IBridge, AccessControl, Pausable { * @dev Constructor. * @notice Grants the DEFAULT_ADMIN_ROLE and PAUSER_ROLE to the msg.sender. */ - constructor(address _bridgeContract) { + constructor(address _bridgeContract, TokenLimits memory nativeTokenLimits) { if (_bridgeContract == address(0)) revert InvalidBridgeContract(); _grantRole(DEFAULT_ADMIN_ROLE, msg.sender); _grantRole(PAUSER_ROLE, msg.sender); bridgeContract = _bridgeContract; + _configureTokenData(MOCK_ADDRESS_FOR_NATIVE_DEPOSIT, nativeTokenLimits, true); } /** @@ -198,7 +203,7 @@ abstract contract Bridge is IBridge, AccessControl, Pausable { * @param limits The token limits to configure. * @param newToken Whether the token is new. */ - function _configureTokenData(address token, TokenLimits calldata limits, bool newToken) internal { + function _configureTokenData(address token, TokenLimits memory limits, bool newToken) internal { uint256 currMinAmount = tokenData[token].limits.minAmount; if (limits.minAmount == 0 || (newToken ? currMinAmount != 0 : currMinAmount == 0)) { revert InvalidTokenConfig(); @@ -214,7 +219,7 @@ abstract contract Bridge is IBridge, AccessControl, Pausable { /** * @inheritdoc IBridge */ - function configureToken(address token, TokenLimits calldata limits) external onlyRole(DEFAULT_ADMIN_ROLE) { + function configureToken(address token, TokenLimits memory limits) external onlyRole(DEFAULT_ADMIN_ROLE) { _configureTokenData(token, limits, false); } @@ -224,7 +229,7 @@ abstract contract Bridge is IBridge, AccessControl, Pausable { * @param mirrorToken Token that will be deposited in the mirror contract. * @param limits Token limits associated with the token. */ - function _whitelistToken(address token, address mirrorToken, TokenLimits calldata limits) internal { + function _whitelistToken(address token, address mirrorToken, TokenLimits memory limits) internal { if (mirrorTokens[mirrorToken] != address(0)) { revert InvalidTokenConfig(); } diff --git a/protocol/src/libraries/PodMintBalance.sol b/protocol/src/libraries/PodMintBalance.sol index 16703b7c..91c9c4b4 100644 --- a/protocol/src/libraries/PodMintBalance.sol +++ b/protocol/src/libraries/PodMintBalance.sol @@ -1,19 +1,19 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.28; +// // SPDX-License-Identifier: MIT +// pragma solidity ^0.8.28; -library PodMintBalance { - /** - * @dev The address of the external pod mint balance precompile. - */ - address constant PRECOMPILE_ADDRESS = address(uint160(uint256(keccak256("POD_MINT_BALANCE")))); +// library PodMintBalance { +// /** +// * @dev The address of the external pod mint balance precompile. +// */ +// address constant PRECOMPILE_ADDRESS = address(uint160(uint256(keccak256("POD_MINT_BALANCE")))); - /** - * @dev Mints tokens to the caller. - * @param amount The amount of tokens to mint. - * @return success Whether the minting was successful. - */ - function mint(uint256 amount) external view returns (bool) { - (bool success,) = PRECOMPILE_ADDRESS.staticcall(abi.encode(amount)); - return success; - } -} +// /** +// * @dev Mints tokens to the caller. +// * @param amount The amount of tokens to mint. +// * @return success Whether the minting was successful. +// */ +// function mint(uint256 amount) external view returns (bool) { +// (bool success,) = PRECOMPILE_ADDRESS.staticcall(abi.encode(amount)); +// return success; +// } +// } diff --git a/protocol/src/libraries/PodPrecompileHelper.sol b/protocol/src/libraries/PodPrecompileHelper.sol new file mode 100644 index 00000000..b65c3663 --- /dev/null +++ b/protocol/src/libraries/PodPrecompileHelper.sol @@ -0,0 +1,74 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.28; + +import {EthGetLogsTypes} from "pod-sdk/types/EthGetLogsTypes.sol"; +import {EthGetBlockByNumberTypes} from "pod-sdk/types/EthGetBlockByNumberTypes.sol"; +import {TxInfo, getTxInfo} from "pod-sdk/Context.sol"; +import {HexUtils} from "./HexUtils.sol"; + +library PodPrecompileHelper { + error PrecompileCallFailed(); + + /** + * @dev The address of the external pod mint balance precompile. + */ + address constant POD_MINT_BALANCE_PRECOMPILE_ADDRESS = address(uint160(uint256(keccak256("POD_MINT_BALANCE")))); + + /** + * @dev Mints tokens to the caller. + * @param amount The amount of tokens to mint. + * @return success Whether the minting was successful. + */ + function mint(uint256 amount) external view returns (bool) { + (bool success,) = POD_MINT_BALANCE_PRECOMPILE_ADDRESS.staticcall(abi.encode(amount)); + return success; + } + + /** + * @dev Gets the finalized block number. + * @return blockNumber The finalized block number. + */ + function getFinalizedBlockNumber() internal view returns (uint256) { + (bool success, bytes memory output) = EthGetBlockByNumberTypes.PRECOMPILE_ADDRESS.staticcall( + abi.encode( + EthGetBlockByNumberTypes.PrecompileArgs( + 1, EthGetBlockByNumberTypes.RpcArgs(hex"66696e616c697a6564", false) + ) + ) + ); + if (!success) revert PrecompileCallFailed(); + return HexUtils.uintFromBigEndian(abi.decode(output, (EthGetBlockByNumberTypes.RpcBlock)).number); + } + + /** + * @dev Gets the logs. + * @param blockNumber The block number to get the logs for. + * @param topics The topics to get the logs for. + * @param bridgeContract The bridge contract to get the logs for. + * @return logs The logs. + */ + function getLogs(uint256 chainId, uint256 blockNumber, bytes32[] memory topics, address bridgeContract) + internal + view + returns (EthGetLogsTypes.RpcLog[] memory) + { + bytes memory n = HexUtils.toBytesMinimal(blockNumber); + (bool success, bytes memory output) = EthGetLogsTypes.PRECOMPILE_ADDRESS.staticcall( + abi.encode( + EthGetLogsTypes.PrecompileArgs( + chainId, EthGetLogsTypes.RpcArgs(n, n, bridgeContract, bytes32(0), topics) + ) + ) + ); + if (!success) revert PrecompileCallFailed(); + + EthGetLogsTypes.RpcLog[] memory logs = abi.decode(output, (EthGetLogsTypes.RpcLog[])); + + return logs; + } + + function getTxHash() internal view returns (uint256) { + TxInfo memory txInfo = getTxInfo(); + return uint256(txInfo.txHash); + } +} diff --git a/protocol/test/BridgeDepositWithdraw.t.sol b/protocol/test/BridgeDepositWithdraw.t.sol index 326880fa..fb30563f 100644 --- a/protocol/test/BridgeDepositWithdraw.t.sol +++ b/protocol/test/BridgeDepositWithdraw.t.sol @@ -44,7 +44,7 @@ contract BridgeDepositWithdrawTest is BridgeBehaviorTest { } podRegistry = new PodRegistry(initialValidators); - _bridge = new BridgeDepositWithdraw(address(podRegistry), OTHER_BRIDGE_CONTRACT); + _bridge = new BridgeDepositWithdraw(address(podRegistry), OTHER_BRIDGE_CONTRACT, nativeTokenLimits); _token = new WrappedToken("InitialToken", "ITKN", 18); _token.mint(user, INITIAL_BALANCE); @@ -281,7 +281,8 @@ contract BridgeDepositWithdrawTest is BridgeBehaviorTest { function test_Migrate_NoWhitelistedTokens() public { vm.prank(admin); - BridgeDepositWithdraw fresh = new BridgeDepositWithdraw(address(podRegistry), OTHER_BRIDGE_CONTRACT); + BridgeDepositWithdraw fresh = + new BridgeDepositWithdraw(address(podRegistry), OTHER_BRIDGE_CONTRACT, nativeTokenLimits); vm.prank(admin); fresh.pause(); vm.prank(admin); diff --git a/protocol/test/BridgeMintBurn.t.sol b/protocol/test/BridgeMintBurn.t.sol index 10bfd272..e9eb0fee 100644 --- a/protocol/test/BridgeMintBurn.t.sol +++ b/protocol/test/BridgeMintBurn.t.sol @@ -13,11 +13,12 @@ import {EthGetLogsTypes} from "pod-sdk/types/EthGetLogsTypes.sol"; import {EthGetBlockByNumberTypes} from "pod-sdk/types/EthGetBlockByNumberTypes.sol"; import {HexUtils} from "../src/libraries/HexUtils.sol"; import {TxInfo} from "pod-sdk/Context.sol"; +import {VmSafe} from "forge-std/Vm.sol"; contract BridgeMintBurnTest is BridgeBehaviorTest { BridgeMintBurn private _bridge; WrappedToken private _token; - address immutable _mirror = makeAddr("mirrorToken"); + address immutable MIRROR_TOKEN_ADDRESS = makeAddr("mirrorToken"); address immutable OTHER_BRIDGE_CONTRACT = makeAddr("otherBridgeContract"); function bridge() internal view override returns (Bridge) { @@ -30,10 +31,12 @@ contract BridgeMintBurnTest is BridgeBehaviorTest { function setUpSuite() public override { vm.startPrank(admin); - _bridge = new BridgeMintBurn(OTHER_BRIDGE_CONTRACT); + _bridge = new BridgeMintBurn(OTHER_BRIDGE_CONTRACT, nativeTokenLimits); _token = WrappedToken( - _bridge.createAndWhitelistMirrorToken("Token", "TKN", address(0), address(_mirror), 18, tokenLimits) + _bridge.createAndWhitelistMirrorToken( + "Token", "TKN", address(0), address(MIRROR_TOKEN_ADDRESS), 18, tokenLimits + ) ); vm.stopPrank(); @@ -58,15 +61,15 @@ contract BridgeMintBurnTest is BridgeBehaviorTest { function test_Claim_SingleLog_MintsToRecipient() public { EthGetLogsTypes.RpcLog[] memory logs = new EthGetLogsTypes.RpcLog[](1); - logs[0] = _makeLog(0, _mirror, DEPOSIT_AMOUNT, recipient); - _mockEthGetLogs(0, 1, 1, _mirror, logs); + logs[0] = _makeLog(0, MIRROR_TOKEN_ADDRESS, DEPOSIT_AMOUNT, recipient); + _mockEthGetLogs(0, 1, 1, MIRROR_TOKEN_ADDRESS, logs); _mockEthGetBlockByNumber(2); _mockTxInfo(TxInfo({txHash: bytes32(0), nonce: 0})); assertEq(_token.balanceOf(recipient), 0); - // vm.expectEmit(true, true, true, true); - emit IBridge.Claim(0, address(_token), _mirror, DEPOSIT_AMOUNT, recipient); - _bridge.claim(0, _mirror, 1); + vm.expectEmit(true, false, false, true); + emit IBridge.Claim(0, address(_token), MIRROR_TOKEN_ADDRESS, DEPOSIT_AMOUNT, recipient); + _bridge.claim(0, MIRROR_TOKEN_ADDRESS, 1); assertEq(_token.balanceOf(recipient), DEPOSIT_AMOUNT); @@ -79,56 +82,57 @@ contract BridgeMintBurnTest is BridgeBehaviorTest { function test_Claim_RevertIfDailyLimitExhausted() public { EthGetLogsTypes.RpcLog[] memory logs = new EthGetLogsTypes.RpcLog[](1); - logs[0] = _makeLog(0, _mirror, tokenLimits.claim + 1, recipient); + logs[0] = _makeLog(0, MIRROR_TOKEN_ADDRESS, tokenLimits.claim + 1, recipient); _mockEthGetBlockByNumber(1); - _mockEthGetLogs(0, 1, 1, _mirror, logs); + _mockEthGetLogs(0, 1, 1, MIRROR_TOKEN_ADDRESS, logs); vm.expectRevert(abi.encodeWithSelector(IBridge.DailyLimitExhausted.selector)); - _bridge.claim(0, _mirror, 1); + _bridge.claim(0, MIRROR_TOKEN_ADDRESS, 1); } - function test_Claim_RevertIfInvalidBridgeContract() public { - EthGetLogsTypes.RpcLog[] memory logs = new EthGetLogsTypes.RpcLog[](1); - logs[0] = _makeLog(0, _mirror, DEPOSIT_AMOUNT, recipient); - logs[0].addr = address(0xBEEF); - _mockEthGetBlockByNumber(1); - _mockEthGetLogs(0, 1, 1, _mirror, logs); - vm.expectRevert(abi.encodeWithSelector(IBridge.InvalidBridgeContract.selector)); - _bridge.claim(0, _mirror, 1); - } + // TODO: redundant test, add if the check is added back. + // function test_Claim_RevertIfInvalidBridgeContract() public { + // EthGetLogsTypes.RpcLog[] memory logs = new EthGetLogsTypes.RpcLog[](1); + // logs[0] = _makeLog(0, MIRROR_TOKEN_ADDRESS, DEPOSIT_AMOUNT, recipient); + // logs[0].addr = address(0xBEEF); + // _mockEthGetBlockByNumber(1); + // _mockEthGetLogs(0, 1, 1, MIRROR_TOKEN_ADDRESS, logs); + // vm.expectRevert(abi.encodeWithSelector(IBridge.InvalidBridgeContract.selector)); + // _bridge.claim(0, MIRROR_TOKEN_ADDRESS, 1); + // } function test_Claim_RevertIfDailyLimitExhausted_ButSucceedAfterOneDay() public { EthGetLogsTypes.RpcLog[] memory logs = new EthGetLogsTypes.RpcLog[](1); - logs[0] = _makeLog(0, _mirror, DEPOSIT_AMOUNT, recipient); + logs[0] = _makeLog(0, MIRROR_TOKEN_ADDRESS, DEPOSIT_AMOUNT, recipient); _mockEthGetBlockByNumber(1); - _mockEthGetLogs(0, 1, 1, _mirror, logs); - _bridge.claim(0, _mirror, 1); - logs[0] = _makeLog(1, _mirror, tokenLimits.claim, recipient); + _mockEthGetLogs(0, 1, 1, MIRROR_TOKEN_ADDRESS, logs); + _bridge.claim(0, MIRROR_TOKEN_ADDRESS, 1); + logs[0] = _makeLog(1, MIRROR_TOKEN_ADDRESS, tokenLimits.claim, recipient); _mockEthGetBlockByNumber(1); - _mockEthGetLogs(1, 1, 1, _mirror, logs); + _mockEthGetLogs(1, 1, 1, MIRROR_TOKEN_ADDRESS, logs); vm.expectRevert(abi.encodeWithSelector(IBridge.DailyLimitExhausted.selector)); - _bridge.claim(1, _mirror, 1); + _bridge.claim(1, MIRROR_TOKEN_ADDRESS, 1); vm.warp(block.timestamp + 1 days + 1); _mockEthGetBlockByNumber(1); - _mockEthGetLogs(1, 1, 1, _mirror, logs); - _bridge.claim(1, _mirror, 1); + _mockEthGetLogs(1, 1, 1, MIRROR_TOKEN_ADDRESS, logs); + _bridge.claim(1, MIRROR_TOKEN_ADDRESS, 1); } function test_Claim_RevertIfNoDepositsFound() public { EthGetLogsTypes.RpcLog[] memory logs = new EthGetLogsTypes.RpcLog[](0); _mockEthGetBlockByNumber(1); - _mockEthGetLogs(0, 1, 1, _mirror, logs); + _mockEthGetLogs(0, 1, 1, MIRROR_TOKEN_ADDRESS, logs); vm.expectRevert(abi.encodeWithSelector(IBridge.InvalidDepositLog.selector)); - _bridge.claim(0, _mirror, 1); + _bridge.claim(0, MIRROR_TOKEN_ADDRESS, 1); } function test_Claim_RevertIfMultipleDepositsFound() public { EthGetLogsTypes.RpcLog[] memory logs = new EthGetLogsTypes.RpcLog[](2); - logs[0] = _makeLog(0, _mirror, DEPOSIT_AMOUNT, recipient); - logs[1] = _makeLog(0, _mirror, DEPOSIT_AMOUNT, recipient); + logs[0] = _makeLog(0, MIRROR_TOKEN_ADDRESS, DEPOSIT_AMOUNT, recipient); + logs[1] = _makeLog(0, MIRROR_TOKEN_ADDRESS, DEPOSIT_AMOUNT, recipient); _mockEthGetBlockByNumber(1); - _mockEthGetLogs(0, 1, 1, _mirror, logs); + _mockEthGetLogs(0, 1, 1, MIRROR_TOKEN_ADDRESS, logs); vm.expectRevert(abi.encodeWithSelector(IBridge.InvalidDepositLog.selector)); - _bridge.claim(0, _mirror, 1); + _bridge.claim(0, MIRROR_TOKEN_ADDRESS, 1); } function test_Claim_RevertIfMirrorTokenNotFound() public { @@ -145,57 +149,57 @@ contract BridgeMintBurnTest is BridgeBehaviorTest { function test_Claim_RevertIfBlockNotFinalized() public { EthGetLogsTypes.RpcLog[] memory logs = new EthGetLogsTypes.RpcLog[](1); - logs[0] = _makeLog(0, _mirror, DEPOSIT_AMOUNT, recipient); + logs[0] = _makeLog(0, MIRROR_TOKEN_ADDRESS, DEPOSIT_AMOUNT, recipient); _mockEthGetBlockByNumber(1); - _mockEthGetLogs(0, 1, 1, _mirror, logs); + _mockEthGetLogs(0, 1, 1, MIRROR_TOKEN_ADDRESS, logs); vm.expectRevert(abi.encodeWithSelector(IBridgeMintBurn.BlockNotFinalized.selector)); - _bridge.claim(0, _mirror, 10); + _bridge.claim(0, MIRROR_TOKEN_ADDRESS, 10); } function test_Claim_RevertIfAlreadyProcessed() public { EthGetLogsTypes.RpcLog[] memory logs = new EthGetLogsTypes.RpcLog[](1); - logs[0] = _makeLog(0, _mirror, DEPOSIT_AMOUNT, recipient); + logs[0] = _makeLog(0, MIRROR_TOKEN_ADDRESS, DEPOSIT_AMOUNT, recipient); _mockEthGetBlockByNumber(1); - _mockEthGetLogs(0, 1, 1, _mirror, logs); - _bridge.claim(0, _mirror, 1); + _mockEthGetLogs(0, 1, 1, MIRROR_TOKEN_ADDRESS, logs); + _bridge.claim(0, MIRROR_TOKEN_ADDRESS, 1); // Mock again with same log so requestId is identical _mockEthGetBlockByNumber(1); - _mockEthGetLogs(0, 1, 1, _mirror, logs); + _mockEthGetLogs(0, 1, 1, MIRROR_TOKEN_ADDRESS, logs); vm.expectRevert(abi.encodeWithSelector(IBridge.RequestAlreadyProcessed.selector)); - _bridge.claim(0, _mirror, 1); + _bridge.claim(0, MIRROR_TOKEN_ADDRESS, 1); } function test_Claim_RevertIfPaused() public { vm.prank(admin); _bridge.pause(); vm.expectRevert(abi.encodeWithSelector(Pausable.EnforcedPause.selector)); - _bridge.claim(0, _mirror, 1); + _bridge.claim(0, MIRROR_TOKEN_ADDRESS, 1); } function test_Claim_RevertIfInvalidLog() public { EthGetLogsTypes.RpcLog[] memory logs = new EthGetLogsTypes.RpcLog[](2); - logs[0] = _makeLog(0, _mirror, DEPOSIT_AMOUNT, recipient); - logs[1] = _makeLog(1, _mirror, DEPOSIT_AMOUNT, recipient); + logs[0] = _makeLog(0, MIRROR_TOKEN_ADDRESS, DEPOSIT_AMOUNT, recipient); + logs[1] = _makeLog(1, MIRROR_TOKEN_ADDRESS, DEPOSIT_AMOUNT, recipient); _mockEthGetBlockByNumber(1); - _mockEthGetLogs(0, 1, 1, _mirror, logs); + _mockEthGetLogs(0, 1, 1, MIRROR_TOKEN_ADDRESS, logs); vm.expectRevert(abi.encodeWithSelector(IBridge.InvalidDepositLog.selector)); - _bridge.claim(0, _mirror, 1); + _bridge.claim(0, MIRROR_TOKEN_ADDRESS, 1); logs = new EthGetLogsTypes.RpcLog[](0); _mockEthGetBlockByNumber(1); - _mockEthGetLogs(0, 1, 1, _mirror, logs); + _mockEthGetLogs(0, 1, 1, MIRROR_TOKEN_ADDRESS, logs); vm.expectRevert(abi.encodeWithSelector(IBridge.InvalidDepositLog.selector)); - _bridge.claim(0, _mirror, 1); + _bridge.claim(0, MIRROR_TOKEN_ADDRESS, 1); } function test_Claim_RevertIfPrecompileCallFails() public { _mockEthGetBlockByNumber(1); - EthGetLogsTypes.PrecompileArgs memory args = _buildArgs(0, 1, 1, _mirror); + EthGetLogsTypes.PrecompileArgs memory args = _buildArgs(0, 1, 1, MIRROR_TOKEN_ADDRESS); podMockEthGetLogsRevert(abi.encode(args)); vm.expectRevert(abi.encodeWithSelector(IBridgeMintBurn.PrecompileCallFailed.selector)); - _bridge.claim(0, _mirror, 1); + _bridge.claim(0, MIRROR_TOKEN_ADDRESS, 1); } function test_ClaimNative() public { @@ -207,7 +211,7 @@ contract BridgeMintBurnTest is BridgeBehaviorTest { vm.expectEmit(true, false, false, true); emit IBridge.ClaimNative(0, DEPOSIT_AMOUNT, recipient); - vm.prank(recipient); + vm.prank(user); _bridge.claimNative(0, 1); // should be done by precompile assertEq(recipient.balance, DEPOSIT_AMOUNT); @@ -256,39 +260,38 @@ contract BridgeMintBurnTest is BridgeBehaviorTest { _bridge.claimNative(0, 10); } - function test_ClaimNative_RevertIfInvalidBridgeContract() public { - EthGetLogsTypes.RpcLog[] memory logs = new EthGetLogsTypes.RpcLog[](1); - logs[0] = _makeLog(0, address(0), DEPOSIT_AMOUNT, recipient); - logs[0].addr = address(0xBEEF); - _mockEthGetBlockByNumber(1); - _mockEthGetLogs(0, 1, 1, address(0), logs); - vm.expectRevert(abi.encodeWithSelector(IBridge.InvalidBridgeContract.selector)); - _bridge.claimNative(0, 1); - } + // TODO: redundant test, add if the check is added back. + // function test_ClaimNative_RevertIfInvalidBridgeContract() public { + // EthGetLogsTypes.RpcLog[] memory logs = new EthGetLogsTypes.RpcLog[](1); + // logs[0] = _makeLog(0, address(0), DEPOSIT_AMOUNT, recipient); + // logs[0].addr = address(0xBEEF); + // _mockEthGetBlockByNumber(1); + // _mockEthGetLogs(0, 1, 1, address(0), logs); + // vm.expectRevert(abi.encodeWithSelector(IBridge.InvalidBridgeContract.selector)); + // _bridge.claimNative(0, 1); + // } - function test_ClaimNative_RevertIfRequestAlreadyProcessed() public { + function test_ClaimNative_DoNothingIfRequestAlreadyProcessed() public { EthGetLogsTypes.RpcLog[] memory logs = new EthGetLogsTypes.RpcLog[](1); logs[0] = _makeLog(0, address(0), DEPOSIT_AMOUNT, recipient); _mockEthGetBlockByNumber(1); _mockEthGetLogs(0, 1, 1, address(0), logs); + vm.expectEmit(true, false, false, true); + emit IBridge.ClaimNative(0, DEPOSIT_AMOUNT, recipient); vm.prank(recipient); _bridge.claimNative(0, 1); _mockEthGetBlockByNumber(1); _mockEthGetLogs(0, 1, 1, address(0), logs); - vm.expectRevert(abi.encodeWithSelector(IBridge.RequestAlreadyProcessed.selector)); - vm.prank(recipient); - _bridge.claimNative(0, 1); - } - function test_ClaimNative_RevertIfInvalidToAddress() public { - EthGetLogsTypes.RpcLog[] memory logs = new EthGetLogsTypes.RpcLog[](1); - logs[0] = _makeLog(0, address(0), DEPOSIT_AMOUNT, address(0xBEEF)); - _mockEthGetBlockByNumber(1); - _mockEthGetLogs(0, 1, 1, address(0), logs); + // record that no logs are emitted + vm.recordLogs(); vm.prank(recipient); - vm.expectRevert(abi.encodeWithSelector(IBridge.InvalidToAddress.selector)); _bridge.claimNative(0, 1); + + // confirm that nothing happens when the request is already processed + VmSafe.Log[] memory recordedLogs = vm.getRecordedLogs(); + assertEq(recordedLogs.length, 0); } function test_Migrate_TransfersRolesToNewBridge() public { diff --git a/protocol/test/abstract/Bridge.t.sol b/protocol/test/abstract/Bridge.t.sol index 80cc3372..bb459b02 100644 --- a/protocol/test/abstract/Bridge.t.sol +++ b/protocol/test/abstract/Bridge.t.sol @@ -17,6 +17,7 @@ abstract contract BridgeBehaviorTest is PodTest { uint256 public constant DEPOSIT_AMOUNT = 100e18; IBridge.TokenLimits public tokenLimits; + IBridge.TokenLimits public nativeTokenLimits; // Hooks each concrete suite must implement function bridge() internal view virtual returns (Bridge); @@ -25,6 +26,7 @@ abstract contract BridgeBehaviorTest is PodTest { function setUp() public virtual { tokenLimits = IBridge.TokenLimits({minAmount: 1e18, deposit: 500e18, claim: 400e18}); + nativeTokenLimits = IBridge.TokenLimits({minAmount: 0.01 ether, deposit: 500e18, claim: 400e18}); setUpSuite(); } @@ -76,7 +78,7 @@ abstract contract BridgeBehaviorTest is PodTest { vm.deal(user, DEPOSIT_AMOUNT); vm.expectRevert(abi.encodeWithSelector(IBridge.InvalidAmount.selector)); vm.prank(user); - bridge().depositNative{value: 0.001 ether}(recipient); + bridge().depositNative{value: nativeTokenLimits.minAmount - 1}(recipient); } function test_Deposit_ZeroRecipientAndPause() public { From 7c66bfd3452955836a3456c6cd3b1b88840f8e4c Mon Sep 17 00:00:00 2001 From: Jakov Mitrovski Date: Thu, 18 Sep 2025 19:53:23 +0200 Subject: [PATCH 52/64] configurable limits for native token, gas reduction, library refactor --- protocol/src/BridgeMintBurn.sol | 4 +-- protocol/src/libraries/PodMintBalance.sol | 19 ----------- protocol/test/BridgeMintBurn.t.sol | 40 +++++++++++------------ 3 files changed, 22 insertions(+), 41 deletions(-) delete mode 100644 protocol/src/libraries/PodMintBalance.sol diff --git a/protocol/src/BridgeMintBurn.sol b/protocol/src/BridgeMintBurn.sol index 5849b313..d9fb8cf5 100644 --- a/protocol/src/BridgeMintBurn.sol +++ b/protocol/src/BridgeMintBurn.sol @@ -96,8 +96,8 @@ contract BridgeMintBurn is Bridge, IBridgeMintBurn { if (logs.length != 1) revert InvalidDepositLog(); - // TODO: redunatnt check for extra security, removing because of gas, add it if gas limit permits. - // if (logs[0].addr != bridgeContract) revert InvalidBridgeContract(); + //redunatnt check for extra security, can be removed for gas purposes. + if (logs[0].addr != bridgeContract) revert InvalidBridgeContract(); (decodedAmount, decodedTo) = abi.decode(logs[0].data, (uint256, address)); requestId = _hashRequest(id, token, decodedAmount, decodedTo); diff --git a/protocol/src/libraries/PodMintBalance.sol b/protocol/src/libraries/PodMintBalance.sol deleted file mode 100644 index 91c9c4b4..00000000 --- a/protocol/src/libraries/PodMintBalance.sol +++ /dev/null @@ -1,19 +0,0 @@ -// // SPDX-License-Identifier: MIT -// pragma solidity ^0.8.28; - -// library PodMintBalance { -// /** -// * @dev The address of the external pod mint balance precompile. -// */ -// address constant PRECOMPILE_ADDRESS = address(uint160(uint256(keccak256("POD_MINT_BALANCE")))); - -// /** -// * @dev Mints tokens to the caller. -// * @param amount The amount of tokens to mint. -// * @return success Whether the minting was successful. -// */ -// function mint(uint256 amount) external view returns (bool) { -// (bool success,) = PRECOMPILE_ADDRESS.staticcall(abi.encode(amount)); -// return success; -// } -// } diff --git a/protocol/test/BridgeMintBurn.t.sol b/protocol/test/BridgeMintBurn.t.sol index e9eb0fee..e27f5360 100644 --- a/protocol/test/BridgeMintBurn.t.sol +++ b/protocol/test/BridgeMintBurn.t.sol @@ -89,16 +89,16 @@ contract BridgeMintBurnTest is BridgeBehaviorTest { _bridge.claim(0, MIRROR_TOKEN_ADDRESS, 1); } - // TODO: redundant test, add if the check is added back. - // function test_Claim_RevertIfInvalidBridgeContract() public { - // EthGetLogsTypes.RpcLog[] memory logs = new EthGetLogsTypes.RpcLog[](1); - // logs[0] = _makeLog(0, MIRROR_TOKEN_ADDRESS, DEPOSIT_AMOUNT, recipient); - // logs[0].addr = address(0xBEEF); - // _mockEthGetBlockByNumber(1); - // _mockEthGetLogs(0, 1, 1, MIRROR_TOKEN_ADDRESS, logs); - // vm.expectRevert(abi.encodeWithSelector(IBridge.InvalidBridgeContract.selector)); - // _bridge.claim(0, MIRROR_TOKEN_ADDRESS, 1); - // } + // TODO: redundant test, remove if the check is removed again. + function test_Claim_RevertIfInvalidBridgeContract() public { + EthGetLogsTypes.RpcLog[] memory logs = new EthGetLogsTypes.RpcLog[](1); + logs[0] = _makeLog(0, MIRROR_TOKEN_ADDRESS, DEPOSIT_AMOUNT, recipient); + logs[0].addr = address(0xBEEF); + _mockEthGetBlockByNumber(1); + _mockEthGetLogs(0, 1, 1, MIRROR_TOKEN_ADDRESS, logs); + vm.expectRevert(abi.encodeWithSelector(IBridge.InvalidBridgeContract.selector)); + _bridge.claim(0, MIRROR_TOKEN_ADDRESS, 1); + } function test_Claim_RevertIfDailyLimitExhausted_ButSucceedAfterOneDay() public { EthGetLogsTypes.RpcLog[] memory logs = new EthGetLogsTypes.RpcLog[](1); @@ -260,16 +260,16 @@ contract BridgeMintBurnTest is BridgeBehaviorTest { _bridge.claimNative(0, 10); } - // TODO: redundant test, add if the check is added back. - // function test_ClaimNative_RevertIfInvalidBridgeContract() public { - // EthGetLogsTypes.RpcLog[] memory logs = new EthGetLogsTypes.RpcLog[](1); - // logs[0] = _makeLog(0, address(0), DEPOSIT_AMOUNT, recipient); - // logs[0].addr = address(0xBEEF); - // _mockEthGetBlockByNumber(1); - // _mockEthGetLogs(0, 1, 1, address(0), logs); - // vm.expectRevert(abi.encodeWithSelector(IBridge.InvalidBridgeContract.selector)); - // _bridge.claimNative(0, 1); - // } + // TODO: redundant test, add if the check is removed again. + function test_ClaimNative_RevertIfInvalidBridgeContract() public { + EthGetLogsTypes.RpcLog[] memory logs = new EthGetLogsTypes.RpcLog[](1); + logs[0] = _makeLog(0, address(0), DEPOSIT_AMOUNT, recipient); + logs[0].addr = address(0xBEEF); + _mockEthGetBlockByNumber(1); + _mockEthGetLogs(0, 1, 1, address(0), logs); + vm.expectRevert(abi.encodeWithSelector(IBridge.InvalidBridgeContract.selector)); + _bridge.claimNative(0, 1); + } function test_ClaimNative_DoNothingIfRequestAlreadyProcessed() public { EthGetLogsTypes.RpcLog[] memory logs = new EthGetLogsTypes.RpcLog[](1); From a27ddc2f94581a735f7d7fa93fc067e00a58ca1a Mon Sep 17 00:00:00 2001 From: Jakov Mitrovski Date: Thu, 18 Sep 2025 20:11:59 +0200 Subject: [PATCH 53/64] add tests for consumption of native bridging --- protocol/src/BridgeDepositWithdraw.sol | 2 +- protocol/src/BridgeMintBurn.sol | 4 +- protocol/src/abstract/Bridge.sol | 2 +- protocol/src/interfaces/IBridge.sol | 5 -- protocol/test/BridgeDepositWithdraw.t.sol | 8 ++- protocol/test/BridgeMintBurn.t.sol | 70 +++++++++++++++++------ protocol/test/abstract/Bridge.t.sol | 42 +++++++++++++- 7 files changed, 103 insertions(+), 30 deletions(-) diff --git a/protocol/src/BridgeDepositWithdraw.sol b/protocol/src/BridgeDepositWithdraw.sol index 40df63a4..f6810563 100644 --- a/protocol/src/BridgeDepositWithdraw.sol +++ b/protocol/src/BridgeDepositWithdraw.sol @@ -140,7 +140,7 @@ contract BridgeDepositWithdraw is Bridge, IBridgeDepositWithdraw { function claimNative(PodECDSA.CertifiedLog calldata certifiedLog) public override whenNotPaused { (uint256 id, uint256 amount, address to) = _decodeDepositNativeLog(certifiedLog.log); - if (amount < 0.01 ether) revert InvalidAmount(); + if (!_isValidTokenAmount(MOCK_ADDRESS_FOR_NATIVE_DEPOSIT, amount, false)) revert InvalidTokenAmount(); bytes32 requestId = _hashRequest(id, address(0), amount, to); if (processedRequests[requestId]) revert RequestAlreadyProcessed(); diff --git a/protocol/src/BridgeMintBurn.sol b/protocol/src/BridgeMintBurn.sol index d9fb8cf5..a6335d1e 100644 --- a/protocol/src/BridgeMintBurn.sol +++ b/protocol/src/BridgeMintBurn.sol @@ -97,7 +97,7 @@ contract BridgeMintBurn is Bridge, IBridgeMintBurn { if (logs.length != 1) revert InvalidDepositLog(); //redunatnt check for extra security, can be removed for gas purposes. - if (logs[0].addr != bridgeContract) revert InvalidBridgeContract(); + // if (logs[0].addr != bridgeContract) revert InvalidBridgeContract(); (decodedAmount, decodedTo) = abi.decode(logs[0].data, (uint256, address)); requestId = _hashRequest(id, token, decodedAmount, decodedTo); @@ -119,7 +119,7 @@ contract BridgeMintBurn is Bridge, IBridgeMintBurn { (uint256 decodedAmount, address decodedTo, bytes32 requestId) = _claim(id, address(0), blockNumber, topics); - if (!_isValidTokenAmount(MOCK_ADDRESS_FOR_NATIVE_DEPOSIT, decodedAmount, false)) revert InvalidAmount(); + if (!_isValidTokenAmount(MOCK_ADDRESS_FOR_NATIVE_DEPOSIT, decodedAmount, false)) revert InvalidTokenAmount(); bool isProcessed = processedRequests[requestId]; diff --git a/protocol/src/abstract/Bridge.sol b/protocol/src/abstract/Bridge.sol index 3d94ab5a..9ef586d0 100644 --- a/protocol/src/abstract/Bridge.sol +++ b/protocol/src/abstract/Bridge.sol @@ -173,7 +173,7 @@ abstract contract Bridge is IBridge, AccessControl, Pausable { * @inheritdoc IBridge */ function depositNative(address to) external payable override whenNotPaused { - if (msg.value < 0.01 ether) revert InvalidAmount(); + if (!_isValidTokenAmount(MOCK_ADDRESS_FOR_NATIVE_DEPOSIT, msg.value, true)) revert InvalidTokenAmount(); uint256 id = _getDepositId(); emit DepositNative(id, msg.value, to); } diff --git a/protocol/src/interfaces/IBridge.sol b/protocol/src/interfaces/IBridge.sol index cd10e67e..ee8a163e 100644 --- a/protocol/src/interfaces/IBridge.sol +++ b/protocol/src/interfaces/IBridge.sol @@ -19,11 +19,6 @@ interface IBridge { */ error InvalidTokenAmount(); - /** - * @dev Error thrown when the provided amount is invalid. - */ - error InvalidAmount(); - /** * @dev Error thrown when the destination address is zero or invalid. */ diff --git a/protocol/test/BridgeDepositWithdraw.t.sol b/protocol/test/BridgeDepositWithdraw.t.sol index fb30563f..cc3a7404 100644 --- a/protocol/test/BridgeDepositWithdraw.t.sol +++ b/protocol/test/BridgeDepositWithdraw.t.sol @@ -145,6 +145,10 @@ contract BridgeDepositWithdrawTest is BridgeBehaviorTest { _bridge.claimNative(certifiedLog); assertEq(address(bridge()).balance, 0); assertEq(recipient.balance, DEPOSIT_AMOUNT); + (, IBridge.TokenUsage memory dep, IBridge.TokenUsage memory claimUsage) = + bridge().tokenData(MOCK_ADDRESS_FOR_NATIVE_DEPOSIT); + assertEq(dep.consumed, DEPOSIT_AMOUNT); + assertEq(claimUsage.consumed, DEPOSIT_AMOUNT); } function test_ClaimNative_RevertIfPaused() public { @@ -174,8 +178,8 @@ contract BridgeDepositWithdrawTest is BridgeBehaviorTest { vm.prank(admin); _bridge.depositNative{value: DEPOSIT_AMOUNT}(recipient); PodECDSA.CertifiedLog memory certifiedLog = createNativeCertifiedLog(3); - certifiedLog.log.data = abi.encode(uint256(0.001 ether), recipient); - vm.expectRevert(abi.encodeWithSelector(IBridge.InvalidAmount.selector)); + certifiedLog.log.data = abi.encode(nativeTokenLimits.minAmount - 1, recipient); + vm.expectRevert(abi.encodeWithSelector(IBridge.InvalidTokenAmount.selector)); _bridge.claimNative(certifiedLog); assertEq(address(bridge()).balance, DEPOSIT_AMOUNT); assertEq(recipient.balance, 0); diff --git a/protocol/test/BridgeMintBurn.t.sol b/protocol/test/BridgeMintBurn.t.sol index e27f5360..d24ffa41 100644 --- a/protocol/test/BridgeMintBurn.t.sol +++ b/protocol/test/BridgeMintBurn.t.sol @@ -90,15 +90,15 @@ contract BridgeMintBurnTest is BridgeBehaviorTest { } // TODO: redundant test, remove if the check is removed again. - function test_Claim_RevertIfInvalidBridgeContract() public { - EthGetLogsTypes.RpcLog[] memory logs = new EthGetLogsTypes.RpcLog[](1); - logs[0] = _makeLog(0, MIRROR_TOKEN_ADDRESS, DEPOSIT_AMOUNT, recipient); - logs[0].addr = address(0xBEEF); - _mockEthGetBlockByNumber(1); - _mockEthGetLogs(0, 1, 1, MIRROR_TOKEN_ADDRESS, logs); - vm.expectRevert(abi.encodeWithSelector(IBridge.InvalidBridgeContract.selector)); - _bridge.claim(0, MIRROR_TOKEN_ADDRESS, 1); - } + // function test_Claim_RevertIfInvalidBridgeContract() public { + // EthGetLogsTypes.RpcLog[] memory logs = new EthGetLogsTypes.RpcLog[](1); + // logs[0] = _makeLog(0, MIRROR_TOKEN_ADDRESS, DEPOSIT_AMOUNT, recipient); + // logs[0].addr = address(0xBEEF); + // _mockEthGetBlockByNumber(1); + // _mockEthGetLogs(0, 1, 1, MIRROR_TOKEN_ADDRESS, logs); + // vm.expectRevert(abi.encodeWithSelector(IBridge.InvalidBridgeContract.selector)); + // _bridge.claim(0, MIRROR_TOKEN_ADDRESS, 1); + // } function test_Claim_RevertIfDailyLimitExhausted_ButSucceedAfterOneDay() public { EthGetLogsTypes.RpcLog[] memory logs = new EthGetLogsTypes.RpcLog[](1); @@ -244,33 +244,67 @@ contract BridgeMintBurnTest is BridgeBehaviorTest { function test_ClaimNative_RevertIfInvalidAmount() public { EthGetLogsTypes.RpcLog[] memory logs = new EthGetLogsTypes.RpcLog[](1); - logs[0] = _makeLog(0, address(0), 0.001 ether, recipient); + logs[0] = _makeLog(0, address(0), nativeTokenLimits.minAmount - 1, recipient); _mockEthGetBlockByNumber(1); _mockEthGetLogs(0, 1, 1, address(0), logs); - vm.expectRevert(abi.encodeWithSelector(IBridge.InvalidAmount.selector)); + vm.expectRevert(abi.encodeWithSelector(IBridge.InvalidTokenAmount.selector)); _bridge.claimNative(0, 1); } - function test_ClaimNative_RevertIfBlockNotFinalized() public { + function test_ClaimNative_TracksConsumed() public { EthGetLogsTypes.RpcLog[] memory logs = new EthGetLogsTypes.RpcLog[](1); logs[0] = _makeLog(0, address(0), DEPOSIT_AMOUNT, recipient); _mockEthGetBlockByNumber(1); _mockEthGetLogs(0, 1, 1, address(0), logs); - vm.expectRevert(abi.encodeWithSelector(IBridgeMintBurn.BlockNotFinalized.selector)); - _bridge.claimNative(0, 10); + _bridge.claimNative(0, 1); + (, IBridge.TokenUsage memory dep, IBridge.TokenUsage memory claimUsage) = + bridge().tokenData(MOCK_ADDRESS_FOR_NATIVE_DEPOSIT); + assertEq(claimUsage.consumed, DEPOSIT_AMOUNT); + logs[0] = _makeLog(1, address(0), DEPOSIT_AMOUNT, recipient); + _mockEthGetBlockByNumber(1); + _mockEthGetLogs(1, 1, 1, address(0), logs); + _bridge.claimNative(1, 1); + (, dep, claimUsage) = bridge().tokenData(MOCK_ADDRESS_FOR_NATIVE_DEPOSIT); + assertEq(claimUsage.consumed, DEPOSIT_AMOUNT * 2); } - // TODO: redundant test, add if the check is removed again. - function test_ClaimNative_RevertIfInvalidBridgeContract() public { + function test_ClaimNative_RevertIfMoreThanClaimLimitButSucceedAfterOneDay() public { EthGetLogsTypes.RpcLog[] memory logs = new EthGetLogsTypes.RpcLog[](1); logs[0] = _makeLog(0, address(0), DEPOSIT_AMOUNT, recipient); - logs[0].addr = address(0xBEEF); _mockEthGetBlockByNumber(1); _mockEthGetLogs(0, 1, 1, address(0), logs); - vm.expectRevert(abi.encodeWithSelector(IBridge.InvalidBridgeContract.selector)); _bridge.claimNative(0, 1); + logs[0] = _makeLog(1, address(0), nativeTokenLimits.claim, recipient); + _mockEthGetBlockByNumber(2); + _mockEthGetLogs(1, 2, 2, address(0), logs); + vm.expectRevert(abi.encodeWithSelector(IBridge.DailyLimitExhausted.selector)); + _bridge.claimNative(1, 2); + vm.warp(block.timestamp + 1 days + 1); + _mockEthGetBlockByNumber(2); + _mockEthGetLogs(1, 2, 2, address(0), logs); + _bridge.claimNative(1, 2); + } + + function test_ClaimNative_RevertIfBlockNotFinalized() public { + EthGetLogsTypes.RpcLog[] memory logs = new EthGetLogsTypes.RpcLog[](1); + logs[0] = _makeLog(0, address(0), DEPOSIT_AMOUNT, recipient); + _mockEthGetBlockByNumber(1); + _mockEthGetLogs(0, 1, 1, address(0), logs); + vm.expectRevert(abi.encodeWithSelector(IBridgeMintBurn.BlockNotFinalized.selector)); + _bridge.claimNative(0, 10); } + // TODO: redundant test, add if the check is removed again. + // function test_ClaimNative_RevertIfInvalidBridgeContract() public { + // EthGetLogsTypes.RpcLog[] memory logs = new EthGetLogsTypes.RpcLog[](1); + // logs[0] = _makeLog(0, address(0), DEPOSIT_AMOUNT, recipient); + // logs[0].addr = address(0xBEEF); + // _mockEthGetBlockByNumber(1); + // _mockEthGetLogs(0, 1, 1, address(0), logs); + // vm.expectRevert(abi.encodeWithSelector(IBridge.InvalidBridgeContract.selector)); + // _bridge.claimNative(0, 1); + // } + function test_ClaimNative_DoNothingIfRequestAlreadyProcessed() public { EthGetLogsTypes.RpcLog[] memory logs = new EthGetLogsTypes.RpcLog[](1); logs[0] = _makeLog(0, address(0), DEPOSIT_AMOUNT, recipient); diff --git a/protocol/test/abstract/Bridge.t.sol b/protocol/test/abstract/Bridge.t.sol index bb459b02..e3d5671a 100644 --- a/protocol/test/abstract/Bridge.t.sol +++ b/protocol/test/abstract/Bridge.t.sol @@ -19,6 +19,9 @@ abstract contract BridgeBehaviorTest is PodTest { IBridge.TokenLimits public tokenLimits; IBridge.TokenLimits public nativeTokenLimits; + address public constant MOCK_ADDRESS_FOR_NATIVE_DEPOSIT = + address(uint160(uint256(keccak256("MOCK_ADDRESS_FOR_NATIVE_DEPOSIT")))); + // Hooks each concrete suite must implement function bridge() internal view virtual returns (Bridge); function token() internal view virtual returns (IERC20); @@ -65,6 +68,35 @@ abstract contract BridgeBehaviorTest is PodTest { assertEq(address(bridge()).balance, DEPOSIT_AMOUNT); } + function test_DepositNative_RevertIfLessThanMinAmount() public { + vm.deal(user, DEPOSIT_AMOUNT); + vm.expectRevert(abi.encodeWithSelector(IBridge.InvalidTokenAmount.selector)); + vm.prank(user); + bridge().depositNative{value: nativeTokenLimits.minAmount - 1}(recipient); + } + + function test_DepositNative_RevertIfMoreThanDailyLimit() public { + vm.deal(user, nativeTokenLimits.deposit + 1); + vm.prank(admin); + bridge().pause(); + vm.expectRevert(Pausable.EnforcedPause.selector); + vm.prank(user); + bridge().depositNative{value: nativeTokenLimits.deposit + 1}(recipient); + } + + function test_DepositNative_RevertIfMoreThanClaimLimitButSucceedAfterOneDay() public { + vm.deal(user, nativeTokenLimits.deposit + DEPOSIT_AMOUNT); + vm.prank(user); + vm.warp(block.timestamp + 1 days - 1); + bridge().depositNative{value: DEPOSIT_AMOUNT}(recipient); + vm.expectRevert(abi.encodeWithSelector(IBridge.DailyLimitExhausted.selector)); + vm.prank(user); + bridge().depositNative{value: nativeTokenLimits.deposit - 1}(recipient); + vm.warp(block.timestamp + 2); + vm.prank(user); + bridge().depositNative{value: nativeTokenLimits.deposit - 1}(recipient); + } + function test_DepositNative_RevertIfPaused() public { vm.deal(user, DEPOSIT_AMOUNT); vm.prank(admin); @@ -76,11 +108,19 @@ abstract contract BridgeBehaviorTest is PodTest { function test_DepositNative_RevertIfInvalidAmount() public { vm.deal(user, DEPOSIT_AMOUNT); - vm.expectRevert(abi.encodeWithSelector(IBridge.InvalidAmount.selector)); + vm.expectRevert(abi.encodeWithSelector(IBridge.InvalidTokenAmount.selector)); vm.prank(user); bridge().depositNative{value: nativeTokenLimits.minAmount - 1}(recipient); } + function test_DepositNative_TracksConsumed() public { + vm.deal(user, DEPOSIT_AMOUNT); + vm.prank(user); + bridge().depositNative{value: DEPOSIT_AMOUNT}(recipient); + (, IBridge.TokenUsage memory dep,) = bridge().tokenData(MOCK_ADDRESS_FOR_NATIVE_DEPOSIT); + assertEq(dep.consumed, DEPOSIT_AMOUNT); + } + function test_Deposit_ZeroRecipientAndPause() public { vm.prank(user); vm.expectRevert(abi.encodeWithSelector(IBridge.InvalidToAddress.selector)); From ad35e1bfb46645338c595fe59544f5136fa26715 Mon Sep 17 00:00:00 2001 From: Jakov Mitrovski Date: Mon, 22 Sep 2025 15:01:37 +0200 Subject: [PATCH 54/64] bindings and deploy script update --- .github/workflows/test.yml | 6 + Cargo.toml | 1 + .../contracts/AbsBonding.sol | 2 +- examples/optimistic-auction/foundry.toml | 3 +- examples/solidity/script/Deploy.s.sol | 8 + protocol/Makefile | 10 + protocol/bindings/Cargo.toml | 8 + .../bindings/src/bridge_deposit_withdraw.rs | 12133 ++++++++++++++++ protocol/bindings/src/bridge_mint_burn.rs | 10361 +++++++++++++ protocol/bindings/src/lib.rs | 7 + protocol/script/DeployMintBurn.s.sol | 2 +- protocol/src/BridgeDepositWithdraw.sol | 6 +- protocol/src/BridgeMintBurn.sol | 18 +- protocol/test/BridgeMintBurn.t.sol | 14 +- 14 files changed, 22558 insertions(+), 21 deletions(-) create mode 100644 protocol/Makefile create mode 100644 protocol/bindings/Cargo.toml create mode 100644 protocol/bindings/src/bridge_deposit_withdraw.rs create mode 100644 protocol/bindings/src/bridge_mint_burn.rs create mode 100644 protocol/bindings/src/lib.rs diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index b2c595c5..009613cf 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -98,6 +98,12 @@ jobs: id: test working-directory: protocol + - name: Check bindings + run: | + make check + working-directory: protocol + id: bindings + solidity-sdk: name: solidity-sdk runs-on: ubuntu-latest diff --git a/Cargo.toml b/Cargo.toml index 455f20a5..80f81e04 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,5 +12,6 @@ members = [ "examples/tokens", "examples/bsky/plc", "examples/optimism-tx-auction", + "protocol/bindings", ] resolver = "2" diff --git a/examples/optimistic-auction/contracts/AbsBonding.sol b/examples/optimistic-auction/contracts/AbsBonding.sol index b06326a8..dce2d00d 100644 --- a/examples/optimistic-auction/contracts/AbsBonding.sol +++ b/examples/optimistic-auction/contracts/AbsBonding.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.20; -import {Ownable} from "openzeppelin-contracts/access/Ownable.sol"; +import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; abstract contract AbsBonding is Ownable { uint256 public immutable BOND_AMOUNT; diff --git a/examples/optimistic-auction/foundry.toml b/examples/optimistic-auction/foundry.toml index fbb4eef8..bdbaa529 100644 --- a/examples/optimistic-auction/foundry.toml +++ b/examples/optimistic-auction/foundry.toml @@ -10,7 +10,8 @@ remappings = [ "pod-sdk/=../../solidity-sdk/src/", "pod-protocol/=../../protocol/src", "pod-protocol-scripts/=../../protocol/script/", - "optimistic-auction/=contracts/" + "optimistic-auction/=contracts/", + "@openzeppelin/=lib/openzeppelin-contracts/", ] allow_paths = [ "../../solidity-sdk", diff --git a/examples/solidity/script/Deploy.s.sol b/examples/solidity/script/Deploy.s.sol index 72b03f19..152afa7e 100644 --- a/examples/solidity/script/Deploy.s.sol +++ b/examples/solidity/script/Deploy.s.sol @@ -10,6 +10,8 @@ import {BaseDeployer} from "pod-protocol-scripts/BaseDeployer.s.sol"; import {PodRegistry} from "pod-protocol/PodRegistry.sol"; import {PodAuctionConsumer} from "optimistic-auction/PodAuctionConsumer.sol"; import {TestMintBalancePrecompile} from "../src/TestMintBalancePrecompile.sol"; +import {BridgeMintBurn} from "pod-protocol/BridgeMintBurn.sol"; +import {IBridge} from "pod-protocol/interfaces/IBridge.sol"; contract Deployer is BaseDeployer { function run() public { @@ -31,6 +33,12 @@ contract Deployer is BaseDeployer { if (testContracts) { address[] memory initialValidators = getValidatorAddresses(); + address otherBridgeContract = makeAddr("otherBridgeContract"); + IBridge.TokenLimits nativeTokenLimits = + IBridge.TokenLimits({minAmount: 0.01 ether, deposit: 500e18, claim: 400e18}); + BridgeMintBurn bridgeMintBurn = new BridgeMintBurn(otherBridgeContract, nativeTokenLimits); + console.log("BridgeMintBurn deployed at:", address(bridgeMintBurn)); + PodRegistry podRegistry = new PodRegistry(initialValidators); console.log("PodRegistry deployed at:", address(podRegistry)); diff --git a/protocol/Makefile b/protocol/Makefile new file mode 100644 index 00000000..99babe12 --- /dev/null +++ b/protocol/Makefile @@ -0,0 +1,10 @@ +generate: + forge bind --crate-name pod-protocol --bindings-path ./bindings --alloy-version 1.0.24 --force --no-metadata --select "^BridgeMintBurn$$" --select "^BridgeDepositWithdraw$$" --overwrite + +check: + forge bind --crate-name pod-protocol --bindings-path ./bindings --alloy-version 1.0.24 --force --no-metadata --select "^BridgeMintBurn$$" --select "^BridgeDepositWithdraw$$" + + + +.PHONY: generate +.PHONY: check \ No newline at end of file diff --git a/protocol/bindings/Cargo.toml b/protocol/bindings/Cargo.toml new file mode 100644 index 00000000..b0ef5ac3 --- /dev/null +++ b/protocol/bindings/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "pod-protocol" +version = "0.1.0" +edition = "2021" + +[dependencies] +alloy = { version = "1.0.24", features = ["sol-types", "contract"] } +serde = { version = "1.0", features = ["derive"] } \ No newline at end of file diff --git a/protocol/bindings/src/bridge_deposit_withdraw.rs b/protocol/bindings/src/bridge_deposit_withdraw.rs new file mode 100644 index 00000000..114128ec --- /dev/null +++ b/protocol/bindings/src/bridge_deposit_withdraw.rs @@ -0,0 +1,12133 @@ +///Module containing a contract's types and functions. +/** + +```solidity +library IBridge { + struct TokenLimits { uint256 minAmount; uint256 deposit; uint256 claim; } + struct TokenUsage { uint256 consumed; uint256 lastUpdated; } +} +```*/ +#[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style, + clippy::empty_structs_with_brackets +)] +pub mod IBridge { + use super::*; + use alloy::sol_types as alloy_sol_types; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**```solidity +struct TokenLimits { uint256 minAmount; uint256 deposit; uint256 claim; } +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct TokenLimits { + #[allow(missing_docs)] + pub minAmount: alloy::sol_types::private::primitives::aliases::U256, + #[allow(missing_docs)] + pub deposit: alloy::sol_types::private::primitives::aliases::U256, + #[allow(missing_docs)] + pub claim: alloy::sol_types::private::primitives::aliases::U256, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[doc(hidden)] + type UnderlyingSolTuple<'a> = ( + alloy::sol_types::sol_data::Uint<256>, + alloy::sol_types::sol_data::Uint<256>, + alloy::sol_types::sol_data::Uint<256>, + ); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = ( + alloy::sol_types::private::primitives::aliases::U256, + alloy::sol_types::private::primitives::aliases::U256, + alloy::sol_types::private::primitives::aliases::U256, + ); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: TokenLimits) -> Self { + (value.minAmount, value.deposit, value.claim) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for TokenLimits { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { + minAmount: tuple.0, + deposit: tuple.1, + claim: tuple.2, + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolValue for TokenLimits { + type SolType = Self; + } + #[automatically_derived] + impl alloy_sol_types::private::SolTypeValue for TokenLimits { + #[inline] + fn stv_to_tokens(&self) -> ::Token<'_> { + ( + as alloy_sol_types::SolType>::tokenize(&self.minAmount), + as alloy_sol_types::SolType>::tokenize(&self.deposit), + as alloy_sol_types::SolType>::tokenize(&self.claim), + ) + } + #[inline] + fn stv_abi_encoded_size(&self) -> usize { + if let Some(size) = ::ENCODED_SIZE { + return size; + } + let tuple = as ::core::convert::From>::from(self.clone()); + as alloy_sol_types::SolType>::abi_encoded_size(&tuple) + } + #[inline] + fn stv_eip712_data_word(&self) -> alloy_sol_types::Word { + ::eip712_hash_struct(self) + } + #[inline] + fn stv_abi_encode_packed_to( + &self, + out: &mut alloy_sol_types::private::Vec, + ) { + let tuple = as ::core::convert::From>::from(self.clone()); + as alloy_sol_types::SolType>::abi_encode_packed_to(&tuple, out) + } + #[inline] + fn stv_abi_packed_encoded_size(&self) -> usize { + if let Some(size) = ::PACKED_ENCODED_SIZE { + return size; + } + let tuple = as ::core::convert::From>::from(self.clone()); + as alloy_sol_types::SolType>::abi_packed_encoded_size(&tuple) + } + } + #[automatically_derived] + impl alloy_sol_types::SolType for TokenLimits { + type RustType = Self; + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SOL_NAME: &'static str = ::NAME; + const ENCODED_SIZE: Option = as alloy_sol_types::SolType>::ENCODED_SIZE; + const PACKED_ENCODED_SIZE: Option = as alloy_sol_types::SolType>::PACKED_ENCODED_SIZE; + #[inline] + fn valid_token(token: &Self::Token<'_>) -> bool { + as alloy_sol_types::SolType>::valid_token(token) + } + #[inline] + fn detokenize(token: Self::Token<'_>) -> Self::RustType { + let tuple = as alloy_sol_types::SolType>::detokenize(token); + >>::from(tuple) + } + } + #[automatically_derived] + impl alloy_sol_types::SolStruct for TokenLimits { + const NAME: &'static str = "TokenLimits"; + #[inline] + fn eip712_root_type() -> alloy_sol_types::private::Cow<'static, str> { + alloy_sol_types::private::Cow::Borrowed( + "TokenLimits(uint256 minAmount,uint256 deposit,uint256 claim)", + ) + } + #[inline] + fn eip712_components() -> alloy_sol_types::private::Vec< + alloy_sol_types::private::Cow<'static, str>, + > { + alloy_sol_types::private::Vec::new() + } + #[inline] + fn eip712_encode_type() -> alloy_sol_types::private::Cow<'static, str> { + ::eip712_root_type() + } + #[inline] + fn eip712_encode_data(&self) -> alloy_sol_types::private::Vec { + [ + as alloy_sol_types::SolType>::eip712_data_word(&self.minAmount) + .0, + as alloy_sol_types::SolType>::eip712_data_word(&self.deposit) + .0, + as alloy_sol_types::SolType>::eip712_data_word(&self.claim) + .0, + ] + .concat() + } + } + #[automatically_derived] + impl alloy_sol_types::EventTopic for TokenLimits { + #[inline] + fn topic_preimage_length(rust: &Self::RustType) -> usize { + 0usize + + as alloy_sol_types::EventTopic>::topic_preimage_length( + &rust.minAmount, + ) + + as alloy_sol_types::EventTopic>::topic_preimage_length( + &rust.deposit, + ) + + as alloy_sol_types::EventTopic>::topic_preimage_length(&rust.claim) + } + #[inline] + fn encode_topic_preimage( + rust: &Self::RustType, + out: &mut alloy_sol_types::private::Vec, + ) { + out.reserve( + ::topic_preimage_length(rust), + ); + as alloy_sol_types::EventTopic>::encode_topic_preimage( + &rust.minAmount, + out, + ); + as alloy_sol_types::EventTopic>::encode_topic_preimage( + &rust.deposit, + out, + ); + as alloy_sol_types::EventTopic>::encode_topic_preimage( + &rust.claim, + out, + ); + } + #[inline] + fn encode_topic( + rust: &Self::RustType, + ) -> alloy_sol_types::abi::token::WordToken { + let mut out = alloy_sol_types::private::Vec::new(); + ::encode_topic_preimage( + rust, + &mut out, + ); + alloy_sol_types::abi::token::WordToken( + alloy_sol_types::private::keccak256(out), + ) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**```solidity +struct TokenUsage { uint256 consumed; uint256 lastUpdated; } +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct TokenUsage { + #[allow(missing_docs)] + pub consumed: alloy::sol_types::private::primitives::aliases::U256, + #[allow(missing_docs)] + pub lastUpdated: alloy::sol_types::private::primitives::aliases::U256, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[doc(hidden)] + type UnderlyingSolTuple<'a> = ( + alloy::sol_types::sol_data::Uint<256>, + alloy::sol_types::sol_data::Uint<256>, + ); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = ( + alloy::sol_types::private::primitives::aliases::U256, + alloy::sol_types::private::primitives::aliases::U256, + ); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: TokenUsage) -> Self { + (value.consumed, value.lastUpdated) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for TokenUsage { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { + consumed: tuple.0, + lastUpdated: tuple.1, + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolValue for TokenUsage { + type SolType = Self; + } + #[automatically_derived] + impl alloy_sol_types::private::SolTypeValue for TokenUsage { + #[inline] + fn stv_to_tokens(&self) -> ::Token<'_> { + ( + as alloy_sol_types::SolType>::tokenize(&self.consumed), + as alloy_sol_types::SolType>::tokenize(&self.lastUpdated), + ) + } + #[inline] + fn stv_abi_encoded_size(&self) -> usize { + if let Some(size) = ::ENCODED_SIZE { + return size; + } + let tuple = as ::core::convert::From>::from(self.clone()); + as alloy_sol_types::SolType>::abi_encoded_size(&tuple) + } + #[inline] + fn stv_eip712_data_word(&self) -> alloy_sol_types::Word { + ::eip712_hash_struct(self) + } + #[inline] + fn stv_abi_encode_packed_to( + &self, + out: &mut alloy_sol_types::private::Vec, + ) { + let tuple = as ::core::convert::From>::from(self.clone()); + as alloy_sol_types::SolType>::abi_encode_packed_to(&tuple, out) + } + #[inline] + fn stv_abi_packed_encoded_size(&self) -> usize { + if let Some(size) = ::PACKED_ENCODED_SIZE { + return size; + } + let tuple = as ::core::convert::From>::from(self.clone()); + as alloy_sol_types::SolType>::abi_packed_encoded_size(&tuple) + } + } + #[automatically_derived] + impl alloy_sol_types::SolType for TokenUsage { + type RustType = Self; + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SOL_NAME: &'static str = ::NAME; + const ENCODED_SIZE: Option = as alloy_sol_types::SolType>::ENCODED_SIZE; + const PACKED_ENCODED_SIZE: Option = as alloy_sol_types::SolType>::PACKED_ENCODED_SIZE; + #[inline] + fn valid_token(token: &Self::Token<'_>) -> bool { + as alloy_sol_types::SolType>::valid_token(token) + } + #[inline] + fn detokenize(token: Self::Token<'_>) -> Self::RustType { + let tuple = as alloy_sol_types::SolType>::detokenize(token); + >>::from(tuple) + } + } + #[automatically_derived] + impl alloy_sol_types::SolStruct for TokenUsage { + const NAME: &'static str = "TokenUsage"; + #[inline] + fn eip712_root_type() -> alloy_sol_types::private::Cow<'static, str> { + alloy_sol_types::private::Cow::Borrowed( + "TokenUsage(uint256 consumed,uint256 lastUpdated)", + ) + } + #[inline] + fn eip712_components() -> alloy_sol_types::private::Vec< + alloy_sol_types::private::Cow<'static, str>, + > { + alloy_sol_types::private::Vec::new() + } + #[inline] + fn eip712_encode_type() -> alloy_sol_types::private::Cow<'static, str> { + ::eip712_root_type() + } + #[inline] + fn eip712_encode_data(&self) -> alloy_sol_types::private::Vec { + [ + as alloy_sol_types::SolType>::eip712_data_word(&self.consumed) + .0, + as alloy_sol_types::SolType>::eip712_data_word(&self.lastUpdated) + .0, + ] + .concat() + } + } + #[automatically_derived] + impl alloy_sol_types::EventTopic for TokenUsage { + #[inline] + fn topic_preimage_length(rust: &Self::RustType) -> usize { + 0usize + + as alloy_sol_types::EventTopic>::topic_preimage_length( + &rust.consumed, + ) + + as alloy_sol_types::EventTopic>::topic_preimage_length( + &rust.lastUpdated, + ) + } + #[inline] + fn encode_topic_preimage( + rust: &Self::RustType, + out: &mut alloy_sol_types::private::Vec, + ) { + out.reserve( + ::topic_preimage_length(rust), + ); + as alloy_sol_types::EventTopic>::encode_topic_preimage( + &rust.consumed, + out, + ); + as alloy_sol_types::EventTopic>::encode_topic_preimage( + &rust.lastUpdated, + out, + ); + } + #[inline] + fn encode_topic( + rust: &Self::RustType, + ) -> alloy_sol_types::abi::token::WordToken { + let mut out = alloy_sol_types::private::Vec::new(); + ::encode_topic_preimage( + rust, + &mut out, + ); + alloy_sol_types::abi::token::WordToken( + alloy_sol_types::private::keccak256(out), + ) + } + } + }; + use alloy::contract as alloy_contract; + /**Creates a new wrapper around an on-chain [`IBridge`](self) contract instance. + +See the [wrapper's documentation](`IBridgeInstance`) for more details.*/ + #[inline] + pub const fn new< + P: alloy_contract::private::Provider, + N: alloy_contract::private::Network, + >(address: alloy_sol_types::private::Address, provider: P) -> IBridgeInstance { + IBridgeInstance::::new(address, provider) + } + /**A [`IBridge`](self) instance. + +Contains type-safe methods for interacting with an on-chain instance of the +[`IBridge`](self) contract located at a given `address`, using a given +provider `P`. + +If the contract bytecode is available (see the [`sol!`](alloy_sol_types::sol!) +documentation on how to provide it), the `deploy` and `deploy_builder` methods can +be used to deploy a new instance of the contract. + +See the [module-level documentation](self) for all the available methods.*/ + #[derive(Clone)] + pub struct IBridgeInstance { + address: alloy_sol_types::private::Address, + provider: P, + _network: ::core::marker::PhantomData, + } + #[automatically_derived] + impl ::core::fmt::Debug for IBridgeInstance { + #[inline] + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + f.debug_tuple("IBridgeInstance").field(&self.address).finish() + } + } + /// Instantiation and getters/setters. + #[automatically_derived] + impl< + P: alloy_contract::private::Provider, + N: alloy_contract::private::Network, + > IBridgeInstance { + /**Creates a new wrapper around an on-chain [`IBridge`](self) contract instance. + +See the [wrapper's documentation](`IBridgeInstance`) for more details.*/ + #[inline] + pub const fn new( + address: alloy_sol_types::private::Address, + provider: P, + ) -> Self { + Self { + address, + provider, + _network: ::core::marker::PhantomData, + } + } + /// Returns a reference to the address. + #[inline] + pub const fn address(&self) -> &alloy_sol_types::private::Address { + &self.address + } + /// Sets the address. + #[inline] + pub fn set_address(&mut self, address: alloy_sol_types::private::Address) { + self.address = address; + } + /// Sets the address and returns `self`. + pub fn at(mut self, address: alloy_sol_types::private::Address) -> Self { + self.set_address(address); + self + } + /// Returns a reference to the provider. + #[inline] + pub const fn provider(&self) -> &P { + &self.provider + } + } + impl IBridgeInstance<&P, N> { + /// Clones the provider and returns a new instance with the cloned provider. + #[inline] + pub fn with_cloned_provider(self) -> IBridgeInstance { + IBridgeInstance { + address: self.address, + provider: ::core::clone::Clone::clone(&self.provider), + _network: ::core::marker::PhantomData, + } + } + } + /// Function calls. + #[automatically_derived] + impl< + P: alloy_contract::private::Provider, + N: alloy_contract::private::Network, + > IBridgeInstance { + /// Creates a new call builder using this contract instance's provider and address. + /// + /// Note that the call can be any function call, not just those defined in this + /// contract. Prefer using the other methods for building type-safe contract calls. + pub fn call_builder( + &self, + call: &C, + ) -> alloy_contract::SolCallBuilder<&P, C, N> { + alloy_contract::SolCallBuilder::new_sol(&self.provider, &self.address, call) + } + } + /// Event filters. + #[automatically_derived] + impl< + P: alloy_contract::private::Provider, + N: alloy_contract::private::Network, + > IBridgeInstance { + /// Creates a new event filter using this contract instance's provider and address. + /// + /// Note that the type can be any event, not just those defined in this contract. + /// Prefer using the other methods for building type-safe event filters. + pub fn event_filter( + &self, + ) -> alloy_contract::Event<&P, E, N> { + alloy_contract::Event::new_sol(&self.provider, &self.address) + } + } +} +///Module containing a contract's types and functions. +/** + +```solidity +library MerkleTree { + struct Proof { bytes32[] path; } +} +```*/ +#[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style, + clippy::empty_structs_with_brackets +)] +pub mod MerkleTree { + use super::*; + use alloy::sol_types as alloy_sol_types; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**```solidity +struct Proof { bytes32[] path; } +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct Proof { + #[allow(missing_docs)] + pub path: alloy::sol_types::private::Vec< + alloy::sol_types::private::FixedBytes<32>, + >, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[doc(hidden)] + type UnderlyingSolTuple<'a> = ( + alloy::sol_types::sol_data::Array< + alloy::sol_types::sol_data::FixedBytes<32>, + >, + ); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = ( + alloy::sol_types::private::Vec>, + ); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: Proof) -> Self { + (value.path,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for Proof { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { path: tuple.0 } + } + } + #[automatically_derived] + impl alloy_sol_types::SolValue for Proof { + type SolType = Self; + } + #[automatically_derived] + impl alloy_sol_types::private::SolTypeValue for Proof { + #[inline] + fn stv_to_tokens(&self) -> ::Token<'_> { + ( + , + > as alloy_sol_types::SolType>::tokenize(&self.path), + ) + } + #[inline] + fn stv_abi_encoded_size(&self) -> usize { + if let Some(size) = ::ENCODED_SIZE { + return size; + } + let tuple = as ::core::convert::From>::from(self.clone()); + as alloy_sol_types::SolType>::abi_encoded_size(&tuple) + } + #[inline] + fn stv_eip712_data_word(&self) -> alloy_sol_types::Word { + ::eip712_hash_struct(self) + } + #[inline] + fn stv_abi_encode_packed_to( + &self, + out: &mut alloy_sol_types::private::Vec, + ) { + let tuple = as ::core::convert::From>::from(self.clone()); + as alloy_sol_types::SolType>::abi_encode_packed_to(&tuple, out) + } + #[inline] + fn stv_abi_packed_encoded_size(&self) -> usize { + if let Some(size) = ::PACKED_ENCODED_SIZE { + return size; + } + let tuple = as ::core::convert::From>::from(self.clone()); + as alloy_sol_types::SolType>::abi_packed_encoded_size(&tuple) + } + } + #[automatically_derived] + impl alloy_sol_types::SolType for Proof { + type RustType = Self; + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SOL_NAME: &'static str = ::NAME; + const ENCODED_SIZE: Option = as alloy_sol_types::SolType>::ENCODED_SIZE; + const PACKED_ENCODED_SIZE: Option = as alloy_sol_types::SolType>::PACKED_ENCODED_SIZE; + #[inline] + fn valid_token(token: &Self::Token<'_>) -> bool { + as alloy_sol_types::SolType>::valid_token(token) + } + #[inline] + fn detokenize(token: Self::Token<'_>) -> Self::RustType { + let tuple = as alloy_sol_types::SolType>::detokenize(token); + >>::from(tuple) + } + } + #[automatically_derived] + impl alloy_sol_types::SolStruct for Proof { + const NAME: &'static str = "Proof"; + #[inline] + fn eip712_root_type() -> alloy_sol_types::private::Cow<'static, str> { + alloy_sol_types::private::Cow::Borrowed("Proof(bytes32[] path)") + } + #[inline] + fn eip712_components() -> alloy_sol_types::private::Vec< + alloy_sol_types::private::Cow<'static, str>, + > { + alloy_sol_types::private::Vec::new() + } + #[inline] + fn eip712_encode_type() -> alloy_sol_types::private::Cow<'static, str> { + ::eip712_root_type() + } + #[inline] + fn eip712_encode_data(&self) -> alloy_sol_types::private::Vec { + , + > as alloy_sol_types::SolType>::eip712_data_word(&self.path) + .0 + .to_vec() + } + } + #[automatically_derived] + impl alloy_sol_types::EventTopic for Proof { + #[inline] + fn topic_preimage_length(rust: &Self::RustType) -> usize { + 0usize + + , + > as alloy_sol_types::EventTopic>::topic_preimage_length(&rust.path) + } + #[inline] + fn encode_topic_preimage( + rust: &Self::RustType, + out: &mut alloy_sol_types::private::Vec, + ) { + out.reserve( + ::topic_preimage_length(rust), + ); + , + > as alloy_sol_types::EventTopic>::encode_topic_preimage( + &rust.path, + out, + ); + } + #[inline] + fn encode_topic( + rust: &Self::RustType, + ) -> alloy_sol_types::abi::token::WordToken { + let mut out = alloy_sol_types::private::Vec::new(); + ::encode_topic_preimage( + rust, + &mut out, + ); + alloy_sol_types::abi::token::WordToken( + alloy_sol_types::private::keccak256(out), + ) + } + } + }; + use alloy::contract as alloy_contract; + /**Creates a new wrapper around an on-chain [`MerkleTree`](self) contract instance. + +See the [wrapper's documentation](`MerkleTreeInstance`) for more details.*/ + #[inline] + pub const fn new< + P: alloy_contract::private::Provider, + N: alloy_contract::private::Network, + >( + address: alloy_sol_types::private::Address, + provider: P, + ) -> MerkleTreeInstance { + MerkleTreeInstance::::new(address, provider) + } + /**A [`MerkleTree`](self) instance. + +Contains type-safe methods for interacting with an on-chain instance of the +[`MerkleTree`](self) contract located at a given `address`, using a given +provider `P`. + +If the contract bytecode is available (see the [`sol!`](alloy_sol_types::sol!) +documentation on how to provide it), the `deploy` and `deploy_builder` methods can +be used to deploy a new instance of the contract. + +See the [module-level documentation](self) for all the available methods.*/ + #[derive(Clone)] + pub struct MerkleTreeInstance { + address: alloy_sol_types::private::Address, + provider: P, + _network: ::core::marker::PhantomData, + } + #[automatically_derived] + impl ::core::fmt::Debug for MerkleTreeInstance { + #[inline] + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + f.debug_tuple("MerkleTreeInstance").field(&self.address).finish() + } + } + /// Instantiation and getters/setters. + #[automatically_derived] + impl< + P: alloy_contract::private::Provider, + N: alloy_contract::private::Network, + > MerkleTreeInstance { + /**Creates a new wrapper around an on-chain [`MerkleTree`](self) contract instance. + +See the [wrapper's documentation](`MerkleTreeInstance`) for more details.*/ + #[inline] + pub const fn new( + address: alloy_sol_types::private::Address, + provider: P, + ) -> Self { + Self { + address, + provider, + _network: ::core::marker::PhantomData, + } + } + /// Returns a reference to the address. + #[inline] + pub const fn address(&self) -> &alloy_sol_types::private::Address { + &self.address + } + /// Sets the address. + #[inline] + pub fn set_address(&mut self, address: alloy_sol_types::private::Address) { + self.address = address; + } + /// Sets the address and returns `self`. + pub fn at(mut self, address: alloy_sol_types::private::Address) -> Self { + self.set_address(address); + self + } + /// Returns a reference to the provider. + #[inline] + pub const fn provider(&self) -> &P { + &self.provider + } + } + impl MerkleTreeInstance<&P, N> { + /// Clones the provider and returns a new instance with the cloned provider. + #[inline] + pub fn with_cloned_provider(self) -> MerkleTreeInstance { + MerkleTreeInstance { + address: self.address, + provider: ::core::clone::Clone::clone(&self.provider), + _network: ::core::marker::PhantomData, + } + } + } + /// Function calls. + #[automatically_derived] + impl< + P: alloy_contract::private::Provider, + N: alloy_contract::private::Network, + > MerkleTreeInstance { + /// Creates a new call builder using this contract instance's provider and address. + /// + /// Note that the call can be any function call, not just those defined in this + /// contract. Prefer using the other methods for building type-safe contract calls. + pub fn call_builder( + &self, + call: &C, + ) -> alloy_contract::SolCallBuilder<&P, C, N> { + alloy_contract::SolCallBuilder::new_sol(&self.provider, &self.address, call) + } + } + /// Event filters. + #[automatically_derived] + impl< + P: alloy_contract::private::Provider, + N: alloy_contract::private::Network, + > MerkleTreeInstance { + /// Creates a new event filter using this contract instance's provider and address. + /// + /// Note that the type can be any event, not just those defined in this contract. + /// Prefer using the other methods for building type-safe event filters. + pub fn event_filter( + &self, + ) -> alloy_contract::Event<&P, E, N> { + alloy_contract::Event::new_sol(&self.provider, &self.address) + } + } +} +///Module containing a contract's types and functions. +/** + +```solidity +library PodECDSA { + struct Certificate { CertifiedReceipt certifiedReceipt; bytes32 leaf; MerkleTree.Proof proof; } + struct CertifiedLog { Log log; uint256 logIndex; Certificate certificate; } + struct CertifiedReceipt { bytes32 receiptRoot; bytes aggregateSignature; uint256[] sortedAttestationTimestamps; } + struct Log { address addr; bytes32[] topics; bytes data; } +} +```*/ +#[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style, + clippy::empty_structs_with_brackets +)] +pub mod PodECDSA { + use super::*; + use alloy::sol_types as alloy_sol_types; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**```solidity +struct Certificate { CertifiedReceipt certifiedReceipt; bytes32 leaf; MerkleTree.Proof proof; } +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct Certificate { + #[allow(missing_docs)] + pub certifiedReceipt: ::RustType, + #[allow(missing_docs)] + pub leaf: alloy::sol_types::private::FixedBytes<32>, + #[allow(missing_docs)] + pub proof: ::RustType, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[doc(hidden)] + type UnderlyingSolTuple<'a> = ( + CertifiedReceipt, + alloy::sol_types::sol_data::FixedBytes<32>, + MerkleTree::Proof, + ); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = ( + ::RustType, + alloy::sol_types::private::FixedBytes<32>, + ::RustType, + ); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: Certificate) -> Self { + (value.certifiedReceipt, value.leaf, value.proof) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for Certificate { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { + certifiedReceipt: tuple.0, + leaf: tuple.1, + proof: tuple.2, + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolValue for Certificate { + type SolType = Self; + } + #[automatically_derived] + impl alloy_sol_types::private::SolTypeValue for Certificate { + #[inline] + fn stv_to_tokens(&self) -> ::Token<'_> { + ( + ::tokenize( + &self.certifiedReceipt, + ), + as alloy_sol_types::SolType>::tokenize(&self.leaf), + ::tokenize( + &self.proof, + ), + ) + } + #[inline] + fn stv_abi_encoded_size(&self) -> usize { + if let Some(size) = ::ENCODED_SIZE { + return size; + } + let tuple = as ::core::convert::From>::from(self.clone()); + as alloy_sol_types::SolType>::abi_encoded_size(&tuple) + } + #[inline] + fn stv_eip712_data_word(&self) -> alloy_sol_types::Word { + ::eip712_hash_struct(self) + } + #[inline] + fn stv_abi_encode_packed_to( + &self, + out: &mut alloy_sol_types::private::Vec, + ) { + let tuple = as ::core::convert::From>::from(self.clone()); + as alloy_sol_types::SolType>::abi_encode_packed_to(&tuple, out) + } + #[inline] + fn stv_abi_packed_encoded_size(&self) -> usize { + if let Some(size) = ::PACKED_ENCODED_SIZE { + return size; + } + let tuple = as ::core::convert::From>::from(self.clone()); + as alloy_sol_types::SolType>::abi_packed_encoded_size(&tuple) + } + } + #[automatically_derived] + impl alloy_sol_types::SolType for Certificate { + type RustType = Self; + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SOL_NAME: &'static str = ::NAME; + const ENCODED_SIZE: Option = as alloy_sol_types::SolType>::ENCODED_SIZE; + const PACKED_ENCODED_SIZE: Option = as alloy_sol_types::SolType>::PACKED_ENCODED_SIZE; + #[inline] + fn valid_token(token: &Self::Token<'_>) -> bool { + as alloy_sol_types::SolType>::valid_token(token) + } + #[inline] + fn detokenize(token: Self::Token<'_>) -> Self::RustType { + let tuple = as alloy_sol_types::SolType>::detokenize(token); + >>::from(tuple) + } + } + #[automatically_derived] + impl alloy_sol_types::SolStruct for Certificate { + const NAME: &'static str = "Certificate"; + #[inline] + fn eip712_root_type() -> alloy_sol_types::private::Cow<'static, str> { + alloy_sol_types::private::Cow::Borrowed( + "Certificate(CertifiedReceipt certifiedReceipt,bytes32 leaf,Proof proof)", + ) + } + #[inline] + fn eip712_components() -> alloy_sol_types::private::Vec< + alloy_sol_types::private::Cow<'static, str>, + > { + let mut components = alloy_sol_types::private::Vec::with_capacity(2); + components + .push( + ::eip712_root_type(), + ); + components + .extend( + ::eip712_components(), + ); + components + .push( + ::eip712_root_type(), + ); + components + .extend( + ::eip712_components(), + ); + components + } + #[inline] + fn eip712_encode_data(&self) -> alloy_sol_types::private::Vec { + [ + ::eip712_data_word( + &self.certifiedReceipt, + ) + .0, + as alloy_sol_types::SolType>::eip712_data_word(&self.leaf) + .0, + ::eip712_data_word( + &self.proof, + ) + .0, + ] + .concat() + } + } + #[automatically_derived] + impl alloy_sol_types::EventTopic for Certificate { + #[inline] + fn topic_preimage_length(rust: &Self::RustType) -> usize { + 0usize + + ::topic_preimage_length( + &rust.certifiedReceipt, + ) + + as alloy_sol_types::EventTopic>::topic_preimage_length(&rust.leaf) + + ::topic_preimage_length( + &rust.proof, + ) + } + #[inline] + fn encode_topic_preimage( + rust: &Self::RustType, + out: &mut alloy_sol_types::private::Vec, + ) { + out.reserve( + ::topic_preimage_length(rust), + ); + ::encode_topic_preimage( + &rust.certifiedReceipt, + out, + ); + as alloy_sol_types::EventTopic>::encode_topic_preimage( + &rust.leaf, + out, + ); + ::encode_topic_preimage( + &rust.proof, + out, + ); + } + #[inline] + fn encode_topic( + rust: &Self::RustType, + ) -> alloy_sol_types::abi::token::WordToken { + let mut out = alloy_sol_types::private::Vec::new(); + ::encode_topic_preimage( + rust, + &mut out, + ); + alloy_sol_types::abi::token::WordToken( + alloy_sol_types::private::keccak256(out), + ) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**```solidity +struct CertifiedLog { Log log; uint256 logIndex; Certificate certificate; } +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct CertifiedLog { + #[allow(missing_docs)] + pub log: ::RustType, + #[allow(missing_docs)] + pub logIndex: alloy::sol_types::private::primitives::aliases::U256, + #[allow(missing_docs)] + pub certificate: ::RustType, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[doc(hidden)] + type UnderlyingSolTuple<'a> = ( + Log, + alloy::sol_types::sol_data::Uint<256>, + Certificate, + ); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = ( + ::RustType, + alloy::sol_types::private::primitives::aliases::U256, + ::RustType, + ); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: CertifiedLog) -> Self { + (value.log, value.logIndex, value.certificate) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for CertifiedLog { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { + log: tuple.0, + logIndex: tuple.1, + certificate: tuple.2, + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolValue for CertifiedLog { + type SolType = Self; + } + #[automatically_derived] + impl alloy_sol_types::private::SolTypeValue for CertifiedLog { + #[inline] + fn stv_to_tokens(&self) -> ::Token<'_> { + ( + ::tokenize(&self.log), + as alloy_sol_types::SolType>::tokenize(&self.logIndex), + ::tokenize( + &self.certificate, + ), + ) + } + #[inline] + fn stv_abi_encoded_size(&self) -> usize { + if let Some(size) = ::ENCODED_SIZE { + return size; + } + let tuple = as ::core::convert::From>::from(self.clone()); + as alloy_sol_types::SolType>::abi_encoded_size(&tuple) + } + #[inline] + fn stv_eip712_data_word(&self) -> alloy_sol_types::Word { + ::eip712_hash_struct(self) + } + #[inline] + fn stv_abi_encode_packed_to( + &self, + out: &mut alloy_sol_types::private::Vec, + ) { + let tuple = as ::core::convert::From>::from(self.clone()); + as alloy_sol_types::SolType>::abi_encode_packed_to(&tuple, out) + } + #[inline] + fn stv_abi_packed_encoded_size(&self) -> usize { + if let Some(size) = ::PACKED_ENCODED_SIZE { + return size; + } + let tuple = as ::core::convert::From>::from(self.clone()); + as alloy_sol_types::SolType>::abi_packed_encoded_size(&tuple) + } + } + #[automatically_derived] + impl alloy_sol_types::SolType for CertifiedLog { + type RustType = Self; + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SOL_NAME: &'static str = ::NAME; + const ENCODED_SIZE: Option = as alloy_sol_types::SolType>::ENCODED_SIZE; + const PACKED_ENCODED_SIZE: Option = as alloy_sol_types::SolType>::PACKED_ENCODED_SIZE; + #[inline] + fn valid_token(token: &Self::Token<'_>) -> bool { + as alloy_sol_types::SolType>::valid_token(token) + } + #[inline] + fn detokenize(token: Self::Token<'_>) -> Self::RustType { + let tuple = as alloy_sol_types::SolType>::detokenize(token); + >>::from(tuple) + } + } + #[automatically_derived] + impl alloy_sol_types::SolStruct for CertifiedLog { + const NAME: &'static str = "CertifiedLog"; + #[inline] + fn eip712_root_type() -> alloy_sol_types::private::Cow<'static, str> { + alloy_sol_types::private::Cow::Borrowed( + "CertifiedLog(Log log,uint256 logIndex,Certificate certificate)", + ) + } + #[inline] + fn eip712_components() -> alloy_sol_types::private::Vec< + alloy_sol_types::private::Cow<'static, str>, + > { + let mut components = alloy_sol_types::private::Vec::with_capacity(2); + components.push(::eip712_root_type()); + components + .extend(::eip712_components()); + components + .push( + ::eip712_root_type(), + ); + components + .extend( + ::eip712_components(), + ); + components + } + #[inline] + fn eip712_encode_data(&self) -> alloy_sol_types::private::Vec { + [ + ::eip712_data_word(&self.log).0, + as alloy_sol_types::SolType>::eip712_data_word(&self.logIndex) + .0, + ::eip712_data_word( + &self.certificate, + ) + .0, + ] + .concat() + } + } + #[automatically_derived] + impl alloy_sol_types::EventTopic for CertifiedLog { + #[inline] + fn topic_preimage_length(rust: &Self::RustType) -> usize { + 0usize + + ::topic_preimage_length( + &rust.log, + ) + + as alloy_sol_types::EventTopic>::topic_preimage_length( + &rust.logIndex, + ) + + ::topic_preimage_length( + &rust.certificate, + ) + } + #[inline] + fn encode_topic_preimage( + rust: &Self::RustType, + out: &mut alloy_sol_types::private::Vec, + ) { + out.reserve( + ::topic_preimage_length(rust), + ); + ::encode_topic_preimage( + &rust.log, + out, + ); + as alloy_sol_types::EventTopic>::encode_topic_preimage( + &rust.logIndex, + out, + ); + ::encode_topic_preimage( + &rust.certificate, + out, + ); + } + #[inline] + fn encode_topic( + rust: &Self::RustType, + ) -> alloy_sol_types::abi::token::WordToken { + let mut out = alloy_sol_types::private::Vec::new(); + ::encode_topic_preimage( + rust, + &mut out, + ); + alloy_sol_types::abi::token::WordToken( + alloy_sol_types::private::keccak256(out), + ) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**```solidity +struct CertifiedReceipt { bytes32 receiptRoot; bytes aggregateSignature; uint256[] sortedAttestationTimestamps; } +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct CertifiedReceipt { + #[allow(missing_docs)] + pub receiptRoot: alloy::sol_types::private::FixedBytes<32>, + #[allow(missing_docs)] + pub aggregateSignature: alloy::sol_types::private::Bytes, + #[allow(missing_docs)] + pub sortedAttestationTimestamps: alloy::sol_types::private::Vec< + alloy::sol_types::private::primitives::aliases::U256, + >, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[doc(hidden)] + type UnderlyingSolTuple<'a> = ( + alloy::sol_types::sol_data::FixedBytes<32>, + alloy::sol_types::sol_data::Bytes, + alloy::sol_types::sol_data::Array>, + ); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = ( + alloy::sol_types::private::FixedBytes<32>, + alloy::sol_types::private::Bytes, + alloy::sol_types::private::Vec< + alloy::sol_types::private::primitives::aliases::U256, + >, + ); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: CertifiedReceipt) -> Self { + ( + value.receiptRoot, + value.aggregateSignature, + value.sortedAttestationTimestamps, + ) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for CertifiedReceipt { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { + receiptRoot: tuple.0, + aggregateSignature: tuple.1, + sortedAttestationTimestamps: tuple.2, + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolValue for CertifiedReceipt { + type SolType = Self; + } + #[automatically_derived] + impl alloy_sol_types::private::SolTypeValue for CertifiedReceipt { + #[inline] + fn stv_to_tokens(&self) -> ::Token<'_> { + ( + as alloy_sol_types::SolType>::tokenize(&self.receiptRoot), + ::tokenize( + &self.aggregateSignature, + ), + , + > as alloy_sol_types::SolType>::tokenize( + &self.sortedAttestationTimestamps, + ), + ) + } + #[inline] + fn stv_abi_encoded_size(&self) -> usize { + if let Some(size) = ::ENCODED_SIZE { + return size; + } + let tuple = as ::core::convert::From>::from(self.clone()); + as alloy_sol_types::SolType>::abi_encoded_size(&tuple) + } + #[inline] + fn stv_eip712_data_word(&self) -> alloy_sol_types::Word { + ::eip712_hash_struct(self) + } + #[inline] + fn stv_abi_encode_packed_to( + &self, + out: &mut alloy_sol_types::private::Vec, + ) { + let tuple = as ::core::convert::From>::from(self.clone()); + as alloy_sol_types::SolType>::abi_encode_packed_to(&tuple, out) + } + #[inline] + fn stv_abi_packed_encoded_size(&self) -> usize { + if let Some(size) = ::PACKED_ENCODED_SIZE { + return size; + } + let tuple = as ::core::convert::From>::from(self.clone()); + as alloy_sol_types::SolType>::abi_packed_encoded_size(&tuple) + } + } + #[automatically_derived] + impl alloy_sol_types::SolType for CertifiedReceipt { + type RustType = Self; + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SOL_NAME: &'static str = ::NAME; + const ENCODED_SIZE: Option = as alloy_sol_types::SolType>::ENCODED_SIZE; + const PACKED_ENCODED_SIZE: Option = as alloy_sol_types::SolType>::PACKED_ENCODED_SIZE; + #[inline] + fn valid_token(token: &Self::Token<'_>) -> bool { + as alloy_sol_types::SolType>::valid_token(token) + } + #[inline] + fn detokenize(token: Self::Token<'_>) -> Self::RustType { + let tuple = as alloy_sol_types::SolType>::detokenize(token); + >>::from(tuple) + } + } + #[automatically_derived] + impl alloy_sol_types::SolStruct for CertifiedReceipt { + const NAME: &'static str = "CertifiedReceipt"; + #[inline] + fn eip712_root_type() -> alloy_sol_types::private::Cow<'static, str> { + alloy_sol_types::private::Cow::Borrowed( + "CertifiedReceipt(bytes32 receiptRoot,bytes aggregateSignature,uint256[] sortedAttestationTimestamps)", + ) + } + #[inline] + fn eip712_components() -> alloy_sol_types::private::Vec< + alloy_sol_types::private::Cow<'static, str>, + > { + alloy_sol_types::private::Vec::new() + } + #[inline] + fn eip712_encode_type() -> alloy_sol_types::private::Cow<'static, str> { + ::eip712_root_type() + } + #[inline] + fn eip712_encode_data(&self) -> alloy_sol_types::private::Vec { + [ + as alloy_sol_types::SolType>::eip712_data_word(&self.receiptRoot) + .0, + ::eip712_data_word( + &self.aggregateSignature, + ) + .0, + , + > as alloy_sol_types::SolType>::eip712_data_word( + &self.sortedAttestationTimestamps, + ) + .0, + ] + .concat() + } + } + #[automatically_derived] + impl alloy_sol_types::EventTopic for CertifiedReceipt { + #[inline] + fn topic_preimage_length(rust: &Self::RustType) -> usize { + 0usize + + as alloy_sol_types::EventTopic>::topic_preimage_length( + &rust.receiptRoot, + ) + + ::topic_preimage_length( + &rust.aggregateSignature, + ) + + , + > as alloy_sol_types::EventTopic>::topic_preimage_length( + &rust.sortedAttestationTimestamps, + ) + } + #[inline] + fn encode_topic_preimage( + rust: &Self::RustType, + out: &mut alloy_sol_types::private::Vec, + ) { + out.reserve( + ::topic_preimage_length(rust), + ); + as alloy_sol_types::EventTopic>::encode_topic_preimage( + &rust.receiptRoot, + out, + ); + ::encode_topic_preimage( + &rust.aggregateSignature, + out, + ); + , + > as alloy_sol_types::EventTopic>::encode_topic_preimage( + &rust.sortedAttestationTimestamps, + out, + ); + } + #[inline] + fn encode_topic( + rust: &Self::RustType, + ) -> alloy_sol_types::abi::token::WordToken { + let mut out = alloy_sol_types::private::Vec::new(); + ::encode_topic_preimage( + rust, + &mut out, + ); + alloy_sol_types::abi::token::WordToken( + alloy_sol_types::private::keccak256(out), + ) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**```solidity +struct Log { address addr; bytes32[] topics; bytes data; } +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct Log { + #[allow(missing_docs)] + pub addr: alloy::sol_types::private::Address, + #[allow(missing_docs)] + pub topics: alloy::sol_types::private::Vec< + alloy::sol_types::private::FixedBytes<32>, + >, + #[allow(missing_docs)] + pub data: alloy::sol_types::private::Bytes, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[doc(hidden)] + type UnderlyingSolTuple<'a> = ( + alloy::sol_types::sol_data::Address, + alloy::sol_types::sol_data::Array< + alloy::sol_types::sol_data::FixedBytes<32>, + >, + alloy::sol_types::sol_data::Bytes, + ); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = ( + alloy::sol_types::private::Address, + alloy::sol_types::private::Vec>, + alloy::sol_types::private::Bytes, + ); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: Log) -> Self { + (value.addr, value.topics, value.data) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for Log { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { + addr: tuple.0, + topics: tuple.1, + data: tuple.2, + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolValue for Log { + type SolType = Self; + } + #[automatically_derived] + impl alloy_sol_types::private::SolTypeValue for Log { + #[inline] + fn stv_to_tokens(&self) -> ::Token<'_> { + ( + ::tokenize( + &self.addr, + ), + , + > as alloy_sol_types::SolType>::tokenize(&self.topics), + ::tokenize( + &self.data, + ), + ) + } + #[inline] + fn stv_abi_encoded_size(&self) -> usize { + if let Some(size) = ::ENCODED_SIZE { + return size; + } + let tuple = as ::core::convert::From>::from(self.clone()); + as alloy_sol_types::SolType>::abi_encoded_size(&tuple) + } + #[inline] + fn stv_eip712_data_word(&self) -> alloy_sol_types::Word { + ::eip712_hash_struct(self) + } + #[inline] + fn stv_abi_encode_packed_to( + &self, + out: &mut alloy_sol_types::private::Vec, + ) { + let tuple = as ::core::convert::From>::from(self.clone()); + as alloy_sol_types::SolType>::abi_encode_packed_to(&tuple, out) + } + #[inline] + fn stv_abi_packed_encoded_size(&self) -> usize { + if let Some(size) = ::PACKED_ENCODED_SIZE { + return size; + } + let tuple = as ::core::convert::From>::from(self.clone()); + as alloy_sol_types::SolType>::abi_packed_encoded_size(&tuple) + } + } + #[automatically_derived] + impl alloy_sol_types::SolType for Log { + type RustType = Self; + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SOL_NAME: &'static str = ::NAME; + const ENCODED_SIZE: Option = as alloy_sol_types::SolType>::ENCODED_SIZE; + const PACKED_ENCODED_SIZE: Option = as alloy_sol_types::SolType>::PACKED_ENCODED_SIZE; + #[inline] + fn valid_token(token: &Self::Token<'_>) -> bool { + as alloy_sol_types::SolType>::valid_token(token) + } + #[inline] + fn detokenize(token: Self::Token<'_>) -> Self::RustType { + let tuple = as alloy_sol_types::SolType>::detokenize(token); + >>::from(tuple) + } + } + #[automatically_derived] + impl alloy_sol_types::SolStruct for Log { + const NAME: &'static str = "Log"; + #[inline] + fn eip712_root_type() -> alloy_sol_types::private::Cow<'static, str> { + alloy_sol_types::private::Cow::Borrowed( + "Log(address addr,bytes32[] topics,bytes data)", + ) + } + #[inline] + fn eip712_components() -> alloy_sol_types::private::Vec< + alloy_sol_types::private::Cow<'static, str>, + > { + alloy_sol_types::private::Vec::new() + } + #[inline] + fn eip712_encode_type() -> alloy_sol_types::private::Cow<'static, str> { + ::eip712_root_type() + } + #[inline] + fn eip712_encode_data(&self) -> alloy_sol_types::private::Vec { + [ + ::eip712_data_word( + &self.addr, + ) + .0, + , + > as alloy_sol_types::SolType>::eip712_data_word(&self.topics) + .0, + ::eip712_data_word( + &self.data, + ) + .0, + ] + .concat() + } + } + #[automatically_derived] + impl alloy_sol_types::EventTopic for Log { + #[inline] + fn topic_preimage_length(rust: &Self::RustType) -> usize { + 0usize + + ::topic_preimage_length( + &rust.addr, + ) + + , + > as alloy_sol_types::EventTopic>::topic_preimage_length( + &rust.topics, + ) + + ::topic_preimage_length( + &rust.data, + ) + } + #[inline] + fn encode_topic_preimage( + rust: &Self::RustType, + out: &mut alloy_sol_types::private::Vec, + ) { + out.reserve( + ::topic_preimage_length(rust), + ); + ::encode_topic_preimage( + &rust.addr, + out, + ); + , + > as alloy_sol_types::EventTopic>::encode_topic_preimage( + &rust.topics, + out, + ); + ::encode_topic_preimage( + &rust.data, + out, + ); + } + #[inline] + fn encode_topic( + rust: &Self::RustType, + ) -> alloy_sol_types::abi::token::WordToken { + let mut out = alloy_sol_types::private::Vec::new(); + ::encode_topic_preimage( + rust, + &mut out, + ); + alloy_sol_types::abi::token::WordToken( + alloy_sol_types::private::keccak256(out), + ) + } + } + }; + use alloy::contract as alloy_contract; + /**Creates a new wrapper around an on-chain [`PodECDSA`](self) contract instance. + +See the [wrapper's documentation](`PodECDSAInstance`) for more details.*/ + #[inline] + pub const fn new< + P: alloy_contract::private::Provider, + N: alloy_contract::private::Network, + >( + address: alloy_sol_types::private::Address, + provider: P, + ) -> PodECDSAInstance { + PodECDSAInstance::::new(address, provider) + } + /**A [`PodECDSA`](self) instance. + +Contains type-safe methods for interacting with an on-chain instance of the +[`PodECDSA`](self) contract located at a given `address`, using a given +provider `P`. + +If the contract bytecode is available (see the [`sol!`](alloy_sol_types::sol!) +documentation on how to provide it), the `deploy` and `deploy_builder` methods can +be used to deploy a new instance of the contract. + +See the [module-level documentation](self) for all the available methods.*/ + #[derive(Clone)] + pub struct PodECDSAInstance { + address: alloy_sol_types::private::Address, + provider: P, + _network: ::core::marker::PhantomData, + } + #[automatically_derived] + impl ::core::fmt::Debug for PodECDSAInstance { + #[inline] + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + f.debug_tuple("PodECDSAInstance").field(&self.address).finish() + } + } + /// Instantiation and getters/setters. + #[automatically_derived] + impl< + P: alloy_contract::private::Provider, + N: alloy_contract::private::Network, + > PodECDSAInstance { + /**Creates a new wrapper around an on-chain [`PodECDSA`](self) contract instance. + +See the [wrapper's documentation](`PodECDSAInstance`) for more details.*/ + #[inline] + pub const fn new( + address: alloy_sol_types::private::Address, + provider: P, + ) -> Self { + Self { + address, + provider, + _network: ::core::marker::PhantomData, + } + } + /// Returns a reference to the address. + #[inline] + pub const fn address(&self) -> &alloy_sol_types::private::Address { + &self.address + } + /// Sets the address. + #[inline] + pub fn set_address(&mut self, address: alloy_sol_types::private::Address) { + self.address = address; + } + /// Sets the address and returns `self`. + pub fn at(mut self, address: alloy_sol_types::private::Address) -> Self { + self.set_address(address); + self + } + /// Returns a reference to the provider. + #[inline] + pub const fn provider(&self) -> &P { + &self.provider + } + } + impl PodECDSAInstance<&P, N> { + /// Clones the provider and returns a new instance with the cloned provider. + #[inline] + pub fn with_cloned_provider(self) -> PodECDSAInstance { + PodECDSAInstance { + address: self.address, + provider: ::core::clone::Clone::clone(&self.provider), + _network: ::core::marker::PhantomData, + } + } + } + /// Function calls. + #[automatically_derived] + impl< + P: alloy_contract::private::Provider, + N: alloy_contract::private::Network, + > PodECDSAInstance { + /// Creates a new call builder using this contract instance's provider and address. + /// + /// Note that the call can be any function call, not just those defined in this + /// contract. Prefer using the other methods for building type-safe contract calls. + pub fn call_builder( + &self, + call: &C, + ) -> alloy_contract::SolCallBuilder<&P, C, N> { + alloy_contract::SolCallBuilder::new_sol(&self.provider, &self.address, call) + } + } + /// Event filters. + #[automatically_derived] + impl< + P: alloy_contract::private::Provider, + N: alloy_contract::private::Network, + > PodECDSAInstance { + /// Creates a new event filter using this contract instance's provider and address. + /// + /// Note that the type can be any event, not just those defined in this contract. + /// Prefer using the other methods for building type-safe event filters. + pub fn event_filter( + &self, + ) -> alloy_contract::Event<&P, E, N> { + alloy_contract::Event::new_sol(&self.provider, &self.address) + } + } +} +/** + +Generated by the following Solidity interface... +```solidity +library IBridge { + struct TokenLimits { + uint256 minAmount; + uint256 deposit; + uint256 claim; + } + struct TokenUsage { + uint256 consumed; + uint256 lastUpdated; + } +} + +library MerkleTree { + struct Proof { + bytes32[] path; + } +} + +library PodECDSA { + struct Certificate { + CertifiedReceipt certifiedReceipt; + bytes32 leaf; + MerkleTree.Proof proof; + } + struct CertifiedLog { + Log log; + uint256 logIndex; + Certificate certificate; + } + struct CertifiedReceipt { + bytes32 receiptRoot; + bytes aggregateSignature; + uint256[] sortedAttestationTimestamps; + } + struct Log { + address addr; + bytes32[] topics; + bytes data; + } +} + +interface BridgeDepositWithdraw { + error AccessControlBadConfirmation(); + error AccessControlUnauthorizedAccount(address account, bytes32 neededRole); + error ContractMigrated(); + error DailyLimitExhausted(); + error EnforcedPause(); + error ExpectedPause(); + error InvalidBridgeContract(); + error InvalidCertificate(); + error InvalidDepositLog(); + error InvalidNonce(); + error InvalidToAddress(); + error InvalidTokenAmount(); + error InvalidTokenConfig(); + error MirrorTokenNotFound(); + error RequestAlreadyProcessed(); + error SafeERC20FailedOperation(address token); + + event Claim(uint256 indexed id, address indexed mirrorToken, address indexed token, uint256 amount, address to); + event ClaimNative(uint256 indexed id, uint256 amount, address to); + event Deposit(uint256 indexed id, address indexed token, uint256 amount, address to); + event DepositNative(uint256 indexed id, uint256 amount, address to); + event Paused(address account); + event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole); + event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender); + event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender); + event Unpaused(address account); + + constructor(address _podRegistry, address _bridgeContract, IBridge.TokenLimits nativeTokenLimits); + + function DEFAULT_ADMIN_ROLE() external view returns (bytes32); + function PAUSER_ROLE() external view returns (bytes32); + function bridgeContract() external view returns (address); + function claim(PodECDSA.CertifiedLog memory certifiedLog) external; + function claimNative(PodECDSA.CertifiedLog memory certifiedLog) external; + function configureToken(address token, IBridge.TokenLimits memory limits) external; + function deposit(address token, uint256 amount, address to) external; + function depositIndex() external view returns (uint256); + function depositNative(address to) external payable; + function getRoleAdmin(bytes32 role) external view returns (bytes32); + function grantRole(bytes32 role, address account) external; + function hasRole(bytes32 role, address account) external view returns (bool); + function migrate(address _newContract) external; + function migratedContract() external view returns (address); + function mirrorTokens(address) external view returns (address); + function pause() external; + function paused() external view returns (bool); + function podConfig() external view returns (uint8 thresholdNumerator, uint8 thresholdDenominator, address registry); + function processedRequests(bytes32) external view returns (bool); + function renounceRole(bytes32 role, address callerConfirmation) external; + function revokeRole(bytes32 role, address account) external; + function supportsInterface(bytes4 interfaceId) external view returns (bool); + function tokenData(address) external view returns (IBridge.TokenLimits memory limits, IBridge.TokenUsage memory deposit, IBridge.TokenUsage memory claim); + function unpause() external; + function usedNonces(uint256) external view returns (bool); + function whiteListToken(address token, address mirrorToken, IBridge.TokenLimits memory limits) external; + function whitelistedTokens(uint256) external view returns (address); +} +``` + +...which was generated by the following JSON ABI: +```json +[ + { + "type": "constructor", + "inputs": [ + { + "name": "_podRegistry", + "type": "address", + "internalType": "address" + }, + { + "name": "_bridgeContract", + "type": "address", + "internalType": "address" + }, + { + "name": "nativeTokenLimits", + "type": "tuple", + "internalType": "struct IBridge.TokenLimits", + "components": [ + { + "name": "minAmount", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "deposit", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "claim", + "type": "uint256", + "internalType": "uint256" + } + ] + } + ], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "DEFAULT_ADMIN_ROLE", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "bytes32", + "internalType": "bytes32" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "PAUSER_ROLE", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "bytes32", + "internalType": "bytes32" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "bridgeContract", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "claim", + "inputs": [ + { + "name": "certifiedLog", + "type": "tuple", + "internalType": "struct PodECDSA.CertifiedLog", + "components": [ + { + "name": "log", + "type": "tuple", + "internalType": "struct PodECDSA.Log", + "components": [ + { + "name": "addr", + "type": "address", + "internalType": "address" + }, + { + "name": "topics", + "type": "bytes32[]", + "internalType": "bytes32[]" + }, + { + "name": "data", + "type": "bytes", + "internalType": "bytes" + } + ] + }, + { + "name": "logIndex", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "certificate", + "type": "tuple", + "internalType": "struct PodECDSA.Certificate", + "components": [ + { + "name": "certifiedReceipt", + "type": "tuple", + "internalType": "struct PodECDSA.CertifiedReceipt", + "components": [ + { + "name": "receiptRoot", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "aggregateSignature", + "type": "bytes", + "internalType": "bytes" + }, + { + "name": "sortedAttestationTimestamps", + "type": "uint256[]", + "internalType": "uint256[]" + } + ] + }, + { + "name": "leaf", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "proof", + "type": "tuple", + "internalType": "struct MerkleTree.Proof", + "components": [ + { + "name": "path", + "type": "bytes32[]", + "internalType": "bytes32[]" + } + ] + } + ] + } + ] + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "claimNative", + "inputs": [ + { + "name": "certifiedLog", + "type": "tuple", + "internalType": "struct PodECDSA.CertifiedLog", + "components": [ + { + "name": "log", + "type": "tuple", + "internalType": "struct PodECDSA.Log", + "components": [ + { + "name": "addr", + "type": "address", + "internalType": "address" + }, + { + "name": "topics", + "type": "bytes32[]", + "internalType": "bytes32[]" + }, + { + "name": "data", + "type": "bytes", + "internalType": "bytes" + } + ] + }, + { + "name": "logIndex", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "certificate", + "type": "tuple", + "internalType": "struct PodECDSA.Certificate", + "components": [ + { + "name": "certifiedReceipt", + "type": "tuple", + "internalType": "struct PodECDSA.CertifiedReceipt", + "components": [ + { + "name": "receiptRoot", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "aggregateSignature", + "type": "bytes", + "internalType": "bytes" + }, + { + "name": "sortedAttestationTimestamps", + "type": "uint256[]", + "internalType": "uint256[]" + } + ] + }, + { + "name": "leaf", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "proof", + "type": "tuple", + "internalType": "struct MerkleTree.Proof", + "components": [ + { + "name": "path", + "type": "bytes32[]", + "internalType": "bytes32[]" + } + ] + } + ] + } + ] + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "configureToken", + "inputs": [ + { + "name": "token", + "type": "address", + "internalType": "address" + }, + { + "name": "limits", + "type": "tuple", + "internalType": "struct IBridge.TokenLimits", + "components": [ + { + "name": "minAmount", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "deposit", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "claim", + "type": "uint256", + "internalType": "uint256" + } + ] + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "deposit", + "inputs": [ + { + "name": "token", + "type": "address", + "internalType": "address" + }, + { + "name": "amount", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "to", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "depositIndex", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "depositNative", + "inputs": [ + { + "name": "to", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "payable" + }, + { + "type": "function", + "name": "getRoleAdmin", + "inputs": [ + { + "name": "role", + "type": "bytes32", + "internalType": "bytes32" + } + ], + "outputs": [ + { + "name": "", + "type": "bytes32", + "internalType": "bytes32" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "grantRole", + "inputs": [ + { + "name": "role", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "account", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "hasRole", + "inputs": [ + { + "name": "role", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "account", + "type": "address", + "internalType": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "bool", + "internalType": "bool" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "migrate", + "inputs": [ + { + "name": "_newContract", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "migratedContract", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "mirrorTokens", + "inputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "pause", + "inputs": [], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "paused", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "bool", + "internalType": "bool" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "podConfig", + "inputs": [], + "outputs": [ + { + "name": "thresholdNumerator", + "type": "uint8", + "internalType": "uint8" + }, + { + "name": "thresholdDenominator", + "type": "uint8", + "internalType": "uint8" + }, + { + "name": "registry", + "type": "address", + "internalType": "contract IPodRegistry" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "processedRequests", + "inputs": [ + { + "name": "", + "type": "bytes32", + "internalType": "bytes32" + } + ], + "outputs": [ + { + "name": "", + "type": "bool", + "internalType": "bool" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "renounceRole", + "inputs": [ + { + "name": "role", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "callerConfirmation", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "revokeRole", + "inputs": [ + { + "name": "role", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "account", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "supportsInterface", + "inputs": [ + { + "name": "interfaceId", + "type": "bytes4", + "internalType": "bytes4" + } + ], + "outputs": [ + { + "name": "", + "type": "bool", + "internalType": "bool" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "tokenData", + "inputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "outputs": [ + { + "name": "limits", + "type": "tuple", + "internalType": "struct IBridge.TokenLimits", + "components": [ + { + "name": "minAmount", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "deposit", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "claim", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "name": "deposit", + "type": "tuple", + "internalType": "struct IBridge.TokenUsage", + "components": [ + { + "name": "consumed", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "lastUpdated", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "name": "claim", + "type": "tuple", + "internalType": "struct IBridge.TokenUsage", + "components": [ + { + "name": "consumed", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "lastUpdated", + "type": "uint256", + "internalType": "uint256" + } + ] + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "unpause", + "inputs": [], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "usedNonces", + "inputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [ + { + "name": "", + "type": "bool", + "internalType": "bool" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "whiteListToken", + "inputs": [ + { + "name": "token", + "type": "address", + "internalType": "address" + }, + { + "name": "mirrorToken", + "type": "address", + "internalType": "address" + }, + { + "name": "limits", + "type": "tuple", + "internalType": "struct IBridge.TokenLimits", + "components": [ + { + "name": "minAmount", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "deposit", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "claim", + "type": "uint256", + "internalType": "uint256" + } + ] + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "whitelistedTokens", + "inputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "view" + }, + { + "type": "event", + "name": "Claim", + "inputs": [ + { + "name": "id", + "type": "uint256", + "indexed": true, + "internalType": "uint256" + }, + { + "name": "mirrorToken", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "token", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "amount", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + }, + { + "name": "to", + "type": "address", + "indexed": false, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "ClaimNative", + "inputs": [ + { + "name": "id", + "type": "uint256", + "indexed": true, + "internalType": "uint256" + }, + { + "name": "amount", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + }, + { + "name": "to", + "type": "address", + "indexed": false, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "Deposit", + "inputs": [ + { + "name": "id", + "type": "uint256", + "indexed": true, + "internalType": "uint256" + }, + { + "name": "token", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "amount", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + }, + { + "name": "to", + "type": "address", + "indexed": false, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "DepositNative", + "inputs": [ + { + "name": "id", + "type": "uint256", + "indexed": true, + "internalType": "uint256" + }, + { + "name": "amount", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + }, + { + "name": "to", + "type": "address", + "indexed": false, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "Paused", + "inputs": [ + { + "name": "account", + "type": "address", + "indexed": false, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "RoleAdminChanged", + "inputs": [ + { + "name": "role", + "type": "bytes32", + "indexed": true, + "internalType": "bytes32" + }, + { + "name": "previousAdminRole", + "type": "bytes32", + "indexed": true, + "internalType": "bytes32" + }, + { + "name": "newAdminRole", + "type": "bytes32", + "indexed": true, + "internalType": "bytes32" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "RoleGranted", + "inputs": [ + { + "name": "role", + "type": "bytes32", + "indexed": true, + "internalType": "bytes32" + }, + { + "name": "account", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "sender", + "type": "address", + "indexed": true, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "RoleRevoked", + "inputs": [ + { + "name": "role", + "type": "bytes32", + "indexed": true, + "internalType": "bytes32" + }, + { + "name": "account", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "sender", + "type": "address", + "indexed": true, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "Unpaused", + "inputs": [ + { + "name": "account", + "type": "address", + "indexed": false, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "type": "error", + "name": "AccessControlBadConfirmation", + "inputs": [] + }, + { + "type": "error", + "name": "AccessControlUnauthorizedAccount", + "inputs": [ + { + "name": "account", + "type": "address", + "internalType": "address" + }, + { + "name": "neededRole", + "type": "bytes32", + "internalType": "bytes32" + } + ] + }, + { + "type": "error", + "name": "ContractMigrated", + "inputs": [] + }, + { + "type": "error", + "name": "DailyLimitExhausted", + "inputs": [] + }, + { + "type": "error", + "name": "EnforcedPause", + "inputs": [] + }, + { + "type": "error", + "name": "ExpectedPause", + "inputs": [] + }, + { + "type": "error", + "name": "InvalidBridgeContract", + "inputs": [] + }, + { + "type": "error", + "name": "InvalidCertificate", + "inputs": [] + }, + { + "type": "error", + "name": "InvalidDepositLog", + "inputs": [] + }, + { + "type": "error", + "name": "InvalidNonce", + "inputs": [] + }, + { + "type": "error", + "name": "InvalidToAddress", + "inputs": [] + }, + { + "type": "error", + "name": "InvalidTokenAmount", + "inputs": [] + }, + { + "type": "error", + "name": "InvalidTokenConfig", + "inputs": [] + }, + { + "type": "error", + "name": "MirrorTokenNotFound", + "inputs": [] + }, + { + "type": "error", + "name": "RequestAlreadyProcessed", + "inputs": [] + }, + { + "type": "error", + "name": "SafeERC20FailedOperation", + "inputs": [ + { + "name": "token", + "type": "address", + "internalType": "address" + } + ] + } +] +```*/ +#[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style, + clippy::empty_structs_with_brackets +)] +pub mod BridgeDepositWithdraw { + use super::*; + use alloy::sol_types as alloy_sol_types; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Custom error with signature `AccessControlBadConfirmation()` and selector `0x6697b232`. +```solidity +error AccessControlBadConfirmation(); +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct AccessControlBadConfirmation; + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From + for UnderlyingRustTuple<'_> { + fn from(value: AccessControlBadConfirmation) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> + for AccessControlBadConfirmation { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self + } + } + #[automatically_derived] + impl alloy_sol_types::SolError for AccessControlBadConfirmation { + type Parameters<'a> = UnderlyingSolTuple<'a>; + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "AccessControlBadConfirmation()"; + const SELECTOR: [u8; 4] = [102u8, 151u8, 178u8, 50u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + () + } + #[inline] + fn abi_decode_raw_validate(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(Self::new) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Custom error with signature `AccessControlUnauthorizedAccount(address,bytes32)` and selector `0xe2517d3f`. +```solidity +error AccessControlUnauthorizedAccount(address account, bytes32 neededRole); +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct AccessControlUnauthorizedAccount { + #[allow(missing_docs)] + pub account: alloy::sol_types::private::Address, + #[allow(missing_docs)] + pub neededRole: alloy::sol_types::private::FixedBytes<32>, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[doc(hidden)] + type UnderlyingSolTuple<'a> = ( + alloy::sol_types::sol_data::Address, + alloy::sol_types::sol_data::FixedBytes<32>, + ); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = ( + alloy::sol_types::private::Address, + alloy::sol_types::private::FixedBytes<32>, + ); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From + for UnderlyingRustTuple<'_> { + fn from(value: AccessControlUnauthorizedAccount) -> Self { + (value.account, value.neededRole) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> + for AccessControlUnauthorizedAccount { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { + account: tuple.0, + neededRole: tuple.1, + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolError for AccessControlUnauthorizedAccount { + type Parameters<'a> = UnderlyingSolTuple<'a>; + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "AccessControlUnauthorizedAccount(address,bytes32)"; + const SELECTOR: [u8; 4] = [226u8, 81u8, 125u8, 63u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + ( + ::tokenize( + &self.account, + ), + as alloy_sol_types::SolType>::tokenize(&self.neededRole), + ) + } + #[inline] + fn abi_decode_raw_validate(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(Self::new) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Custom error with signature `ContractMigrated()` and selector `0x3f4f6896`. +```solidity +error ContractMigrated(); +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct ContractMigrated; + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: ContractMigrated) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for ContractMigrated { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self + } + } + #[automatically_derived] + impl alloy_sol_types::SolError for ContractMigrated { + type Parameters<'a> = UnderlyingSolTuple<'a>; + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "ContractMigrated()"; + const SELECTOR: [u8; 4] = [63u8, 79u8, 104u8, 150u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + () + } + #[inline] + fn abi_decode_raw_validate(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(Self::new) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Custom error with signature `DailyLimitExhausted()` and selector `0xbdc4df72`. +```solidity +error DailyLimitExhausted(); +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct DailyLimitExhausted; + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: DailyLimitExhausted) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for DailyLimitExhausted { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self + } + } + #[automatically_derived] + impl alloy_sol_types::SolError for DailyLimitExhausted { + type Parameters<'a> = UnderlyingSolTuple<'a>; + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "DailyLimitExhausted()"; + const SELECTOR: [u8; 4] = [189u8, 196u8, 223u8, 114u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + () + } + #[inline] + fn abi_decode_raw_validate(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(Self::new) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Custom error with signature `EnforcedPause()` and selector `0xd93c0665`. +```solidity +error EnforcedPause(); +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct EnforcedPause; + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: EnforcedPause) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for EnforcedPause { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self + } + } + #[automatically_derived] + impl alloy_sol_types::SolError for EnforcedPause { + type Parameters<'a> = UnderlyingSolTuple<'a>; + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "EnforcedPause()"; + const SELECTOR: [u8; 4] = [217u8, 60u8, 6u8, 101u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + () + } + #[inline] + fn abi_decode_raw_validate(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(Self::new) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Custom error with signature `ExpectedPause()` and selector `0x8dfc202b`. +```solidity +error ExpectedPause(); +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct ExpectedPause; + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: ExpectedPause) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for ExpectedPause { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self + } + } + #[automatically_derived] + impl alloy_sol_types::SolError for ExpectedPause { + type Parameters<'a> = UnderlyingSolTuple<'a>; + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "ExpectedPause()"; + const SELECTOR: [u8; 4] = [141u8, 252u8, 32u8, 43u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + () + } + #[inline] + fn abi_decode_raw_validate(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(Self::new) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Custom error with signature `InvalidBridgeContract()` and selector `0x66da8037`. +```solidity +error InvalidBridgeContract(); +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct InvalidBridgeContract; + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: InvalidBridgeContract) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for InvalidBridgeContract { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self + } + } + #[automatically_derived] + impl alloy_sol_types::SolError for InvalidBridgeContract { + type Parameters<'a> = UnderlyingSolTuple<'a>; + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "InvalidBridgeContract()"; + const SELECTOR: [u8; 4] = [102u8, 218u8, 128u8, 55u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + () + } + #[inline] + fn abi_decode_raw_validate(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(Self::new) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Custom error with signature `InvalidCertificate()` and selector `0x1d39f946`. +```solidity +error InvalidCertificate(); +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct InvalidCertificate; + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: InvalidCertificate) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for InvalidCertificate { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self + } + } + #[automatically_derived] + impl alloy_sol_types::SolError for InvalidCertificate { + type Parameters<'a> = UnderlyingSolTuple<'a>; + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "InvalidCertificate()"; + const SELECTOR: [u8; 4] = [29u8, 57u8, 249u8, 70u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + () + } + #[inline] + fn abi_decode_raw_validate(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(Self::new) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Custom error with signature `InvalidDepositLog()` and selector `0xc12dcbc2`. +```solidity +error InvalidDepositLog(); +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct InvalidDepositLog; + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: InvalidDepositLog) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for InvalidDepositLog { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self + } + } + #[automatically_derived] + impl alloy_sol_types::SolError for InvalidDepositLog { + type Parameters<'a> = UnderlyingSolTuple<'a>; + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "InvalidDepositLog()"; + const SELECTOR: [u8; 4] = [193u8, 45u8, 203u8, 194u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + () + } + #[inline] + fn abi_decode_raw_validate(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(Self::new) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Custom error with signature `InvalidNonce()` and selector `0x756688fe`. +```solidity +error InvalidNonce(); +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct InvalidNonce; + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: InvalidNonce) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for InvalidNonce { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self + } + } + #[automatically_derived] + impl alloy_sol_types::SolError for InvalidNonce { + type Parameters<'a> = UnderlyingSolTuple<'a>; + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "InvalidNonce()"; + const SELECTOR: [u8; 4] = [117u8, 102u8, 136u8, 254u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + () + } + #[inline] + fn abi_decode_raw_validate(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(Self::new) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Custom error with signature `InvalidToAddress()` and selector `0x8aa3a72f`. +```solidity +error InvalidToAddress(); +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct InvalidToAddress; + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: InvalidToAddress) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for InvalidToAddress { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self + } + } + #[automatically_derived] + impl alloy_sol_types::SolError for InvalidToAddress { + type Parameters<'a> = UnderlyingSolTuple<'a>; + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "InvalidToAddress()"; + const SELECTOR: [u8; 4] = [138u8, 163u8, 167u8, 47u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + () + } + #[inline] + fn abi_decode_raw_validate(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(Self::new) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Custom error with signature `InvalidTokenAmount()` and selector `0x21607339`. +```solidity +error InvalidTokenAmount(); +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct InvalidTokenAmount; + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: InvalidTokenAmount) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for InvalidTokenAmount { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self + } + } + #[automatically_derived] + impl alloy_sol_types::SolError for InvalidTokenAmount { + type Parameters<'a> = UnderlyingSolTuple<'a>; + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "InvalidTokenAmount()"; + const SELECTOR: [u8; 4] = [33u8, 96u8, 115u8, 57u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + () + } + #[inline] + fn abi_decode_raw_validate(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(Self::new) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Custom error with signature `InvalidTokenConfig()` and selector `0x07fe7bae`. +```solidity +error InvalidTokenConfig(); +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct InvalidTokenConfig; + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: InvalidTokenConfig) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for InvalidTokenConfig { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self + } + } + #[automatically_derived] + impl alloy_sol_types::SolError for InvalidTokenConfig { + type Parameters<'a> = UnderlyingSolTuple<'a>; + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "InvalidTokenConfig()"; + const SELECTOR: [u8; 4] = [7u8, 254u8, 123u8, 174u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + () + } + #[inline] + fn abi_decode_raw_validate(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(Self::new) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Custom error with signature `MirrorTokenNotFound()` and selector `0xa8ddb64d`. +```solidity +error MirrorTokenNotFound(); +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct MirrorTokenNotFound; + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: MirrorTokenNotFound) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for MirrorTokenNotFound { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self + } + } + #[automatically_derived] + impl alloy_sol_types::SolError for MirrorTokenNotFound { + type Parameters<'a> = UnderlyingSolTuple<'a>; + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "MirrorTokenNotFound()"; + const SELECTOR: [u8; 4] = [168u8, 221u8, 182u8, 77u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + () + } + #[inline] + fn abi_decode_raw_validate(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(Self::new) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Custom error with signature `RequestAlreadyProcessed()` and selector `0xa6bc74c4`. +```solidity +error RequestAlreadyProcessed(); +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct RequestAlreadyProcessed; + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: RequestAlreadyProcessed) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for RequestAlreadyProcessed { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self + } + } + #[automatically_derived] + impl alloy_sol_types::SolError for RequestAlreadyProcessed { + type Parameters<'a> = UnderlyingSolTuple<'a>; + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "RequestAlreadyProcessed()"; + const SELECTOR: [u8; 4] = [166u8, 188u8, 116u8, 196u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + () + } + #[inline] + fn abi_decode_raw_validate(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(Self::new) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Custom error with signature `SafeERC20FailedOperation(address)` and selector `0x5274afe7`. +```solidity +error SafeERC20FailedOperation(address token); +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct SafeERC20FailedOperation { + #[allow(missing_docs)] + pub token: alloy::sol_types::private::Address, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (alloy::sol_types::sol_data::Address,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (alloy::sol_types::private::Address,); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From + for UnderlyingRustTuple<'_> { + fn from(value: SafeERC20FailedOperation) -> Self { + (value.token,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> + for SafeERC20FailedOperation { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { token: tuple.0 } + } + } + #[automatically_derived] + impl alloy_sol_types::SolError for SafeERC20FailedOperation { + type Parameters<'a> = UnderlyingSolTuple<'a>; + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "SafeERC20FailedOperation(address)"; + const SELECTOR: [u8; 4] = [82u8, 116u8, 175u8, 231u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + ( + ::tokenize( + &self.token, + ), + ) + } + #[inline] + fn abi_decode_raw_validate(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(Self::new) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Event with signature `Claim(uint256,address,address,uint256,address)` and selector `0xaf3f1a12344bbeaab954d412e821d6b6a06d5cd5d27be204353bd4ea9b55a504`. +```solidity +event Claim(uint256 indexed id, address indexed mirrorToken, address indexed token, uint256 amount, address to); +```*/ + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + #[derive(Clone)] + pub struct Claim { + #[allow(missing_docs)] + pub id: alloy::sol_types::private::primitives::aliases::U256, + #[allow(missing_docs)] + pub mirrorToken: alloy::sol_types::private::Address, + #[allow(missing_docs)] + pub token: alloy::sol_types::private::Address, + #[allow(missing_docs)] + pub amount: alloy::sol_types::private::primitives::aliases::U256, + #[allow(missing_docs)] + pub to: alloy::sol_types::private::Address, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[automatically_derived] + impl alloy_sol_types::SolEvent for Claim { + type DataTuple<'a> = ( + alloy::sol_types::sol_data::Uint<256>, + alloy::sol_types::sol_data::Address, + ); + type DataToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + type TopicList = ( + alloy_sol_types::sol_data::FixedBytes<32>, + alloy::sol_types::sol_data::Uint<256>, + alloy::sol_types::sol_data::Address, + alloy::sol_types::sol_data::Address, + ); + const SIGNATURE: &'static str = "Claim(uint256,address,address,uint256,address)"; + const SIGNATURE_HASH: alloy_sol_types::private::B256 = alloy_sol_types::private::B256::new([ + 175u8, 63u8, 26u8, 18u8, 52u8, 75u8, 190u8, 170u8, 185u8, 84u8, 212u8, + 18u8, 232u8, 33u8, 214u8, 182u8, 160u8, 109u8, 92u8, 213u8, 210u8, 123u8, + 226u8, 4u8, 53u8, 59u8, 212u8, 234u8, 155u8, 85u8, 165u8, 4u8, + ]); + const ANONYMOUS: bool = false; + #[allow(unused_variables)] + #[inline] + fn new( + topics: ::RustType, + data: as alloy_sol_types::SolType>::RustType, + ) -> Self { + Self { + id: topics.1, + mirrorToken: topics.2, + token: topics.3, + amount: data.0, + to: data.1, + } + } + #[inline] + fn check_signature( + topics: &::RustType, + ) -> alloy_sol_types::Result<()> { + if topics.0 != Self::SIGNATURE_HASH { + return Err( + alloy_sol_types::Error::invalid_event_signature_hash( + Self::SIGNATURE, + topics.0, + Self::SIGNATURE_HASH, + ), + ); + } + Ok(()) + } + #[inline] + fn tokenize_body(&self) -> Self::DataToken<'_> { + ( + as alloy_sol_types::SolType>::tokenize(&self.amount), + ::tokenize( + &self.to, + ), + ) + } + #[inline] + fn topics(&self) -> ::RustType { + ( + Self::SIGNATURE_HASH.into(), + self.id.clone(), + self.mirrorToken.clone(), + self.token.clone(), + ) + } + #[inline] + fn encode_topics_raw( + &self, + out: &mut [alloy_sol_types::abi::token::WordToken], + ) -> alloy_sol_types::Result<()> { + if out.len() < ::COUNT { + return Err(alloy_sol_types::Error::Overrun); + } + out[0usize] = alloy_sol_types::abi::token::WordToken( + Self::SIGNATURE_HASH, + ); + out[1usize] = as alloy_sol_types::EventTopic>::encode_topic(&self.id); + out[2usize] = ::encode_topic( + &self.mirrorToken, + ); + out[3usize] = ::encode_topic( + &self.token, + ); + Ok(()) + } + } + #[automatically_derived] + impl alloy_sol_types::private::IntoLogData for Claim { + fn to_log_data(&self) -> alloy_sol_types::private::LogData { + From::from(self) + } + fn into_log_data(self) -> alloy_sol_types::private::LogData { + From::from(&self) + } + } + #[automatically_derived] + impl From<&Claim> for alloy_sol_types::private::LogData { + #[inline] + fn from(this: &Claim) -> alloy_sol_types::private::LogData { + alloy_sol_types::SolEvent::encode_log_data(this) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Event with signature `ClaimNative(uint256,uint256,address)` and selector `0x913168da07c3f7f5f3c523933316328b0d0611b627f12eb11c22ca44fbb19dc6`. +```solidity +event ClaimNative(uint256 indexed id, uint256 amount, address to); +```*/ + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + #[derive(Clone)] + pub struct ClaimNative { + #[allow(missing_docs)] + pub id: alloy::sol_types::private::primitives::aliases::U256, + #[allow(missing_docs)] + pub amount: alloy::sol_types::private::primitives::aliases::U256, + #[allow(missing_docs)] + pub to: alloy::sol_types::private::Address, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[automatically_derived] + impl alloy_sol_types::SolEvent for ClaimNative { + type DataTuple<'a> = ( + alloy::sol_types::sol_data::Uint<256>, + alloy::sol_types::sol_data::Address, + ); + type DataToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + type TopicList = ( + alloy_sol_types::sol_data::FixedBytes<32>, + alloy::sol_types::sol_data::Uint<256>, + ); + const SIGNATURE: &'static str = "ClaimNative(uint256,uint256,address)"; + const SIGNATURE_HASH: alloy_sol_types::private::B256 = alloy_sol_types::private::B256::new([ + 145u8, 49u8, 104u8, 218u8, 7u8, 195u8, 247u8, 245u8, 243u8, 197u8, 35u8, + 147u8, 51u8, 22u8, 50u8, 139u8, 13u8, 6u8, 17u8, 182u8, 39u8, 241u8, + 46u8, 177u8, 28u8, 34u8, 202u8, 68u8, 251u8, 177u8, 157u8, 198u8, + ]); + const ANONYMOUS: bool = false; + #[allow(unused_variables)] + #[inline] + fn new( + topics: ::RustType, + data: as alloy_sol_types::SolType>::RustType, + ) -> Self { + Self { + id: topics.1, + amount: data.0, + to: data.1, + } + } + #[inline] + fn check_signature( + topics: &::RustType, + ) -> alloy_sol_types::Result<()> { + if topics.0 != Self::SIGNATURE_HASH { + return Err( + alloy_sol_types::Error::invalid_event_signature_hash( + Self::SIGNATURE, + topics.0, + Self::SIGNATURE_HASH, + ), + ); + } + Ok(()) + } + #[inline] + fn tokenize_body(&self) -> Self::DataToken<'_> { + ( + as alloy_sol_types::SolType>::tokenize(&self.amount), + ::tokenize( + &self.to, + ), + ) + } + #[inline] + fn topics(&self) -> ::RustType { + (Self::SIGNATURE_HASH.into(), self.id.clone()) + } + #[inline] + fn encode_topics_raw( + &self, + out: &mut [alloy_sol_types::abi::token::WordToken], + ) -> alloy_sol_types::Result<()> { + if out.len() < ::COUNT { + return Err(alloy_sol_types::Error::Overrun); + } + out[0usize] = alloy_sol_types::abi::token::WordToken( + Self::SIGNATURE_HASH, + ); + out[1usize] = as alloy_sol_types::EventTopic>::encode_topic(&self.id); + Ok(()) + } + } + #[automatically_derived] + impl alloy_sol_types::private::IntoLogData for ClaimNative { + fn to_log_data(&self) -> alloy_sol_types::private::LogData { + From::from(self) + } + fn into_log_data(self) -> alloy_sol_types::private::LogData { + From::from(&self) + } + } + #[automatically_derived] + impl From<&ClaimNative> for alloy_sol_types::private::LogData { + #[inline] + fn from(this: &ClaimNative) -> alloy_sol_types::private::LogData { + alloy_sol_types::SolEvent::encode_log_data(this) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Event with signature `Deposit(uint256,address,uint256,address)` and selector `0x05e57fa62d890603d85944c963ddc7fbe77cde5ea69cad7033fc6f76b7ddd2ab`. +```solidity +event Deposit(uint256 indexed id, address indexed token, uint256 amount, address to); +```*/ + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + #[derive(Clone)] + pub struct Deposit { + #[allow(missing_docs)] + pub id: alloy::sol_types::private::primitives::aliases::U256, + #[allow(missing_docs)] + pub token: alloy::sol_types::private::Address, + #[allow(missing_docs)] + pub amount: alloy::sol_types::private::primitives::aliases::U256, + #[allow(missing_docs)] + pub to: alloy::sol_types::private::Address, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[automatically_derived] + impl alloy_sol_types::SolEvent for Deposit { + type DataTuple<'a> = ( + alloy::sol_types::sol_data::Uint<256>, + alloy::sol_types::sol_data::Address, + ); + type DataToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + type TopicList = ( + alloy_sol_types::sol_data::FixedBytes<32>, + alloy::sol_types::sol_data::Uint<256>, + alloy::sol_types::sol_data::Address, + ); + const SIGNATURE: &'static str = "Deposit(uint256,address,uint256,address)"; + const SIGNATURE_HASH: alloy_sol_types::private::B256 = alloy_sol_types::private::B256::new([ + 5u8, 229u8, 127u8, 166u8, 45u8, 137u8, 6u8, 3u8, 216u8, 89u8, 68u8, + 201u8, 99u8, 221u8, 199u8, 251u8, 231u8, 124u8, 222u8, 94u8, 166u8, + 156u8, 173u8, 112u8, 51u8, 252u8, 111u8, 118u8, 183u8, 221u8, 210u8, + 171u8, + ]); + const ANONYMOUS: bool = false; + #[allow(unused_variables)] + #[inline] + fn new( + topics: ::RustType, + data: as alloy_sol_types::SolType>::RustType, + ) -> Self { + Self { + id: topics.1, + token: topics.2, + amount: data.0, + to: data.1, + } + } + #[inline] + fn check_signature( + topics: &::RustType, + ) -> alloy_sol_types::Result<()> { + if topics.0 != Self::SIGNATURE_HASH { + return Err( + alloy_sol_types::Error::invalid_event_signature_hash( + Self::SIGNATURE, + topics.0, + Self::SIGNATURE_HASH, + ), + ); + } + Ok(()) + } + #[inline] + fn tokenize_body(&self) -> Self::DataToken<'_> { + ( + as alloy_sol_types::SolType>::tokenize(&self.amount), + ::tokenize( + &self.to, + ), + ) + } + #[inline] + fn topics(&self) -> ::RustType { + (Self::SIGNATURE_HASH.into(), self.id.clone(), self.token.clone()) + } + #[inline] + fn encode_topics_raw( + &self, + out: &mut [alloy_sol_types::abi::token::WordToken], + ) -> alloy_sol_types::Result<()> { + if out.len() < ::COUNT { + return Err(alloy_sol_types::Error::Overrun); + } + out[0usize] = alloy_sol_types::abi::token::WordToken( + Self::SIGNATURE_HASH, + ); + out[1usize] = as alloy_sol_types::EventTopic>::encode_topic(&self.id); + out[2usize] = ::encode_topic( + &self.token, + ); + Ok(()) + } + } + #[automatically_derived] + impl alloy_sol_types::private::IntoLogData for Deposit { + fn to_log_data(&self) -> alloy_sol_types::private::LogData { + From::from(self) + } + fn into_log_data(self) -> alloy_sol_types::private::LogData { + From::from(&self) + } + } + #[automatically_derived] + impl From<&Deposit> for alloy_sol_types::private::LogData { + #[inline] + fn from(this: &Deposit) -> alloy_sol_types::private::LogData { + alloy_sol_types::SolEvent::encode_log_data(this) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Event with signature `DepositNative(uint256,uint256,address)` and selector `0x40352b63d0a9c92983fcf19d8c3fc28ca0bcc8fa9ffeb5be28e14a3f758ab39e`. +```solidity +event DepositNative(uint256 indexed id, uint256 amount, address to); +```*/ + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + #[derive(Clone)] + pub struct DepositNative { + #[allow(missing_docs)] + pub id: alloy::sol_types::private::primitives::aliases::U256, + #[allow(missing_docs)] + pub amount: alloy::sol_types::private::primitives::aliases::U256, + #[allow(missing_docs)] + pub to: alloy::sol_types::private::Address, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[automatically_derived] + impl alloy_sol_types::SolEvent for DepositNative { + type DataTuple<'a> = ( + alloy::sol_types::sol_data::Uint<256>, + alloy::sol_types::sol_data::Address, + ); + type DataToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + type TopicList = ( + alloy_sol_types::sol_data::FixedBytes<32>, + alloy::sol_types::sol_data::Uint<256>, + ); + const SIGNATURE: &'static str = "DepositNative(uint256,uint256,address)"; + const SIGNATURE_HASH: alloy_sol_types::private::B256 = alloy_sol_types::private::B256::new([ + 64u8, 53u8, 43u8, 99u8, 208u8, 169u8, 201u8, 41u8, 131u8, 252u8, 241u8, + 157u8, 140u8, 63u8, 194u8, 140u8, 160u8, 188u8, 200u8, 250u8, 159u8, + 254u8, 181u8, 190u8, 40u8, 225u8, 74u8, 63u8, 117u8, 138u8, 179u8, 158u8, + ]); + const ANONYMOUS: bool = false; + #[allow(unused_variables)] + #[inline] + fn new( + topics: ::RustType, + data: as alloy_sol_types::SolType>::RustType, + ) -> Self { + Self { + id: topics.1, + amount: data.0, + to: data.1, + } + } + #[inline] + fn check_signature( + topics: &::RustType, + ) -> alloy_sol_types::Result<()> { + if topics.0 != Self::SIGNATURE_HASH { + return Err( + alloy_sol_types::Error::invalid_event_signature_hash( + Self::SIGNATURE, + topics.0, + Self::SIGNATURE_HASH, + ), + ); + } + Ok(()) + } + #[inline] + fn tokenize_body(&self) -> Self::DataToken<'_> { + ( + as alloy_sol_types::SolType>::tokenize(&self.amount), + ::tokenize( + &self.to, + ), + ) + } + #[inline] + fn topics(&self) -> ::RustType { + (Self::SIGNATURE_HASH.into(), self.id.clone()) + } + #[inline] + fn encode_topics_raw( + &self, + out: &mut [alloy_sol_types::abi::token::WordToken], + ) -> alloy_sol_types::Result<()> { + if out.len() < ::COUNT { + return Err(alloy_sol_types::Error::Overrun); + } + out[0usize] = alloy_sol_types::abi::token::WordToken( + Self::SIGNATURE_HASH, + ); + out[1usize] = as alloy_sol_types::EventTopic>::encode_topic(&self.id); + Ok(()) + } + } + #[automatically_derived] + impl alloy_sol_types::private::IntoLogData for DepositNative { + fn to_log_data(&self) -> alloy_sol_types::private::LogData { + From::from(self) + } + fn into_log_data(self) -> alloy_sol_types::private::LogData { + From::from(&self) + } + } + #[automatically_derived] + impl From<&DepositNative> for alloy_sol_types::private::LogData { + #[inline] + fn from(this: &DepositNative) -> alloy_sol_types::private::LogData { + alloy_sol_types::SolEvent::encode_log_data(this) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Event with signature `Paused(address)` and selector `0x62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258`. +```solidity +event Paused(address account); +```*/ + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + #[derive(Clone)] + pub struct Paused { + #[allow(missing_docs)] + pub account: alloy::sol_types::private::Address, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[automatically_derived] + impl alloy_sol_types::SolEvent for Paused { + type DataTuple<'a> = (alloy::sol_types::sol_data::Address,); + type DataToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + type TopicList = (alloy_sol_types::sol_data::FixedBytes<32>,); + const SIGNATURE: &'static str = "Paused(address)"; + const SIGNATURE_HASH: alloy_sol_types::private::B256 = alloy_sol_types::private::B256::new([ + 98u8, 231u8, 140u8, 234u8, 1u8, 190u8, 227u8, 32u8, 205u8, 78u8, 66u8, + 2u8, 112u8, 181u8, 234u8, 116u8, 0u8, 13u8, 17u8, 176u8, 201u8, 247u8, + 71u8, 84u8, 235u8, 219u8, 252u8, 84u8, 75u8, 5u8, 162u8, 88u8, + ]); + const ANONYMOUS: bool = false; + #[allow(unused_variables)] + #[inline] + fn new( + topics: ::RustType, + data: as alloy_sol_types::SolType>::RustType, + ) -> Self { + Self { account: data.0 } + } + #[inline] + fn check_signature( + topics: &::RustType, + ) -> alloy_sol_types::Result<()> { + if topics.0 != Self::SIGNATURE_HASH { + return Err( + alloy_sol_types::Error::invalid_event_signature_hash( + Self::SIGNATURE, + topics.0, + Self::SIGNATURE_HASH, + ), + ); + } + Ok(()) + } + #[inline] + fn tokenize_body(&self) -> Self::DataToken<'_> { + ( + ::tokenize( + &self.account, + ), + ) + } + #[inline] + fn topics(&self) -> ::RustType { + (Self::SIGNATURE_HASH.into(),) + } + #[inline] + fn encode_topics_raw( + &self, + out: &mut [alloy_sol_types::abi::token::WordToken], + ) -> alloy_sol_types::Result<()> { + if out.len() < ::COUNT { + return Err(alloy_sol_types::Error::Overrun); + } + out[0usize] = alloy_sol_types::abi::token::WordToken( + Self::SIGNATURE_HASH, + ); + Ok(()) + } + } + #[automatically_derived] + impl alloy_sol_types::private::IntoLogData for Paused { + fn to_log_data(&self) -> alloy_sol_types::private::LogData { + From::from(self) + } + fn into_log_data(self) -> alloy_sol_types::private::LogData { + From::from(&self) + } + } + #[automatically_derived] + impl From<&Paused> for alloy_sol_types::private::LogData { + #[inline] + fn from(this: &Paused) -> alloy_sol_types::private::LogData { + alloy_sol_types::SolEvent::encode_log_data(this) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Event with signature `RoleAdminChanged(bytes32,bytes32,bytes32)` and selector `0xbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff`. +```solidity +event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole); +```*/ + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + #[derive(Clone)] + pub struct RoleAdminChanged { + #[allow(missing_docs)] + pub role: alloy::sol_types::private::FixedBytes<32>, + #[allow(missing_docs)] + pub previousAdminRole: alloy::sol_types::private::FixedBytes<32>, + #[allow(missing_docs)] + pub newAdminRole: alloy::sol_types::private::FixedBytes<32>, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[automatically_derived] + impl alloy_sol_types::SolEvent for RoleAdminChanged { + type DataTuple<'a> = (); + type DataToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + type TopicList = ( + alloy_sol_types::sol_data::FixedBytes<32>, + alloy::sol_types::sol_data::FixedBytes<32>, + alloy::sol_types::sol_data::FixedBytes<32>, + alloy::sol_types::sol_data::FixedBytes<32>, + ); + const SIGNATURE: &'static str = "RoleAdminChanged(bytes32,bytes32,bytes32)"; + const SIGNATURE_HASH: alloy_sol_types::private::B256 = alloy_sol_types::private::B256::new([ + 189u8, 121u8, 184u8, 111u8, 254u8, 10u8, 184u8, 232u8, 119u8, 97u8, 81u8, + 81u8, 66u8, 23u8, 205u8, 124u8, 172u8, 213u8, 44u8, 144u8, 159u8, 102u8, + 71u8, 92u8, 58u8, 244u8, 78u8, 18u8, 159u8, 11u8, 0u8, 255u8, + ]); + const ANONYMOUS: bool = false; + #[allow(unused_variables)] + #[inline] + fn new( + topics: ::RustType, + data: as alloy_sol_types::SolType>::RustType, + ) -> Self { + Self { + role: topics.1, + previousAdminRole: topics.2, + newAdminRole: topics.3, + } + } + #[inline] + fn check_signature( + topics: &::RustType, + ) -> alloy_sol_types::Result<()> { + if topics.0 != Self::SIGNATURE_HASH { + return Err( + alloy_sol_types::Error::invalid_event_signature_hash( + Self::SIGNATURE, + topics.0, + Self::SIGNATURE_HASH, + ), + ); + } + Ok(()) + } + #[inline] + fn tokenize_body(&self) -> Self::DataToken<'_> { + () + } + #[inline] + fn topics(&self) -> ::RustType { + ( + Self::SIGNATURE_HASH.into(), + self.role.clone(), + self.previousAdminRole.clone(), + self.newAdminRole.clone(), + ) + } + #[inline] + fn encode_topics_raw( + &self, + out: &mut [alloy_sol_types::abi::token::WordToken], + ) -> alloy_sol_types::Result<()> { + if out.len() < ::COUNT { + return Err(alloy_sol_types::Error::Overrun); + } + out[0usize] = alloy_sol_types::abi::token::WordToken( + Self::SIGNATURE_HASH, + ); + out[1usize] = as alloy_sol_types::EventTopic>::encode_topic(&self.role); + out[2usize] = as alloy_sol_types::EventTopic>::encode_topic(&self.previousAdminRole); + out[3usize] = as alloy_sol_types::EventTopic>::encode_topic(&self.newAdminRole); + Ok(()) + } + } + #[automatically_derived] + impl alloy_sol_types::private::IntoLogData for RoleAdminChanged { + fn to_log_data(&self) -> alloy_sol_types::private::LogData { + From::from(self) + } + fn into_log_data(self) -> alloy_sol_types::private::LogData { + From::from(&self) + } + } + #[automatically_derived] + impl From<&RoleAdminChanged> for alloy_sol_types::private::LogData { + #[inline] + fn from(this: &RoleAdminChanged) -> alloy_sol_types::private::LogData { + alloy_sol_types::SolEvent::encode_log_data(this) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Event with signature `RoleGranted(bytes32,address,address)` and selector `0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d`. +```solidity +event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender); +```*/ + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + #[derive(Clone)] + pub struct RoleGranted { + #[allow(missing_docs)] + pub role: alloy::sol_types::private::FixedBytes<32>, + #[allow(missing_docs)] + pub account: alloy::sol_types::private::Address, + #[allow(missing_docs)] + pub sender: alloy::sol_types::private::Address, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[automatically_derived] + impl alloy_sol_types::SolEvent for RoleGranted { + type DataTuple<'a> = (); + type DataToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + type TopicList = ( + alloy_sol_types::sol_data::FixedBytes<32>, + alloy::sol_types::sol_data::FixedBytes<32>, + alloy::sol_types::sol_data::Address, + alloy::sol_types::sol_data::Address, + ); + const SIGNATURE: &'static str = "RoleGranted(bytes32,address,address)"; + const SIGNATURE_HASH: alloy_sol_types::private::B256 = alloy_sol_types::private::B256::new([ + 47u8, 135u8, 136u8, 17u8, 126u8, 126u8, 255u8, 29u8, 130u8, 233u8, 38u8, + 236u8, 121u8, 73u8, 1u8, 209u8, 124u8, 120u8, 2u8, 74u8, 80u8, 39u8, 9u8, + 64u8, 48u8, 69u8, 64u8, 167u8, 51u8, 101u8, 111u8, 13u8, + ]); + const ANONYMOUS: bool = false; + #[allow(unused_variables)] + #[inline] + fn new( + topics: ::RustType, + data: as alloy_sol_types::SolType>::RustType, + ) -> Self { + Self { + role: topics.1, + account: topics.2, + sender: topics.3, + } + } + #[inline] + fn check_signature( + topics: &::RustType, + ) -> alloy_sol_types::Result<()> { + if topics.0 != Self::SIGNATURE_HASH { + return Err( + alloy_sol_types::Error::invalid_event_signature_hash( + Self::SIGNATURE, + topics.0, + Self::SIGNATURE_HASH, + ), + ); + } + Ok(()) + } + #[inline] + fn tokenize_body(&self) -> Self::DataToken<'_> { + () + } + #[inline] + fn topics(&self) -> ::RustType { + ( + Self::SIGNATURE_HASH.into(), + self.role.clone(), + self.account.clone(), + self.sender.clone(), + ) + } + #[inline] + fn encode_topics_raw( + &self, + out: &mut [alloy_sol_types::abi::token::WordToken], + ) -> alloy_sol_types::Result<()> { + if out.len() < ::COUNT { + return Err(alloy_sol_types::Error::Overrun); + } + out[0usize] = alloy_sol_types::abi::token::WordToken( + Self::SIGNATURE_HASH, + ); + out[1usize] = as alloy_sol_types::EventTopic>::encode_topic(&self.role); + out[2usize] = ::encode_topic( + &self.account, + ); + out[3usize] = ::encode_topic( + &self.sender, + ); + Ok(()) + } + } + #[automatically_derived] + impl alloy_sol_types::private::IntoLogData for RoleGranted { + fn to_log_data(&self) -> alloy_sol_types::private::LogData { + From::from(self) + } + fn into_log_data(self) -> alloy_sol_types::private::LogData { + From::from(&self) + } + } + #[automatically_derived] + impl From<&RoleGranted> for alloy_sol_types::private::LogData { + #[inline] + fn from(this: &RoleGranted) -> alloy_sol_types::private::LogData { + alloy_sol_types::SolEvent::encode_log_data(this) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Event with signature `RoleRevoked(bytes32,address,address)` and selector `0xf6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b`. +```solidity +event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender); +```*/ + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + #[derive(Clone)] + pub struct RoleRevoked { + #[allow(missing_docs)] + pub role: alloy::sol_types::private::FixedBytes<32>, + #[allow(missing_docs)] + pub account: alloy::sol_types::private::Address, + #[allow(missing_docs)] + pub sender: alloy::sol_types::private::Address, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[automatically_derived] + impl alloy_sol_types::SolEvent for RoleRevoked { + type DataTuple<'a> = (); + type DataToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + type TopicList = ( + alloy_sol_types::sol_data::FixedBytes<32>, + alloy::sol_types::sol_data::FixedBytes<32>, + alloy::sol_types::sol_data::Address, + alloy::sol_types::sol_data::Address, + ); + const SIGNATURE: &'static str = "RoleRevoked(bytes32,address,address)"; + const SIGNATURE_HASH: alloy_sol_types::private::B256 = alloy_sol_types::private::B256::new([ + 246u8, 57u8, 31u8, 92u8, 50u8, 217u8, 198u8, 157u8, 42u8, 71u8, 234u8, + 103u8, 11u8, 68u8, 41u8, 116u8, 181u8, 57u8, 53u8, 209u8, 237u8, 199u8, + 253u8, 100u8, 235u8, 33u8, 224u8, 71u8, 168u8, 57u8, 23u8, 27u8, + ]); + const ANONYMOUS: bool = false; + #[allow(unused_variables)] + #[inline] + fn new( + topics: ::RustType, + data: as alloy_sol_types::SolType>::RustType, + ) -> Self { + Self { + role: topics.1, + account: topics.2, + sender: topics.3, + } + } + #[inline] + fn check_signature( + topics: &::RustType, + ) -> alloy_sol_types::Result<()> { + if topics.0 != Self::SIGNATURE_HASH { + return Err( + alloy_sol_types::Error::invalid_event_signature_hash( + Self::SIGNATURE, + topics.0, + Self::SIGNATURE_HASH, + ), + ); + } + Ok(()) + } + #[inline] + fn tokenize_body(&self) -> Self::DataToken<'_> { + () + } + #[inline] + fn topics(&self) -> ::RustType { + ( + Self::SIGNATURE_HASH.into(), + self.role.clone(), + self.account.clone(), + self.sender.clone(), + ) + } + #[inline] + fn encode_topics_raw( + &self, + out: &mut [alloy_sol_types::abi::token::WordToken], + ) -> alloy_sol_types::Result<()> { + if out.len() < ::COUNT { + return Err(alloy_sol_types::Error::Overrun); + } + out[0usize] = alloy_sol_types::abi::token::WordToken( + Self::SIGNATURE_HASH, + ); + out[1usize] = as alloy_sol_types::EventTopic>::encode_topic(&self.role); + out[2usize] = ::encode_topic( + &self.account, + ); + out[3usize] = ::encode_topic( + &self.sender, + ); + Ok(()) + } + } + #[automatically_derived] + impl alloy_sol_types::private::IntoLogData for RoleRevoked { + fn to_log_data(&self) -> alloy_sol_types::private::LogData { + From::from(self) + } + fn into_log_data(self) -> alloy_sol_types::private::LogData { + From::from(&self) + } + } + #[automatically_derived] + impl From<&RoleRevoked> for alloy_sol_types::private::LogData { + #[inline] + fn from(this: &RoleRevoked) -> alloy_sol_types::private::LogData { + alloy_sol_types::SolEvent::encode_log_data(this) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Event with signature `Unpaused(address)` and selector `0x5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa`. +```solidity +event Unpaused(address account); +```*/ + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + #[derive(Clone)] + pub struct Unpaused { + #[allow(missing_docs)] + pub account: alloy::sol_types::private::Address, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[automatically_derived] + impl alloy_sol_types::SolEvent for Unpaused { + type DataTuple<'a> = (alloy::sol_types::sol_data::Address,); + type DataToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + type TopicList = (alloy_sol_types::sol_data::FixedBytes<32>,); + const SIGNATURE: &'static str = "Unpaused(address)"; + const SIGNATURE_HASH: alloy_sol_types::private::B256 = alloy_sol_types::private::B256::new([ + 93u8, 185u8, 238u8, 10u8, 73u8, 91u8, 242u8, 230u8, 255u8, 156u8, 145u8, + 167u8, 131u8, 76u8, 27u8, 164u8, 253u8, 210u8, 68u8, 165u8, 232u8, 170u8, + 78u8, 83u8, 123u8, 211u8, 138u8, 234u8, 228u8, 176u8, 115u8, 170u8, + ]); + const ANONYMOUS: bool = false; + #[allow(unused_variables)] + #[inline] + fn new( + topics: ::RustType, + data: as alloy_sol_types::SolType>::RustType, + ) -> Self { + Self { account: data.0 } + } + #[inline] + fn check_signature( + topics: &::RustType, + ) -> alloy_sol_types::Result<()> { + if topics.0 != Self::SIGNATURE_HASH { + return Err( + alloy_sol_types::Error::invalid_event_signature_hash( + Self::SIGNATURE, + topics.0, + Self::SIGNATURE_HASH, + ), + ); + } + Ok(()) + } + #[inline] + fn tokenize_body(&self) -> Self::DataToken<'_> { + ( + ::tokenize( + &self.account, + ), + ) + } + #[inline] + fn topics(&self) -> ::RustType { + (Self::SIGNATURE_HASH.into(),) + } + #[inline] + fn encode_topics_raw( + &self, + out: &mut [alloy_sol_types::abi::token::WordToken], + ) -> alloy_sol_types::Result<()> { + if out.len() < ::COUNT { + return Err(alloy_sol_types::Error::Overrun); + } + out[0usize] = alloy_sol_types::abi::token::WordToken( + Self::SIGNATURE_HASH, + ); + Ok(()) + } + } + #[automatically_derived] + impl alloy_sol_types::private::IntoLogData for Unpaused { + fn to_log_data(&self) -> alloy_sol_types::private::LogData { + From::from(self) + } + fn into_log_data(self) -> alloy_sol_types::private::LogData { + From::from(&self) + } + } + #[automatically_derived] + impl From<&Unpaused> for alloy_sol_types::private::LogData { + #[inline] + fn from(this: &Unpaused) -> alloy_sol_types::private::LogData { + alloy_sol_types::SolEvent::encode_log_data(this) + } + } + }; + /**Constructor`. +```solidity +constructor(address _podRegistry, address _bridgeContract, IBridge.TokenLimits nativeTokenLimits); +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct constructorCall { + #[allow(missing_docs)] + pub _podRegistry: alloy::sol_types::private::Address, + #[allow(missing_docs)] + pub _bridgeContract: alloy::sol_types::private::Address, + #[allow(missing_docs)] + pub nativeTokenLimits: ::RustType, + } + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = ( + alloy::sol_types::sol_data::Address, + alloy::sol_types::sol_data::Address, + IBridge::TokenLimits, + ); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = ( + alloy::sol_types::private::Address, + alloy::sol_types::private::Address, + ::RustType, + ); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: constructorCall) -> Self { + (value._podRegistry, value._bridgeContract, value.nativeTokenLimits) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for constructorCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { + _podRegistry: tuple.0, + _bridgeContract: tuple.1, + nativeTokenLimits: tuple.2, + } + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolConstructor for constructorCall { + type Parameters<'a> = ( + alloy::sol_types::sol_data::Address, + alloy::sol_types::sol_data::Address, + IBridge::TokenLimits, + ); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + ( + ::tokenize( + &self._podRegistry, + ), + ::tokenize( + &self._bridgeContract, + ), + ::tokenize( + &self.nativeTokenLimits, + ), + ) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Function with signature `DEFAULT_ADMIN_ROLE()` and selector `0xa217fddf`. +```solidity +function DEFAULT_ADMIN_ROLE() external view returns (bytes32); +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct DEFAULT_ADMIN_ROLECall; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + ///Container type for the return parameters of the [`DEFAULT_ADMIN_ROLE()`](DEFAULT_ADMIN_ROLECall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct DEFAULT_ADMIN_ROLEReturn { + #[allow(missing_docs)] + pub _0: alloy::sol_types::private::FixedBytes<32>, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From + for UnderlyingRustTuple<'_> { + fn from(value: DEFAULT_ADMIN_ROLECall) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> + for DEFAULT_ADMIN_ROLECall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self + } + } + } + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (alloy::sol_types::sol_data::FixedBytes<32>,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (alloy::sol_types::private::FixedBytes<32>,); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From + for UnderlyingRustTuple<'_> { + fn from(value: DEFAULT_ADMIN_ROLEReturn) -> Self { + (value._0,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> + for DEFAULT_ADMIN_ROLEReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { _0: tuple.0 } + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for DEFAULT_ADMIN_ROLECall { + type Parameters<'a> = (); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = alloy::sol_types::private::FixedBytes<32>; + type ReturnTuple<'a> = (alloy::sol_types::sol_data::FixedBytes<32>,); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "DEFAULT_ADMIN_ROLE()"; + const SELECTOR: [u8; 4] = [162u8, 23u8, 253u8, 223u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + () + } + #[inline] + fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> { + ( + as alloy_sol_types::SolType>::tokenize(ret), + ) + } + #[inline] + fn abi_decode_returns(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data) + .map(|r| { + let r: DEFAULT_ADMIN_ROLEReturn = r.into(); + r._0 + }) + } + #[inline] + fn abi_decode_returns_validate( + data: &[u8], + ) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(|r| { + let r: DEFAULT_ADMIN_ROLEReturn = r.into(); + r._0 + }) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Function with signature `PAUSER_ROLE()` and selector `0xe63ab1e9`. +```solidity +function PAUSER_ROLE() external view returns (bytes32); +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct PAUSER_ROLECall; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + ///Container type for the return parameters of the [`PAUSER_ROLE()`](PAUSER_ROLECall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct PAUSER_ROLEReturn { + #[allow(missing_docs)] + pub _0: alloy::sol_types::private::FixedBytes<32>, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: PAUSER_ROLECall) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for PAUSER_ROLECall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self + } + } + } + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (alloy::sol_types::sol_data::FixedBytes<32>,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (alloy::sol_types::private::FixedBytes<32>,); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: PAUSER_ROLEReturn) -> Self { + (value._0,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for PAUSER_ROLEReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { _0: tuple.0 } + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for PAUSER_ROLECall { + type Parameters<'a> = (); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = alloy::sol_types::private::FixedBytes<32>; + type ReturnTuple<'a> = (alloy::sol_types::sol_data::FixedBytes<32>,); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "PAUSER_ROLE()"; + const SELECTOR: [u8; 4] = [230u8, 58u8, 177u8, 233u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + () + } + #[inline] + fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> { + ( + as alloy_sol_types::SolType>::tokenize(ret), + ) + } + #[inline] + fn abi_decode_returns(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data) + .map(|r| { + let r: PAUSER_ROLEReturn = r.into(); + r._0 + }) + } + #[inline] + fn abi_decode_returns_validate( + data: &[u8], + ) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(|r| { + let r: PAUSER_ROLEReturn = r.into(); + r._0 + }) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Function with signature `bridgeContract()` and selector `0xcd596583`. +```solidity +function bridgeContract() external view returns (address); +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct bridgeContractCall; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + ///Container type for the return parameters of the [`bridgeContract()`](bridgeContractCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct bridgeContractReturn { + #[allow(missing_docs)] + pub _0: alloy::sol_types::private::Address, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: bridgeContractCall) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for bridgeContractCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self + } + } + } + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (alloy::sol_types::sol_data::Address,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (alloy::sol_types::private::Address,); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From + for UnderlyingRustTuple<'_> { + fn from(value: bridgeContractReturn) -> Self { + (value._0,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> + for bridgeContractReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { _0: tuple.0 } + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for bridgeContractCall { + type Parameters<'a> = (); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = alloy::sol_types::private::Address; + type ReturnTuple<'a> = (alloy::sol_types::sol_data::Address,); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "bridgeContract()"; + const SELECTOR: [u8; 4] = [205u8, 89u8, 101u8, 131u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + () + } + #[inline] + fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> { + ( + ::tokenize( + ret, + ), + ) + } + #[inline] + fn abi_decode_returns(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data) + .map(|r| { + let r: bridgeContractReturn = r.into(); + r._0 + }) + } + #[inline] + fn abi_decode_returns_validate( + data: &[u8], + ) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(|r| { + let r: bridgeContractReturn = r.into(); + r._0 + }) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive()] + /**Function with signature `claim(((address,bytes32[],bytes),uint256,((bytes32,bytes,uint256[]),bytes32,(bytes32[]))))` and selector `0x4319e6db`. +```solidity +function claim(PodECDSA.CertifiedLog memory certifiedLog) external; +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct claimCall { + #[allow(missing_docs)] + pub certifiedLog: ::RustType, + } + ///Container type for the return parameters of the [`claim(((address,bytes32[],bytes),uint256,((bytes32,bytes,uint256[]),bytes32,(bytes32[]))))`](claimCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct claimReturn {} + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (PodECDSA::CertifiedLog,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = ( + ::RustType, + ); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: claimCall) -> Self { + (value.certifiedLog,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for claimCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { certifiedLog: tuple.0 } + } + } + } + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: claimReturn) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for claimReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self {} + } + } + } + impl claimReturn { + fn _tokenize( + &self, + ) -> ::ReturnToken<'_> { + () + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for claimCall { + type Parameters<'a> = (PodECDSA::CertifiedLog,); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = claimReturn; + type ReturnTuple<'a> = (); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "claim(((address,bytes32[],bytes),uint256,((bytes32,bytes,uint256[]),bytes32,(bytes32[]))))"; + const SELECTOR: [u8; 4] = [67u8, 25u8, 230u8, 219u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + ( + ::tokenize( + &self.certifiedLog, + ), + ) + } + #[inline] + fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> { + claimReturn::_tokenize(ret) + } + #[inline] + fn abi_decode_returns(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data) + .map(Into::into) + } + #[inline] + fn abi_decode_returns_validate( + data: &[u8], + ) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(Into::into) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive()] + /**Function with signature `claimNative(((address,bytes32[],bytes),uint256,((bytes32,bytes,uint256[]),bytes32,(bytes32[]))))` and selector `0x57143be1`. +```solidity +function claimNative(PodECDSA.CertifiedLog memory certifiedLog) external; +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct claimNativeCall { + #[allow(missing_docs)] + pub certifiedLog: ::RustType, + } + ///Container type for the return parameters of the [`claimNative(((address,bytes32[],bytes),uint256,((bytes32,bytes,uint256[]),bytes32,(bytes32[]))))`](claimNativeCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct claimNativeReturn {} + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (PodECDSA::CertifiedLog,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = ( + ::RustType, + ); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: claimNativeCall) -> Self { + (value.certifiedLog,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for claimNativeCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { certifiedLog: tuple.0 } + } + } + } + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: claimNativeReturn) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for claimNativeReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self {} + } + } + } + impl claimNativeReturn { + fn _tokenize( + &self, + ) -> ::ReturnToken<'_> { + () + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for claimNativeCall { + type Parameters<'a> = (PodECDSA::CertifiedLog,); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = claimNativeReturn; + type ReturnTuple<'a> = (); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "claimNative(((address,bytes32[],bytes),uint256,((bytes32,bytes,uint256[]),bytes32,(bytes32[]))))"; + const SELECTOR: [u8; 4] = [87u8, 20u8, 59u8, 225u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + ( + ::tokenize( + &self.certifiedLog, + ), + ) + } + #[inline] + fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> { + claimNativeReturn::_tokenize(ret) + } + #[inline] + fn abi_decode_returns(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data) + .map(Into::into) + } + #[inline] + fn abi_decode_returns_validate( + data: &[u8], + ) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(Into::into) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Function with signature `configureToken(address,(uint256,uint256,uint256))` and selector `0x9267b153`. +```solidity +function configureToken(address token, IBridge.TokenLimits memory limits) external; +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct configureTokenCall { + #[allow(missing_docs)] + pub token: alloy::sol_types::private::Address, + #[allow(missing_docs)] + pub limits: ::RustType, + } + ///Container type for the return parameters of the [`configureToken(address,(uint256,uint256,uint256))`](configureTokenCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct configureTokenReturn {} + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = ( + alloy::sol_types::sol_data::Address, + IBridge::TokenLimits, + ); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = ( + alloy::sol_types::private::Address, + ::RustType, + ); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: configureTokenCall) -> Self { + (value.token, value.limits) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for configureTokenCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { + token: tuple.0, + limits: tuple.1, + } + } + } + } + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From + for UnderlyingRustTuple<'_> { + fn from(value: configureTokenReturn) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> + for configureTokenReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self {} + } + } + } + impl configureTokenReturn { + fn _tokenize( + &self, + ) -> ::ReturnToken<'_> { + () + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for configureTokenCall { + type Parameters<'a> = ( + alloy::sol_types::sol_data::Address, + IBridge::TokenLimits, + ); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = configureTokenReturn; + type ReturnTuple<'a> = (); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "configureToken(address,(uint256,uint256,uint256))"; + const SELECTOR: [u8; 4] = [146u8, 103u8, 177u8, 83u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + ( + ::tokenize( + &self.token, + ), + ::tokenize( + &self.limits, + ), + ) + } + #[inline] + fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> { + configureTokenReturn::_tokenize(ret) + } + #[inline] + fn abi_decode_returns(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data) + .map(Into::into) + } + #[inline] + fn abi_decode_returns_validate( + data: &[u8], + ) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(Into::into) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Function with signature `deposit(address,uint256,address)` and selector `0xf45346dc`. +```solidity +function deposit(address token, uint256 amount, address to) external; +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct depositCall { + #[allow(missing_docs)] + pub token: alloy::sol_types::private::Address, + #[allow(missing_docs)] + pub amount: alloy::sol_types::private::primitives::aliases::U256, + #[allow(missing_docs)] + pub to: alloy::sol_types::private::Address, + } + ///Container type for the return parameters of the [`deposit(address,uint256,address)`](depositCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct depositReturn {} + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = ( + alloy::sol_types::sol_data::Address, + alloy::sol_types::sol_data::Uint<256>, + alloy::sol_types::sol_data::Address, + ); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = ( + alloy::sol_types::private::Address, + alloy::sol_types::private::primitives::aliases::U256, + alloy::sol_types::private::Address, + ); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: depositCall) -> Self { + (value.token, value.amount, value.to) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for depositCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { + token: tuple.0, + amount: tuple.1, + to: tuple.2, + } + } + } + } + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: depositReturn) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for depositReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self {} + } + } + } + impl depositReturn { + fn _tokenize( + &self, + ) -> ::ReturnToken<'_> { + () + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for depositCall { + type Parameters<'a> = ( + alloy::sol_types::sol_data::Address, + alloy::sol_types::sol_data::Uint<256>, + alloy::sol_types::sol_data::Address, + ); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = depositReturn; + type ReturnTuple<'a> = (); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "deposit(address,uint256,address)"; + const SELECTOR: [u8; 4] = [244u8, 83u8, 70u8, 220u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + ( + ::tokenize( + &self.token, + ), + as alloy_sol_types::SolType>::tokenize(&self.amount), + ::tokenize( + &self.to, + ), + ) + } + #[inline] + fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> { + depositReturn::_tokenize(ret) + } + #[inline] + fn abi_decode_returns(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data) + .map(Into::into) + } + #[inline] + fn abi_decode_returns_validate( + data: &[u8], + ) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(Into::into) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Function with signature `depositIndex()` and selector `0x7b898939`. +```solidity +function depositIndex() external view returns (uint256); +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct depositIndexCall; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + ///Container type for the return parameters of the [`depositIndex()`](depositIndexCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct depositIndexReturn { + #[allow(missing_docs)] + pub _0: alloy::sol_types::private::primitives::aliases::U256, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: depositIndexCall) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for depositIndexCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self + } + } + } + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (alloy::sol_types::sol_data::Uint<256>,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = ( + alloy::sol_types::private::primitives::aliases::U256, + ); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: depositIndexReturn) -> Self { + (value._0,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for depositIndexReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { _0: tuple.0 } + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for depositIndexCall { + type Parameters<'a> = (); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = alloy::sol_types::private::primitives::aliases::U256; + type ReturnTuple<'a> = (alloy::sol_types::sol_data::Uint<256>,); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "depositIndex()"; + const SELECTOR: [u8; 4] = [123u8, 137u8, 137u8, 57u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + () + } + #[inline] + fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> { + ( + as alloy_sol_types::SolType>::tokenize(ret), + ) + } + #[inline] + fn abi_decode_returns(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data) + .map(|r| { + let r: depositIndexReturn = r.into(); + r._0 + }) + } + #[inline] + fn abi_decode_returns_validate( + data: &[u8], + ) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(|r| { + let r: depositIndexReturn = r.into(); + r._0 + }) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Function with signature `depositNative(address)` and selector `0x33bb7f91`. +```solidity +function depositNative(address to) external payable; +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct depositNativeCall { + #[allow(missing_docs)] + pub to: alloy::sol_types::private::Address, + } + ///Container type for the return parameters of the [`depositNative(address)`](depositNativeCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct depositNativeReturn {} + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (alloy::sol_types::sol_data::Address,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (alloy::sol_types::private::Address,); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: depositNativeCall) -> Self { + (value.to,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for depositNativeCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { to: tuple.0 } + } + } + } + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: depositNativeReturn) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for depositNativeReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self {} + } + } + } + impl depositNativeReturn { + fn _tokenize( + &self, + ) -> ::ReturnToken<'_> { + () + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for depositNativeCall { + type Parameters<'a> = (alloy::sol_types::sol_data::Address,); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = depositNativeReturn; + type ReturnTuple<'a> = (); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "depositNative(address)"; + const SELECTOR: [u8; 4] = [51u8, 187u8, 127u8, 145u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + ( + ::tokenize( + &self.to, + ), + ) + } + #[inline] + fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> { + depositNativeReturn::_tokenize(ret) + } + #[inline] + fn abi_decode_returns(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data) + .map(Into::into) + } + #[inline] + fn abi_decode_returns_validate( + data: &[u8], + ) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(Into::into) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Function with signature `getRoleAdmin(bytes32)` and selector `0x248a9ca3`. +```solidity +function getRoleAdmin(bytes32 role) external view returns (bytes32); +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct getRoleAdminCall { + #[allow(missing_docs)] + pub role: alloy::sol_types::private::FixedBytes<32>, + } + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + ///Container type for the return parameters of the [`getRoleAdmin(bytes32)`](getRoleAdminCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct getRoleAdminReturn { + #[allow(missing_docs)] + pub _0: alloy::sol_types::private::FixedBytes<32>, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (alloy::sol_types::sol_data::FixedBytes<32>,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (alloy::sol_types::private::FixedBytes<32>,); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: getRoleAdminCall) -> Self { + (value.role,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for getRoleAdminCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { role: tuple.0 } + } + } + } + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (alloy::sol_types::sol_data::FixedBytes<32>,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (alloy::sol_types::private::FixedBytes<32>,); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: getRoleAdminReturn) -> Self { + (value._0,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for getRoleAdminReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { _0: tuple.0 } + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for getRoleAdminCall { + type Parameters<'a> = (alloy::sol_types::sol_data::FixedBytes<32>,); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = alloy::sol_types::private::FixedBytes<32>; + type ReturnTuple<'a> = (alloy::sol_types::sol_data::FixedBytes<32>,); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "getRoleAdmin(bytes32)"; + const SELECTOR: [u8; 4] = [36u8, 138u8, 156u8, 163u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + ( + as alloy_sol_types::SolType>::tokenize(&self.role), + ) + } + #[inline] + fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> { + ( + as alloy_sol_types::SolType>::tokenize(ret), + ) + } + #[inline] + fn abi_decode_returns(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data) + .map(|r| { + let r: getRoleAdminReturn = r.into(); + r._0 + }) + } + #[inline] + fn abi_decode_returns_validate( + data: &[u8], + ) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(|r| { + let r: getRoleAdminReturn = r.into(); + r._0 + }) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Function with signature `grantRole(bytes32,address)` and selector `0x2f2ff15d`. +```solidity +function grantRole(bytes32 role, address account) external; +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct grantRoleCall { + #[allow(missing_docs)] + pub role: alloy::sol_types::private::FixedBytes<32>, + #[allow(missing_docs)] + pub account: alloy::sol_types::private::Address, + } + ///Container type for the return parameters of the [`grantRole(bytes32,address)`](grantRoleCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct grantRoleReturn {} + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = ( + alloy::sol_types::sol_data::FixedBytes<32>, + alloy::sol_types::sol_data::Address, + ); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = ( + alloy::sol_types::private::FixedBytes<32>, + alloy::sol_types::private::Address, + ); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: grantRoleCall) -> Self { + (value.role, value.account) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for grantRoleCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { + role: tuple.0, + account: tuple.1, + } + } + } + } + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: grantRoleReturn) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for grantRoleReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self {} + } + } + } + impl grantRoleReturn { + fn _tokenize( + &self, + ) -> ::ReturnToken<'_> { + () + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for grantRoleCall { + type Parameters<'a> = ( + alloy::sol_types::sol_data::FixedBytes<32>, + alloy::sol_types::sol_data::Address, + ); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = grantRoleReturn; + type ReturnTuple<'a> = (); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "grantRole(bytes32,address)"; + const SELECTOR: [u8; 4] = [47u8, 47u8, 241u8, 93u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + ( + as alloy_sol_types::SolType>::tokenize(&self.role), + ::tokenize( + &self.account, + ), + ) + } + #[inline] + fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> { + grantRoleReturn::_tokenize(ret) + } + #[inline] + fn abi_decode_returns(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data) + .map(Into::into) + } + #[inline] + fn abi_decode_returns_validate( + data: &[u8], + ) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(Into::into) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Function with signature `hasRole(bytes32,address)` and selector `0x91d14854`. +```solidity +function hasRole(bytes32 role, address account) external view returns (bool); +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct hasRoleCall { + #[allow(missing_docs)] + pub role: alloy::sol_types::private::FixedBytes<32>, + #[allow(missing_docs)] + pub account: alloy::sol_types::private::Address, + } + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + ///Container type for the return parameters of the [`hasRole(bytes32,address)`](hasRoleCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct hasRoleReturn { + #[allow(missing_docs)] + pub _0: bool, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = ( + alloy::sol_types::sol_data::FixedBytes<32>, + alloy::sol_types::sol_data::Address, + ); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = ( + alloy::sol_types::private::FixedBytes<32>, + alloy::sol_types::private::Address, + ); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: hasRoleCall) -> Self { + (value.role, value.account) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for hasRoleCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { + role: tuple.0, + account: tuple.1, + } + } + } + } + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (alloy::sol_types::sol_data::Bool,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (bool,); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: hasRoleReturn) -> Self { + (value._0,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for hasRoleReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { _0: tuple.0 } + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for hasRoleCall { + type Parameters<'a> = ( + alloy::sol_types::sol_data::FixedBytes<32>, + alloy::sol_types::sol_data::Address, + ); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = bool; + type ReturnTuple<'a> = (alloy::sol_types::sol_data::Bool,); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "hasRole(bytes32,address)"; + const SELECTOR: [u8; 4] = [145u8, 209u8, 72u8, 84u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + ( + as alloy_sol_types::SolType>::tokenize(&self.role), + ::tokenize( + &self.account, + ), + ) + } + #[inline] + fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> { + ( + ::tokenize( + ret, + ), + ) + } + #[inline] + fn abi_decode_returns(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data) + .map(|r| { + let r: hasRoleReturn = r.into(); + r._0 + }) + } + #[inline] + fn abi_decode_returns_validate( + data: &[u8], + ) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(|r| { + let r: hasRoleReturn = r.into(); + r._0 + }) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Function with signature `migrate(address)` and selector `0xce5494bb`. +```solidity +function migrate(address _newContract) external; +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct migrateCall { + #[allow(missing_docs)] + pub _newContract: alloy::sol_types::private::Address, + } + ///Container type for the return parameters of the [`migrate(address)`](migrateCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct migrateReturn {} + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (alloy::sol_types::sol_data::Address,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (alloy::sol_types::private::Address,); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: migrateCall) -> Self { + (value._newContract,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for migrateCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { _newContract: tuple.0 } + } + } + } + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: migrateReturn) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for migrateReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self {} + } + } + } + impl migrateReturn { + fn _tokenize( + &self, + ) -> ::ReturnToken<'_> { + () + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for migrateCall { + type Parameters<'a> = (alloy::sol_types::sol_data::Address,); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = migrateReturn; + type ReturnTuple<'a> = (); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "migrate(address)"; + const SELECTOR: [u8; 4] = [206u8, 84u8, 148u8, 187u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + ( + ::tokenize( + &self._newContract, + ), + ) + } + #[inline] + fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> { + migrateReturn::_tokenize(ret) + } + #[inline] + fn abi_decode_returns(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data) + .map(Into::into) + } + #[inline] + fn abi_decode_returns_validate( + data: &[u8], + ) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(Into::into) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Function with signature `migratedContract()` and selector `0x7486fa4e`. +```solidity +function migratedContract() external view returns (address); +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct migratedContractCall; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + ///Container type for the return parameters of the [`migratedContract()`](migratedContractCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct migratedContractReturn { + #[allow(missing_docs)] + pub _0: alloy::sol_types::private::Address, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From + for UnderlyingRustTuple<'_> { + fn from(value: migratedContractCall) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> + for migratedContractCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self + } + } + } + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (alloy::sol_types::sol_data::Address,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (alloy::sol_types::private::Address,); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From + for UnderlyingRustTuple<'_> { + fn from(value: migratedContractReturn) -> Self { + (value._0,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> + for migratedContractReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { _0: tuple.0 } + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for migratedContractCall { + type Parameters<'a> = (); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = alloy::sol_types::private::Address; + type ReturnTuple<'a> = (alloy::sol_types::sol_data::Address,); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "migratedContract()"; + const SELECTOR: [u8; 4] = [116u8, 134u8, 250u8, 78u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + () + } + #[inline] + fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> { + ( + ::tokenize( + ret, + ), + ) + } + #[inline] + fn abi_decode_returns(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data) + .map(|r| { + let r: migratedContractReturn = r.into(); + r._0 + }) + } + #[inline] + fn abi_decode_returns_validate( + data: &[u8], + ) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(|r| { + let r: migratedContractReturn = r.into(); + r._0 + }) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Function with signature `mirrorTokens(address)` and selector `0xfeaeb43e`. +```solidity +function mirrorTokens(address) external view returns (address); +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct mirrorTokensCall(pub alloy::sol_types::private::Address); + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + ///Container type for the return parameters of the [`mirrorTokens(address)`](mirrorTokensCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct mirrorTokensReturn { + #[allow(missing_docs)] + pub _0: alloy::sol_types::private::Address, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (alloy::sol_types::sol_data::Address,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (alloy::sol_types::private::Address,); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: mirrorTokensCall) -> Self { + (value.0,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for mirrorTokensCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self(tuple.0) + } + } + } + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (alloy::sol_types::sol_data::Address,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (alloy::sol_types::private::Address,); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: mirrorTokensReturn) -> Self { + (value._0,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for mirrorTokensReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { _0: tuple.0 } + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for mirrorTokensCall { + type Parameters<'a> = (alloy::sol_types::sol_data::Address,); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = alloy::sol_types::private::Address; + type ReturnTuple<'a> = (alloy::sol_types::sol_data::Address,); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "mirrorTokens(address)"; + const SELECTOR: [u8; 4] = [254u8, 174u8, 180u8, 62u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + ( + ::tokenize( + &self.0, + ), + ) + } + #[inline] + fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> { + ( + ::tokenize( + ret, + ), + ) + } + #[inline] + fn abi_decode_returns(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data) + .map(|r| { + let r: mirrorTokensReturn = r.into(); + r._0 + }) + } + #[inline] + fn abi_decode_returns_validate( + data: &[u8], + ) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(|r| { + let r: mirrorTokensReturn = r.into(); + r._0 + }) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Function with signature `pause()` and selector `0x8456cb59`. +```solidity +function pause() external; +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct pauseCall; + ///Container type for the return parameters of the [`pause()`](pauseCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct pauseReturn {} + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: pauseCall) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for pauseCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self + } + } + } + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: pauseReturn) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for pauseReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self {} + } + } + } + impl pauseReturn { + fn _tokenize( + &self, + ) -> ::ReturnToken<'_> { + () + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for pauseCall { + type Parameters<'a> = (); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = pauseReturn; + type ReturnTuple<'a> = (); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "pause()"; + const SELECTOR: [u8; 4] = [132u8, 86u8, 203u8, 89u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + () + } + #[inline] + fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> { + pauseReturn::_tokenize(ret) + } + #[inline] + fn abi_decode_returns(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data) + .map(Into::into) + } + #[inline] + fn abi_decode_returns_validate( + data: &[u8], + ) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(Into::into) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Function with signature `paused()` and selector `0x5c975abb`. +```solidity +function paused() external view returns (bool); +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct pausedCall; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + ///Container type for the return parameters of the [`paused()`](pausedCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct pausedReturn { + #[allow(missing_docs)] + pub _0: bool, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: pausedCall) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for pausedCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self + } + } + } + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (alloy::sol_types::sol_data::Bool,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (bool,); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: pausedReturn) -> Self { + (value._0,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for pausedReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { _0: tuple.0 } + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for pausedCall { + type Parameters<'a> = (); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = bool; + type ReturnTuple<'a> = (alloy::sol_types::sol_data::Bool,); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "paused()"; + const SELECTOR: [u8; 4] = [92u8, 151u8, 90u8, 187u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + () + } + #[inline] + fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> { + ( + ::tokenize( + ret, + ), + ) + } + #[inline] + fn abi_decode_returns(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data) + .map(|r| { + let r: pausedReturn = r.into(); + r._0 + }) + } + #[inline] + fn abi_decode_returns_validate( + data: &[u8], + ) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(|r| { + let r: pausedReturn = r.into(); + r._0 + }) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Function with signature `podConfig()` and selector `0xd328613b`. +```solidity +function podConfig() external view returns (uint8 thresholdNumerator, uint8 thresholdDenominator, address registry); +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct podConfigCall; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + ///Container type for the return parameters of the [`podConfig()`](podConfigCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct podConfigReturn { + #[allow(missing_docs)] + pub thresholdNumerator: u8, + #[allow(missing_docs)] + pub thresholdDenominator: u8, + #[allow(missing_docs)] + pub registry: alloy::sol_types::private::Address, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: podConfigCall) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for podConfigCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self + } + } + } + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = ( + alloy::sol_types::sol_data::Uint<8>, + alloy::sol_types::sol_data::Uint<8>, + alloy::sol_types::sol_data::Address, + ); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (u8, u8, alloy::sol_types::private::Address); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: podConfigReturn) -> Self { + ( + value.thresholdNumerator, + value.thresholdDenominator, + value.registry, + ) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for podConfigReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { + thresholdNumerator: tuple.0, + thresholdDenominator: tuple.1, + registry: tuple.2, + } + } + } + } + impl podConfigReturn { + fn _tokenize( + &self, + ) -> ::ReturnToken<'_> { + ( + as alloy_sol_types::SolType>::tokenize(&self.thresholdNumerator), + as alloy_sol_types::SolType>::tokenize(&self.thresholdDenominator), + ::tokenize( + &self.registry, + ), + ) + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for podConfigCall { + type Parameters<'a> = (); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = podConfigReturn; + type ReturnTuple<'a> = ( + alloy::sol_types::sol_data::Uint<8>, + alloy::sol_types::sol_data::Uint<8>, + alloy::sol_types::sol_data::Address, + ); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "podConfig()"; + const SELECTOR: [u8; 4] = [211u8, 40u8, 97u8, 59u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + () + } + #[inline] + fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> { + podConfigReturn::_tokenize(ret) + } + #[inline] + fn abi_decode_returns(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data) + .map(Into::into) + } + #[inline] + fn abi_decode_returns_validate( + data: &[u8], + ) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(Into::into) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Function with signature `processedRequests(bytes32)` and selector `0xce0fa5a9`. +```solidity +function processedRequests(bytes32) external view returns (bool); +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct processedRequestsCall(pub alloy::sol_types::private::FixedBytes<32>); + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + ///Container type for the return parameters of the [`processedRequests(bytes32)`](processedRequestsCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct processedRequestsReturn { + #[allow(missing_docs)] + pub _0: bool, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (alloy::sol_types::sol_data::FixedBytes<32>,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (alloy::sol_types::private::FixedBytes<32>,); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From + for UnderlyingRustTuple<'_> { + fn from(value: processedRequestsCall) -> Self { + (value.0,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> + for processedRequestsCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self(tuple.0) + } + } + } + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (alloy::sol_types::sol_data::Bool,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (bool,); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From + for UnderlyingRustTuple<'_> { + fn from(value: processedRequestsReturn) -> Self { + (value._0,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> + for processedRequestsReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { _0: tuple.0 } + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for processedRequestsCall { + type Parameters<'a> = (alloy::sol_types::sol_data::FixedBytes<32>,); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = bool; + type ReturnTuple<'a> = (alloy::sol_types::sol_data::Bool,); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "processedRequests(bytes32)"; + const SELECTOR: [u8; 4] = [206u8, 15u8, 165u8, 169u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + ( + as alloy_sol_types::SolType>::tokenize(&self.0), + ) + } + #[inline] + fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> { + ( + ::tokenize( + ret, + ), + ) + } + #[inline] + fn abi_decode_returns(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data) + .map(|r| { + let r: processedRequestsReturn = r.into(); + r._0 + }) + } + #[inline] + fn abi_decode_returns_validate( + data: &[u8], + ) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(|r| { + let r: processedRequestsReturn = r.into(); + r._0 + }) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Function with signature `renounceRole(bytes32,address)` and selector `0x36568abe`. +```solidity +function renounceRole(bytes32 role, address callerConfirmation) external; +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct renounceRoleCall { + #[allow(missing_docs)] + pub role: alloy::sol_types::private::FixedBytes<32>, + #[allow(missing_docs)] + pub callerConfirmation: alloy::sol_types::private::Address, + } + ///Container type for the return parameters of the [`renounceRole(bytes32,address)`](renounceRoleCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct renounceRoleReturn {} + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = ( + alloy::sol_types::sol_data::FixedBytes<32>, + alloy::sol_types::sol_data::Address, + ); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = ( + alloy::sol_types::private::FixedBytes<32>, + alloy::sol_types::private::Address, + ); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: renounceRoleCall) -> Self { + (value.role, value.callerConfirmation) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for renounceRoleCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { + role: tuple.0, + callerConfirmation: tuple.1, + } + } + } + } + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: renounceRoleReturn) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for renounceRoleReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self {} + } + } + } + impl renounceRoleReturn { + fn _tokenize( + &self, + ) -> ::ReturnToken<'_> { + () + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for renounceRoleCall { + type Parameters<'a> = ( + alloy::sol_types::sol_data::FixedBytes<32>, + alloy::sol_types::sol_data::Address, + ); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = renounceRoleReturn; + type ReturnTuple<'a> = (); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "renounceRole(bytes32,address)"; + const SELECTOR: [u8; 4] = [54u8, 86u8, 138u8, 190u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + ( + as alloy_sol_types::SolType>::tokenize(&self.role), + ::tokenize( + &self.callerConfirmation, + ), + ) + } + #[inline] + fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> { + renounceRoleReturn::_tokenize(ret) + } + #[inline] + fn abi_decode_returns(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data) + .map(Into::into) + } + #[inline] + fn abi_decode_returns_validate( + data: &[u8], + ) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(Into::into) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Function with signature `revokeRole(bytes32,address)` and selector `0xd547741f`. +```solidity +function revokeRole(bytes32 role, address account) external; +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct revokeRoleCall { + #[allow(missing_docs)] + pub role: alloy::sol_types::private::FixedBytes<32>, + #[allow(missing_docs)] + pub account: alloy::sol_types::private::Address, + } + ///Container type for the return parameters of the [`revokeRole(bytes32,address)`](revokeRoleCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct revokeRoleReturn {} + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = ( + alloy::sol_types::sol_data::FixedBytes<32>, + alloy::sol_types::sol_data::Address, + ); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = ( + alloy::sol_types::private::FixedBytes<32>, + alloy::sol_types::private::Address, + ); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: revokeRoleCall) -> Self { + (value.role, value.account) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for revokeRoleCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { + role: tuple.0, + account: tuple.1, + } + } + } + } + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: revokeRoleReturn) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for revokeRoleReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self {} + } + } + } + impl revokeRoleReturn { + fn _tokenize( + &self, + ) -> ::ReturnToken<'_> { + () + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for revokeRoleCall { + type Parameters<'a> = ( + alloy::sol_types::sol_data::FixedBytes<32>, + alloy::sol_types::sol_data::Address, + ); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = revokeRoleReturn; + type ReturnTuple<'a> = (); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "revokeRole(bytes32,address)"; + const SELECTOR: [u8; 4] = [213u8, 71u8, 116u8, 31u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + ( + as alloy_sol_types::SolType>::tokenize(&self.role), + ::tokenize( + &self.account, + ), + ) + } + #[inline] + fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> { + revokeRoleReturn::_tokenize(ret) + } + #[inline] + fn abi_decode_returns(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data) + .map(Into::into) + } + #[inline] + fn abi_decode_returns_validate( + data: &[u8], + ) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(Into::into) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Function with signature `supportsInterface(bytes4)` and selector `0x01ffc9a7`. +```solidity +function supportsInterface(bytes4 interfaceId) external view returns (bool); +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct supportsInterfaceCall { + #[allow(missing_docs)] + pub interfaceId: alloy::sol_types::private::FixedBytes<4>, + } + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + ///Container type for the return parameters of the [`supportsInterface(bytes4)`](supportsInterfaceCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct supportsInterfaceReturn { + #[allow(missing_docs)] + pub _0: bool, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (alloy::sol_types::sol_data::FixedBytes<4>,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (alloy::sol_types::private::FixedBytes<4>,); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From + for UnderlyingRustTuple<'_> { + fn from(value: supportsInterfaceCall) -> Self { + (value.interfaceId,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> + for supportsInterfaceCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { interfaceId: tuple.0 } + } + } + } + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (alloy::sol_types::sol_data::Bool,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (bool,); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From + for UnderlyingRustTuple<'_> { + fn from(value: supportsInterfaceReturn) -> Self { + (value._0,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> + for supportsInterfaceReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { _0: tuple.0 } + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for supportsInterfaceCall { + type Parameters<'a> = (alloy::sol_types::sol_data::FixedBytes<4>,); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = bool; + type ReturnTuple<'a> = (alloy::sol_types::sol_data::Bool,); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "supportsInterface(bytes4)"; + const SELECTOR: [u8; 4] = [1u8, 255u8, 201u8, 167u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + ( + as alloy_sol_types::SolType>::tokenize(&self.interfaceId), + ) + } + #[inline] + fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> { + ( + ::tokenize( + ret, + ), + ) + } + #[inline] + fn abi_decode_returns(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data) + .map(|r| { + let r: supportsInterfaceReturn = r.into(); + r._0 + }) + } + #[inline] + fn abi_decode_returns_validate( + data: &[u8], + ) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(|r| { + let r: supportsInterfaceReturn = r.into(); + r._0 + }) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Function with signature `tokenData(address)` and selector `0x27e45c2c`. +```solidity +function tokenData(address) external view returns (IBridge.TokenLimits memory limits, IBridge.TokenUsage memory deposit, IBridge.TokenUsage memory claim); +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct tokenDataCall(pub alloy::sol_types::private::Address); + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + ///Container type for the return parameters of the [`tokenData(address)`](tokenDataCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct tokenDataReturn { + #[allow(missing_docs)] + pub limits: ::RustType, + #[allow(missing_docs)] + pub deposit: ::RustType, + #[allow(missing_docs)] + pub claim: ::RustType, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (alloy::sol_types::sol_data::Address,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (alloy::sol_types::private::Address,); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: tokenDataCall) -> Self { + (value.0,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for tokenDataCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self(tuple.0) + } + } + } + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = ( + IBridge::TokenLimits, + IBridge::TokenUsage, + IBridge::TokenUsage, + ); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = ( + ::RustType, + ::RustType, + ::RustType, + ); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: tokenDataReturn) -> Self { + (value.limits, value.deposit, value.claim) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for tokenDataReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { + limits: tuple.0, + deposit: tuple.1, + claim: tuple.2, + } + } + } + } + impl tokenDataReturn { + fn _tokenize( + &self, + ) -> ::ReturnToken<'_> { + ( + ::tokenize( + &self.limits, + ), + ::tokenize( + &self.deposit, + ), + ::tokenize( + &self.claim, + ), + ) + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for tokenDataCall { + type Parameters<'a> = (alloy::sol_types::sol_data::Address,); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = tokenDataReturn; + type ReturnTuple<'a> = ( + IBridge::TokenLimits, + IBridge::TokenUsage, + IBridge::TokenUsage, + ); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "tokenData(address)"; + const SELECTOR: [u8; 4] = [39u8, 228u8, 92u8, 44u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + ( + ::tokenize( + &self.0, + ), + ) + } + #[inline] + fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> { + tokenDataReturn::_tokenize(ret) + } + #[inline] + fn abi_decode_returns(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data) + .map(Into::into) + } + #[inline] + fn abi_decode_returns_validate( + data: &[u8], + ) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(Into::into) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Function with signature `unpause()` and selector `0x3f4ba83a`. +```solidity +function unpause() external; +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct unpauseCall; + ///Container type for the return parameters of the [`unpause()`](unpauseCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct unpauseReturn {} + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: unpauseCall) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for unpauseCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self + } + } + } + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: unpauseReturn) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for unpauseReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self {} + } + } + } + impl unpauseReturn { + fn _tokenize( + &self, + ) -> ::ReturnToken<'_> { + () + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for unpauseCall { + type Parameters<'a> = (); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = unpauseReturn; + type ReturnTuple<'a> = (); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "unpause()"; + const SELECTOR: [u8; 4] = [63u8, 75u8, 168u8, 58u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + () + } + #[inline] + fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> { + unpauseReturn::_tokenize(ret) + } + #[inline] + fn abi_decode_returns(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data) + .map(Into::into) + } + #[inline] + fn abi_decode_returns_validate( + data: &[u8], + ) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(Into::into) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Function with signature `usedNonces(uint256)` and selector `0x6717e41c`. +```solidity +function usedNonces(uint256) external view returns (bool); +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct usedNoncesCall(pub alloy::sol_types::private::primitives::aliases::U256); + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + ///Container type for the return parameters of the [`usedNonces(uint256)`](usedNoncesCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct usedNoncesReturn { + #[allow(missing_docs)] + pub _0: bool, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (alloy::sol_types::sol_data::Uint<256>,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = ( + alloy::sol_types::private::primitives::aliases::U256, + ); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: usedNoncesCall) -> Self { + (value.0,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for usedNoncesCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self(tuple.0) + } + } + } + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (alloy::sol_types::sol_data::Bool,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (bool,); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: usedNoncesReturn) -> Self { + (value._0,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for usedNoncesReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { _0: tuple.0 } + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for usedNoncesCall { + type Parameters<'a> = (alloy::sol_types::sol_data::Uint<256>,); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = bool; + type ReturnTuple<'a> = (alloy::sol_types::sol_data::Bool,); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "usedNonces(uint256)"; + const SELECTOR: [u8; 4] = [103u8, 23u8, 228u8, 28u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + ( + as alloy_sol_types::SolType>::tokenize(&self.0), + ) + } + #[inline] + fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> { + ( + ::tokenize( + ret, + ), + ) + } + #[inline] + fn abi_decode_returns(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data) + .map(|r| { + let r: usedNoncesReturn = r.into(); + r._0 + }) + } + #[inline] + fn abi_decode_returns_validate( + data: &[u8], + ) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(|r| { + let r: usedNoncesReturn = r.into(); + r._0 + }) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Function with signature `whiteListToken(address,address,(uint256,uint256,uint256))` and selector `0xfc5c5cb3`. +```solidity +function whiteListToken(address token, address mirrorToken, IBridge.TokenLimits memory limits) external; +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct whiteListTokenCall { + #[allow(missing_docs)] + pub token: alloy::sol_types::private::Address, + #[allow(missing_docs)] + pub mirrorToken: alloy::sol_types::private::Address, + #[allow(missing_docs)] + pub limits: ::RustType, + } + ///Container type for the return parameters of the [`whiteListToken(address,address,(uint256,uint256,uint256))`](whiteListTokenCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct whiteListTokenReturn {} + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = ( + alloy::sol_types::sol_data::Address, + alloy::sol_types::sol_data::Address, + IBridge::TokenLimits, + ); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = ( + alloy::sol_types::private::Address, + alloy::sol_types::private::Address, + ::RustType, + ); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: whiteListTokenCall) -> Self { + (value.token, value.mirrorToken, value.limits) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for whiteListTokenCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { + token: tuple.0, + mirrorToken: tuple.1, + limits: tuple.2, + } + } + } + } + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From + for UnderlyingRustTuple<'_> { + fn from(value: whiteListTokenReturn) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> + for whiteListTokenReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self {} + } + } + } + impl whiteListTokenReturn { + fn _tokenize( + &self, + ) -> ::ReturnToken<'_> { + () + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for whiteListTokenCall { + type Parameters<'a> = ( + alloy::sol_types::sol_data::Address, + alloy::sol_types::sol_data::Address, + IBridge::TokenLimits, + ); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = whiteListTokenReturn; + type ReturnTuple<'a> = (); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "whiteListToken(address,address,(uint256,uint256,uint256))"; + const SELECTOR: [u8; 4] = [252u8, 92u8, 92u8, 179u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + ( + ::tokenize( + &self.token, + ), + ::tokenize( + &self.mirrorToken, + ), + ::tokenize( + &self.limits, + ), + ) + } + #[inline] + fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> { + whiteListTokenReturn::_tokenize(ret) + } + #[inline] + fn abi_decode_returns(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data) + .map(Into::into) + } + #[inline] + fn abi_decode_returns_validate( + data: &[u8], + ) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(Into::into) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Function with signature `whitelistedTokens(uint256)` and selector `0x2154bc44`. +```solidity +function whitelistedTokens(uint256) external view returns (address); +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct whitelistedTokensCall( + pub alloy::sol_types::private::primitives::aliases::U256, + ); + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + ///Container type for the return parameters of the [`whitelistedTokens(uint256)`](whitelistedTokensCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct whitelistedTokensReturn { + #[allow(missing_docs)] + pub _0: alloy::sol_types::private::Address, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (alloy::sol_types::sol_data::Uint<256>,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = ( + alloy::sol_types::private::primitives::aliases::U256, + ); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From + for UnderlyingRustTuple<'_> { + fn from(value: whitelistedTokensCall) -> Self { + (value.0,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> + for whitelistedTokensCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self(tuple.0) + } + } + } + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (alloy::sol_types::sol_data::Address,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (alloy::sol_types::private::Address,); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From + for UnderlyingRustTuple<'_> { + fn from(value: whitelistedTokensReturn) -> Self { + (value._0,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> + for whitelistedTokensReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { _0: tuple.0 } + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for whitelistedTokensCall { + type Parameters<'a> = (alloy::sol_types::sol_data::Uint<256>,); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = alloy::sol_types::private::Address; + type ReturnTuple<'a> = (alloy::sol_types::sol_data::Address,); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "whitelistedTokens(uint256)"; + const SELECTOR: [u8; 4] = [33u8, 84u8, 188u8, 68u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + ( + as alloy_sol_types::SolType>::tokenize(&self.0), + ) + } + #[inline] + fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> { + ( + ::tokenize( + ret, + ), + ) + } + #[inline] + fn abi_decode_returns(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data) + .map(|r| { + let r: whitelistedTokensReturn = r.into(); + r._0 + }) + } + #[inline] + fn abi_decode_returns_validate( + data: &[u8], + ) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(|r| { + let r: whitelistedTokensReturn = r.into(); + r._0 + }) + } + } + }; + ///Container for all the [`BridgeDepositWithdraw`](self) function calls. + #[derive(serde::Serialize, serde::Deserialize)] + #[derive()] + pub enum BridgeDepositWithdrawCalls { + #[allow(missing_docs)] + DEFAULT_ADMIN_ROLE(DEFAULT_ADMIN_ROLECall), + #[allow(missing_docs)] + PAUSER_ROLE(PAUSER_ROLECall), + #[allow(missing_docs)] + bridgeContract(bridgeContractCall), + #[allow(missing_docs)] + claim(claimCall), + #[allow(missing_docs)] + claimNative(claimNativeCall), + #[allow(missing_docs)] + configureToken(configureTokenCall), + #[allow(missing_docs)] + deposit(depositCall), + #[allow(missing_docs)] + depositIndex(depositIndexCall), + #[allow(missing_docs)] + depositNative(depositNativeCall), + #[allow(missing_docs)] + getRoleAdmin(getRoleAdminCall), + #[allow(missing_docs)] + grantRole(grantRoleCall), + #[allow(missing_docs)] + hasRole(hasRoleCall), + #[allow(missing_docs)] + migrate(migrateCall), + #[allow(missing_docs)] + migratedContract(migratedContractCall), + #[allow(missing_docs)] + mirrorTokens(mirrorTokensCall), + #[allow(missing_docs)] + pause(pauseCall), + #[allow(missing_docs)] + paused(pausedCall), + #[allow(missing_docs)] + podConfig(podConfigCall), + #[allow(missing_docs)] + processedRequests(processedRequestsCall), + #[allow(missing_docs)] + renounceRole(renounceRoleCall), + #[allow(missing_docs)] + revokeRole(revokeRoleCall), + #[allow(missing_docs)] + supportsInterface(supportsInterfaceCall), + #[allow(missing_docs)] + tokenData(tokenDataCall), + #[allow(missing_docs)] + unpause(unpauseCall), + #[allow(missing_docs)] + usedNonces(usedNoncesCall), + #[allow(missing_docs)] + whiteListToken(whiteListTokenCall), + #[allow(missing_docs)] + whitelistedTokens(whitelistedTokensCall), + } + #[automatically_derived] + impl BridgeDepositWithdrawCalls { + /// All the selectors of this enum. + /// + /// Note that the selectors might not be in the same order as the variants. + /// No guarantees are made about the order of the selectors. + /// + /// Prefer using `SolInterface` methods instead. + pub const SELECTORS: &'static [[u8; 4usize]] = &[ + [1u8, 255u8, 201u8, 167u8], + [33u8, 84u8, 188u8, 68u8], + [36u8, 138u8, 156u8, 163u8], + [39u8, 228u8, 92u8, 44u8], + [47u8, 47u8, 241u8, 93u8], + [51u8, 187u8, 127u8, 145u8], + [54u8, 86u8, 138u8, 190u8], + [63u8, 75u8, 168u8, 58u8], + [67u8, 25u8, 230u8, 219u8], + [87u8, 20u8, 59u8, 225u8], + [92u8, 151u8, 90u8, 187u8], + [103u8, 23u8, 228u8, 28u8], + [116u8, 134u8, 250u8, 78u8], + [123u8, 137u8, 137u8, 57u8], + [132u8, 86u8, 203u8, 89u8], + [145u8, 209u8, 72u8, 84u8], + [146u8, 103u8, 177u8, 83u8], + [162u8, 23u8, 253u8, 223u8], + [205u8, 89u8, 101u8, 131u8], + [206u8, 15u8, 165u8, 169u8], + [206u8, 84u8, 148u8, 187u8], + [211u8, 40u8, 97u8, 59u8], + [213u8, 71u8, 116u8, 31u8], + [230u8, 58u8, 177u8, 233u8], + [244u8, 83u8, 70u8, 220u8], + [252u8, 92u8, 92u8, 179u8], + [254u8, 174u8, 180u8, 62u8], + ]; + } + #[automatically_derived] + impl alloy_sol_types::SolInterface for BridgeDepositWithdrawCalls { + const NAME: &'static str = "BridgeDepositWithdrawCalls"; + const MIN_DATA_LENGTH: usize = 0usize; + const COUNT: usize = 27usize; + #[inline] + fn selector(&self) -> [u8; 4] { + match self { + Self::DEFAULT_ADMIN_ROLE(_) => { + ::SELECTOR + } + Self::PAUSER_ROLE(_) => { + ::SELECTOR + } + Self::bridgeContract(_) => { + ::SELECTOR + } + Self::claim(_) => ::SELECTOR, + Self::claimNative(_) => { + ::SELECTOR + } + Self::configureToken(_) => { + ::SELECTOR + } + Self::deposit(_) => ::SELECTOR, + Self::depositIndex(_) => { + ::SELECTOR + } + Self::depositNative(_) => { + ::SELECTOR + } + Self::getRoleAdmin(_) => { + ::SELECTOR + } + Self::grantRole(_) => { + ::SELECTOR + } + Self::hasRole(_) => ::SELECTOR, + Self::migrate(_) => ::SELECTOR, + Self::migratedContract(_) => { + ::SELECTOR + } + Self::mirrorTokens(_) => { + ::SELECTOR + } + Self::pause(_) => ::SELECTOR, + Self::paused(_) => ::SELECTOR, + Self::podConfig(_) => { + ::SELECTOR + } + Self::processedRequests(_) => { + ::SELECTOR + } + Self::renounceRole(_) => { + ::SELECTOR + } + Self::revokeRole(_) => { + ::SELECTOR + } + Self::supportsInterface(_) => { + ::SELECTOR + } + Self::tokenData(_) => { + ::SELECTOR + } + Self::unpause(_) => ::SELECTOR, + Self::usedNonces(_) => { + ::SELECTOR + } + Self::whiteListToken(_) => { + ::SELECTOR + } + Self::whitelistedTokens(_) => { + ::SELECTOR + } + } + } + #[inline] + fn selector_at(i: usize) -> ::core::option::Option<[u8; 4]> { + Self::SELECTORS.get(i).copied() + } + #[inline] + fn valid_selector(selector: [u8; 4]) -> bool { + Self::SELECTORS.binary_search(&selector).is_ok() + } + #[inline] + #[allow(non_snake_case)] + fn abi_decode_raw( + selector: [u8; 4], + data: &[u8], + ) -> alloy_sol_types::Result { + static DECODE_SHIMS: &[fn( + &[u8], + ) -> alloy_sol_types::Result] = &[ + { + fn supportsInterface( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw( + data, + ) + .map(BridgeDepositWithdrawCalls::supportsInterface) + } + supportsInterface + }, + { + fn whitelistedTokens( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw( + data, + ) + .map(BridgeDepositWithdrawCalls::whitelistedTokens) + } + whitelistedTokens + }, + { + fn getRoleAdmin( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw( + data, + ) + .map(BridgeDepositWithdrawCalls::getRoleAdmin) + } + getRoleAdmin + }, + { + fn tokenData( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw(data) + .map(BridgeDepositWithdrawCalls::tokenData) + } + tokenData + }, + { + fn grantRole( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw(data) + .map(BridgeDepositWithdrawCalls::grantRole) + } + grantRole + }, + { + fn depositNative( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw( + data, + ) + .map(BridgeDepositWithdrawCalls::depositNative) + } + depositNative + }, + { + fn renounceRole( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw( + data, + ) + .map(BridgeDepositWithdrawCalls::renounceRole) + } + renounceRole + }, + { + fn unpause( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw(data) + .map(BridgeDepositWithdrawCalls::unpause) + } + unpause + }, + { + fn claim( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw(data) + .map(BridgeDepositWithdrawCalls::claim) + } + claim + }, + { + fn claimNative( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw( + data, + ) + .map(BridgeDepositWithdrawCalls::claimNative) + } + claimNative + }, + { + fn paused( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw(data) + .map(BridgeDepositWithdrawCalls::paused) + } + paused + }, + { + fn usedNonces( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw( + data, + ) + .map(BridgeDepositWithdrawCalls::usedNonces) + } + usedNonces + }, + { + fn migratedContract( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw( + data, + ) + .map(BridgeDepositWithdrawCalls::migratedContract) + } + migratedContract + }, + { + fn depositIndex( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw( + data, + ) + .map(BridgeDepositWithdrawCalls::depositIndex) + } + depositIndex + }, + { + fn pause( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw(data) + .map(BridgeDepositWithdrawCalls::pause) + } + pause + }, + { + fn hasRole( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw(data) + .map(BridgeDepositWithdrawCalls::hasRole) + } + hasRole + }, + { + fn configureToken( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw( + data, + ) + .map(BridgeDepositWithdrawCalls::configureToken) + } + configureToken + }, + { + fn DEFAULT_ADMIN_ROLE( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw( + data, + ) + .map(BridgeDepositWithdrawCalls::DEFAULT_ADMIN_ROLE) + } + DEFAULT_ADMIN_ROLE + }, + { + fn bridgeContract( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw( + data, + ) + .map(BridgeDepositWithdrawCalls::bridgeContract) + } + bridgeContract + }, + { + fn processedRequests( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw( + data, + ) + .map(BridgeDepositWithdrawCalls::processedRequests) + } + processedRequests + }, + { + fn migrate( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw(data) + .map(BridgeDepositWithdrawCalls::migrate) + } + migrate + }, + { + fn podConfig( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw(data) + .map(BridgeDepositWithdrawCalls::podConfig) + } + podConfig + }, + { + fn revokeRole( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw( + data, + ) + .map(BridgeDepositWithdrawCalls::revokeRole) + } + revokeRole + }, + { + fn PAUSER_ROLE( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw( + data, + ) + .map(BridgeDepositWithdrawCalls::PAUSER_ROLE) + } + PAUSER_ROLE + }, + { + fn deposit( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw(data) + .map(BridgeDepositWithdrawCalls::deposit) + } + deposit + }, + { + fn whiteListToken( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw( + data, + ) + .map(BridgeDepositWithdrawCalls::whiteListToken) + } + whiteListToken + }, + { + fn mirrorTokens( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw( + data, + ) + .map(BridgeDepositWithdrawCalls::mirrorTokens) + } + mirrorTokens + }, + ]; + let Ok(idx) = Self::SELECTORS.binary_search(&selector) else { + return Err( + alloy_sol_types::Error::unknown_selector( + ::NAME, + selector, + ), + ); + }; + DECODE_SHIMS[idx](data) + } + #[inline] + #[allow(non_snake_case)] + fn abi_decode_raw_validate( + selector: [u8; 4], + data: &[u8], + ) -> alloy_sol_types::Result { + static DECODE_VALIDATE_SHIMS: &[fn( + &[u8], + ) -> alloy_sol_types::Result] = &[ + { + fn supportsInterface( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(BridgeDepositWithdrawCalls::supportsInterface) + } + supportsInterface + }, + { + fn whitelistedTokens( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(BridgeDepositWithdrawCalls::whitelistedTokens) + } + whitelistedTokens + }, + { + fn getRoleAdmin( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(BridgeDepositWithdrawCalls::getRoleAdmin) + } + getRoleAdmin + }, + { + fn tokenData( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(BridgeDepositWithdrawCalls::tokenData) + } + tokenData + }, + { + fn grantRole( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(BridgeDepositWithdrawCalls::grantRole) + } + grantRole + }, + { + fn depositNative( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(BridgeDepositWithdrawCalls::depositNative) + } + depositNative + }, + { + fn renounceRole( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(BridgeDepositWithdrawCalls::renounceRole) + } + renounceRole + }, + { + fn unpause( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(BridgeDepositWithdrawCalls::unpause) + } + unpause + }, + { + fn claim( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(BridgeDepositWithdrawCalls::claim) + } + claim + }, + { + fn claimNative( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(BridgeDepositWithdrawCalls::claimNative) + } + claimNative + }, + { + fn paused( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(BridgeDepositWithdrawCalls::paused) + } + paused + }, + { + fn usedNonces( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(BridgeDepositWithdrawCalls::usedNonces) + } + usedNonces + }, + { + fn migratedContract( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(BridgeDepositWithdrawCalls::migratedContract) + } + migratedContract + }, + { + fn depositIndex( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(BridgeDepositWithdrawCalls::depositIndex) + } + depositIndex + }, + { + fn pause( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(BridgeDepositWithdrawCalls::pause) + } + pause + }, + { + fn hasRole( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(BridgeDepositWithdrawCalls::hasRole) + } + hasRole + }, + { + fn configureToken( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(BridgeDepositWithdrawCalls::configureToken) + } + configureToken + }, + { + fn DEFAULT_ADMIN_ROLE( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(BridgeDepositWithdrawCalls::DEFAULT_ADMIN_ROLE) + } + DEFAULT_ADMIN_ROLE + }, + { + fn bridgeContract( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(BridgeDepositWithdrawCalls::bridgeContract) + } + bridgeContract + }, + { + fn processedRequests( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(BridgeDepositWithdrawCalls::processedRequests) + } + processedRequests + }, + { + fn migrate( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(BridgeDepositWithdrawCalls::migrate) + } + migrate + }, + { + fn podConfig( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(BridgeDepositWithdrawCalls::podConfig) + } + podConfig + }, + { + fn revokeRole( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(BridgeDepositWithdrawCalls::revokeRole) + } + revokeRole + }, + { + fn PAUSER_ROLE( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(BridgeDepositWithdrawCalls::PAUSER_ROLE) + } + PAUSER_ROLE + }, + { + fn deposit( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(BridgeDepositWithdrawCalls::deposit) + } + deposit + }, + { + fn whiteListToken( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(BridgeDepositWithdrawCalls::whiteListToken) + } + whiteListToken + }, + { + fn mirrorTokens( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(BridgeDepositWithdrawCalls::mirrorTokens) + } + mirrorTokens + }, + ]; + let Ok(idx) = Self::SELECTORS.binary_search(&selector) else { + return Err( + alloy_sol_types::Error::unknown_selector( + ::NAME, + selector, + ), + ); + }; + DECODE_VALIDATE_SHIMS[idx](data) + } + #[inline] + fn abi_encoded_size(&self) -> usize { + match self { + Self::DEFAULT_ADMIN_ROLE(inner) => { + ::abi_encoded_size( + inner, + ) + } + Self::PAUSER_ROLE(inner) => { + ::abi_encoded_size( + inner, + ) + } + Self::bridgeContract(inner) => { + ::abi_encoded_size( + inner, + ) + } + Self::claim(inner) => { + ::abi_encoded_size(inner) + } + Self::claimNative(inner) => { + ::abi_encoded_size( + inner, + ) + } + Self::configureToken(inner) => { + ::abi_encoded_size( + inner, + ) + } + Self::deposit(inner) => { + ::abi_encoded_size(inner) + } + Self::depositIndex(inner) => { + ::abi_encoded_size( + inner, + ) + } + Self::depositNative(inner) => { + ::abi_encoded_size( + inner, + ) + } + Self::getRoleAdmin(inner) => { + ::abi_encoded_size( + inner, + ) + } + Self::grantRole(inner) => { + ::abi_encoded_size(inner) + } + Self::hasRole(inner) => { + ::abi_encoded_size(inner) + } + Self::migrate(inner) => { + ::abi_encoded_size(inner) + } + Self::migratedContract(inner) => { + ::abi_encoded_size( + inner, + ) + } + Self::mirrorTokens(inner) => { + ::abi_encoded_size( + inner, + ) + } + Self::pause(inner) => { + ::abi_encoded_size(inner) + } + Self::paused(inner) => { + ::abi_encoded_size(inner) + } + Self::podConfig(inner) => { + ::abi_encoded_size(inner) + } + Self::processedRequests(inner) => { + ::abi_encoded_size( + inner, + ) + } + Self::renounceRole(inner) => { + ::abi_encoded_size( + inner, + ) + } + Self::revokeRole(inner) => { + ::abi_encoded_size(inner) + } + Self::supportsInterface(inner) => { + ::abi_encoded_size( + inner, + ) + } + Self::tokenData(inner) => { + ::abi_encoded_size(inner) + } + Self::unpause(inner) => { + ::abi_encoded_size(inner) + } + Self::usedNonces(inner) => { + ::abi_encoded_size(inner) + } + Self::whiteListToken(inner) => { + ::abi_encoded_size( + inner, + ) + } + Self::whitelistedTokens(inner) => { + ::abi_encoded_size( + inner, + ) + } + } + } + #[inline] + fn abi_encode_raw(&self, out: &mut alloy_sol_types::private::Vec) { + match self { + Self::DEFAULT_ADMIN_ROLE(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } + Self::PAUSER_ROLE(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } + Self::bridgeContract(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } + Self::claim(inner) => { + ::abi_encode_raw(inner, out) + } + Self::claimNative(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } + Self::configureToken(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } + Self::deposit(inner) => { + ::abi_encode_raw(inner, out) + } + Self::depositIndex(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } + Self::depositNative(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } + Self::getRoleAdmin(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } + Self::grantRole(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } + Self::hasRole(inner) => { + ::abi_encode_raw(inner, out) + } + Self::migrate(inner) => { + ::abi_encode_raw(inner, out) + } + Self::migratedContract(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } + Self::mirrorTokens(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } + Self::pause(inner) => { + ::abi_encode_raw(inner, out) + } + Self::paused(inner) => { + ::abi_encode_raw(inner, out) + } + Self::podConfig(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } + Self::processedRequests(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } + Self::renounceRole(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } + Self::revokeRole(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } + Self::supportsInterface(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } + Self::tokenData(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } + Self::unpause(inner) => { + ::abi_encode_raw(inner, out) + } + Self::usedNonces(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } + Self::whiteListToken(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } + Self::whitelistedTokens(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } + } + } + } + ///Container for all the [`BridgeDepositWithdraw`](self) custom errors. + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Debug, PartialEq, Eq, Hash)] + pub enum BridgeDepositWithdrawErrors { + #[allow(missing_docs)] + AccessControlBadConfirmation(AccessControlBadConfirmation), + #[allow(missing_docs)] + AccessControlUnauthorizedAccount(AccessControlUnauthorizedAccount), + #[allow(missing_docs)] + ContractMigrated(ContractMigrated), + #[allow(missing_docs)] + DailyLimitExhausted(DailyLimitExhausted), + #[allow(missing_docs)] + EnforcedPause(EnforcedPause), + #[allow(missing_docs)] + ExpectedPause(ExpectedPause), + #[allow(missing_docs)] + InvalidBridgeContract(InvalidBridgeContract), + #[allow(missing_docs)] + InvalidCertificate(InvalidCertificate), + #[allow(missing_docs)] + InvalidDepositLog(InvalidDepositLog), + #[allow(missing_docs)] + InvalidNonce(InvalidNonce), + #[allow(missing_docs)] + InvalidToAddress(InvalidToAddress), + #[allow(missing_docs)] + InvalidTokenAmount(InvalidTokenAmount), + #[allow(missing_docs)] + InvalidTokenConfig(InvalidTokenConfig), + #[allow(missing_docs)] + MirrorTokenNotFound(MirrorTokenNotFound), + #[allow(missing_docs)] + RequestAlreadyProcessed(RequestAlreadyProcessed), + #[allow(missing_docs)] + SafeERC20FailedOperation(SafeERC20FailedOperation), + } + #[automatically_derived] + impl BridgeDepositWithdrawErrors { + /// All the selectors of this enum. + /// + /// Note that the selectors might not be in the same order as the variants. + /// No guarantees are made about the order of the selectors. + /// + /// Prefer using `SolInterface` methods instead. + pub const SELECTORS: &'static [[u8; 4usize]] = &[ + [7u8, 254u8, 123u8, 174u8], + [29u8, 57u8, 249u8, 70u8], + [33u8, 96u8, 115u8, 57u8], + [63u8, 79u8, 104u8, 150u8], + [82u8, 116u8, 175u8, 231u8], + [102u8, 151u8, 178u8, 50u8], + [102u8, 218u8, 128u8, 55u8], + [117u8, 102u8, 136u8, 254u8], + [138u8, 163u8, 167u8, 47u8], + [141u8, 252u8, 32u8, 43u8], + [166u8, 188u8, 116u8, 196u8], + [168u8, 221u8, 182u8, 77u8], + [189u8, 196u8, 223u8, 114u8], + [193u8, 45u8, 203u8, 194u8], + [217u8, 60u8, 6u8, 101u8], + [226u8, 81u8, 125u8, 63u8], + ]; + } + #[automatically_derived] + impl alloy_sol_types::SolInterface for BridgeDepositWithdrawErrors { + const NAME: &'static str = "BridgeDepositWithdrawErrors"; + const MIN_DATA_LENGTH: usize = 0usize; + const COUNT: usize = 16usize; + #[inline] + fn selector(&self) -> [u8; 4] { + match self { + Self::AccessControlBadConfirmation(_) => { + ::SELECTOR + } + Self::AccessControlUnauthorizedAccount(_) => { + ::SELECTOR + } + Self::ContractMigrated(_) => { + ::SELECTOR + } + Self::DailyLimitExhausted(_) => { + ::SELECTOR + } + Self::EnforcedPause(_) => { + ::SELECTOR + } + Self::ExpectedPause(_) => { + ::SELECTOR + } + Self::InvalidBridgeContract(_) => { + ::SELECTOR + } + Self::InvalidCertificate(_) => { + ::SELECTOR + } + Self::InvalidDepositLog(_) => { + ::SELECTOR + } + Self::InvalidNonce(_) => { + ::SELECTOR + } + Self::InvalidToAddress(_) => { + ::SELECTOR + } + Self::InvalidTokenAmount(_) => { + ::SELECTOR + } + Self::InvalidTokenConfig(_) => { + ::SELECTOR + } + Self::MirrorTokenNotFound(_) => { + ::SELECTOR + } + Self::RequestAlreadyProcessed(_) => { + ::SELECTOR + } + Self::SafeERC20FailedOperation(_) => { + ::SELECTOR + } + } + } + #[inline] + fn selector_at(i: usize) -> ::core::option::Option<[u8; 4]> { + Self::SELECTORS.get(i).copied() + } + #[inline] + fn valid_selector(selector: [u8; 4]) -> bool { + Self::SELECTORS.binary_search(&selector).is_ok() + } + #[inline] + #[allow(non_snake_case)] + fn abi_decode_raw( + selector: [u8; 4], + data: &[u8], + ) -> alloy_sol_types::Result { + static DECODE_SHIMS: &[fn( + &[u8], + ) -> alloy_sol_types::Result] = &[ + { + fn InvalidTokenConfig( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw( + data, + ) + .map(BridgeDepositWithdrawErrors::InvalidTokenConfig) + } + InvalidTokenConfig + }, + { + fn InvalidCertificate( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw( + data, + ) + .map(BridgeDepositWithdrawErrors::InvalidCertificate) + } + InvalidCertificate + }, + { + fn InvalidTokenAmount( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw( + data, + ) + .map(BridgeDepositWithdrawErrors::InvalidTokenAmount) + } + InvalidTokenAmount + }, + { + fn ContractMigrated( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw( + data, + ) + .map(BridgeDepositWithdrawErrors::ContractMigrated) + } + ContractMigrated + }, + { + fn SafeERC20FailedOperation( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw( + data, + ) + .map(BridgeDepositWithdrawErrors::SafeERC20FailedOperation) + } + SafeERC20FailedOperation + }, + { + fn AccessControlBadConfirmation( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw( + data, + ) + .map( + BridgeDepositWithdrawErrors::AccessControlBadConfirmation, + ) + } + AccessControlBadConfirmation + }, + { + fn InvalidBridgeContract( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw( + data, + ) + .map(BridgeDepositWithdrawErrors::InvalidBridgeContract) + } + InvalidBridgeContract + }, + { + fn InvalidNonce( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw(data) + .map(BridgeDepositWithdrawErrors::InvalidNonce) + } + InvalidNonce + }, + { + fn InvalidToAddress( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw( + data, + ) + .map(BridgeDepositWithdrawErrors::InvalidToAddress) + } + InvalidToAddress + }, + { + fn ExpectedPause( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw( + data, + ) + .map(BridgeDepositWithdrawErrors::ExpectedPause) + } + ExpectedPause + }, + { + fn RequestAlreadyProcessed( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw( + data, + ) + .map(BridgeDepositWithdrawErrors::RequestAlreadyProcessed) + } + RequestAlreadyProcessed + }, + { + fn MirrorTokenNotFound( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw( + data, + ) + .map(BridgeDepositWithdrawErrors::MirrorTokenNotFound) + } + MirrorTokenNotFound + }, + { + fn DailyLimitExhausted( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw( + data, + ) + .map(BridgeDepositWithdrawErrors::DailyLimitExhausted) + } + DailyLimitExhausted + }, + { + fn InvalidDepositLog( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw( + data, + ) + .map(BridgeDepositWithdrawErrors::InvalidDepositLog) + } + InvalidDepositLog + }, + { + fn EnforcedPause( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw( + data, + ) + .map(BridgeDepositWithdrawErrors::EnforcedPause) + } + EnforcedPause + }, + { + fn AccessControlUnauthorizedAccount( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw( + data, + ) + .map( + BridgeDepositWithdrawErrors::AccessControlUnauthorizedAccount, + ) + } + AccessControlUnauthorizedAccount + }, + ]; + let Ok(idx) = Self::SELECTORS.binary_search(&selector) else { + return Err( + alloy_sol_types::Error::unknown_selector( + ::NAME, + selector, + ), + ); + }; + DECODE_SHIMS[idx](data) + } + #[inline] + #[allow(non_snake_case)] + fn abi_decode_raw_validate( + selector: [u8; 4], + data: &[u8], + ) -> alloy_sol_types::Result { + static DECODE_VALIDATE_SHIMS: &[fn( + &[u8], + ) -> alloy_sol_types::Result] = &[ + { + fn InvalidTokenConfig( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(BridgeDepositWithdrawErrors::InvalidTokenConfig) + } + InvalidTokenConfig + }, + { + fn InvalidCertificate( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(BridgeDepositWithdrawErrors::InvalidCertificate) + } + InvalidCertificate + }, + { + fn InvalidTokenAmount( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(BridgeDepositWithdrawErrors::InvalidTokenAmount) + } + InvalidTokenAmount + }, + { + fn ContractMigrated( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(BridgeDepositWithdrawErrors::ContractMigrated) + } + ContractMigrated + }, + { + fn SafeERC20FailedOperation( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(BridgeDepositWithdrawErrors::SafeERC20FailedOperation) + } + SafeERC20FailedOperation + }, + { + fn AccessControlBadConfirmation( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map( + BridgeDepositWithdrawErrors::AccessControlBadConfirmation, + ) + } + AccessControlBadConfirmation + }, + { + fn InvalidBridgeContract( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(BridgeDepositWithdrawErrors::InvalidBridgeContract) + } + InvalidBridgeContract + }, + { + fn InvalidNonce( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(BridgeDepositWithdrawErrors::InvalidNonce) + } + InvalidNonce + }, + { + fn InvalidToAddress( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(BridgeDepositWithdrawErrors::InvalidToAddress) + } + InvalidToAddress + }, + { + fn ExpectedPause( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(BridgeDepositWithdrawErrors::ExpectedPause) + } + ExpectedPause + }, + { + fn RequestAlreadyProcessed( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(BridgeDepositWithdrawErrors::RequestAlreadyProcessed) + } + RequestAlreadyProcessed + }, + { + fn MirrorTokenNotFound( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(BridgeDepositWithdrawErrors::MirrorTokenNotFound) + } + MirrorTokenNotFound + }, + { + fn DailyLimitExhausted( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(BridgeDepositWithdrawErrors::DailyLimitExhausted) + } + DailyLimitExhausted + }, + { + fn InvalidDepositLog( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(BridgeDepositWithdrawErrors::InvalidDepositLog) + } + InvalidDepositLog + }, + { + fn EnforcedPause( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(BridgeDepositWithdrawErrors::EnforcedPause) + } + EnforcedPause + }, + { + fn AccessControlUnauthorizedAccount( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map( + BridgeDepositWithdrawErrors::AccessControlUnauthorizedAccount, + ) + } + AccessControlUnauthorizedAccount + }, + ]; + let Ok(idx) = Self::SELECTORS.binary_search(&selector) else { + return Err( + alloy_sol_types::Error::unknown_selector( + ::NAME, + selector, + ), + ); + }; + DECODE_VALIDATE_SHIMS[idx](data) + } + #[inline] + fn abi_encoded_size(&self) -> usize { + match self { + Self::AccessControlBadConfirmation(inner) => { + ::abi_encoded_size( + inner, + ) + } + Self::AccessControlUnauthorizedAccount(inner) => { + ::abi_encoded_size( + inner, + ) + } + Self::ContractMigrated(inner) => { + ::abi_encoded_size( + inner, + ) + } + Self::DailyLimitExhausted(inner) => { + ::abi_encoded_size( + inner, + ) + } + Self::EnforcedPause(inner) => { + ::abi_encoded_size(inner) + } + Self::ExpectedPause(inner) => { + ::abi_encoded_size(inner) + } + Self::InvalidBridgeContract(inner) => { + ::abi_encoded_size( + inner, + ) + } + Self::InvalidCertificate(inner) => { + ::abi_encoded_size( + inner, + ) + } + Self::InvalidDepositLog(inner) => { + ::abi_encoded_size( + inner, + ) + } + Self::InvalidNonce(inner) => { + ::abi_encoded_size(inner) + } + Self::InvalidToAddress(inner) => { + ::abi_encoded_size( + inner, + ) + } + Self::InvalidTokenAmount(inner) => { + ::abi_encoded_size( + inner, + ) + } + Self::InvalidTokenConfig(inner) => { + ::abi_encoded_size( + inner, + ) + } + Self::MirrorTokenNotFound(inner) => { + ::abi_encoded_size( + inner, + ) + } + Self::RequestAlreadyProcessed(inner) => { + ::abi_encoded_size( + inner, + ) + } + Self::SafeERC20FailedOperation(inner) => { + ::abi_encoded_size( + inner, + ) + } + } + } + #[inline] + fn abi_encode_raw(&self, out: &mut alloy_sol_types::private::Vec) { + match self { + Self::AccessControlBadConfirmation(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } + Self::AccessControlUnauthorizedAccount(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } + Self::ContractMigrated(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } + Self::DailyLimitExhausted(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } + Self::EnforcedPause(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } + Self::ExpectedPause(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } + Self::InvalidBridgeContract(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } + Self::InvalidCertificate(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } + Self::InvalidDepositLog(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } + Self::InvalidNonce(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } + Self::InvalidToAddress(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } + Self::InvalidTokenAmount(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } + Self::InvalidTokenConfig(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } + Self::MirrorTokenNotFound(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } + Self::RequestAlreadyProcessed(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } + Self::SafeERC20FailedOperation(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } + } + } + } + ///Container for all the [`BridgeDepositWithdraw`](self) events. + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Debug, PartialEq, Eq, Hash)] + pub enum BridgeDepositWithdrawEvents { + #[allow(missing_docs)] + Claim(Claim), + #[allow(missing_docs)] + ClaimNative(ClaimNative), + #[allow(missing_docs)] + Deposit(Deposit), + #[allow(missing_docs)] + DepositNative(DepositNative), + #[allow(missing_docs)] + Paused(Paused), + #[allow(missing_docs)] + RoleAdminChanged(RoleAdminChanged), + #[allow(missing_docs)] + RoleGranted(RoleGranted), + #[allow(missing_docs)] + RoleRevoked(RoleRevoked), + #[allow(missing_docs)] + Unpaused(Unpaused), + } + #[automatically_derived] + impl BridgeDepositWithdrawEvents { + /// All the selectors of this enum. + /// + /// Note that the selectors might not be in the same order as the variants. + /// No guarantees are made about the order of the selectors. + /// + /// Prefer using `SolInterface` methods instead. + pub const SELECTORS: &'static [[u8; 32usize]] = &[ + [ + 5u8, 229u8, 127u8, 166u8, 45u8, 137u8, 6u8, 3u8, 216u8, 89u8, 68u8, + 201u8, 99u8, 221u8, 199u8, 251u8, 231u8, 124u8, 222u8, 94u8, 166u8, + 156u8, 173u8, 112u8, 51u8, 252u8, 111u8, 118u8, 183u8, 221u8, 210u8, + 171u8, + ], + [ + 47u8, 135u8, 136u8, 17u8, 126u8, 126u8, 255u8, 29u8, 130u8, 233u8, 38u8, + 236u8, 121u8, 73u8, 1u8, 209u8, 124u8, 120u8, 2u8, 74u8, 80u8, 39u8, 9u8, + 64u8, 48u8, 69u8, 64u8, 167u8, 51u8, 101u8, 111u8, 13u8, + ], + [ + 64u8, 53u8, 43u8, 99u8, 208u8, 169u8, 201u8, 41u8, 131u8, 252u8, 241u8, + 157u8, 140u8, 63u8, 194u8, 140u8, 160u8, 188u8, 200u8, 250u8, 159u8, + 254u8, 181u8, 190u8, 40u8, 225u8, 74u8, 63u8, 117u8, 138u8, 179u8, 158u8, + ], + [ + 93u8, 185u8, 238u8, 10u8, 73u8, 91u8, 242u8, 230u8, 255u8, 156u8, 145u8, + 167u8, 131u8, 76u8, 27u8, 164u8, 253u8, 210u8, 68u8, 165u8, 232u8, 170u8, + 78u8, 83u8, 123u8, 211u8, 138u8, 234u8, 228u8, 176u8, 115u8, 170u8, + ], + [ + 98u8, 231u8, 140u8, 234u8, 1u8, 190u8, 227u8, 32u8, 205u8, 78u8, 66u8, + 2u8, 112u8, 181u8, 234u8, 116u8, 0u8, 13u8, 17u8, 176u8, 201u8, 247u8, + 71u8, 84u8, 235u8, 219u8, 252u8, 84u8, 75u8, 5u8, 162u8, 88u8, + ], + [ + 145u8, 49u8, 104u8, 218u8, 7u8, 195u8, 247u8, 245u8, 243u8, 197u8, 35u8, + 147u8, 51u8, 22u8, 50u8, 139u8, 13u8, 6u8, 17u8, 182u8, 39u8, 241u8, + 46u8, 177u8, 28u8, 34u8, 202u8, 68u8, 251u8, 177u8, 157u8, 198u8, + ], + [ + 175u8, 63u8, 26u8, 18u8, 52u8, 75u8, 190u8, 170u8, 185u8, 84u8, 212u8, + 18u8, 232u8, 33u8, 214u8, 182u8, 160u8, 109u8, 92u8, 213u8, 210u8, 123u8, + 226u8, 4u8, 53u8, 59u8, 212u8, 234u8, 155u8, 85u8, 165u8, 4u8, + ], + [ + 189u8, 121u8, 184u8, 111u8, 254u8, 10u8, 184u8, 232u8, 119u8, 97u8, 81u8, + 81u8, 66u8, 23u8, 205u8, 124u8, 172u8, 213u8, 44u8, 144u8, 159u8, 102u8, + 71u8, 92u8, 58u8, 244u8, 78u8, 18u8, 159u8, 11u8, 0u8, 255u8, + ], + [ + 246u8, 57u8, 31u8, 92u8, 50u8, 217u8, 198u8, 157u8, 42u8, 71u8, 234u8, + 103u8, 11u8, 68u8, 41u8, 116u8, 181u8, 57u8, 53u8, 209u8, 237u8, 199u8, + 253u8, 100u8, 235u8, 33u8, 224u8, 71u8, 168u8, 57u8, 23u8, 27u8, + ], + ]; + } + #[automatically_derived] + impl alloy_sol_types::SolEventInterface for BridgeDepositWithdrawEvents { + const NAME: &'static str = "BridgeDepositWithdrawEvents"; + const COUNT: usize = 9usize; + fn decode_raw_log( + topics: &[alloy_sol_types::Word], + data: &[u8], + ) -> alloy_sol_types::Result { + match topics.first().copied() { + Some(::SIGNATURE_HASH) => { + ::decode_raw_log(topics, data) + .map(Self::Claim) + } + Some(::SIGNATURE_HASH) => { + ::decode_raw_log( + topics, + data, + ) + .map(Self::ClaimNative) + } + Some(::SIGNATURE_HASH) => { + ::decode_raw_log(topics, data) + .map(Self::Deposit) + } + Some(::SIGNATURE_HASH) => { + ::decode_raw_log( + topics, + data, + ) + .map(Self::DepositNative) + } + Some(::SIGNATURE_HASH) => { + ::decode_raw_log(topics, data) + .map(Self::Paused) + } + Some(::SIGNATURE_HASH) => { + ::decode_raw_log( + topics, + data, + ) + .map(Self::RoleAdminChanged) + } + Some(::SIGNATURE_HASH) => { + ::decode_raw_log( + topics, + data, + ) + .map(Self::RoleGranted) + } + Some(::SIGNATURE_HASH) => { + ::decode_raw_log( + topics, + data, + ) + .map(Self::RoleRevoked) + } + Some(::SIGNATURE_HASH) => { + ::decode_raw_log(topics, data) + .map(Self::Unpaused) + } + _ => { + alloy_sol_types::private::Err(alloy_sol_types::Error::InvalidLog { + name: ::NAME, + log: alloy_sol_types::private::Box::new( + alloy_sol_types::private::LogData::new_unchecked( + topics.to_vec(), + data.to_vec().into(), + ), + ), + }) + } + } + } + } + #[automatically_derived] + impl alloy_sol_types::private::IntoLogData for BridgeDepositWithdrawEvents { + fn to_log_data(&self) -> alloy_sol_types::private::LogData { + match self { + Self::Claim(inner) => { + alloy_sol_types::private::IntoLogData::to_log_data(inner) + } + Self::ClaimNative(inner) => { + alloy_sol_types::private::IntoLogData::to_log_data(inner) + } + Self::Deposit(inner) => { + alloy_sol_types::private::IntoLogData::to_log_data(inner) + } + Self::DepositNative(inner) => { + alloy_sol_types::private::IntoLogData::to_log_data(inner) + } + Self::Paused(inner) => { + alloy_sol_types::private::IntoLogData::to_log_data(inner) + } + Self::RoleAdminChanged(inner) => { + alloy_sol_types::private::IntoLogData::to_log_data(inner) + } + Self::RoleGranted(inner) => { + alloy_sol_types::private::IntoLogData::to_log_data(inner) + } + Self::RoleRevoked(inner) => { + alloy_sol_types::private::IntoLogData::to_log_data(inner) + } + Self::Unpaused(inner) => { + alloy_sol_types::private::IntoLogData::to_log_data(inner) + } + } + } + fn into_log_data(self) -> alloy_sol_types::private::LogData { + match self { + Self::Claim(inner) => { + alloy_sol_types::private::IntoLogData::into_log_data(inner) + } + Self::ClaimNative(inner) => { + alloy_sol_types::private::IntoLogData::into_log_data(inner) + } + Self::Deposit(inner) => { + alloy_sol_types::private::IntoLogData::into_log_data(inner) + } + Self::DepositNative(inner) => { + alloy_sol_types::private::IntoLogData::into_log_data(inner) + } + Self::Paused(inner) => { + alloy_sol_types::private::IntoLogData::into_log_data(inner) + } + Self::RoleAdminChanged(inner) => { + alloy_sol_types::private::IntoLogData::into_log_data(inner) + } + Self::RoleGranted(inner) => { + alloy_sol_types::private::IntoLogData::into_log_data(inner) + } + Self::RoleRevoked(inner) => { + alloy_sol_types::private::IntoLogData::into_log_data(inner) + } + Self::Unpaused(inner) => { + alloy_sol_types::private::IntoLogData::into_log_data(inner) + } + } + } + } + use alloy::contract as alloy_contract; + /**Creates a new wrapper around an on-chain [`BridgeDepositWithdraw`](self) contract instance. + +See the [wrapper's documentation](`BridgeDepositWithdrawInstance`) for more details.*/ + #[inline] + pub const fn new< + P: alloy_contract::private::Provider, + N: alloy_contract::private::Network, + >( + address: alloy_sol_types::private::Address, + provider: P, + ) -> BridgeDepositWithdrawInstance { + BridgeDepositWithdrawInstance::::new(address, provider) + } + /**A [`BridgeDepositWithdraw`](self) instance. + +Contains type-safe methods for interacting with an on-chain instance of the +[`BridgeDepositWithdraw`](self) contract located at a given `address`, using a given +provider `P`. + +If the contract bytecode is available (see the [`sol!`](alloy_sol_types::sol!) +documentation on how to provide it), the `deploy` and `deploy_builder` methods can +be used to deploy a new instance of the contract. + +See the [module-level documentation](self) for all the available methods.*/ + #[derive(Clone)] + pub struct BridgeDepositWithdrawInstance { + address: alloy_sol_types::private::Address, + provider: P, + _network: ::core::marker::PhantomData, + } + #[automatically_derived] + impl ::core::fmt::Debug for BridgeDepositWithdrawInstance { + #[inline] + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + f.debug_tuple("BridgeDepositWithdrawInstance").field(&self.address).finish() + } + } + /// Instantiation and getters/setters. + #[automatically_derived] + impl< + P: alloy_contract::private::Provider, + N: alloy_contract::private::Network, + > BridgeDepositWithdrawInstance { + /**Creates a new wrapper around an on-chain [`BridgeDepositWithdraw`](self) contract instance. + +See the [wrapper's documentation](`BridgeDepositWithdrawInstance`) for more details.*/ + #[inline] + pub const fn new( + address: alloy_sol_types::private::Address, + provider: P, + ) -> Self { + Self { + address, + provider, + _network: ::core::marker::PhantomData, + } + } + /// Returns a reference to the address. + #[inline] + pub const fn address(&self) -> &alloy_sol_types::private::Address { + &self.address + } + /// Sets the address. + #[inline] + pub fn set_address(&mut self, address: alloy_sol_types::private::Address) { + self.address = address; + } + /// Sets the address and returns `self`. + pub fn at(mut self, address: alloy_sol_types::private::Address) -> Self { + self.set_address(address); + self + } + /// Returns a reference to the provider. + #[inline] + pub const fn provider(&self) -> &P { + &self.provider + } + } + impl BridgeDepositWithdrawInstance<&P, N> { + /// Clones the provider and returns a new instance with the cloned provider. + #[inline] + pub fn with_cloned_provider(self) -> BridgeDepositWithdrawInstance { + BridgeDepositWithdrawInstance { + address: self.address, + provider: ::core::clone::Clone::clone(&self.provider), + _network: ::core::marker::PhantomData, + } + } + } + /// Function calls. + #[automatically_derived] + impl< + P: alloy_contract::private::Provider, + N: alloy_contract::private::Network, + > BridgeDepositWithdrawInstance { + /// Creates a new call builder using this contract instance's provider and address. + /// + /// Note that the call can be any function call, not just those defined in this + /// contract. Prefer using the other methods for building type-safe contract calls. + pub fn call_builder( + &self, + call: &C, + ) -> alloy_contract::SolCallBuilder<&P, C, N> { + alloy_contract::SolCallBuilder::new_sol(&self.provider, &self.address, call) + } + ///Creates a new call builder for the [`DEFAULT_ADMIN_ROLE`] function. + pub fn DEFAULT_ADMIN_ROLE( + &self, + ) -> alloy_contract::SolCallBuilder<&P, DEFAULT_ADMIN_ROLECall, N> { + self.call_builder(&DEFAULT_ADMIN_ROLECall) + } + ///Creates a new call builder for the [`PAUSER_ROLE`] function. + pub fn PAUSER_ROLE( + &self, + ) -> alloy_contract::SolCallBuilder<&P, PAUSER_ROLECall, N> { + self.call_builder(&PAUSER_ROLECall) + } + ///Creates a new call builder for the [`bridgeContract`] function. + pub fn bridgeContract( + &self, + ) -> alloy_contract::SolCallBuilder<&P, bridgeContractCall, N> { + self.call_builder(&bridgeContractCall) + } + ///Creates a new call builder for the [`claim`] function. + pub fn claim( + &self, + certifiedLog: ::RustType, + ) -> alloy_contract::SolCallBuilder<&P, claimCall, N> { + self.call_builder(&claimCall { certifiedLog }) + } + ///Creates a new call builder for the [`claimNative`] function. + pub fn claimNative( + &self, + certifiedLog: ::RustType, + ) -> alloy_contract::SolCallBuilder<&P, claimNativeCall, N> { + self.call_builder(&claimNativeCall { certifiedLog }) + } + ///Creates a new call builder for the [`configureToken`] function. + pub fn configureToken( + &self, + token: alloy::sol_types::private::Address, + limits: ::RustType, + ) -> alloy_contract::SolCallBuilder<&P, configureTokenCall, N> { + self.call_builder( + &configureTokenCall { + token, + limits, + }, + ) + } + ///Creates a new call builder for the [`deposit`] function. + pub fn deposit( + &self, + token: alloy::sol_types::private::Address, + amount: alloy::sol_types::private::primitives::aliases::U256, + to: alloy::sol_types::private::Address, + ) -> alloy_contract::SolCallBuilder<&P, depositCall, N> { + self.call_builder(&depositCall { token, amount, to }) + } + ///Creates a new call builder for the [`depositIndex`] function. + pub fn depositIndex( + &self, + ) -> alloy_contract::SolCallBuilder<&P, depositIndexCall, N> { + self.call_builder(&depositIndexCall) + } + ///Creates a new call builder for the [`depositNative`] function. + pub fn depositNative( + &self, + to: alloy::sol_types::private::Address, + ) -> alloy_contract::SolCallBuilder<&P, depositNativeCall, N> { + self.call_builder(&depositNativeCall { to }) + } + ///Creates a new call builder for the [`getRoleAdmin`] function. + pub fn getRoleAdmin( + &self, + role: alloy::sol_types::private::FixedBytes<32>, + ) -> alloy_contract::SolCallBuilder<&P, getRoleAdminCall, N> { + self.call_builder(&getRoleAdminCall { role }) + } + ///Creates a new call builder for the [`grantRole`] function. + pub fn grantRole( + &self, + role: alloy::sol_types::private::FixedBytes<32>, + account: alloy::sol_types::private::Address, + ) -> alloy_contract::SolCallBuilder<&P, grantRoleCall, N> { + self.call_builder(&grantRoleCall { role, account }) + } + ///Creates a new call builder for the [`hasRole`] function. + pub fn hasRole( + &self, + role: alloy::sol_types::private::FixedBytes<32>, + account: alloy::sol_types::private::Address, + ) -> alloy_contract::SolCallBuilder<&P, hasRoleCall, N> { + self.call_builder(&hasRoleCall { role, account }) + } + ///Creates a new call builder for the [`migrate`] function. + pub fn migrate( + &self, + _newContract: alloy::sol_types::private::Address, + ) -> alloy_contract::SolCallBuilder<&P, migrateCall, N> { + self.call_builder(&migrateCall { _newContract }) + } + ///Creates a new call builder for the [`migratedContract`] function. + pub fn migratedContract( + &self, + ) -> alloy_contract::SolCallBuilder<&P, migratedContractCall, N> { + self.call_builder(&migratedContractCall) + } + ///Creates a new call builder for the [`mirrorTokens`] function. + pub fn mirrorTokens( + &self, + _0: alloy::sol_types::private::Address, + ) -> alloy_contract::SolCallBuilder<&P, mirrorTokensCall, N> { + self.call_builder(&mirrorTokensCall(_0)) + } + ///Creates a new call builder for the [`pause`] function. + pub fn pause(&self) -> alloy_contract::SolCallBuilder<&P, pauseCall, N> { + self.call_builder(&pauseCall) + } + ///Creates a new call builder for the [`paused`] function. + pub fn paused(&self) -> alloy_contract::SolCallBuilder<&P, pausedCall, N> { + self.call_builder(&pausedCall) + } + ///Creates a new call builder for the [`podConfig`] function. + pub fn podConfig(&self) -> alloy_contract::SolCallBuilder<&P, podConfigCall, N> { + self.call_builder(&podConfigCall) + } + ///Creates a new call builder for the [`processedRequests`] function. + pub fn processedRequests( + &self, + _0: alloy::sol_types::private::FixedBytes<32>, + ) -> alloy_contract::SolCallBuilder<&P, processedRequestsCall, N> { + self.call_builder(&processedRequestsCall(_0)) + } + ///Creates a new call builder for the [`renounceRole`] function. + pub fn renounceRole( + &self, + role: alloy::sol_types::private::FixedBytes<32>, + callerConfirmation: alloy::sol_types::private::Address, + ) -> alloy_contract::SolCallBuilder<&P, renounceRoleCall, N> { + self.call_builder( + &renounceRoleCall { + role, + callerConfirmation, + }, + ) + } + ///Creates a new call builder for the [`revokeRole`] function. + pub fn revokeRole( + &self, + role: alloy::sol_types::private::FixedBytes<32>, + account: alloy::sol_types::private::Address, + ) -> alloy_contract::SolCallBuilder<&P, revokeRoleCall, N> { + self.call_builder(&revokeRoleCall { role, account }) + } + ///Creates a new call builder for the [`supportsInterface`] function. + pub fn supportsInterface( + &self, + interfaceId: alloy::sol_types::private::FixedBytes<4>, + ) -> alloy_contract::SolCallBuilder<&P, supportsInterfaceCall, N> { + self.call_builder( + &supportsInterfaceCall { + interfaceId, + }, + ) + } + ///Creates a new call builder for the [`tokenData`] function. + pub fn tokenData( + &self, + _0: alloy::sol_types::private::Address, + ) -> alloy_contract::SolCallBuilder<&P, tokenDataCall, N> { + self.call_builder(&tokenDataCall(_0)) + } + ///Creates a new call builder for the [`unpause`] function. + pub fn unpause(&self) -> alloy_contract::SolCallBuilder<&P, unpauseCall, N> { + self.call_builder(&unpauseCall) + } + ///Creates a new call builder for the [`usedNonces`] function. + pub fn usedNonces( + &self, + _0: alloy::sol_types::private::primitives::aliases::U256, + ) -> alloy_contract::SolCallBuilder<&P, usedNoncesCall, N> { + self.call_builder(&usedNoncesCall(_0)) + } + ///Creates a new call builder for the [`whiteListToken`] function. + pub fn whiteListToken( + &self, + token: alloy::sol_types::private::Address, + mirrorToken: alloy::sol_types::private::Address, + limits: ::RustType, + ) -> alloy_contract::SolCallBuilder<&P, whiteListTokenCall, N> { + self.call_builder( + &whiteListTokenCall { + token, + mirrorToken, + limits, + }, + ) + } + ///Creates a new call builder for the [`whitelistedTokens`] function. + pub fn whitelistedTokens( + &self, + _0: alloy::sol_types::private::primitives::aliases::U256, + ) -> alloy_contract::SolCallBuilder<&P, whitelistedTokensCall, N> { + self.call_builder(&whitelistedTokensCall(_0)) + } + } + /// Event filters. + #[automatically_derived] + impl< + P: alloy_contract::private::Provider, + N: alloy_contract::private::Network, + > BridgeDepositWithdrawInstance { + /// Creates a new event filter using this contract instance's provider and address. + /// + /// Note that the type can be any event, not just those defined in this contract. + /// Prefer using the other methods for building type-safe event filters. + pub fn event_filter( + &self, + ) -> alloy_contract::Event<&P, E, N> { + alloy_contract::Event::new_sol(&self.provider, &self.address) + } + ///Creates a new event filter for the [`Claim`] event. + pub fn Claim_filter(&self) -> alloy_contract::Event<&P, Claim, N> { + self.event_filter::() + } + ///Creates a new event filter for the [`ClaimNative`] event. + pub fn ClaimNative_filter(&self) -> alloy_contract::Event<&P, ClaimNative, N> { + self.event_filter::() + } + ///Creates a new event filter for the [`Deposit`] event. + pub fn Deposit_filter(&self) -> alloy_contract::Event<&P, Deposit, N> { + self.event_filter::() + } + ///Creates a new event filter for the [`DepositNative`] event. + pub fn DepositNative_filter( + &self, + ) -> alloy_contract::Event<&P, DepositNative, N> { + self.event_filter::() + } + ///Creates a new event filter for the [`Paused`] event. + pub fn Paused_filter(&self) -> alloy_contract::Event<&P, Paused, N> { + self.event_filter::() + } + ///Creates a new event filter for the [`RoleAdminChanged`] event. + pub fn RoleAdminChanged_filter( + &self, + ) -> alloy_contract::Event<&P, RoleAdminChanged, N> { + self.event_filter::() + } + ///Creates a new event filter for the [`RoleGranted`] event. + pub fn RoleGranted_filter(&self) -> alloy_contract::Event<&P, RoleGranted, N> { + self.event_filter::() + } + ///Creates a new event filter for the [`RoleRevoked`] event. + pub fn RoleRevoked_filter(&self) -> alloy_contract::Event<&P, RoleRevoked, N> { + self.event_filter::() + } + ///Creates a new event filter for the [`Unpaused`] event. + pub fn Unpaused_filter(&self) -> alloy_contract::Event<&P, Unpaused, N> { + self.event_filter::() + } + } +} diff --git a/protocol/bindings/src/bridge_mint_burn.rs b/protocol/bindings/src/bridge_mint_burn.rs new file mode 100644 index 00000000..46a78328 --- /dev/null +++ b/protocol/bindings/src/bridge_mint_burn.rs @@ -0,0 +1,10361 @@ +///Module containing a contract's types and functions. +/** + +```solidity +library IBridge { + struct TokenLimits { uint256 minAmount; uint256 deposit; uint256 claim; } + struct TokenUsage { uint256 consumed; uint256 lastUpdated; } +} +```*/ +#[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style, + clippy::empty_structs_with_brackets +)] +pub mod IBridge { + use super::*; + use alloy::sol_types as alloy_sol_types; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**```solidity +struct TokenLimits { uint256 minAmount; uint256 deposit; uint256 claim; } +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct TokenLimits { + #[allow(missing_docs)] + pub minAmount: alloy::sol_types::private::primitives::aliases::U256, + #[allow(missing_docs)] + pub deposit: alloy::sol_types::private::primitives::aliases::U256, + #[allow(missing_docs)] + pub claim: alloy::sol_types::private::primitives::aliases::U256, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[doc(hidden)] + type UnderlyingSolTuple<'a> = ( + alloy::sol_types::sol_data::Uint<256>, + alloy::sol_types::sol_data::Uint<256>, + alloy::sol_types::sol_data::Uint<256>, + ); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = ( + alloy::sol_types::private::primitives::aliases::U256, + alloy::sol_types::private::primitives::aliases::U256, + alloy::sol_types::private::primitives::aliases::U256, + ); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: TokenLimits) -> Self { + (value.minAmount, value.deposit, value.claim) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for TokenLimits { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { + minAmount: tuple.0, + deposit: tuple.1, + claim: tuple.2, + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolValue for TokenLimits { + type SolType = Self; + } + #[automatically_derived] + impl alloy_sol_types::private::SolTypeValue for TokenLimits { + #[inline] + fn stv_to_tokens(&self) -> ::Token<'_> { + ( + as alloy_sol_types::SolType>::tokenize(&self.minAmount), + as alloy_sol_types::SolType>::tokenize(&self.deposit), + as alloy_sol_types::SolType>::tokenize(&self.claim), + ) + } + #[inline] + fn stv_abi_encoded_size(&self) -> usize { + if let Some(size) = ::ENCODED_SIZE { + return size; + } + let tuple = as ::core::convert::From>::from(self.clone()); + as alloy_sol_types::SolType>::abi_encoded_size(&tuple) + } + #[inline] + fn stv_eip712_data_word(&self) -> alloy_sol_types::Word { + ::eip712_hash_struct(self) + } + #[inline] + fn stv_abi_encode_packed_to( + &self, + out: &mut alloy_sol_types::private::Vec, + ) { + let tuple = as ::core::convert::From>::from(self.clone()); + as alloy_sol_types::SolType>::abi_encode_packed_to(&tuple, out) + } + #[inline] + fn stv_abi_packed_encoded_size(&self) -> usize { + if let Some(size) = ::PACKED_ENCODED_SIZE { + return size; + } + let tuple = as ::core::convert::From>::from(self.clone()); + as alloy_sol_types::SolType>::abi_packed_encoded_size(&tuple) + } + } + #[automatically_derived] + impl alloy_sol_types::SolType for TokenLimits { + type RustType = Self; + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SOL_NAME: &'static str = ::NAME; + const ENCODED_SIZE: Option = as alloy_sol_types::SolType>::ENCODED_SIZE; + const PACKED_ENCODED_SIZE: Option = as alloy_sol_types::SolType>::PACKED_ENCODED_SIZE; + #[inline] + fn valid_token(token: &Self::Token<'_>) -> bool { + as alloy_sol_types::SolType>::valid_token(token) + } + #[inline] + fn detokenize(token: Self::Token<'_>) -> Self::RustType { + let tuple = as alloy_sol_types::SolType>::detokenize(token); + >>::from(tuple) + } + } + #[automatically_derived] + impl alloy_sol_types::SolStruct for TokenLimits { + const NAME: &'static str = "TokenLimits"; + #[inline] + fn eip712_root_type() -> alloy_sol_types::private::Cow<'static, str> { + alloy_sol_types::private::Cow::Borrowed( + "TokenLimits(uint256 minAmount,uint256 deposit,uint256 claim)", + ) + } + #[inline] + fn eip712_components() -> alloy_sol_types::private::Vec< + alloy_sol_types::private::Cow<'static, str>, + > { + alloy_sol_types::private::Vec::new() + } + #[inline] + fn eip712_encode_type() -> alloy_sol_types::private::Cow<'static, str> { + ::eip712_root_type() + } + #[inline] + fn eip712_encode_data(&self) -> alloy_sol_types::private::Vec { + [ + as alloy_sol_types::SolType>::eip712_data_word(&self.minAmount) + .0, + as alloy_sol_types::SolType>::eip712_data_word(&self.deposit) + .0, + as alloy_sol_types::SolType>::eip712_data_word(&self.claim) + .0, + ] + .concat() + } + } + #[automatically_derived] + impl alloy_sol_types::EventTopic for TokenLimits { + #[inline] + fn topic_preimage_length(rust: &Self::RustType) -> usize { + 0usize + + as alloy_sol_types::EventTopic>::topic_preimage_length( + &rust.minAmount, + ) + + as alloy_sol_types::EventTopic>::topic_preimage_length( + &rust.deposit, + ) + + as alloy_sol_types::EventTopic>::topic_preimage_length(&rust.claim) + } + #[inline] + fn encode_topic_preimage( + rust: &Self::RustType, + out: &mut alloy_sol_types::private::Vec, + ) { + out.reserve( + ::topic_preimage_length(rust), + ); + as alloy_sol_types::EventTopic>::encode_topic_preimage( + &rust.minAmount, + out, + ); + as alloy_sol_types::EventTopic>::encode_topic_preimage( + &rust.deposit, + out, + ); + as alloy_sol_types::EventTopic>::encode_topic_preimage( + &rust.claim, + out, + ); + } + #[inline] + fn encode_topic( + rust: &Self::RustType, + ) -> alloy_sol_types::abi::token::WordToken { + let mut out = alloy_sol_types::private::Vec::new(); + ::encode_topic_preimage( + rust, + &mut out, + ); + alloy_sol_types::abi::token::WordToken( + alloy_sol_types::private::keccak256(out), + ) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**```solidity +struct TokenUsage { uint256 consumed; uint256 lastUpdated; } +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct TokenUsage { + #[allow(missing_docs)] + pub consumed: alloy::sol_types::private::primitives::aliases::U256, + #[allow(missing_docs)] + pub lastUpdated: alloy::sol_types::private::primitives::aliases::U256, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[doc(hidden)] + type UnderlyingSolTuple<'a> = ( + alloy::sol_types::sol_data::Uint<256>, + alloy::sol_types::sol_data::Uint<256>, + ); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = ( + alloy::sol_types::private::primitives::aliases::U256, + alloy::sol_types::private::primitives::aliases::U256, + ); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: TokenUsage) -> Self { + (value.consumed, value.lastUpdated) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for TokenUsage { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { + consumed: tuple.0, + lastUpdated: tuple.1, + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolValue for TokenUsage { + type SolType = Self; + } + #[automatically_derived] + impl alloy_sol_types::private::SolTypeValue for TokenUsage { + #[inline] + fn stv_to_tokens(&self) -> ::Token<'_> { + ( + as alloy_sol_types::SolType>::tokenize(&self.consumed), + as alloy_sol_types::SolType>::tokenize(&self.lastUpdated), + ) + } + #[inline] + fn stv_abi_encoded_size(&self) -> usize { + if let Some(size) = ::ENCODED_SIZE { + return size; + } + let tuple = as ::core::convert::From>::from(self.clone()); + as alloy_sol_types::SolType>::abi_encoded_size(&tuple) + } + #[inline] + fn stv_eip712_data_word(&self) -> alloy_sol_types::Word { + ::eip712_hash_struct(self) + } + #[inline] + fn stv_abi_encode_packed_to( + &self, + out: &mut alloy_sol_types::private::Vec, + ) { + let tuple = as ::core::convert::From>::from(self.clone()); + as alloy_sol_types::SolType>::abi_encode_packed_to(&tuple, out) + } + #[inline] + fn stv_abi_packed_encoded_size(&self) -> usize { + if let Some(size) = ::PACKED_ENCODED_SIZE { + return size; + } + let tuple = as ::core::convert::From>::from(self.clone()); + as alloy_sol_types::SolType>::abi_packed_encoded_size(&tuple) + } + } + #[automatically_derived] + impl alloy_sol_types::SolType for TokenUsage { + type RustType = Self; + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SOL_NAME: &'static str = ::NAME; + const ENCODED_SIZE: Option = as alloy_sol_types::SolType>::ENCODED_SIZE; + const PACKED_ENCODED_SIZE: Option = as alloy_sol_types::SolType>::PACKED_ENCODED_SIZE; + #[inline] + fn valid_token(token: &Self::Token<'_>) -> bool { + as alloy_sol_types::SolType>::valid_token(token) + } + #[inline] + fn detokenize(token: Self::Token<'_>) -> Self::RustType { + let tuple = as alloy_sol_types::SolType>::detokenize(token); + >>::from(tuple) + } + } + #[automatically_derived] + impl alloy_sol_types::SolStruct for TokenUsage { + const NAME: &'static str = "TokenUsage"; + #[inline] + fn eip712_root_type() -> alloy_sol_types::private::Cow<'static, str> { + alloy_sol_types::private::Cow::Borrowed( + "TokenUsage(uint256 consumed,uint256 lastUpdated)", + ) + } + #[inline] + fn eip712_components() -> alloy_sol_types::private::Vec< + alloy_sol_types::private::Cow<'static, str>, + > { + alloy_sol_types::private::Vec::new() + } + #[inline] + fn eip712_encode_type() -> alloy_sol_types::private::Cow<'static, str> { + ::eip712_root_type() + } + #[inline] + fn eip712_encode_data(&self) -> alloy_sol_types::private::Vec { + [ + as alloy_sol_types::SolType>::eip712_data_word(&self.consumed) + .0, + as alloy_sol_types::SolType>::eip712_data_word(&self.lastUpdated) + .0, + ] + .concat() + } + } + #[automatically_derived] + impl alloy_sol_types::EventTopic for TokenUsage { + #[inline] + fn topic_preimage_length(rust: &Self::RustType) -> usize { + 0usize + + as alloy_sol_types::EventTopic>::topic_preimage_length( + &rust.consumed, + ) + + as alloy_sol_types::EventTopic>::topic_preimage_length( + &rust.lastUpdated, + ) + } + #[inline] + fn encode_topic_preimage( + rust: &Self::RustType, + out: &mut alloy_sol_types::private::Vec, + ) { + out.reserve( + ::topic_preimage_length(rust), + ); + as alloy_sol_types::EventTopic>::encode_topic_preimage( + &rust.consumed, + out, + ); + as alloy_sol_types::EventTopic>::encode_topic_preimage( + &rust.lastUpdated, + out, + ); + } + #[inline] + fn encode_topic( + rust: &Self::RustType, + ) -> alloy_sol_types::abi::token::WordToken { + let mut out = alloy_sol_types::private::Vec::new(); + ::encode_topic_preimage( + rust, + &mut out, + ); + alloy_sol_types::abi::token::WordToken( + alloy_sol_types::private::keccak256(out), + ) + } + } + }; + use alloy::contract as alloy_contract; + /**Creates a new wrapper around an on-chain [`IBridge`](self) contract instance. + +See the [wrapper's documentation](`IBridgeInstance`) for more details.*/ + #[inline] + pub const fn new< + P: alloy_contract::private::Provider, + N: alloy_contract::private::Network, + >(address: alloy_sol_types::private::Address, provider: P) -> IBridgeInstance { + IBridgeInstance::::new(address, provider) + } + /**A [`IBridge`](self) instance. + +Contains type-safe methods for interacting with an on-chain instance of the +[`IBridge`](self) contract located at a given `address`, using a given +provider `P`. + +If the contract bytecode is available (see the [`sol!`](alloy_sol_types::sol!) +documentation on how to provide it), the `deploy` and `deploy_builder` methods can +be used to deploy a new instance of the contract. + +See the [module-level documentation](self) for all the available methods.*/ + #[derive(Clone)] + pub struct IBridgeInstance { + address: alloy_sol_types::private::Address, + provider: P, + _network: ::core::marker::PhantomData, + } + #[automatically_derived] + impl ::core::fmt::Debug for IBridgeInstance { + #[inline] + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + f.debug_tuple("IBridgeInstance").field(&self.address).finish() + } + } + /// Instantiation and getters/setters. + #[automatically_derived] + impl< + P: alloy_contract::private::Provider, + N: alloy_contract::private::Network, + > IBridgeInstance { + /**Creates a new wrapper around an on-chain [`IBridge`](self) contract instance. + +See the [wrapper's documentation](`IBridgeInstance`) for more details.*/ + #[inline] + pub const fn new( + address: alloy_sol_types::private::Address, + provider: P, + ) -> Self { + Self { + address, + provider, + _network: ::core::marker::PhantomData, + } + } + /// Returns a reference to the address. + #[inline] + pub const fn address(&self) -> &alloy_sol_types::private::Address { + &self.address + } + /// Sets the address. + #[inline] + pub fn set_address(&mut self, address: alloy_sol_types::private::Address) { + self.address = address; + } + /// Sets the address and returns `self`. + pub fn at(mut self, address: alloy_sol_types::private::Address) -> Self { + self.set_address(address); + self + } + /// Returns a reference to the provider. + #[inline] + pub const fn provider(&self) -> &P { + &self.provider + } + } + impl IBridgeInstance<&P, N> { + /// Clones the provider and returns a new instance with the cloned provider. + #[inline] + pub fn with_cloned_provider(self) -> IBridgeInstance { + IBridgeInstance { + address: self.address, + provider: ::core::clone::Clone::clone(&self.provider), + _network: ::core::marker::PhantomData, + } + } + } + /// Function calls. + #[automatically_derived] + impl< + P: alloy_contract::private::Provider, + N: alloy_contract::private::Network, + > IBridgeInstance { + /// Creates a new call builder using this contract instance's provider and address. + /// + /// Note that the call can be any function call, not just those defined in this + /// contract. Prefer using the other methods for building type-safe contract calls. + pub fn call_builder( + &self, + call: &C, + ) -> alloy_contract::SolCallBuilder<&P, C, N> { + alloy_contract::SolCallBuilder::new_sol(&self.provider, &self.address, call) + } + } + /// Event filters. + #[automatically_derived] + impl< + P: alloy_contract::private::Provider, + N: alloy_contract::private::Network, + > IBridgeInstance { + /// Creates a new event filter using this contract instance's provider and address. + /// + /// Note that the type can be any event, not just those defined in this contract. + /// Prefer using the other methods for building type-safe event filters. + pub fn event_filter( + &self, + ) -> alloy_contract::Event<&P, E, N> { + alloy_contract::Event::new_sol(&self.provider, &self.address) + } + } +} +/** + +Generated by the following Solidity interface... +```solidity +library IBridge { + struct TokenLimits { + uint256 minAmount; + uint256 deposit; + uint256 claim; + } + struct TokenUsage { + uint256 consumed; + uint256 lastUpdated; + } +} + +interface BridgeMintBurn { + error AccessControlBadConfirmation(); + error AccessControlUnauthorizedAccount(address account, bytes32 neededRole); + error BlockNotFinalized(); + error ContractMigrated(); + error DailyLimitExhausted(); + error Empty(); + error EnforcedPause(); + error ExpectedPause(); + error InvalidBridgeContract(); + error InvalidDepositLog(); + error InvalidNonce(); + error InvalidToAddress(); + error InvalidTokenAmount(); + error InvalidTokenConfig(); + error MirrorTokenNotFound(); + error Overflow256(); + error PrecompileCallFailed(); + error RequestAlreadyProcessed(); + + event Claim(uint256 indexed id, address indexed mirrorToken, address indexed token, uint256 amount, address to); + event ClaimNative(uint256 indexed id, uint256 amount, address to); + event Deposit(uint256 indexed id, address indexed token, uint256 amount, address to); + event DepositNative(uint256 indexed id, uint256 amount, address to); + event Paused(address account); + event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole); + event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender); + event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender); + event Unpaused(address account); + + constructor(address _bridgeContract, IBridge.TokenLimits nativeTokenLimits, uint96 _sourceChainId); + + function DEFAULT_ADMIN_ROLE() external view returns (bytes32); + function PAUSER_ROLE() external view returns (bytes32); + function bridgeContract() external view returns (address); + function claim(uint256 id, address token, uint256 blockNumber) external; + function claimNative(uint256 id, uint256 blockNumber) external; + function configureToken(address token, IBridge.TokenLimits memory limits) external; + function createAndWhitelistMirrorToken(string memory tokenName, string memory tokenSymbol, address existingToken, address mirrorToken, uint8 mirrorTokenDecimals, IBridge.TokenLimits memory limits) external returns (address token); + function deposit(address token, uint256 amount, address to) external; + function depositNative(address to) external payable; + function getRoleAdmin(bytes32 role) external view returns (bytes32); + function grantRole(bytes32 role, address account) external; + function hasRole(bytes32 role, address account) external view returns (bool); + function migrate(address _newContract) external; + function migratedContract() external view returns (address); + function mirrorTokens(address) external view returns (address); + function pause() external; + function paused() external view returns (bool); + function processedRequests(bytes32) external view returns (bool); + function renounceRole(bytes32 role, address callerConfirmation) external; + function revokeRole(bytes32 role, address account) external; + function supportsInterface(bytes4 interfaceId) external view returns (bool); + function tokenData(address) external view returns (IBridge.TokenLimits memory limits, IBridge.TokenUsage memory deposit, IBridge.TokenUsage memory claim); + function unpause() external; + function usedNonces(uint256) external view returns (bool); + function whitelistedTokens(uint256) external view returns (address); +} +``` + +...which was generated by the following JSON ABI: +```json +[ + { + "type": "constructor", + "inputs": [ + { + "name": "_bridgeContract", + "type": "address", + "internalType": "address" + }, + { + "name": "nativeTokenLimits", + "type": "tuple", + "internalType": "struct IBridge.TokenLimits", + "components": [ + { + "name": "minAmount", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "deposit", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "claim", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "name": "_sourceChainId", + "type": "uint96", + "internalType": "uint96" + } + ], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "DEFAULT_ADMIN_ROLE", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "bytes32", + "internalType": "bytes32" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "PAUSER_ROLE", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "bytes32", + "internalType": "bytes32" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "bridgeContract", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "claim", + "inputs": [ + { + "name": "id", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "token", + "type": "address", + "internalType": "address" + }, + { + "name": "blockNumber", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "claimNative", + "inputs": [ + { + "name": "id", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "blockNumber", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "configureToken", + "inputs": [ + { + "name": "token", + "type": "address", + "internalType": "address" + }, + { + "name": "limits", + "type": "tuple", + "internalType": "struct IBridge.TokenLimits", + "components": [ + { + "name": "minAmount", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "deposit", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "claim", + "type": "uint256", + "internalType": "uint256" + } + ] + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "createAndWhitelistMirrorToken", + "inputs": [ + { + "name": "tokenName", + "type": "string", + "internalType": "string" + }, + { + "name": "tokenSymbol", + "type": "string", + "internalType": "string" + }, + { + "name": "existingToken", + "type": "address", + "internalType": "address" + }, + { + "name": "mirrorToken", + "type": "address", + "internalType": "address" + }, + { + "name": "mirrorTokenDecimals", + "type": "uint8", + "internalType": "uint8" + }, + { + "name": "limits", + "type": "tuple", + "internalType": "struct IBridge.TokenLimits", + "components": [ + { + "name": "minAmount", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "deposit", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "claim", + "type": "uint256", + "internalType": "uint256" + } + ] + } + ], + "outputs": [ + { + "name": "token", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "deposit", + "inputs": [ + { + "name": "token", + "type": "address", + "internalType": "address" + }, + { + "name": "amount", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "to", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "depositNative", + "inputs": [ + { + "name": "to", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "payable" + }, + { + "type": "function", + "name": "getRoleAdmin", + "inputs": [ + { + "name": "role", + "type": "bytes32", + "internalType": "bytes32" + } + ], + "outputs": [ + { + "name": "", + "type": "bytes32", + "internalType": "bytes32" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "grantRole", + "inputs": [ + { + "name": "role", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "account", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "hasRole", + "inputs": [ + { + "name": "role", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "account", + "type": "address", + "internalType": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "bool", + "internalType": "bool" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "migrate", + "inputs": [ + { + "name": "_newContract", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "migratedContract", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "mirrorTokens", + "inputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "pause", + "inputs": [], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "paused", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "bool", + "internalType": "bool" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "processedRequests", + "inputs": [ + { + "name": "", + "type": "bytes32", + "internalType": "bytes32" + } + ], + "outputs": [ + { + "name": "", + "type": "bool", + "internalType": "bool" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "renounceRole", + "inputs": [ + { + "name": "role", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "callerConfirmation", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "revokeRole", + "inputs": [ + { + "name": "role", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "account", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "supportsInterface", + "inputs": [ + { + "name": "interfaceId", + "type": "bytes4", + "internalType": "bytes4" + } + ], + "outputs": [ + { + "name": "", + "type": "bool", + "internalType": "bool" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "tokenData", + "inputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "outputs": [ + { + "name": "limits", + "type": "tuple", + "internalType": "struct IBridge.TokenLimits", + "components": [ + { + "name": "minAmount", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "deposit", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "claim", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "name": "deposit", + "type": "tuple", + "internalType": "struct IBridge.TokenUsage", + "components": [ + { + "name": "consumed", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "lastUpdated", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "name": "claim", + "type": "tuple", + "internalType": "struct IBridge.TokenUsage", + "components": [ + { + "name": "consumed", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "lastUpdated", + "type": "uint256", + "internalType": "uint256" + } + ] + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "unpause", + "inputs": [], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "usedNonces", + "inputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [ + { + "name": "", + "type": "bool", + "internalType": "bool" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "whitelistedTokens", + "inputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "view" + }, + { + "type": "event", + "name": "Claim", + "inputs": [ + { + "name": "id", + "type": "uint256", + "indexed": true, + "internalType": "uint256" + }, + { + "name": "mirrorToken", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "token", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "amount", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + }, + { + "name": "to", + "type": "address", + "indexed": false, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "ClaimNative", + "inputs": [ + { + "name": "id", + "type": "uint256", + "indexed": true, + "internalType": "uint256" + }, + { + "name": "amount", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + }, + { + "name": "to", + "type": "address", + "indexed": false, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "Deposit", + "inputs": [ + { + "name": "id", + "type": "uint256", + "indexed": true, + "internalType": "uint256" + }, + { + "name": "token", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "amount", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + }, + { + "name": "to", + "type": "address", + "indexed": false, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "DepositNative", + "inputs": [ + { + "name": "id", + "type": "uint256", + "indexed": true, + "internalType": "uint256" + }, + { + "name": "amount", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + }, + { + "name": "to", + "type": "address", + "indexed": false, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "Paused", + "inputs": [ + { + "name": "account", + "type": "address", + "indexed": false, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "RoleAdminChanged", + "inputs": [ + { + "name": "role", + "type": "bytes32", + "indexed": true, + "internalType": "bytes32" + }, + { + "name": "previousAdminRole", + "type": "bytes32", + "indexed": true, + "internalType": "bytes32" + }, + { + "name": "newAdminRole", + "type": "bytes32", + "indexed": true, + "internalType": "bytes32" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "RoleGranted", + "inputs": [ + { + "name": "role", + "type": "bytes32", + "indexed": true, + "internalType": "bytes32" + }, + { + "name": "account", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "sender", + "type": "address", + "indexed": true, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "RoleRevoked", + "inputs": [ + { + "name": "role", + "type": "bytes32", + "indexed": true, + "internalType": "bytes32" + }, + { + "name": "account", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "sender", + "type": "address", + "indexed": true, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "Unpaused", + "inputs": [ + { + "name": "account", + "type": "address", + "indexed": false, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "type": "error", + "name": "AccessControlBadConfirmation", + "inputs": [] + }, + { + "type": "error", + "name": "AccessControlUnauthorizedAccount", + "inputs": [ + { + "name": "account", + "type": "address", + "internalType": "address" + }, + { + "name": "neededRole", + "type": "bytes32", + "internalType": "bytes32" + } + ] + }, + { + "type": "error", + "name": "BlockNotFinalized", + "inputs": [] + }, + { + "type": "error", + "name": "ContractMigrated", + "inputs": [] + }, + { + "type": "error", + "name": "DailyLimitExhausted", + "inputs": [] + }, + { + "type": "error", + "name": "Empty", + "inputs": [] + }, + { + "type": "error", + "name": "EnforcedPause", + "inputs": [] + }, + { + "type": "error", + "name": "ExpectedPause", + "inputs": [] + }, + { + "type": "error", + "name": "InvalidBridgeContract", + "inputs": [] + }, + { + "type": "error", + "name": "InvalidDepositLog", + "inputs": [] + }, + { + "type": "error", + "name": "InvalidNonce", + "inputs": [] + }, + { + "type": "error", + "name": "InvalidToAddress", + "inputs": [] + }, + { + "type": "error", + "name": "InvalidTokenAmount", + "inputs": [] + }, + { + "type": "error", + "name": "InvalidTokenConfig", + "inputs": [] + }, + { + "type": "error", + "name": "MirrorTokenNotFound", + "inputs": [] + }, + { + "type": "error", + "name": "Overflow256", + "inputs": [] + }, + { + "type": "error", + "name": "PrecompileCallFailed", + "inputs": [] + }, + { + "type": "error", + "name": "RequestAlreadyProcessed", + "inputs": [] + } +] +```*/ +#[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style, + clippy::empty_structs_with_brackets +)] +pub mod BridgeMintBurn { + use super::*; + use alloy::sol_types as alloy_sol_types; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Custom error with signature `AccessControlBadConfirmation()` and selector `0x6697b232`. +```solidity +error AccessControlBadConfirmation(); +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct AccessControlBadConfirmation; + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From + for UnderlyingRustTuple<'_> { + fn from(value: AccessControlBadConfirmation) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> + for AccessControlBadConfirmation { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self + } + } + #[automatically_derived] + impl alloy_sol_types::SolError for AccessControlBadConfirmation { + type Parameters<'a> = UnderlyingSolTuple<'a>; + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "AccessControlBadConfirmation()"; + const SELECTOR: [u8; 4] = [102u8, 151u8, 178u8, 50u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + () + } + #[inline] + fn abi_decode_raw_validate(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(Self::new) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Custom error with signature `AccessControlUnauthorizedAccount(address,bytes32)` and selector `0xe2517d3f`. +```solidity +error AccessControlUnauthorizedAccount(address account, bytes32 neededRole); +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct AccessControlUnauthorizedAccount { + #[allow(missing_docs)] + pub account: alloy::sol_types::private::Address, + #[allow(missing_docs)] + pub neededRole: alloy::sol_types::private::FixedBytes<32>, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[doc(hidden)] + type UnderlyingSolTuple<'a> = ( + alloy::sol_types::sol_data::Address, + alloy::sol_types::sol_data::FixedBytes<32>, + ); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = ( + alloy::sol_types::private::Address, + alloy::sol_types::private::FixedBytes<32>, + ); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From + for UnderlyingRustTuple<'_> { + fn from(value: AccessControlUnauthorizedAccount) -> Self { + (value.account, value.neededRole) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> + for AccessControlUnauthorizedAccount { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { + account: tuple.0, + neededRole: tuple.1, + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolError for AccessControlUnauthorizedAccount { + type Parameters<'a> = UnderlyingSolTuple<'a>; + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "AccessControlUnauthorizedAccount(address,bytes32)"; + const SELECTOR: [u8; 4] = [226u8, 81u8, 125u8, 63u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + ( + ::tokenize( + &self.account, + ), + as alloy_sol_types::SolType>::tokenize(&self.neededRole), + ) + } + #[inline] + fn abi_decode_raw_validate(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(Self::new) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Custom error with signature `BlockNotFinalized()` and selector `0x6d77eea2`. +```solidity +error BlockNotFinalized(); +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct BlockNotFinalized; + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: BlockNotFinalized) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for BlockNotFinalized { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self + } + } + #[automatically_derived] + impl alloy_sol_types::SolError for BlockNotFinalized { + type Parameters<'a> = UnderlyingSolTuple<'a>; + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "BlockNotFinalized()"; + const SELECTOR: [u8; 4] = [109u8, 119u8, 238u8, 162u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + () + } + #[inline] + fn abi_decode_raw_validate(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(Self::new) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Custom error with signature `ContractMigrated()` and selector `0x3f4f6896`. +```solidity +error ContractMigrated(); +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct ContractMigrated; + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: ContractMigrated) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for ContractMigrated { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self + } + } + #[automatically_derived] + impl alloy_sol_types::SolError for ContractMigrated { + type Parameters<'a> = UnderlyingSolTuple<'a>; + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "ContractMigrated()"; + const SELECTOR: [u8; 4] = [63u8, 79u8, 104u8, 150u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + () + } + #[inline] + fn abi_decode_raw_validate(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(Self::new) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Custom error with signature `DailyLimitExhausted()` and selector `0xbdc4df72`. +```solidity +error DailyLimitExhausted(); +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct DailyLimitExhausted; + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: DailyLimitExhausted) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for DailyLimitExhausted { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self + } + } + #[automatically_derived] + impl alloy_sol_types::SolError for DailyLimitExhausted { + type Parameters<'a> = UnderlyingSolTuple<'a>; + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "DailyLimitExhausted()"; + const SELECTOR: [u8; 4] = [189u8, 196u8, 223u8, 114u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + () + } + #[inline] + fn abi_decode_raw_validate(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(Self::new) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Custom error with signature `Empty()` and selector `0x3db2a12a`. +```solidity +error Empty(); +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct Empty; + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: Empty) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for Empty { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self + } + } + #[automatically_derived] + impl alloy_sol_types::SolError for Empty { + type Parameters<'a> = UnderlyingSolTuple<'a>; + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "Empty()"; + const SELECTOR: [u8; 4] = [61u8, 178u8, 161u8, 42u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + () + } + #[inline] + fn abi_decode_raw_validate(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(Self::new) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Custom error with signature `EnforcedPause()` and selector `0xd93c0665`. +```solidity +error EnforcedPause(); +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct EnforcedPause; + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: EnforcedPause) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for EnforcedPause { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self + } + } + #[automatically_derived] + impl alloy_sol_types::SolError for EnforcedPause { + type Parameters<'a> = UnderlyingSolTuple<'a>; + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "EnforcedPause()"; + const SELECTOR: [u8; 4] = [217u8, 60u8, 6u8, 101u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + () + } + #[inline] + fn abi_decode_raw_validate(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(Self::new) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Custom error with signature `ExpectedPause()` and selector `0x8dfc202b`. +```solidity +error ExpectedPause(); +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct ExpectedPause; + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: ExpectedPause) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for ExpectedPause { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self + } + } + #[automatically_derived] + impl alloy_sol_types::SolError for ExpectedPause { + type Parameters<'a> = UnderlyingSolTuple<'a>; + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "ExpectedPause()"; + const SELECTOR: [u8; 4] = [141u8, 252u8, 32u8, 43u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + () + } + #[inline] + fn abi_decode_raw_validate(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(Self::new) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Custom error with signature `InvalidBridgeContract()` and selector `0x66da8037`. +```solidity +error InvalidBridgeContract(); +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct InvalidBridgeContract; + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: InvalidBridgeContract) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for InvalidBridgeContract { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self + } + } + #[automatically_derived] + impl alloy_sol_types::SolError for InvalidBridgeContract { + type Parameters<'a> = UnderlyingSolTuple<'a>; + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "InvalidBridgeContract()"; + const SELECTOR: [u8; 4] = [102u8, 218u8, 128u8, 55u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + () + } + #[inline] + fn abi_decode_raw_validate(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(Self::new) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Custom error with signature `InvalidDepositLog()` and selector `0xc12dcbc2`. +```solidity +error InvalidDepositLog(); +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct InvalidDepositLog; + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: InvalidDepositLog) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for InvalidDepositLog { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self + } + } + #[automatically_derived] + impl alloy_sol_types::SolError for InvalidDepositLog { + type Parameters<'a> = UnderlyingSolTuple<'a>; + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "InvalidDepositLog()"; + const SELECTOR: [u8; 4] = [193u8, 45u8, 203u8, 194u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + () + } + #[inline] + fn abi_decode_raw_validate(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(Self::new) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Custom error with signature `InvalidNonce()` and selector `0x756688fe`. +```solidity +error InvalidNonce(); +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct InvalidNonce; + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: InvalidNonce) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for InvalidNonce { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self + } + } + #[automatically_derived] + impl alloy_sol_types::SolError for InvalidNonce { + type Parameters<'a> = UnderlyingSolTuple<'a>; + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "InvalidNonce()"; + const SELECTOR: [u8; 4] = [117u8, 102u8, 136u8, 254u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + () + } + #[inline] + fn abi_decode_raw_validate(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(Self::new) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Custom error with signature `InvalidToAddress()` and selector `0x8aa3a72f`. +```solidity +error InvalidToAddress(); +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct InvalidToAddress; + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: InvalidToAddress) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for InvalidToAddress { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self + } + } + #[automatically_derived] + impl alloy_sol_types::SolError for InvalidToAddress { + type Parameters<'a> = UnderlyingSolTuple<'a>; + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "InvalidToAddress()"; + const SELECTOR: [u8; 4] = [138u8, 163u8, 167u8, 47u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + () + } + #[inline] + fn abi_decode_raw_validate(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(Self::new) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Custom error with signature `InvalidTokenAmount()` and selector `0x21607339`. +```solidity +error InvalidTokenAmount(); +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct InvalidTokenAmount; + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: InvalidTokenAmount) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for InvalidTokenAmount { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self + } + } + #[automatically_derived] + impl alloy_sol_types::SolError for InvalidTokenAmount { + type Parameters<'a> = UnderlyingSolTuple<'a>; + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "InvalidTokenAmount()"; + const SELECTOR: [u8; 4] = [33u8, 96u8, 115u8, 57u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + () + } + #[inline] + fn abi_decode_raw_validate(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(Self::new) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Custom error with signature `InvalidTokenConfig()` and selector `0x07fe7bae`. +```solidity +error InvalidTokenConfig(); +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct InvalidTokenConfig; + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: InvalidTokenConfig) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for InvalidTokenConfig { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self + } + } + #[automatically_derived] + impl alloy_sol_types::SolError for InvalidTokenConfig { + type Parameters<'a> = UnderlyingSolTuple<'a>; + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "InvalidTokenConfig()"; + const SELECTOR: [u8; 4] = [7u8, 254u8, 123u8, 174u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + () + } + #[inline] + fn abi_decode_raw_validate(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(Self::new) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Custom error with signature `MirrorTokenNotFound()` and selector `0xa8ddb64d`. +```solidity +error MirrorTokenNotFound(); +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct MirrorTokenNotFound; + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: MirrorTokenNotFound) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for MirrorTokenNotFound { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self + } + } + #[automatically_derived] + impl alloy_sol_types::SolError for MirrorTokenNotFound { + type Parameters<'a> = UnderlyingSolTuple<'a>; + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "MirrorTokenNotFound()"; + const SELECTOR: [u8; 4] = [168u8, 221u8, 182u8, 77u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + () + } + #[inline] + fn abi_decode_raw_validate(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(Self::new) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Custom error with signature `Overflow256()` and selector `0x1c41481c`. +```solidity +error Overflow256(); +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct Overflow256; + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: Overflow256) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for Overflow256 { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self + } + } + #[automatically_derived] + impl alloy_sol_types::SolError for Overflow256 { + type Parameters<'a> = UnderlyingSolTuple<'a>; + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "Overflow256()"; + const SELECTOR: [u8; 4] = [28u8, 65u8, 72u8, 28u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + () + } + #[inline] + fn abi_decode_raw_validate(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(Self::new) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Custom error with signature `PrecompileCallFailed()` and selector `0xfd23ff64`. +```solidity +error PrecompileCallFailed(); +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct PrecompileCallFailed; + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: PrecompileCallFailed) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for PrecompileCallFailed { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self + } + } + #[automatically_derived] + impl alloy_sol_types::SolError for PrecompileCallFailed { + type Parameters<'a> = UnderlyingSolTuple<'a>; + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "PrecompileCallFailed()"; + const SELECTOR: [u8; 4] = [253u8, 35u8, 255u8, 100u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + () + } + #[inline] + fn abi_decode_raw_validate(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(Self::new) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Custom error with signature `RequestAlreadyProcessed()` and selector `0xa6bc74c4`. +```solidity +error RequestAlreadyProcessed(); +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct RequestAlreadyProcessed; + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: RequestAlreadyProcessed) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for RequestAlreadyProcessed { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self + } + } + #[automatically_derived] + impl alloy_sol_types::SolError for RequestAlreadyProcessed { + type Parameters<'a> = UnderlyingSolTuple<'a>; + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "RequestAlreadyProcessed()"; + const SELECTOR: [u8; 4] = [166u8, 188u8, 116u8, 196u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + () + } + #[inline] + fn abi_decode_raw_validate(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(Self::new) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Event with signature `Claim(uint256,address,address,uint256,address)` and selector `0xaf3f1a12344bbeaab954d412e821d6b6a06d5cd5d27be204353bd4ea9b55a504`. +```solidity +event Claim(uint256 indexed id, address indexed mirrorToken, address indexed token, uint256 amount, address to); +```*/ + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + #[derive(Clone)] + pub struct Claim { + #[allow(missing_docs)] + pub id: alloy::sol_types::private::primitives::aliases::U256, + #[allow(missing_docs)] + pub mirrorToken: alloy::sol_types::private::Address, + #[allow(missing_docs)] + pub token: alloy::sol_types::private::Address, + #[allow(missing_docs)] + pub amount: alloy::sol_types::private::primitives::aliases::U256, + #[allow(missing_docs)] + pub to: alloy::sol_types::private::Address, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[automatically_derived] + impl alloy_sol_types::SolEvent for Claim { + type DataTuple<'a> = ( + alloy::sol_types::sol_data::Uint<256>, + alloy::sol_types::sol_data::Address, + ); + type DataToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + type TopicList = ( + alloy_sol_types::sol_data::FixedBytes<32>, + alloy::sol_types::sol_data::Uint<256>, + alloy::sol_types::sol_data::Address, + alloy::sol_types::sol_data::Address, + ); + const SIGNATURE: &'static str = "Claim(uint256,address,address,uint256,address)"; + const SIGNATURE_HASH: alloy_sol_types::private::B256 = alloy_sol_types::private::B256::new([ + 175u8, 63u8, 26u8, 18u8, 52u8, 75u8, 190u8, 170u8, 185u8, 84u8, 212u8, + 18u8, 232u8, 33u8, 214u8, 182u8, 160u8, 109u8, 92u8, 213u8, 210u8, 123u8, + 226u8, 4u8, 53u8, 59u8, 212u8, 234u8, 155u8, 85u8, 165u8, 4u8, + ]); + const ANONYMOUS: bool = false; + #[allow(unused_variables)] + #[inline] + fn new( + topics: ::RustType, + data: as alloy_sol_types::SolType>::RustType, + ) -> Self { + Self { + id: topics.1, + mirrorToken: topics.2, + token: topics.3, + amount: data.0, + to: data.1, + } + } + #[inline] + fn check_signature( + topics: &::RustType, + ) -> alloy_sol_types::Result<()> { + if topics.0 != Self::SIGNATURE_HASH { + return Err( + alloy_sol_types::Error::invalid_event_signature_hash( + Self::SIGNATURE, + topics.0, + Self::SIGNATURE_HASH, + ), + ); + } + Ok(()) + } + #[inline] + fn tokenize_body(&self) -> Self::DataToken<'_> { + ( + as alloy_sol_types::SolType>::tokenize(&self.amount), + ::tokenize( + &self.to, + ), + ) + } + #[inline] + fn topics(&self) -> ::RustType { + ( + Self::SIGNATURE_HASH.into(), + self.id.clone(), + self.mirrorToken.clone(), + self.token.clone(), + ) + } + #[inline] + fn encode_topics_raw( + &self, + out: &mut [alloy_sol_types::abi::token::WordToken], + ) -> alloy_sol_types::Result<()> { + if out.len() < ::COUNT { + return Err(alloy_sol_types::Error::Overrun); + } + out[0usize] = alloy_sol_types::abi::token::WordToken( + Self::SIGNATURE_HASH, + ); + out[1usize] = as alloy_sol_types::EventTopic>::encode_topic(&self.id); + out[2usize] = ::encode_topic( + &self.mirrorToken, + ); + out[3usize] = ::encode_topic( + &self.token, + ); + Ok(()) + } + } + #[automatically_derived] + impl alloy_sol_types::private::IntoLogData for Claim { + fn to_log_data(&self) -> alloy_sol_types::private::LogData { + From::from(self) + } + fn into_log_data(self) -> alloy_sol_types::private::LogData { + From::from(&self) + } + } + #[automatically_derived] + impl From<&Claim> for alloy_sol_types::private::LogData { + #[inline] + fn from(this: &Claim) -> alloy_sol_types::private::LogData { + alloy_sol_types::SolEvent::encode_log_data(this) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Event with signature `ClaimNative(uint256,uint256,address)` and selector `0x913168da07c3f7f5f3c523933316328b0d0611b627f12eb11c22ca44fbb19dc6`. +```solidity +event ClaimNative(uint256 indexed id, uint256 amount, address to); +```*/ + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + #[derive(Clone)] + pub struct ClaimNative { + #[allow(missing_docs)] + pub id: alloy::sol_types::private::primitives::aliases::U256, + #[allow(missing_docs)] + pub amount: alloy::sol_types::private::primitives::aliases::U256, + #[allow(missing_docs)] + pub to: alloy::sol_types::private::Address, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[automatically_derived] + impl alloy_sol_types::SolEvent for ClaimNative { + type DataTuple<'a> = ( + alloy::sol_types::sol_data::Uint<256>, + alloy::sol_types::sol_data::Address, + ); + type DataToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + type TopicList = ( + alloy_sol_types::sol_data::FixedBytes<32>, + alloy::sol_types::sol_data::Uint<256>, + ); + const SIGNATURE: &'static str = "ClaimNative(uint256,uint256,address)"; + const SIGNATURE_HASH: alloy_sol_types::private::B256 = alloy_sol_types::private::B256::new([ + 145u8, 49u8, 104u8, 218u8, 7u8, 195u8, 247u8, 245u8, 243u8, 197u8, 35u8, + 147u8, 51u8, 22u8, 50u8, 139u8, 13u8, 6u8, 17u8, 182u8, 39u8, 241u8, + 46u8, 177u8, 28u8, 34u8, 202u8, 68u8, 251u8, 177u8, 157u8, 198u8, + ]); + const ANONYMOUS: bool = false; + #[allow(unused_variables)] + #[inline] + fn new( + topics: ::RustType, + data: as alloy_sol_types::SolType>::RustType, + ) -> Self { + Self { + id: topics.1, + amount: data.0, + to: data.1, + } + } + #[inline] + fn check_signature( + topics: &::RustType, + ) -> alloy_sol_types::Result<()> { + if topics.0 != Self::SIGNATURE_HASH { + return Err( + alloy_sol_types::Error::invalid_event_signature_hash( + Self::SIGNATURE, + topics.0, + Self::SIGNATURE_HASH, + ), + ); + } + Ok(()) + } + #[inline] + fn tokenize_body(&self) -> Self::DataToken<'_> { + ( + as alloy_sol_types::SolType>::tokenize(&self.amount), + ::tokenize( + &self.to, + ), + ) + } + #[inline] + fn topics(&self) -> ::RustType { + (Self::SIGNATURE_HASH.into(), self.id.clone()) + } + #[inline] + fn encode_topics_raw( + &self, + out: &mut [alloy_sol_types::abi::token::WordToken], + ) -> alloy_sol_types::Result<()> { + if out.len() < ::COUNT { + return Err(alloy_sol_types::Error::Overrun); + } + out[0usize] = alloy_sol_types::abi::token::WordToken( + Self::SIGNATURE_HASH, + ); + out[1usize] = as alloy_sol_types::EventTopic>::encode_topic(&self.id); + Ok(()) + } + } + #[automatically_derived] + impl alloy_sol_types::private::IntoLogData for ClaimNative { + fn to_log_data(&self) -> alloy_sol_types::private::LogData { + From::from(self) + } + fn into_log_data(self) -> alloy_sol_types::private::LogData { + From::from(&self) + } + } + #[automatically_derived] + impl From<&ClaimNative> for alloy_sol_types::private::LogData { + #[inline] + fn from(this: &ClaimNative) -> alloy_sol_types::private::LogData { + alloy_sol_types::SolEvent::encode_log_data(this) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Event with signature `Deposit(uint256,address,uint256,address)` and selector `0x05e57fa62d890603d85944c963ddc7fbe77cde5ea69cad7033fc6f76b7ddd2ab`. +```solidity +event Deposit(uint256 indexed id, address indexed token, uint256 amount, address to); +```*/ + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + #[derive(Clone)] + pub struct Deposit { + #[allow(missing_docs)] + pub id: alloy::sol_types::private::primitives::aliases::U256, + #[allow(missing_docs)] + pub token: alloy::sol_types::private::Address, + #[allow(missing_docs)] + pub amount: alloy::sol_types::private::primitives::aliases::U256, + #[allow(missing_docs)] + pub to: alloy::sol_types::private::Address, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[automatically_derived] + impl alloy_sol_types::SolEvent for Deposit { + type DataTuple<'a> = ( + alloy::sol_types::sol_data::Uint<256>, + alloy::sol_types::sol_data::Address, + ); + type DataToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + type TopicList = ( + alloy_sol_types::sol_data::FixedBytes<32>, + alloy::sol_types::sol_data::Uint<256>, + alloy::sol_types::sol_data::Address, + ); + const SIGNATURE: &'static str = "Deposit(uint256,address,uint256,address)"; + const SIGNATURE_HASH: alloy_sol_types::private::B256 = alloy_sol_types::private::B256::new([ + 5u8, 229u8, 127u8, 166u8, 45u8, 137u8, 6u8, 3u8, 216u8, 89u8, 68u8, + 201u8, 99u8, 221u8, 199u8, 251u8, 231u8, 124u8, 222u8, 94u8, 166u8, + 156u8, 173u8, 112u8, 51u8, 252u8, 111u8, 118u8, 183u8, 221u8, 210u8, + 171u8, + ]); + const ANONYMOUS: bool = false; + #[allow(unused_variables)] + #[inline] + fn new( + topics: ::RustType, + data: as alloy_sol_types::SolType>::RustType, + ) -> Self { + Self { + id: topics.1, + token: topics.2, + amount: data.0, + to: data.1, + } + } + #[inline] + fn check_signature( + topics: &::RustType, + ) -> alloy_sol_types::Result<()> { + if topics.0 != Self::SIGNATURE_HASH { + return Err( + alloy_sol_types::Error::invalid_event_signature_hash( + Self::SIGNATURE, + topics.0, + Self::SIGNATURE_HASH, + ), + ); + } + Ok(()) + } + #[inline] + fn tokenize_body(&self) -> Self::DataToken<'_> { + ( + as alloy_sol_types::SolType>::tokenize(&self.amount), + ::tokenize( + &self.to, + ), + ) + } + #[inline] + fn topics(&self) -> ::RustType { + (Self::SIGNATURE_HASH.into(), self.id.clone(), self.token.clone()) + } + #[inline] + fn encode_topics_raw( + &self, + out: &mut [alloy_sol_types::abi::token::WordToken], + ) -> alloy_sol_types::Result<()> { + if out.len() < ::COUNT { + return Err(alloy_sol_types::Error::Overrun); + } + out[0usize] = alloy_sol_types::abi::token::WordToken( + Self::SIGNATURE_HASH, + ); + out[1usize] = as alloy_sol_types::EventTopic>::encode_topic(&self.id); + out[2usize] = ::encode_topic( + &self.token, + ); + Ok(()) + } + } + #[automatically_derived] + impl alloy_sol_types::private::IntoLogData for Deposit { + fn to_log_data(&self) -> alloy_sol_types::private::LogData { + From::from(self) + } + fn into_log_data(self) -> alloy_sol_types::private::LogData { + From::from(&self) + } + } + #[automatically_derived] + impl From<&Deposit> for alloy_sol_types::private::LogData { + #[inline] + fn from(this: &Deposit) -> alloy_sol_types::private::LogData { + alloy_sol_types::SolEvent::encode_log_data(this) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Event with signature `DepositNative(uint256,uint256,address)` and selector `0x40352b63d0a9c92983fcf19d8c3fc28ca0bcc8fa9ffeb5be28e14a3f758ab39e`. +```solidity +event DepositNative(uint256 indexed id, uint256 amount, address to); +```*/ + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + #[derive(Clone)] + pub struct DepositNative { + #[allow(missing_docs)] + pub id: alloy::sol_types::private::primitives::aliases::U256, + #[allow(missing_docs)] + pub amount: alloy::sol_types::private::primitives::aliases::U256, + #[allow(missing_docs)] + pub to: alloy::sol_types::private::Address, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[automatically_derived] + impl alloy_sol_types::SolEvent for DepositNative { + type DataTuple<'a> = ( + alloy::sol_types::sol_data::Uint<256>, + alloy::sol_types::sol_data::Address, + ); + type DataToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + type TopicList = ( + alloy_sol_types::sol_data::FixedBytes<32>, + alloy::sol_types::sol_data::Uint<256>, + ); + const SIGNATURE: &'static str = "DepositNative(uint256,uint256,address)"; + const SIGNATURE_HASH: alloy_sol_types::private::B256 = alloy_sol_types::private::B256::new([ + 64u8, 53u8, 43u8, 99u8, 208u8, 169u8, 201u8, 41u8, 131u8, 252u8, 241u8, + 157u8, 140u8, 63u8, 194u8, 140u8, 160u8, 188u8, 200u8, 250u8, 159u8, + 254u8, 181u8, 190u8, 40u8, 225u8, 74u8, 63u8, 117u8, 138u8, 179u8, 158u8, + ]); + const ANONYMOUS: bool = false; + #[allow(unused_variables)] + #[inline] + fn new( + topics: ::RustType, + data: as alloy_sol_types::SolType>::RustType, + ) -> Self { + Self { + id: topics.1, + amount: data.0, + to: data.1, + } + } + #[inline] + fn check_signature( + topics: &::RustType, + ) -> alloy_sol_types::Result<()> { + if topics.0 != Self::SIGNATURE_HASH { + return Err( + alloy_sol_types::Error::invalid_event_signature_hash( + Self::SIGNATURE, + topics.0, + Self::SIGNATURE_HASH, + ), + ); + } + Ok(()) + } + #[inline] + fn tokenize_body(&self) -> Self::DataToken<'_> { + ( + as alloy_sol_types::SolType>::tokenize(&self.amount), + ::tokenize( + &self.to, + ), + ) + } + #[inline] + fn topics(&self) -> ::RustType { + (Self::SIGNATURE_HASH.into(), self.id.clone()) + } + #[inline] + fn encode_topics_raw( + &self, + out: &mut [alloy_sol_types::abi::token::WordToken], + ) -> alloy_sol_types::Result<()> { + if out.len() < ::COUNT { + return Err(alloy_sol_types::Error::Overrun); + } + out[0usize] = alloy_sol_types::abi::token::WordToken( + Self::SIGNATURE_HASH, + ); + out[1usize] = as alloy_sol_types::EventTopic>::encode_topic(&self.id); + Ok(()) + } + } + #[automatically_derived] + impl alloy_sol_types::private::IntoLogData for DepositNative { + fn to_log_data(&self) -> alloy_sol_types::private::LogData { + From::from(self) + } + fn into_log_data(self) -> alloy_sol_types::private::LogData { + From::from(&self) + } + } + #[automatically_derived] + impl From<&DepositNative> for alloy_sol_types::private::LogData { + #[inline] + fn from(this: &DepositNative) -> alloy_sol_types::private::LogData { + alloy_sol_types::SolEvent::encode_log_data(this) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Event with signature `Paused(address)` and selector `0x62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258`. +```solidity +event Paused(address account); +```*/ + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + #[derive(Clone)] + pub struct Paused { + #[allow(missing_docs)] + pub account: alloy::sol_types::private::Address, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[automatically_derived] + impl alloy_sol_types::SolEvent for Paused { + type DataTuple<'a> = (alloy::sol_types::sol_data::Address,); + type DataToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + type TopicList = (alloy_sol_types::sol_data::FixedBytes<32>,); + const SIGNATURE: &'static str = "Paused(address)"; + const SIGNATURE_HASH: alloy_sol_types::private::B256 = alloy_sol_types::private::B256::new([ + 98u8, 231u8, 140u8, 234u8, 1u8, 190u8, 227u8, 32u8, 205u8, 78u8, 66u8, + 2u8, 112u8, 181u8, 234u8, 116u8, 0u8, 13u8, 17u8, 176u8, 201u8, 247u8, + 71u8, 84u8, 235u8, 219u8, 252u8, 84u8, 75u8, 5u8, 162u8, 88u8, + ]); + const ANONYMOUS: bool = false; + #[allow(unused_variables)] + #[inline] + fn new( + topics: ::RustType, + data: as alloy_sol_types::SolType>::RustType, + ) -> Self { + Self { account: data.0 } + } + #[inline] + fn check_signature( + topics: &::RustType, + ) -> alloy_sol_types::Result<()> { + if topics.0 != Self::SIGNATURE_HASH { + return Err( + alloy_sol_types::Error::invalid_event_signature_hash( + Self::SIGNATURE, + topics.0, + Self::SIGNATURE_HASH, + ), + ); + } + Ok(()) + } + #[inline] + fn tokenize_body(&self) -> Self::DataToken<'_> { + ( + ::tokenize( + &self.account, + ), + ) + } + #[inline] + fn topics(&self) -> ::RustType { + (Self::SIGNATURE_HASH.into(),) + } + #[inline] + fn encode_topics_raw( + &self, + out: &mut [alloy_sol_types::abi::token::WordToken], + ) -> alloy_sol_types::Result<()> { + if out.len() < ::COUNT { + return Err(alloy_sol_types::Error::Overrun); + } + out[0usize] = alloy_sol_types::abi::token::WordToken( + Self::SIGNATURE_HASH, + ); + Ok(()) + } + } + #[automatically_derived] + impl alloy_sol_types::private::IntoLogData for Paused { + fn to_log_data(&self) -> alloy_sol_types::private::LogData { + From::from(self) + } + fn into_log_data(self) -> alloy_sol_types::private::LogData { + From::from(&self) + } + } + #[automatically_derived] + impl From<&Paused> for alloy_sol_types::private::LogData { + #[inline] + fn from(this: &Paused) -> alloy_sol_types::private::LogData { + alloy_sol_types::SolEvent::encode_log_data(this) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Event with signature `RoleAdminChanged(bytes32,bytes32,bytes32)` and selector `0xbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff`. +```solidity +event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole); +```*/ + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + #[derive(Clone)] + pub struct RoleAdminChanged { + #[allow(missing_docs)] + pub role: alloy::sol_types::private::FixedBytes<32>, + #[allow(missing_docs)] + pub previousAdminRole: alloy::sol_types::private::FixedBytes<32>, + #[allow(missing_docs)] + pub newAdminRole: alloy::sol_types::private::FixedBytes<32>, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[automatically_derived] + impl alloy_sol_types::SolEvent for RoleAdminChanged { + type DataTuple<'a> = (); + type DataToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + type TopicList = ( + alloy_sol_types::sol_data::FixedBytes<32>, + alloy::sol_types::sol_data::FixedBytes<32>, + alloy::sol_types::sol_data::FixedBytes<32>, + alloy::sol_types::sol_data::FixedBytes<32>, + ); + const SIGNATURE: &'static str = "RoleAdminChanged(bytes32,bytes32,bytes32)"; + const SIGNATURE_HASH: alloy_sol_types::private::B256 = alloy_sol_types::private::B256::new([ + 189u8, 121u8, 184u8, 111u8, 254u8, 10u8, 184u8, 232u8, 119u8, 97u8, 81u8, + 81u8, 66u8, 23u8, 205u8, 124u8, 172u8, 213u8, 44u8, 144u8, 159u8, 102u8, + 71u8, 92u8, 58u8, 244u8, 78u8, 18u8, 159u8, 11u8, 0u8, 255u8, + ]); + const ANONYMOUS: bool = false; + #[allow(unused_variables)] + #[inline] + fn new( + topics: ::RustType, + data: as alloy_sol_types::SolType>::RustType, + ) -> Self { + Self { + role: topics.1, + previousAdminRole: topics.2, + newAdminRole: topics.3, + } + } + #[inline] + fn check_signature( + topics: &::RustType, + ) -> alloy_sol_types::Result<()> { + if topics.0 != Self::SIGNATURE_HASH { + return Err( + alloy_sol_types::Error::invalid_event_signature_hash( + Self::SIGNATURE, + topics.0, + Self::SIGNATURE_HASH, + ), + ); + } + Ok(()) + } + #[inline] + fn tokenize_body(&self) -> Self::DataToken<'_> { + () + } + #[inline] + fn topics(&self) -> ::RustType { + ( + Self::SIGNATURE_HASH.into(), + self.role.clone(), + self.previousAdminRole.clone(), + self.newAdminRole.clone(), + ) + } + #[inline] + fn encode_topics_raw( + &self, + out: &mut [alloy_sol_types::abi::token::WordToken], + ) -> alloy_sol_types::Result<()> { + if out.len() < ::COUNT { + return Err(alloy_sol_types::Error::Overrun); + } + out[0usize] = alloy_sol_types::abi::token::WordToken( + Self::SIGNATURE_HASH, + ); + out[1usize] = as alloy_sol_types::EventTopic>::encode_topic(&self.role); + out[2usize] = as alloy_sol_types::EventTopic>::encode_topic(&self.previousAdminRole); + out[3usize] = as alloy_sol_types::EventTopic>::encode_topic(&self.newAdminRole); + Ok(()) + } + } + #[automatically_derived] + impl alloy_sol_types::private::IntoLogData for RoleAdminChanged { + fn to_log_data(&self) -> alloy_sol_types::private::LogData { + From::from(self) + } + fn into_log_data(self) -> alloy_sol_types::private::LogData { + From::from(&self) + } + } + #[automatically_derived] + impl From<&RoleAdminChanged> for alloy_sol_types::private::LogData { + #[inline] + fn from(this: &RoleAdminChanged) -> alloy_sol_types::private::LogData { + alloy_sol_types::SolEvent::encode_log_data(this) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Event with signature `RoleGranted(bytes32,address,address)` and selector `0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d`. +```solidity +event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender); +```*/ + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + #[derive(Clone)] + pub struct RoleGranted { + #[allow(missing_docs)] + pub role: alloy::sol_types::private::FixedBytes<32>, + #[allow(missing_docs)] + pub account: alloy::sol_types::private::Address, + #[allow(missing_docs)] + pub sender: alloy::sol_types::private::Address, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[automatically_derived] + impl alloy_sol_types::SolEvent for RoleGranted { + type DataTuple<'a> = (); + type DataToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + type TopicList = ( + alloy_sol_types::sol_data::FixedBytes<32>, + alloy::sol_types::sol_data::FixedBytes<32>, + alloy::sol_types::sol_data::Address, + alloy::sol_types::sol_data::Address, + ); + const SIGNATURE: &'static str = "RoleGranted(bytes32,address,address)"; + const SIGNATURE_HASH: alloy_sol_types::private::B256 = alloy_sol_types::private::B256::new([ + 47u8, 135u8, 136u8, 17u8, 126u8, 126u8, 255u8, 29u8, 130u8, 233u8, 38u8, + 236u8, 121u8, 73u8, 1u8, 209u8, 124u8, 120u8, 2u8, 74u8, 80u8, 39u8, 9u8, + 64u8, 48u8, 69u8, 64u8, 167u8, 51u8, 101u8, 111u8, 13u8, + ]); + const ANONYMOUS: bool = false; + #[allow(unused_variables)] + #[inline] + fn new( + topics: ::RustType, + data: as alloy_sol_types::SolType>::RustType, + ) -> Self { + Self { + role: topics.1, + account: topics.2, + sender: topics.3, + } + } + #[inline] + fn check_signature( + topics: &::RustType, + ) -> alloy_sol_types::Result<()> { + if topics.0 != Self::SIGNATURE_HASH { + return Err( + alloy_sol_types::Error::invalid_event_signature_hash( + Self::SIGNATURE, + topics.0, + Self::SIGNATURE_HASH, + ), + ); + } + Ok(()) + } + #[inline] + fn tokenize_body(&self) -> Self::DataToken<'_> { + () + } + #[inline] + fn topics(&self) -> ::RustType { + ( + Self::SIGNATURE_HASH.into(), + self.role.clone(), + self.account.clone(), + self.sender.clone(), + ) + } + #[inline] + fn encode_topics_raw( + &self, + out: &mut [alloy_sol_types::abi::token::WordToken], + ) -> alloy_sol_types::Result<()> { + if out.len() < ::COUNT { + return Err(alloy_sol_types::Error::Overrun); + } + out[0usize] = alloy_sol_types::abi::token::WordToken( + Self::SIGNATURE_HASH, + ); + out[1usize] = as alloy_sol_types::EventTopic>::encode_topic(&self.role); + out[2usize] = ::encode_topic( + &self.account, + ); + out[3usize] = ::encode_topic( + &self.sender, + ); + Ok(()) + } + } + #[automatically_derived] + impl alloy_sol_types::private::IntoLogData for RoleGranted { + fn to_log_data(&self) -> alloy_sol_types::private::LogData { + From::from(self) + } + fn into_log_data(self) -> alloy_sol_types::private::LogData { + From::from(&self) + } + } + #[automatically_derived] + impl From<&RoleGranted> for alloy_sol_types::private::LogData { + #[inline] + fn from(this: &RoleGranted) -> alloy_sol_types::private::LogData { + alloy_sol_types::SolEvent::encode_log_data(this) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Event with signature `RoleRevoked(bytes32,address,address)` and selector `0xf6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b`. +```solidity +event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender); +```*/ + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + #[derive(Clone)] + pub struct RoleRevoked { + #[allow(missing_docs)] + pub role: alloy::sol_types::private::FixedBytes<32>, + #[allow(missing_docs)] + pub account: alloy::sol_types::private::Address, + #[allow(missing_docs)] + pub sender: alloy::sol_types::private::Address, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[automatically_derived] + impl alloy_sol_types::SolEvent for RoleRevoked { + type DataTuple<'a> = (); + type DataToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + type TopicList = ( + alloy_sol_types::sol_data::FixedBytes<32>, + alloy::sol_types::sol_data::FixedBytes<32>, + alloy::sol_types::sol_data::Address, + alloy::sol_types::sol_data::Address, + ); + const SIGNATURE: &'static str = "RoleRevoked(bytes32,address,address)"; + const SIGNATURE_HASH: alloy_sol_types::private::B256 = alloy_sol_types::private::B256::new([ + 246u8, 57u8, 31u8, 92u8, 50u8, 217u8, 198u8, 157u8, 42u8, 71u8, 234u8, + 103u8, 11u8, 68u8, 41u8, 116u8, 181u8, 57u8, 53u8, 209u8, 237u8, 199u8, + 253u8, 100u8, 235u8, 33u8, 224u8, 71u8, 168u8, 57u8, 23u8, 27u8, + ]); + const ANONYMOUS: bool = false; + #[allow(unused_variables)] + #[inline] + fn new( + topics: ::RustType, + data: as alloy_sol_types::SolType>::RustType, + ) -> Self { + Self { + role: topics.1, + account: topics.2, + sender: topics.3, + } + } + #[inline] + fn check_signature( + topics: &::RustType, + ) -> alloy_sol_types::Result<()> { + if topics.0 != Self::SIGNATURE_HASH { + return Err( + alloy_sol_types::Error::invalid_event_signature_hash( + Self::SIGNATURE, + topics.0, + Self::SIGNATURE_HASH, + ), + ); + } + Ok(()) + } + #[inline] + fn tokenize_body(&self) -> Self::DataToken<'_> { + () + } + #[inline] + fn topics(&self) -> ::RustType { + ( + Self::SIGNATURE_HASH.into(), + self.role.clone(), + self.account.clone(), + self.sender.clone(), + ) + } + #[inline] + fn encode_topics_raw( + &self, + out: &mut [alloy_sol_types::abi::token::WordToken], + ) -> alloy_sol_types::Result<()> { + if out.len() < ::COUNT { + return Err(alloy_sol_types::Error::Overrun); + } + out[0usize] = alloy_sol_types::abi::token::WordToken( + Self::SIGNATURE_HASH, + ); + out[1usize] = as alloy_sol_types::EventTopic>::encode_topic(&self.role); + out[2usize] = ::encode_topic( + &self.account, + ); + out[3usize] = ::encode_topic( + &self.sender, + ); + Ok(()) + } + } + #[automatically_derived] + impl alloy_sol_types::private::IntoLogData for RoleRevoked { + fn to_log_data(&self) -> alloy_sol_types::private::LogData { + From::from(self) + } + fn into_log_data(self) -> alloy_sol_types::private::LogData { + From::from(&self) + } + } + #[automatically_derived] + impl From<&RoleRevoked> for alloy_sol_types::private::LogData { + #[inline] + fn from(this: &RoleRevoked) -> alloy_sol_types::private::LogData { + alloy_sol_types::SolEvent::encode_log_data(this) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Event with signature `Unpaused(address)` and selector `0x5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa`. +```solidity +event Unpaused(address account); +```*/ + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + #[derive(Clone)] + pub struct Unpaused { + #[allow(missing_docs)] + pub account: alloy::sol_types::private::Address, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[automatically_derived] + impl alloy_sol_types::SolEvent for Unpaused { + type DataTuple<'a> = (alloy::sol_types::sol_data::Address,); + type DataToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + type TopicList = (alloy_sol_types::sol_data::FixedBytes<32>,); + const SIGNATURE: &'static str = "Unpaused(address)"; + const SIGNATURE_HASH: alloy_sol_types::private::B256 = alloy_sol_types::private::B256::new([ + 93u8, 185u8, 238u8, 10u8, 73u8, 91u8, 242u8, 230u8, 255u8, 156u8, 145u8, + 167u8, 131u8, 76u8, 27u8, 164u8, 253u8, 210u8, 68u8, 165u8, 232u8, 170u8, + 78u8, 83u8, 123u8, 211u8, 138u8, 234u8, 228u8, 176u8, 115u8, 170u8, + ]); + const ANONYMOUS: bool = false; + #[allow(unused_variables)] + #[inline] + fn new( + topics: ::RustType, + data: as alloy_sol_types::SolType>::RustType, + ) -> Self { + Self { account: data.0 } + } + #[inline] + fn check_signature( + topics: &::RustType, + ) -> alloy_sol_types::Result<()> { + if topics.0 != Self::SIGNATURE_HASH { + return Err( + alloy_sol_types::Error::invalid_event_signature_hash( + Self::SIGNATURE, + topics.0, + Self::SIGNATURE_HASH, + ), + ); + } + Ok(()) + } + #[inline] + fn tokenize_body(&self) -> Self::DataToken<'_> { + ( + ::tokenize( + &self.account, + ), + ) + } + #[inline] + fn topics(&self) -> ::RustType { + (Self::SIGNATURE_HASH.into(),) + } + #[inline] + fn encode_topics_raw( + &self, + out: &mut [alloy_sol_types::abi::token::WordToken], + ) -> alloy_sol_types::Result<()> { + if out.len() < ::COUNT { + return Err(alloy_sol_types::Error::Overrun); + } + out[0usize] = alloy_sol_types::abi::token::WordToken( + Self::SIGNATURE_HASH, + ); + Ok(()) + } + } + #[automatically_derived] + impl alloy_sol_types::private::IntoLogData for Unpaused { + fn to_log_data(&self) -> alloy_sol_types::private::LogData { + From::from(self) + } + fn into_log_data(self) -> alloy_sol_types::private::LogData { + From::from(&self) + } + } + #[automatically_derived] + impl From<&Unpaused> for alloy_sol_types::private::LogData { + #[inline] + fn from(this: &Unpaused) -> alloy_sol_types::private::LogData { + alloy_sol_types::SolEvent::encode_log_data(this) + } + } + }; + /**Constructor`. +```solidity +constructor(address _bridgeContract, IBridge.TokenLimits nativeTokenLimits, uint96 _sourceChainId); +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct constructorCall { + #[allow(missing_docs)] + pub _bridgeContract: alloy::sol_types::private::Address, + #[allow(missing_docs)] + pub nativeTokenLimits: ::RustType, + #[allow(missing_docs)] + pub _sourceChainId: alloy::sol_types::private::primitives::aliases::U96, + } + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = ( + alloy::sol_types::sol_data::Address, + IBridge::TokenLimits, + alloy::sol_types::sol_data::Uint<96>, + ); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = ( + alloy::sol_types::private::Address, + ::RustType, + alloy::sol_types::private::primitives::aliases::U96, + ); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: constructorCall) -> Self { + ( + value._bridgeContract, + value.nativeTokenLimits, + value._sourceChainId, + ) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for constructorCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { + _bridgeContract: tuple.0, + nativeTokenLimits: tuple.1, + _sourceChainId: tuple.2, + } + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolConstructor for constructorCall { + type Parameters<'a> = ( + alloy::sol_types::sol_data::Address, + IBridge::TokenLimits, + alloy::sol_types::sol_data::Uint<96>, + ); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + ( + ::tokenize( + &self._bridgeContract, + ), + ::tokenize( + &self.nativeTokenLimits, + ), + as alloy_sol_types::SolType>::tokenize(&self._sourceChainId), + ) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Function with signature `DEFAULT_ADMIN_ROLE()` and selector `0xa217fddf`. +```solidity +function DEFAULT_ADMIN_ROLE() external view returns (bytes32); +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct DEFAULT_ADMIN_ROLECall; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + ///Container type for the return parameters of the [`DEFAULT_ADMIN_ROLE()`](DEFAULT_ADMIN_ROLECall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct DEFAULT_ADMIN_ROLEReturn { + #[allow(missing_docs)] + pub _0: alloy::sol_types::private::FixedBytes<32>, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From + for UnderlyingRustTuple<'_> { + fn from(value: DEFAULT_ADMIN_ROLECall) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> + for DEFAULT_ADMIN_ROLECall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self + } + } + } + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (alloy::sol_types::sol_data::FixedBytes<32>,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (alloy::sol_types::private::FixedBytes<32>,); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From + for UnderlyingRustTuple<'_> { + fn from(value: DEFAULT_ADMIN_ROLEReturn) -> Self { + (value._0,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> + for DEFAULT_ADMIN_ROLEReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { _0: tuple.0 } + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for DEFAULT_ADMIN_ROLECall { + type Parameters<'a> = (); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = alloy::sol_types::private::FixedBytes<32>; + type ReturnTuple<'a> = (alloy::sol_types::sol_data::FixedBytes<32>,); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "DEFAULT_ADMIN_ROLE()"; + const SELECTOR: [u8; 4] = [162u8, 23u8, 253u8, 223u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + () + } + #[inline] + fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> { + ( + as alloy_sol_types::SolType>::tokenize(ret), + ) + } + #[inline] + fn abi_decode_returns(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data) + .map(|r| { + let r: DEFAULT_ADMIN_ROLEReturn = r.into(); + r._0 + }) + } + #[inline] + fn abi_decode_returns_validate( + data: &[u8], + ) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(|r| { + let r: DEFAULT_ADMIN_ROLEReturn = r.into(); + r._0 + }) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Function with signature `PAUSER_ROLE()` and selector `0xe63ab1e9`. +```solidity +function PAUSER_ROLE() external view returns (bytes32); +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct PAUSER_ROLECall; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + ///Container type for the return parameters of the [`PAUSER_ROLE()`](PAUSER_ROLECall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct PAUSER_ROLEReturn { + #[allow(missing_docs)] + pub _0: alloy::sol_types::private::FixedBytes<32>, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: PAUSER_ROLECall) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for PAUSER_ROLECall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self + } + } + } + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (alloy::sol_types::sol_data::FixedBytes<32>,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (alloy::sol_types::private::FixedBytes<32>,); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: PAUSER_ROLEReturn) -> Self { + (value._0,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for PAUSER_ROLEReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { _0: tuple.0 } + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for PAUSER_ROLECall { + type Parameters<'a> = (); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = alloy::sol_types::private::FixedBytes<32>; + type ReturnTuple<'a> = (alloy::sol_types::sol_data::FixedBytes<32>,); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "PAUSER_ROLE()"; + const SELECTOR: [u8; 4] = [230u8, 58u8, 177u8, 233u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + () + } + #[inline] + fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> { + ( + as alloy_sol_types::SolType>::tokenize(ret), + ) + } + #[inline] + fn abi_decode_returns(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data) + .map(|r| { + let r: PAUSER_ROLEReturn = r.into(); + r._0 + }) + } + #[inline] + fn abi_decode_returns_validate( + data: &[u8], + ) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(|r| { + let r: PAUSER_ROLEReturn = r.into(); + r._0 + }) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Function with signature `bridgeContract()` and selector `0xcd596583`. +```solidity +function bridgeContract() external view returns (address); +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct bridgeContractCall; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + ///Container type for the return parameters of the [`bridgeContract()`](bridgeContractCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct bridgeContractReturn { + #[allow(missing_docs)] + pub _0: alloy::sol_types::private::Address, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: bridgeContractCall) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for bridgeContractCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self + } + } + } + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (alloy::sol_types::sol_data::Address,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (alloy::sol_types::private::Address,); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From + for UnderlyingRustTuple<'_> { + fn from(value: bridgeContractReturn) -> Self { + (value._0,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> + for bridgeContractReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { _0: tuple.0 } + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for bridgeContractCall { + type Parameters<'a> = (); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = alloy::sol_types::private::Address; + type ReturnTuple<'a> = (alloy::sol_types::sol_data::Address,); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "bridgeContract()"; + const SELECTOR: [u8; 4] = [205u8, 89u8, 101u8, 131u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + () + } + #[inline] + fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> { + ( + ::tokenize( + ret, + ), + ) + } + #[inline] + fn abi_decode_returns(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data) + .map(|r| { + let r: bridgeContractReturn = r.into(); + r._0 + }) + } + #[inline] + fn abi_decode_returns_validate( + data: &[u8], + ) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(|r| { + let r: bridgeContractReturn = r.into(); + r._0 + }) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Function with signature `claim(uint256,address,uint256)` and selector `0x5e737548`. +```solidity +function claim(uint256 id, address token, uint256 blockNumber) external; +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct claimCall { + #[allow(missing_docs)] + pub id: alloy::sol_types::private::primitives::aliases::U256, + #[allow(missing_docs)] + pub token: alloy::sol_types::private::Address, + #[allow(missing_docs)] + pub blockNumber: alloy::sol_types::private::primitives::aliases::U256, + } + ///Container type for the return parameters of the [`claim(uint256,address,uint256)`](claimCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct claimReturn {} + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = ( + alloy::sol_types::sol_data::Uint<256>, + alloy::sol_types::sol_data::Address, + alloy::sol_types::sol_data::Uint<256>, + ); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = ( + alloy::sol_types::private::primitives::aliases::U256, + alloy::sol_types::private::Address, + alloy::sol_types::private::primitives::aliases::U256, + ); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: claimCall) -> Self { + (value.id, value.token, value.blockNumber) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for claimCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { + id: tuple.0, + token: tuple.1, + blockNumber: tuple.2, + } + } + } + } + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: claimReturn) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for claimReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self {} + } + } + } + impl claimReturn { + fn _tokenize( + &self, + ) -> ::ReturnToken<'_> { + () + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for claimCall { + type Parameters<'a> = ( + alloy::sol_types::sol_data::Uint<256>, + alloy::sol_types::sol_data::Address, + alloy::sol_types::sol_data::Uint<256>, + ); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = claimReturn; + type ReturnTuple<'a> = (); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "claim(uint256,address,uint256)"; + const SELECTOR: [u8; 4] = [94u8, 115u8, 117u8, 72u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + ( + as alloy_sol_types::SolType>::tokenize(&self.id), + ::tokenize( + &self.token, + ), + as alloy_sol_types::SolType>::tokenize(&self.blockNumber), + ) + } + #[inline] + fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> { + claimReturn::_tokenize(ret) + } + #[inline] + fn abi_decode_returns(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data) + .map(Into::into) + } + #[inline] + fn abi_decode_returns_validate( + data: &[u8], + ) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(Into::into) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Function with signature `claimNative(uint256,uint256)` and selector `0xac894391`. +```solidity +function claimNative(uint256 id, uint256 blockNumber) external; +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct claimNativeCall { + #[allow(missing_docs)] + pub id: alloy::sol_types::private::primitives::aliases::U256, + #[allow(missing_docs)] + pub blockNumber: alloy::sol_types::private::primitives::aliases::U256, + } + ///Container type for the return parameters of the [`claimNative(uint256,uint256)`](claimNativeCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct claimNativeReturn {} + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = ( + alloy::sol_types::sol_data::Uint<256>, + alloy::sol_types::sol_data::Uint<256>, + ); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = ( + alloy::sol_types::private::primitives::aliases::U256, + alloy::sol_types::private::primitives::aliases::U256, + ); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: claimNativeCall) -> Self { + (value.id, value.blockNumber) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for claimNativeCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { + id: tuple.0, + blockNumber: tuple.1, + } + } + } + } + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: claimNativeReturn) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for claimNativeReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self {} + } + } + } + impl claimNativeReturn { + fn _tokenize( + &self, + ) -> ::ReturnToken<'_> { + () + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for claimNativeCall { + type Parameters<'a> = ( + alloy::sol_types::sol_data::Uint<256>, + alloy::sol_types::sol_data::Uint<256>, + ); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = claimNativeReturn; + type ReturnTuple<'a> = (); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "claimNative(uint256,uint256)"; + const SELECTOR: [u8; 4] = [172u8, 137u8, 67u8, 145u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + ( + as alloy_sol_types::SolType>::tokenize(&self.id), + as alloy_sol_types::SolType>::tokenize(&self.blockNumber), + ) + } + #[inline] + fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> { + claimNativeReturn::_tokenize(ret) + } + #[inline] + fn abi_decode_returns(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data) + .map(Into::into) + } + #[inline] + fn abi_decode_returns_validate( + data: &[u8], + ) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(Into::into) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Function with signature `configureToken(address,(uint256,uint256,uint256))` and selector `0x9267b153`. +```solidity +function configureToken(address token, IBridge.TokenLimits memory limits) external; +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct configureTokenCall { + #[allow(missing_docs)] + pub token: alloy::sol_types::private::Address, + #[allow(missing_docs)] + pub limits: ::RustType, + } + ///Container type for the return parameters of the [`configureToken(address,(uint256,uint256,uint256))`](configureTokenCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct configureTokenReturn {} + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = ( + alloy::sol_types::sol_data::Address, + IBridge::TokenLimits, + ); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = ( + alloy::sol_types::private::Address, + ::RustType, + ); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: configureTokenCall) -> Self { + (value.token, value.limits) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for configureTokenCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { + token: tuple.0, + limits: tuple.1, + } + } + } + } + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From + for UnderlyingRustTuple<'_> { + fn from(value: configureTokenReturn) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> + for configureTokenReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self {} + } + } + } + impl configureTokenReturn { + fn _tokenize( + &self, + ) -> ::ReturnToken<'_> { + () + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for configureTokenCall { + type Parameters<'a> = ( + alloy::sol_types::sol_data::Address, + IBridge::TokenLimits, + ); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = configureTokenReturn; + type ReturnTuple<'a> = (); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "configureToken(address,(uint256,uint256,uint256))"; + const SELECTOR: [u8; 4] = [146u8, 103u8, 177u8, 83u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + ( + ::tokenize( + &self.token, + ), + ::tokenize( + &self.limits, + ), + ) + } + #[inline] + fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> { + configureTokenReturn::_tokenize(ret) + } + #[inline] + fn abi_decode_returns(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data) + .map(Into::into) + } + #[inline] + fn abi_decode_returns_validate( + data: &[u8], + ) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(Into::into) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Function with signature `createAndWhitelistMirrorToken(string,string,address,address,uint8,(uint256,uint256,uint256))` and selector `0xdf6b022b`. +```solidity +function createAndWhitelistMirrorToken(string memory tokenName, string memory tokenSymbol, address existingToken, address mirrorToken, uint8 mirrorTokenDecimals, IBridge.TokenLimits memory limits) external returns (address token); +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct createAndWhitelistMirrorTokenCall { + #[allow(missing_docs)] + pub tokenName: alloy::sol_types::private::String, + #[allow(missing_docs)] + pub tokenSymbol: alloy::sol_types::private::String, + #[allow(missing_docs)] + pub existingToken: alloy::sol_types::private::Address, + #[allow(missing_docs)] + pub mirrorToken: alloy::sol_types::private::Address, + #[allow(missing_docs)] + pub mirrorTokenDecimals: u8, + #[allow(missing_docs)] + pub limits: ::RustType, + } + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + ///Container type for the return parameters of the [`createAndWhitelistMirrorToken(string,string,address,address,uint8,(uint256,uint256,uint256))`](createAndWhitelistMirrorTokenCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct createAndWhitelistMirrorTokenReturn { + #[allow(missing_docs)] + pub token: alloy::sol_types::private::Address, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = ( + alloy::sol_types::sol_data::String, + alloy::sol_types::sol_data::String, + alloy::sol_types::sol_data::Address, + alloy::sol_types::sol_data::Address, + alloy::sol_types::sol_data::Uint<8>, + IBridge::TokenLimits, + ); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = ( + alloy::sol_types::private::String, + alloy::sol_types::private::String, + alloy::sol_types::private::Address, + alloy::sol_types::private::Address, + u8, + ::RustType, + ); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From + for UnderlyingRustTuple<'_> { + fn from(value: createAndWhitelistMirrorTokenCall) -> Self { + ( + value.tokenName, + value.tokenSymbol, + value.existingToken, + value.mirrorToken, + value.mirrorTokenDecimals, + value.limits, + ) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> + for createAndWhitelistMirrorTokenCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { + tokenName: tuple.0, + tokenSymbol: tuple.1, + existingToken: tuple.2, + mirrorToken: tuple.3, + mirrorTokenDecimals: tuple.4, + limits: tuple.5, + } + } + } + } + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (alloy::sol_types::sol_data::Address,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (alloy::sol_types::private::Address,); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From + for UnderlyingRustTuple<'_> { + fn from(value: createAndWhitelistMirrorTokenReturn) -> Self { + (value.token,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> + for createAndWhitelistMirrorTokenReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { token: tuple.0 } + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for createAndWhitelistMirrorTokenCall { + type Parameters<'a> = ( + alloy::sol_types::sol_data::String, + alloy::sol_types::sol_data::String, + alloy::sol_types::sol_data::Address, + alloy::sol_types::sol_data::Address, + alloy::sol_types::sol_data::Uint<8>, + IBridge::TokenLimits, + ); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = alloy::sol_types::private::Address; + type ReturnTuple<'a> = (alloy::sol_types::sol_data::Address,); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "createAndWhitelistMirrorToken(string,string,address,address,uint8,(uint256,uint256,uint256))"; + const SELECTOR: [u8; 4] = [223u8, 107u8, 2u8, 43u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + ( + ::tokenize( + &self.tokenName, + ), + ::tokenize( + &self.tokenSymbol, + ), + ::tokenize( + &self.existingToken, + ), + ::tokenize( + &self.mirrorToken, + ), + as alloy_sol_types::SolType>::tokenize(&self.mirrorTokenDecimals), + ::tokenize( + &self.limits, + ), + ) + } + #[inline] + fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> { + ( + ::tokenize( + ret, + ), + ) + } + #[inline] + fn abi_decode_returns(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data) + .map(|r| { + let r: createAndWhitelistMirrorTokenReturn = r.into(); + r.token + }) + } + #[inline] + fn abi_decode_returns_validate( + data: &[u8], + ) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(|r| { + let r: createAndWhitelistMirrorTokenReturn = r.into(); + r.token + }) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Function with signature `deposit(address,uint256,address)` and selector `0xf45346dc`. +```solidity +function deposit(address token, uint256 amount, address to) external; +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct depositCall { + #[allow(missing_docs)] + pub token: alloy::sol_types::private::Address, + #[allow(missing_docs)] + pub amount: alloy::sol_types::private::primitives::aliases::U256, + #[allow(missing_docs)] + pub to: alloy::sol_types::private::Address, + } + ///Container type for the return parameters of the [`deposit(address,uint256,address)`](depositCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct depositReturn {} + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = ( + alloy::sol_types::sol_data::Address, + alloy::sol_types::sol_data::Uint<256>, + alloy::sol_types::sol_data::Address, + ); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = ( + alloy::sol_types::private::Address, + alloy::sol_types::private::primitives::aliases::U256, + alloy::sol_types::private::Address, + ); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: depositCall) -> Self { + (value.token, value.amount, value.to) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for depositCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { + token: tuple.0, + amount: tuple.1, + to: tuple.2, + } + } + } + } + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: depositReturn) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for depositReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self {} + } + } + } + impl depositReturn { + fn _tokenize( + &self, + ) -> ::ReturnToken<'_> { + () + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for depositCall { + type Parameters<'a> = ( + alloy::sol_types::sol_data::Address, + alloy::sol_types::sol_data::Uint<256>, + alloy::sol_types::sol_data::Address, + ); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = depositReturn; + type ReturnTuple<'a> = (); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "deposit(address,uint256,address)"; + const SELECTOR: [u8; 4] = [244u8, 83u8, 70u8, 220u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + ( + ::tokenize( + &self.token, + ), + as alloy_sol_types::SolType>::tokenize(&self.amount), + ::tokenize( + &self.to, + ), + ) + } + #[inline] + fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> { + depositReturn::_tokenize(ret) + } + #[inline] + fn abi_decode_returns(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data) + .map(Into::into) + } + #[inline] + fn abi_decode_returns_validate( + data: &[u8], + ) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(Into::into) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Function with signature `depositNative(address)` and selector `0x33bb7f91`. +```solidity +function depositNative(address to) external payable; +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct depositNativeCall { + #[allow(missing_docs)] + pub to: alloy::sol_types::private::Address, + } + ///Container type for the return parameters of the [`depositNative(address)`](depositNativeCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct depositNativeReturn {} + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (alloy::sol_types::sol_data::Address,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (alloy::sol_types::private::Address,); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: depositNativeCall) -> Self { + (value.to,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for depositNativeCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { to: tuple.0 } + } + } + } + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: depositNativeReturn) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for depositNativeReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self {} + } + } + } + impl depositNativeReturn { + fn _tokenize( + &self, + ) -> ::ReturnToken<'_> { + () + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for depositNativeCall { + type Parameters<'a> = (alloy::sol_types::sol_data::Address,); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = depositNativeReturn; + type ReturnTuple<'a> = (); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "depositNative(address)"; + const SELECTOR: [u8; 4] = [51u8, 187u8, 127u8, 145u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + ( + ::tokenize( + &self.to, + ), + ) + } + #[inline] + fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> { + depositNativeReturn::_tokenize(ret) + } + #[inline] + fn abi_decode_returns(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data) + .map(Into::into) + } + #[inline] + fn abi_decode_returns_validate( + data: &[u8], + ) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(Into::into) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Function with signature `getRoleAdmin(bytes32)` and selector `0x248a9ca3`. +```solidity +function getRoleAdmin(bytes32 role) external view returns (bytes32); +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct getRoleAdminCall { + #[allow(missing_docs)] + pub role: alloy::sol_types::private::FixedBytes<32>, + } + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + ///Container type for the return parameters of the [`getRoleAdmin(bytes32)`](getRoleAdminCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct getRoleAdminReturn { + #[allow(missing_docs)] + pub _0: alloy::sol_types::private::FixedBytes<32>, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (alloy::sol_types::sol_data::FixedBytes<32>,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (alloy::sol_types::private::FixedBytes<32>,); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: getRoleAdminCall) -> Self { + (value.role,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for getRoleAdminCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { role: tuple.0 } + } + } + } + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (alloy::sol_types::sol_data::FixedBytes<32>,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (alloy::sol_types::private::FixedBytes<32>,); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: getRoleAdminReturn) -> Self { + (value._0,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for getRoleAdminReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { _0: tuple.0 } + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for getRoleAdminCall { + type Parameters<'a> = (alloy::sol_types::sol_data::FixedBytes<32>,); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = alloy::sol_types::private::FixedBytes<32>; + type ReturnTuple<'a> = (alloy::sol_types::sol_data::FixedBytes<32>,); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "getRoleAdmin(bytes32)"; + const SELECTOR: [u8; 4] = [36u8, 138u8, 156u8, 163u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + ( + as alloy_sol_types::SolType>::tokenize(&self.role), + ) + } + #[inline] + fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> { + ( + as alloy_sol_types::SolType>::tokenize(ret), + ) + } + #[inline] + fn abi_decode_returns(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data) + .map(|r| { + let r: getRoleAdminReturn = r.into(); + r._0 + }) + } + #[inline] + fn abi_decode_returns_validate( + data: &[u8], + ) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(|r| { + let r: getRoleAdminReturn = r.into(); + r._0 + }) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Function with signature `grantRole(bytes32,address)` and selector `0x2f2ff15d`. +```solidity +function grantRole(bytes32 role, address account) external; +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct grantRoleCall { + #[allow(missing_docs)] + pub role: alloy::sol_types::private::FixedBytes<32>, + #[allow(missing_docs)] + pub account: alloy::sol_types::private::Address, + } + ///Container type for the return parameters of the [`grantRole(bytes32,address)`](grantRoleCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct grantRoleReturn {} + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = ( + alloy::sol_types::sol_data::FixedBytes<32>, + alloy::sol_types::sol_data::Address, + ); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = ( + alloy::sol_types::private::FixedBytes<32>, + alloy::sol_types::private::Address, + ); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: grantRoleCall) -> Self { + (value.role, value.account) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for grantRoleCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { + role: tuple.0, + account: tuple.1, + } + } + } + } + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: grantRoleReturn) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for grantRoleReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self {} + } + } + } + impl grantRoleReturn { + fn _tokenize( + &self, + ) -> ::ReturnToken<'_> { + () + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for grantRoleCall { + type Parameters<'a> = ( + alloy::sol_types::sol_data::FixedBytes<32>, + alloy::sol_types::sol_data::Address, + ); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = grantRoleReturn; + type ReturnTuple<'a> = (); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "grantRole(bytes32,address)"; + const SELECTOR: [u8; 4] = [47u8, 47u8, 241u8, 93u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + ( + as alloy_sol_types::SolType>::tokenize(&self.role), + ::tokenize( + &self.account, + ), + ) + } + #[inline] + fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> { + grantRoleReturn::_tokenize(ret) + } + #[inline] + fn abi_decode_returns(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data) + .map(Into::into) + } + #[inline] + fn abi_decode_returns_validate( + data: &[u8], + ) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(Into::into) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Function with signature `hasRole(bytes32,address)` and selector `0x91d14854`. +```solidity +function hasRole(bytes32 role, address account) external view returns (bool); +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct hasRoleCall { + #[allow(missing_docs)] + pub role: alloy::sol_types::private::FixedBytes<32>, + #[allow(missing_docs)] + pub account: alloy::sol_types::private::Address, + } + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + ///Container type for the return parameters of the [`hasRole(bytes32,address)`](hasRoleCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct hasRoleReturn { + #[allow(missing_docs)] + pub _0: bool, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = ( + alloy::sol_types::sol_data::FixedBytes<32>, + alloy::sol_types::sol_data::Address, + ); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = ( + alloy::sol_types::private::FixedBytes<32>, + alloy::sol_types::private::Address, + ); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: hasRoleCall) -> Self { + (value.role, value.account) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for hasRoleCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { + role: tuple.0, + account: tuple.1, + } + } + } + } + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (alloy::sol_types::sol_data::Bool,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (bool,); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: hasRoleReturn) -> Self { + (value._0,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for hasRoleReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { _0: tuple.0 } + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for hasRoleCall { + type Parameters<'a> = ( + alloy::sol_types::sol_data::FixedBytes<32>, + alloy::sol_types::sol_data::Address, + ); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = bool; + type ReturnTuple<'a> = (alloy::sol_types::sol_data::Bool,); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "hasRole(bytes32,address)"; + const SELECTOR: [u8; 4] = [145u8, 209u8, 72u8, 84u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + ( + as alloy_sol_types::SolType>::tokenize(&self.role), + ::tokenize( + &self.account, + ), + ) + } + #[inline] + fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> { + ( + ::tokenize( + ret, + ), + ) + } + #[inline] + fn abi_decode_returns(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data) + .map(|r| { + let r: hasRoleReturn = r.into(); + r._0 + }) + } + #[inline] + fn abi_decode_returns_validate( + data: &[u8], + ) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(|r| { + let r: hasRoleReturn = r.into(); + r._0 + }) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Function with signature `migrate(address)` and selector `0xce5494bb`. +```solidity +function migrate(address _newContract) external; +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct migrateCall { + #[allow(missing_docs)] + pub _newContract: alloy::sol_types::private::Address, + } + ///Container type for the return parameters of the [`migrate(address)`](migrateCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct migrateReturn {} + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (alloy::sol_types::sol_data::Address,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (alloy::sol_types::private::Address,); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: migrateCall) -> Self { + (value._newContract,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for migrateCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { _newContract: tuple.0 } + } + } + } + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: migrateReturn) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for migrateReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self {} + } + } + } + impl migrateReturn { + fn _tokenize( + &self, + ) -> ::ReturnToken<'_> { + () + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for migrateCall { + type Parameters<'a> = (alloy::sol_types::sol_data::Address,); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = migrateReturn; + type ReturnTuple<'a> = (); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "migrate(address)"; + const SELECTOR: [u8; 4] = [206u8, 84u8, 148u8, 187u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + ( + ::tokenize( + &self._newContract, + ), + ) + } + #[inline] + fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> { + migrateReturn::_tokenize(ret) + } + #[inline] + fn abi_decode_returns(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data) + .map(Into::into) + } + #[inline] + fn abi_decode_returns_validate( + data: &[u8], + ) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(Into::into) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Function with signature `migratedContract()` and selector `0x7486fa4e`. +```solidity +function migratedContract() external view returns (address); +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct migratedContractCall; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + ///Container type for the return parameters of the [`migratedContract()`](migratedContractCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct migratedContractReturn { + #[allow(missing_docs)] + pub _0: alloy::sol_types::private::Address, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From + for UnderlyingRustTuple<'_> { + fn from(value: migratedContractCall) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> + for migratedContractCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self + } + } + } + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (alloy::sol_types::sol_data::Address,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (alloy::sol_types::private::Address,); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From + for UnderlyingRustTuple<'_> { + fn from(value: migratedContractReturn) -> Self { + (value._0,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> + for migratedContractReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { _0: tuple.0 } + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for migratedContractCall { + type Parameters<'a> = (); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = alloy::sol_types::private::Address; + type ReturnTuple<'a> = (alloy::sol_types::sol_data::Address,); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "migratedContract()"; + const SELECTOR: [u8; 4] = [116u8, 134u8, 250u8, 78u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + () + } + #[inline] + fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> { + ( + ::tokenize( + ret, + ), + ) + } + #[inline] + fn abi_decode_returns(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data) + .map(|r| { + let r: migratedContractReturn = r.into(); + r._0 + }) + } + #[inline] + fn abi_decode_returns_validate( + data: &[u8], + ) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(|r| { + let r: migratedContractReturn = r.into(); + r._0 + }) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Function with signature `mirrorTokens(address)` and selector `0xfeaeb43e`. +```solidity +function mirrorTokens(address) external view returns (address); +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct mirrorTokensCall(pub alloy::sol_types::private::Address); + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + ///Container type for the return parameters of the [`mirrorTokens(address)`](mirrorTokensCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct mirrorTokensReturn { + #[allow(missing_docs)] + pub _0: alloy::sol_types::private::Address, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (alloy::sol_types::sol_data::Address,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (alloy::sol_types::private::Address,); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: mirrorTokensCall) -> Self { + (value.0,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for mirrorTokensCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self(tuple.0) + } + } + } + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (alloy::sol_types::sol_data::Address,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (alloy::sol_types::private::Address,); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: mirrorTokensReturn) -> Self { + (value._0,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for mirrorTokensReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { _0: tuple.0 } + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for mirrorTokensCall { + type Parameters<'a> = (alloy::sol_types::sol_data::Address,); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = alloy::sol_types::private::Address; + type ReturnTuple<'a> = (alloy::sol_types::sol_data::Address,); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "mirrorTokens(address)"; + const SELECTOR: [u8; 4] = [254u8, 174u8, 180u8, 62u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + ( + ::tokenize( + &self.0, + ), + ) + } + #[inline] + fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> { + ( + ::tokenize( + ret, + ), + ) + } + #[inline] + fn abi_decode_returns(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data) + .map(|r| { + let r: mirrorTokensReturn = r.into(); + r._0 + }) + } + #[inline] + fn abi_decode_returns_validate( + data: &[u8], + ) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(|r| { + let r: mirrorTokensReturn = r.into(); + r._0 + }) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Function with signature `pause()` and selector `0x8456cb59`. +```solidity +function pause() external; +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct pauseCall; + ///Container type for the return parameters of the [`pause()`](pauseCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct pauseReturn {} + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: pauseCall) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for pauseCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self + } + } + } + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: pauseReturn) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for pauseReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self {} + } + } + } + impl pauseReturn { + fn _tokenize( + &self, + ) -> ::ReturnToken<'_> { + () + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for pauseCall { + type Parameters<'a> = (); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = pauseReturn; + type ReturnTuple<'a> = (); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "pause()"; + const SELECTOR: [u8; 4] = [132u8, 86u8, 203u8, 89u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + () + } + #[inline] + fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> { + pauseReturn::_tokenize(ret) + } + #[inline] + fn abi_decode_returns(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data) + .map(Into::into) + } + #[inline] + fn abi_decode_returns_validate( + data: &[u8], + ) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(Into::into) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Function with signature `paused()` and selector `0x5c975abb`. +```solidity +function paused() external view returns (bool); +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct pausedCall; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + ///Container type for the return parameters of the [`paused()`](pausedCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct pausedReturn { + #[allow(missing_docs)] + pub _0: bool, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: pausedCall) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for pausedCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self + } + } + } + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (alloy::sol_types::sol_data::Bool,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (bool,); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: pausedReturn) -> Self { + (value._0,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for pausedReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { _0: tuple.0 } + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for pausedCall { + type Parameters<'a> = (); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = bool; + type ReturnTuple<'a> = (alloy::sol_types::sol_data::Bool,); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "paused()"; + const SELECTOR: [u8; 4] = [92u8, 151u8, 90u8, 187u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + () + } + #[inline] + fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> { + ( + ::tokenize( + ret, + ), + ) + } + #[inline] + fn abi_decode_returns(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data) + .map(|r| { + let r: pausedReturn = r.into(); + r._0 + }) + } + #[inline] + fn abi_decode_returns_validate( + data: &[u8], + ) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(|r| { + let r: pausedReturn = r.into(); + r._0 + }) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Function with signature `processedRequests(bytes32)` and selector `0xce0fa5a9`. +```solidity +function processedRequests(bytes32) external view returns (bool); +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct processedRequestsCall(pub alloy::sol_types::private::FixedBytes<32>); + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + ///Container type for the return parameters of the [`processedRequests(bytes32)`](processedRequestsCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct processedRequestsReturn { + #[allow(missing_docs)] + pub _0: bool, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (alloy::sol_types::sol_data::FixedBytes<32>,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (alloy::sol_types::private::FixedBytes<32>,); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From + for UnderlyingRustTuple<'_> { + fn from(value: processedRequestsCall) -> Self { + (value.0,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> + for processedRequestsCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self(tuple.0) + } + } + } + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (alloy::sol_types::sol_data::Bool,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (bool,); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From + for UnderlyingRustTuple<'_> { + fn from(value: processedRequestsReturn) -> Self { + (value._0,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> + for processedRequestsReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { _0: tuple.0 } + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for processedRequestsCall { + type Parameters<'a> = (alloy::sol_types::sol_data::FixedBytes<32>,); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = bool; + type ReturnTuple<'a> = (alloy::sol_types::sol_data::Bool,); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "processedRequests(bytes32)"; + const SELECTOR: [u8; 4] = [206u8, 15u8, 165u8, 169u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + ( + as alloy_sol_types::SolType>::tokenize(&self.0), + ) + } + #[inline] + fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> { + ( + ::tokenize( + ret, + ), + ) + } + #[inline] + fn abi_decode_returns(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data) + .map(|r| { + let r: processedRequestsReturn = r.into(); + r._0 + }) + } + #[inline] + fn abi_decode_returns_validate( + data: &[u8], + ) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(|r| { + let r: processedRequestsReturn = r.into(); + r._0 + }) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Function with signature `renounceRole(bytes32,address)` and selector `0x36568abe`. +```solidity +function renounceRole(bytes32 role, address callerConfirmation) external; +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct renounceRoleCall { + #[allow(missing_docs)] + pub role: alloy::sol_types::private::FixedBytes<32>, + #[allow(missing_docs)] + pub callerConfirmation: alloy::sol_types::private::Address, + } + ///Container type for the return parameters of the [`renounceRole(bytes32,address)`](renounceRoleCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct renounceRoleReturn {} + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = ( + alloy::sol_types::sol_data::FixedBytes<32>, + alloy::sol_types::sol_data::Address, + ); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = ( + alloy::sol_types::private::FixedBytes<32>, + alloy::sol_types::private::Address, + ); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: renounceRoleCall) -> Self { + (value.role, value.callerConfirmation) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for renounceRoleCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { + role: tuple.0, + callerConfirmation: tuple.1, + } + } + } + } + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: renounceRoleReturn) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for renounceRoleReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self {} + } + } + } + impl renounceRoleReturn { + fn _tokenize( + &self, + ) -> ::ReturnToken<'_> { + () + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for renounceRoleCall { + type Parameters<'a> = ( + alloy::sol_types::sol_data::FixedBytes<32>, + alloy::sol_types::sol_data::Address, + ); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = renounceRoleReturn; + type ReturnTuple<'a> = (); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "renounceRole(bytes32,address)"; + const SELECTOR: [u8; 4] = [54u8, 86u8, 138u8, 190u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + ( + as alloy_sol_types::SolType>::tokenize(&self.role), + ::tokenize( + &self.callerConfirmation, + ), + ) + } + #[inline] + fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> { + renounceRoleReturn::_tokenize(ret) + } + #[inline] + fn abi_decode_returns(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data) + .map(Into::into) + } + #[inline] + fn abi_decode_returns_validate( + data: &[u8], + ) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(Into::into) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Function with signature `revokeRole(bytes32,address)` and selector `0xd547741f`. +```solidity +function revokeRole(bytes32 role, address account) external; +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct revokeRoleCall { + #[allow(missing_docs)] + pub role: alloy::sol_types::private::FixedBytes<32>, + #[allow(missing_docs)] + pub account: alloy::sol_types::private::Address, + } + ///Container type for the return parameters of the [`revokeRole(bytes32,address)`](revokeRoleCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct revokeRoleReturn {} + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = ( + alloy::sol_types::sol_data::FixedBytes<32>, + alloy::sol_types::sol_data::Address, + ); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = ( + alloy::sol_types::private::FixedBytes<32>, + alloy::sol_types::private::Address, + ); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: revokeRoleCall) -> Self { + (value.role, value.account) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for revokeRoleCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { + role: tuple.0, + account: tuple.1, + } + } + } + } + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: revokeRoleReturn) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for revokeRoleReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self {} + } + } + } + impl revokeRoleReturn { + fn _tokenize( + &self, + ) -> ::ReturnToken<'_> { + () + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for revokeRoleCall { + type Parameters<'a> = ( + alloy::sol_types::sol_data::FixedBytes<32>, + alloy::sol_types::sol_data::Address, + ); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = revokeRoleReturn; + type ReturnTuple<'a> = (); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "revokeRole(bytes32,address)"; + const SELECTOR: [u8; 4] = [213u8, 71u8, 116u8, 31u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + ( + as alloy_sol_types::SolType>::tokenize(&self.role), + ::tokenize( + &self.account, + ), + ) + } + #[inline] + fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> { + revokeRoleReturn::_tokenize(ret) + } + #[inline] + fn abi_decode_returns(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data) + .map(Into::into) + } + #[inline] + fn abi_decode_returns_validate( + data: &[u8], + ) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(Into::into) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Function with signature `supportsInterface(bytes4)` and selector `0x01ffc9a7`. +```solidity +function supportsInterface(bytes4 interfaceId) external view returns (bool); +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct supportsInterfaceCall { + #[allow(missing_docs)] + pub interfaceId: alloy::sol_types::private::FixedBytes<4>, + } + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + ///Container type for the return parameters of the [`supportsInterface(bytes4)`](supportsInterfaceCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct supportsInterfaceReturn { + #[allow(missing_docs)] + pub _0: bool, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (alloy::sol_types::sol_data::FixedBytes<4>,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (alloy::sol_types::private::FixedBytes<4>,); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From + for UnderlyingRustTuple<'_> { + fn from(value: supportsInterfaceCall) -> Self { + (value.interfaceId,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> + for supportsInterfaceCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { interfaceId: tuple.0 } + } + } + } + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (alloy::sol_types::sol_data::Bool,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (bool,); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From + for UnderlyingRustTuple<'_> { + fn from(value: supportsInterfaceReturn) -> Self { + (value._0,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> + for supportsInterfaceReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { _0: tuple.0 } + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for supportsInterfaceCall { + type Parameters<'a> = (alloy::sol_types::sol_data::FixedBytes<4>,); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = bool; + type ReturnTuple<'a> = (alloy::sol_types::sol_data::Bool,); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "supportsInterface(bytes4)"; + const SELECTOR: [u8; 4] = [1u8, 255u8, 201u8, 167u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + ( + as alloy_sol_types::SolType>::tokenize(&self.interfaceId), + ) + } + #[inline] + fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> { + ( + ::tokenize( + ret, + ), + ) + } + #[inline] + fn abi_decode_returns(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data) + .map(|r| { + let r: supportsInterfaceReturn = r.into(); + r._0 + }) + } + #[inline] + fn abi_decode_returns_validate( + data: &[u8], + ) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(|r| { + let r: supportsInterfaceReturn = r.into(); + r._0 + }) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Function with signature `tokenData(address)` and selector `0x27e45c2c`. +```solidity +function tokenData(address) external view returns (IBridge.TokenLimits memory limits, IBridge.TokenUsage memory deposit, IBridge.TokenUsage memory claim); +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct tokenDataCall(pub alloy::sol_types::private::Address); + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + ///Container type for the return parameters of the [`tokenData(address)`](tokenDataCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct tokenDataReturn { + #[allow(missing_docs)] + pub limits: ::RustType, + #[allow(missing_docs)] + pub deposit: ::RustType, + #[allow(missing_docs)] + pub claim: ::RustType, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (alloy::sol_types::sol_data::Address,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (alloy::sol_types::private::Address,); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: tokenDataCall) -> Self { + (value.0,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for tokenDataCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self(tuple.0) + } + } + } + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = ( + IBridge::TokenLimits, + IBridge::TokenUsage, + IBridge::TokenUsage, + ); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = ( + ::RustType, + ::RustType, + ::RustType, + ); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: tokenDataReturn) -> Self { + (value.limits, value.deposit, value.claim) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for tokenDataReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { + limits: tuple.0, + deposit: tuple.1, + claim: tuple.2, + } + } + } + } + impl tokenDataReturn { + fn _tokenize( + &self, + ) -> ::ReturnToken<'_> { + ( + ::tokenize( + &self.limits, + ), + ::tokenize( + &self.deposit, + ), + ::tokenize( + &self.claim, + ), + ) + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for tokenDataCall { + type Parameters<'a> = (alloy::sol_types::sol_data::Address,); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = tokenDataReturn; + type ReturnTuple<'a> = ( + IBridge::TokenLimits, + IBridge::TokenUsage, + IBridge::TokenUsage, + ); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "tokenData(address)"; + const SELECTOR: [u8; 4] = [39u8, 228u8, 92u8, 44u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + ( + ::tokenize( + &self.0, + ), + ) + } + #[inline] + fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> { + tokenDataReturn::_tokenize(ret) + } + #[inline] + fn abi_decode_returns(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data) + .map(Into::into) + } + #[inline] + fn abi_decode_returns_validate( + data: &[u8], + ) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(Into::into) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Function with signature `unpause()` and selector `0x3f4ba83a`. +```solidity +function unpause() external; +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct unpauseCall; + ///Container type for the return parameters of the [`unpause()`](unpauseCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct unpauseReturn {} + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: unpauseCall) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for unpauseCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self + } + } + } + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: unpauseReturn) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for unpauseReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self {} + } + } + } + impl unpauseReturn { + fn _tokenize( + &self, + ) -> ::ReturnToken<'_> { + () + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for unpauseCall { + type Parameters<'a> = (); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = unpauseReturn; + type ReturnTuple<'a> = (); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "unpause()"; + const SELECTOR: [u8; 4] = [63u8, 75u8, 168u8, 58u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + () + } + #[inline] + fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> { + unpauseReturn::_tokenize(ret) + } + #[inline] + fn abi_decode_returns(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data) + .map(Into::into) + } + #[inline] + fn abi_decode_returns_validate( + data: &[u8], + ) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(Into::into) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Function with signature `usedNonces(uint256)` and selector `0x6717e41c`. +```solidity +function usedNonces(uint256) external view returns (bool); +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct usedNoncesCall(pub alloy::sol_types::private::primitives::aliases::U256); + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + ///Container type for the return parameters of the [`usedNonces(uint256)`](usedNoncesCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct usedNoncesReturn { + #[allow(missing_docs)] + pub _0: bool, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (alloy::sol_types::sol_data::Uint<256>,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = ( + alloy::sol_types::private::primitives::aliases::U256, + ); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: usedNoncesCall) -> Self { + (value.0,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for usedNoncesCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self(tuple.0) + } + } + } + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (alloy::sol_types::sol_data::Bool,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (bool,); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: usedNoncesReturn) -> Self { + (value._0,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for usedNoncesReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { _0: tuple.0 } + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for usedNoncesCall { + type Parameters<'a> = (alloy::sol_types::sol_data::Uint<256>,); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = bool; + type ReturnTuple<'a> = (alloy::sol_types::sol_data::Bool,); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "usedNonces(uint256)"; + const SELECTOR: [u8; 4] = [103u8, 23u8, 228u8, 28u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + ( + as alloy_sol_types::SolType>::tokenize(&self.0), + ) + } + #[inline] + fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> { + ( + ::tokenize( + ret, + ), + ) + } + #[inline] + fn abi_decode_returns(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data) + .map(|r| { + let r: usedNoncesReturn = r.into(); + r._0 + }) + } + #[inline] + fn abi_decode_returns_validate( + data: &[u8], + ) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(|r| { + let r: usedNoncesReturn = r.into(); + r._0 + }) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Function with signature `whitelistedTokens(uint256)` and selector `0x2154bc44`. +```solidity +function whitelistedTokens(uint256) external view returns (address); +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct whitelistedTokensCall( + pub alloy::sol_types::private::primitives::aliases::U256, + ); + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + ///Container type for the return parameters of the [`whitelistedTokens(uint256)`](whitelistedTokensCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct whitelistedTokensReturn { + #[allow(missing_docs)] + pub _0: alloy::sol_types::private::Address, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (alloy::sol_types::sol_data::Uint<256>,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = ( + alloy::sol_types::private::primitives::aliases::U256, + ); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From + for UnderlyingRustTuple<'_> { + fn from(value: whitelistedTokensCall) -> Self { + (value.0,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> + for whitelistedTokensCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self(tuple.0) + } + } + } + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (alloy::sol_types::sol_data::Address,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (alloy::sol_types::private::Address,); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From + for UnderlyingRustTuple<'_> { + fn from(value: whitelistedTokensReturn) -> Self { + (value._0,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> + for whitelistedTokensReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { _0: tuple.0 } + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for whitelistedTokensCall { + type Parameters<'a> = (alloy::sol_types::sol_data::Uint<256>,); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = alloy::sol_types::private::Address; + type ReturnTuple<'a> = (alloy::sol_types::sol_data::Address,); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "whitelistedTokens(uint256)"; + const SELECTOR: [u8; 4] = [33u8, 84u8, 188u8, 68u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + ( + as alloy_sol_types::SolType>::tokenize(&self.0), + ) + } + #[inline] + fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> { + ( + ::tokenize( + ret, + ), + ) + } + #[inline] + fn abi_decode_returns(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data) + .map(|r| { + let r: whitelistedTokensReturn = r.into(); + r._0 + }) + } + #[inline] + fn abi_decode_returns_validate( + data: &[u8], + ) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(|r| { + let r: whitelistedTokensReturn = r.into(); + r._0 + }) + } + } + }; + ///Container for all the [`BridgeMintBurn`](self) function calls. + #[derive(serde::Serialize, serde::Deserialize)] + #[derive()] + pub enum BridgeMintBurnCalls { + #[allow(missing_docs)] + DEFAULT_ADMIN_ROLE(DEFAULT_ADMIN_ROLECall), + #[allow(missing_docs)] + PAUSER_ROLE(PAUSER_ROLECall), + #[allow(missing_docs)] + bridgeContract(bridgeContractCall), + #[allow(missing_docs)] + claim(claimCall), + #[allow(missing_docs)] + claimNative(claimNativeCall), + #[allow(missing_docs)] + configureToken(configureTokenCall), + #[allow(missing_docs)] + createAndWhitelistMirrorToken(createAndWhitelistMirrorTokenCall), + #[allow(missing_docs)] + deposit(depositCall), + #[allow(missing_docs)] + depositNative(depositNativeCall), + #[allow(missing_docs)] + getRoleAdmin(getRoleAdminCall), + #[allow(missing_docs)] + grantRole(grantRoleCall), + #[allow(missing_docs)] + hasRole(hasRoleCall), + #[allow(missing_docs)] + migrate(migrateCall), + #[allow(missing_docs)] + migratedContract(migratedContractCall), + #[allow(missing_docs)] + mirrorTokens(mirrorTokensCall), + #[allow(missing_docs)] + pause(pauseCall), + #[allow(missing_docs)] + paused(pausedCall), + #[allow(missing_docs)] + processedRequests(processedRequestsCall), + #[allow(missing_docs)] + renounceRole(renounceRoleCall), + #[allow(missing_docs)] + revokeRole(revokeRoleCall), + #[allow(missing_docs)] + supportsInterface(supportsInterfaceCall), + #[allow(missing_docs)] + tokenData(tokenDataCall), + #[allow(missing_docs)] + unpause(unpauseCall), + #[allow(missing_docs)] + usedNonces(usedNoncesCall), + #[allow(missing_docs)] + whitelistedTokens(whitelistedTokensCall), + } + #[automatically_derived] + impl BridgeMintBurnCalls { + /// All the selectors of this enum. + /// + /// Note that the selectors might not be in the same order as the variants. + /// No guarantees are made about the order of the selectors. + /// + /// Prefer using `SolInterface` methods instead. + pub const SELECTORS: &'static [[u8; 4usize]] = &[ + [1u8, 255u8, 201u8, 167u8], + [33u8, 84u8, 188u8, 68u8], + [36u8, 138u8, 156u8, 163u8], + [39u8, 228u8, 92u8, 44u8], + [47u8, 47u8, 241u8, 93u8], + [51u8, 187u8, 127u8, 145u8], + [54u8, 86u8, 138u8, 190u8], + [63u8, 75u8, 168u8, 58u8], + [92u8, 151u8, 90u8, 187u8], + [94u8, 115u8, 117u8, 72u8], + [103u8, 23u8, 228u8, 28u8], + [116u8, 134u8, 250u8, 78u8], + [132u8, 86u8, 203u8, 89u8], + [145u8, 209u8, 72u8, 84u8], + [146u8, 103u8, 177u8, 83u8], + [162u8, 23u8, 253u8, 223u8], + [172u8, 137u8, 67u8, 145u8], + [205u8, 89u8, 101u8, 131u8], + [206u8, 15u8, 165u8, 169u8], + [206u8, 84u8, 148u8, 187u8], + [213u8, 71u8, 116u8, 31u8], + [223u8, 107u8, 2u8, 43u8], + [230u8, 58u8, 177u8, 233u8], + [244u8, 83u8, 70u8, 220u8], + [254u8, 174u8, 180u8, 62u8], + ]; + } + #[automatically_derived] + impl alloy_sol_types::SolInterface for BridgeMintBurnCalls { + const NAME: &'static str = "BridgeMintBurnCalls"; + const MIN_DATA_LENGTH: usize = 0usize; + const COUNT: usize = 25usize; + #[inline] + fn selector(&self) -> [u8; 4] { + match self { + Self::DEFAULT_ADMIN_ROLE(_) => { + ::SELECTOR + } + Self::PAUSER_ROLE(_) => { + ::SELECTOR + } + Self::bridgeContract(_) => { + ::SELECTOR + } + Self::claim(_) => ::SELECTOR, + Self::claimNative(_) => { + ::SELECTOR + } + Self::configureToken(_) => { + ::SELECTOR + } + Self::createAndWhitelistMirrorToken(_) => { + ::SELECTOR + } + Self::deposit(_) => ::SELECTOR, + Self::depositNative(_) => { + ::SELECTOR + } + Self::getRoleAdmin(_) => { + ::SELECTOR + } + Self::grantRole(_) => { + ::SELECTOR + } + Self::hasRole(_) => ::SELECTOR, + Self::migrate(_) => ::SELECTOR, + Self::migratedContract(_) => { + ::SELECTOR + } + Self::mirrorTokens(_) => { + ::SELECTOR + } + Self::pause(_) => ::SELECTOR, + Self::paused(_) => ::SELECTOR, + Self::processedRequests(_) => { + ::SELECTOR + } + Self::renounceRole(_) => { + ::SELECTOR + } + Self::revokeRole(_) => { + ::SELECTOR + } + Self::supportsInterface(_) => { + ::SELECTOR + } + Self::tokenData(_) => { + ::SELECTOR + } + Self::unpause(_) => ::SELECTOR, + Self::usedNonces(_) => { + ::SELECTOR + } + Self::whitelistedTokens(_) => { + ::SELECTOR + } + } + } + #[inline] + fn selector_at(i: usize) -> ::core::option::Option<[u8; 4]> { + Self::SELECTORS.get(i).copied() + } + #[inline] + fn valid_selector(selector: [u8; 4]) -> bool { + Self::SELECTORS.binary_search(&selector).is_ok() + } + #[inline] + #[allow(non_snake_case)] + fn abi_decode_raw( + selector: [u8; 4], + data: &[u8], + ) -> alloy_sol_types::Result { + static DECODE_SHIMS: &[fn( + &[u8], + ) -> alloy_sol_types::Result] = &[ + { + fn supportsInterface( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw( + data, + ) + .map(BridgeMintBurnCalls::supportsInterface) + } + supportsInterface + }, + { + fn whitelistedTokens( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw( + data, + ) + .map(BridgeMintBurnCalls::whitelistedTokens) + } + whitelistedTokens + }, + { + fn getRoleAdmin( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw( + data, + ) + .map(BridgeMintBurnCalls::getRoleAdmin) + } + getRoleAdmin + }, + { + fn tokenData( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw(data) + .map(BridgeMintBurnCalls::tokenData) + } + tokenData + }, + { + fn grantRole( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw(data) + .map(BridgeMintBurnCalls::grantRole) + } + grantRole + }, + { + fn depositNative( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw( + data, + ) + .map(BridgeMintBurnCalls::depositNative) + } + depositNative + }, + { + fn renounceRole( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw( + data, + ) + .map(BridgeMintBurnCalls::renounceRole) + } + renounceRole + }, + { + fn unpause( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw(data) + .map(BridgeMintBurnCalls::unpause) + } + unpause + }, + { + fn paused( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw(data) + .map(BridgeMintBurnCalls::paused) + } + paused + }, + { + fn claim( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw(data) + .map(BridgeMintBurnCalls::claim) + } + claim + }, + { + fn usedNonces( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw( + data, + ) + .map(BridgeMintBurnCalls::usedNonces) + } + usedNonces + }, + { + fn migratedContract( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw( + data, + ) + .map(BridgeMintBurnCalls::migratedContract) + } + migratedContract + }, + { + fn pause( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw(data) + .map(BridgeMintBurnCalls::pause) + } + pause + }, + { + fn hasRole( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw(data) + .map(BridgeMintBurnCalls::hasRole) + } + hasRole + }, + { + fn configureToken( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw( + data, + ) + .map(BridgeMintBurnCalls::configureToken) + } + configureToken + }, + { + fn DEFAULT_ADMIN_ROLE( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw( + data, + ) + .map(BridgeMintBurnCalls::DEFAULT_ADMIN_ROLE) + } + DEFAULT_ADMIN_ROLE + }, + { + fn claimNative( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw( + data, + ) + .map(BridgeMintBurnCalls::claimNative) + } + claimNative + }, + { + fn bridgeContract( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw( + data, + ) + .map(BridgeMintBurnCalls::bridgeContract) + } + bridgeContract + }, + { + fn processedRequests( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw( + data, + ) + .map(BridgeMintBurnCalls::processedRequests) + } + processedRequests + }, + { + fn migrate( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw(data) + .map(BridgeMintBurnCalls::migrate) + } + migrate + }, + { + fn revokeRole( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw( + data, + ) + .map(BridgeMintBurnCalls::revokeRole) + } + revokeRole + }, + { + fn createAndWhitelistMirrorToken( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw( + data, + ) + .map(BridgeMintBurnCalls::createAndWhitelistMirrorToken) + } + createAndWhitelistMirrorToken + }, + { + fn PAUSER_ROLE( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw( + data, + ) + .map(BridgeMintBurnCalls::PAUSER_ROLE) + } + PAUSER_ROLE + }, + { + fn deposit( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw(data) + .map(BridgeMintBurnCalls::deposit) + } + deposit + }, + { + fn mirrorTokens( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw( + data, + ) + .map(BridgeMintBurnCalls::mirrorTokens) + } + mirrorTokens + }, + ]; + let Ok(idx) = Self::SELECTORS.binary_search(&selector) else { + return Err( + alloy_sol_types::Error::unknown_selector( + ::NAME, + selector, + ), + ); + }; + DECODE_SHIMS[idx](data) + } + #[inline] + #[allow(non_snake_case)] + fn abi_decode_raw_validate( + selector: [u8; 4], + data: &[u8], + ) -> alloy_sol_types::Result { + static DECODE_VALIDATE_SHIMS: &[fn( + &[u8], + ) -> alloy_sol_types::Result] = &[ + { + fn supportsInterface( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(BridgeMintBurnCalls::supportsInterface) + } + supportsInterface + }, + { + fn whitelistedTokens( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(BridgeMintBurnCalls::whitelistedTokens) + } + whitelistedTokens + }, + { + fn getRoleAdmin( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(BridgeMintBurnCalls::getRoleAdmin) + } + getRoleAdmin + }, + { + fn tokenData( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(BridgeMintBurnCalls::tokenData) + } + tokenData + }, + { + fn grantRole( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(BridgeMintBurnCalls::grantRole) + } + grantRole + }, + { + fn depositNative( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(BridgeMintBurnCalls::depositNative) + } + depositNative + }, + { + fn renounceRole( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(BridgeMintBurnCalls::renounceRole) + } + renounceRole + }, + { + fn unpause( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(BridgeMintBurnCalls::unpause) + } + unpause + }, + { + fn paused( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(BridgeMintBurnCalls::paused) + } + paused + }, + { + fn claim( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(BridgeMintBurnCalls::claim) + } + claim + }, + { + fn usedNonces( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(BridgeMintBurnCalls::usedNonces) + } + usedNonces + }, + { + fn migratedContract( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(BridgeMintBurnCalls::migratedContract) + } + migratedContract + }, + { + fn pause( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(BridgeMintBurnCalls::pause) + } + pause + }, + { + fn hasRole( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(BridgeMintBurnCalls::hasRole) + } + hasRole + }, + { + fn configureToken( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(BridgeMintBurnCalls::configureToken) + } + configureToken + }, + { + fn DEFAULT_ADMIN_ROLE( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(BridgeMintBurnCalls::DEFAULT_ADMIN_ROLE) + } + DEFAULT_ADMIN_ROLE + }, + { + fn claimNative( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(BridgeMintBurnCalls::claimNative) + } + claimNative + }, + { + fn bridgeContract( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(BridgeMintBurnCalls::bridgeContract) + } + bridgeContract + }, + { + fn processedRequests( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(BridgeMintBurnCalls::processedRequests) + } + processedRequests + }, + { + fn migrate( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(BridgeMintBurnCalls::migrate) + } + migrate + }, + { + fn revokeRole( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(BridgeMintBurnCalls::revokeRole) + } + revokeRole + }, + { + fn createAndWhitelistMirrorToken( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(BridgeMintBurnCalls::createAndWhitelistMirrorToken) + } + createAndWhitelistMirrorToken + }, + { + fn PAUSER_ROLE( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(BridgeMintBurnCalls::PAUSER_ROLE) + } + PAUSER_ROLE + }, + { + fn deposit( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(BridgeMintBurnCalls::deposit) + } + deposit + }, + { + fn mirrorTokens( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(BridgeMintBurnCalls::mirrorTokens) + } + mirrorTokens + }, + ]; + let Ok(idx) = Self::SELECTORS.binary_search(&selector) else { + return Err( + alloy_sol_types::Error::unknown_selector( + ::NAME, + selector, + ), + ); + }; + DECODE_VALIDATE_SHIMS[idx](data) + } + #[inline] + fn abi_encoded_size(&self) -> usize { + match self { + Self::DEFAULT_ADMIN_ROLE(inner) => { + ::abi_encoded_size( + inner, + ) + } + Self::PAUSER_ROLE(inner) => { + ::abi_encoded_size( + inner, + ) + } + Self::bridgeContract(inner) => { + ::abi_encoded_size( + inner, + ) + } + Self::claim(inner) => { + ::abi_encoded_size(inner) + } + Self::claimNative(inner) => { + ::abi_encoded_size( + inner, + ) + } + Self::configureToken(inner) => { + ::abi_encoded_size( + inner, + ) + } + Self::createAndWhitelistMirrorToken(inner) => { + ::abi_encoded_size( + inner, + ) + } + Self::deposit(inner) => { + ::abi_encoded_size(inner) + } + Self::depositNative(inner) => { + ::abi_encoded_size( + inner, + ) + } + Self::getRoleAdmin(inner) => { + ::abi_encoded_size( + inner, + ) + } + Self::grantRole(inner) => { + ::abi_encoded_size(inner) + } + Self::hasRole(inner) => { + ::abi_encoded_size(inner) + } + Self::migrate(inner) => { + ::abi_encoded_size(inner) + } + Self::migratedContract(inner) => { + ::abi_encoded_size( + inner, + ) + } + Self::mirrorTokens(inner) => { + ::abi_encoded_size( + inner, + ) + } + Self::pause(inner) => { + ::abi_encoded_size(inner) + } + Self::paused(inner) => { + ::abi_encoded_size(inner) + } + Self::processedRequests(inner) => { + ::abi_encoded_size( + inner, + ) + } + Self::renounceRole(inner) => { + ::abi_encoded_size( + inner, + ) + } + Self::revokeRole(inner) => { + ::abi_encoded_size(inner) + } + Self::supportsInterface(inner) => { + ::abi_encoded_size( + inner, + ) + } + Self::tokenData(inner) => { + ::abi_encoded_size(inner) + } + Self::unpause(inner) => { + ::abi_encoded_size(inner) + } + Self::usedNonces(inner) => { + ::abi_encoded_size(inner) + } + Self::whitelistedTokens(inner) => { + ::abi_encoded_size( + inner, + ) + } + } + } + #[inline] + fn abi_encode_raw(&self, out: &mut alloy_sol_types::private::Vec) { + match self { + Self::DEFAULT_ADMIN_ROLE(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } + Self::PAUSER_ROLE(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } + Self::bridgeContract(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } + Self::claim(inner) => { + ::abi_encode_raw(inner, out) + } + Self::claimNative(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } + Self::configureToken(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } + Self::createAndWhitelistMirrorToken(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } + Self::deposit(inner) => { + ::abi_encode_raw(inner, out) + } + Self::depositNative(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } + Self::getRoleAdmin(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } + Self::grantRole(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } + Self::hasRole(inner) => { + ::abi_encode_raw(inner, out) + } + Self::migrate(inner) => { + ::abi_encode_raw(inner, out) + } + Self::migratedContract(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } + Self::mirrorTokens(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } + Self::pause(inner) => { + ::abi_encode_raw(inner, out) + } + Self::paused(inner) => { + ::abi_encode_raw(inner, out) + } + Self::processedRequests(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } + Self::renounceRole(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } + Self::revokeRole(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } + Self::supportsInterface(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } + Self::tokenData(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } + Self::unpause(inner) => { + ::abi_encode_raw(inner, out) + } + Self::usedNonces(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } + Self::whitelistedTokens(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } + } + } + } + ///Container for all the [`BridgeMintBurn`](self) custom errors. + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Debug, PartialEq, Eq, Hash)] + pub enum BridgeMintBurnErrors { + #[allow(missing_docs)] + AccessControlBadConfirmation(AccessControlBadConfirmation), + #[allow(missing_docs)] + AccessControlUnauthorizedAccount(AccessControlUnauthorizedAccount), + #[allow(missing_docs)] + BlockNotFinalized(BlockNotFinalized), + #[allow(missing_docs)] + ContractMigrated(ContractMigrated), + #[allow(missing_docs)] + DailyLimitExhausted(DailyLimitExhausted), + #[allow(missing_docs)] + Empty(Empty), + #[allow(missing_docs)] + EnforcedPause(EnforcedPause), + #[allow(missing_docs)] + ExpectedPause(ExpectedPause), + #[allow(missing_docs)] + InvalidBridgeContract(InvalidBridgeContract), + #[allow(missing_docs)] + InvalidDepositLog(InvalidDepositLog), + #[allow(missing_docs)] + InvalidNonce(InvalidNonce), + #[allow(missing_docs)] + InvalidToAddress(InvalidToAddress), + #[allow(missing_docs)] + InvalidTokenAmount(InvalidTokenAmount), + #[allow(missing_docs)] + InvalidTokenConfig(InvalidTokenConfig), + #[allow(missing_docs)] + MirrorTokenNotFound(MirrorTokenNotFound), + #[allow(missing_docs)] + Overflow256(Overflow256), + #[allow(missing_docs)] + PrecompileCallFailed(PrecompileCallFailed), + #[allow(missing_docs)] + RequestAlreadyProcessed(RequestAlreadyProcessed), + } + #[automatically_derived] + impl BridgeMintBurnErrors { + /// All the selectors of this enum. + /// + /// Note that the selectors might not be in the same order as the variants. + /// No guarantees are made about the order of the selectors. + /// + /// Prefer using `SolInterface` methods instead. + pub const SELECTORS: &'static [[u8; 4usize]] = &[ + [7u8, 254u8, 123u8, 174u8], + [28u8, 65u8, 72u8, 28u8], + [33u8, 96u8, 115u8, 57u8], + [61u8, 178u8, 161u8, 42u8], + [63u8, 79u8, 104u8, 150u8], + [102u8, 151u8, 178u8, 50u8], + [102u8, 218u8, 128u8, 55u8], + [109u8, 119u8, 238u8, 162u8], + [117u8, 102u8, 136u8, 254u8], + [138u8, 163u8, 167u8, 47u8], + [141u8, 252u8, 32u8, 43u8], + [166u8, 188u8, 116u8, 196u8], + [168u8, 221u8, 182u8, 77u8], + [189u8, 196u8, 223u8, 114u8], + [193u8, 45u8, 203u8, 194u8], + [217u8, 60u8, 6u8, 101u8], + [226u8, 81u8, 125u8, 63u8], + [253u8, 35u8, 255u8, 100u8], + ]; + } + #[automatically_derived] + impl alloy_sol_types::SolInterface for BridgeMintBurnErrors { + const NAME: &'static str = "BridgeMintBurnErrors"; + const MIN_DATA_LENGTH: usize = 0usize; + const COUNT: usize = 18usize; + #[inline] + fn selector(&self) -> [u8; 4] { + match self { + Self::AccessControlBadConfirmation(_) => { + ::SELECTOR + } + Self::AccessControlUnauthorizedAccount(_) => { + ::SELECTOR + } + Self::BlockNotFinalized(_) => { + ::SELECTOR + } + Self::ContractMigrated(_) => { + ::SELECTOR + } + Self::DailyLimitExhausted(_) => { + ::SELECTOR + } + Self::Empty(_) => ::SELECTOR, + Self::EnforcedPause(_) => { + ::SELECTOR + } + Self::ExpectedPause(_) => { + ::SELECTOR + } + Self::InvalidBridgeContract(_) => { + ::SELECTOR + } + Self::InvalidDepositLog(_) => { + ::SELECTOR + } + Self::InvalidNonce(_) => { + ::SELECTOR + } + Self::InvalidToAddress(_) => { + ::SELECTOR + } + Self::InvalidTokenAmount(_) => { + ::SELECTOR + } + Self::InvalidTokenConfig(_) => { + ::SELECTOR + } + Self::MirrorTokenNotFound(_) => { + ::SELECTOR + } + Self::Overflow256(_) => { + ::SELECTOR + } + Self::PrecompileCallFailed(_) => { + ::SELECTOR + } + Self::RequestAlreadyProcessed(_) => { + ::SELECTOR + } + } + } + #[inline] + fn selector_at(i: usize) -> ::core::option::Option<[u8; 4]> { + Self::SELECTORS.get(i).copied() + } + #[inline] + fn valid_selector(selector: [u8; 4]) -> bool { + Self::SELECTORS.binary_search(&selector).is_ok() + } + #[inline] + #[allow(non_snake_case)] + fn abi_decode_raw( + selector: [u8; 4], + data: &[u8], + ) -> alloy_sol_types::Result { + static DECODE_SHIMS: &[fn( + &[u8], + ) -> alloy_sol_types::Result] = &[ + { + fn InvalidTokenConfig( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw( + data, + ) + .map(BridgeMintBurnErrors::InvalidTokenConfig) + } + InvalidTokenConfig + }, + { + fn Overflow256( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw(data) + .map(BridgeMintBurnErrors::Overflow256) + } + Overflow256 + }, + { + fn InvalidTokenAmount( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw( + data, + ) + .map(BridgeMintBurnErrors::InvalidTokenAmount) + } + InvalidTokenAmount + }, + { + fn Empty( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw(data) + .map(BridgeMintBurnErrors::Empty) + } + Empty + }, + { + fn ContractMigrated( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw( + data, + ) + .map(BridgeMintBurnErrors::ContractMigrated) + } + ContractMigrated + }, + { + fn AccessControlBadConfirmation( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw( + data, + ) + .map(BridgeMintBurnErrors::AccessControlBadConfirmation) + } + AccessControlBadConfirmation + }, + { + fn InvalidBridgeContract( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw( + data, + ) + .map(BridgeMintBurnErrors::InvalidBridgeContract) + } + InvalidBridgeContract + }, + { + fn BlockNotFinalized( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw( + data, + ) + .map(BridgeMintBurnErrors::BlockNotFinalized) + } + BlockNotFinalized + }, + { + fn InvalidNonce( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw(data) + .map(BridgeMintBurnErrors::InvalidNonce) + } + InvalidNonce + }, + { + fn InvalidToAddress( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw( + data, + ) + .map(BridgeMintBurnErrors::InvalidToAddress) + } + InvalidToAddress + }, + { + fn ExpectedPause( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw( + data, + ) + .map(BridgeMintBurnErrors::ExpectedPause) + } + ExpectedPause + }, + { + fn RequestAlreadyProcessed( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw( + data, + ) + .map(BridgeMintBurnErrors::RequestAlreadyProcessed) + } + RequestAlreadyProcessed + }, + { + fn MirrorTokenNotFound( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw( + data, + ) + .map(BridgeMintBurnErrors::MirrorTokenNotFound) + } + MirrorTokenNotFound + }, + { + fn DailyLimitExhausted( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw( + data, + ) + .map(BridgeMintBurnErrors::DailyLimitExhausted) + } + DailyLimitExhausted + }, + { + fn InvalidDepositLog( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw( + data, + ) + .map(BridgeMintBurnErrors::InvalidDepositLog) + } + InvalidDepositLog + }, + { + fn EnforcedPause( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw( + data, + ) + .map(BridgeMintBurnErrors::EnforcedPause) + } + EnforcedPause + }, + { + fn AccessControlUnauthorizedAccount( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw( + data, + ) + .map(BridgeMintBurnErrors::AccessControlUnauthorizedAccount) + } + AccessControlUnauthorizedAccount + }, + { + fn PrecompileCallFailed( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw( + data, + ) + .map(BridgeMintBurnErrors::PrecompileCallFailed) + } + PrecompileCallFailed + }, + ]; + let Ok(idx) = Self::SELECTORS.binary_search(&selector) else { + return Err( + alloy_sol_types::Error::unknown_selector( + ::NAME, + selector, + ), + ); + }; + DECODE_SHIMS[idx](data) + } + #[inline] + #[allow(non_snake_case)] + fn abi_decode_raw_validate( + selector: [u8; 4], + data: &[u8], + ) -> alloy_sol_types::Result { + static DECODE_VALIDATE_SHIMS: &[fn( + &[u8], + ) -> alloy_sol_types::Result] = &[ + { + fn InvalidTokenConfig( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(BridgeMintBurnErrors::InvalidTokenConfig) + } + InvalidTokenConfig + }, + { + fn Overflow256( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(BridgeMintBurnErrors::Overflow256) + } + Overflow256 + }, + { + fn InvalidTokenAmount( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(BridgeMintBurnErrors::InvalidTokenAmount) + } + InvalidTokenAmount + }, + { + fn Empty( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(BridgeMintBurnErrors::Empty) + } + Empty + }, + { + fn ContractMigrated( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(BridgeMintBurnErrors::ContractMigrated) + } + ContractMigrated + }, + { + fn AccessControlBadConfirmation( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(BridgeMintBurnErrors::AccessControlBadConfirmation) + } + AccessControlBadConfirmation + }, + { + fn InvalidBridgeContract( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(BridgeMintBurnErrors::InvalidBridgeContract) + } + InvalidBridgeContract + }, + { + fn BlockNotFinalized( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(BridgeMintBurnErrors::BlockNotFinalized) + } + BlockNotFinalized + }, + { + fn InvalidNonce( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(BridgeMintBurnErrors::InvalidNonce) + } + InvalidNonce + }, + { + fn InvalidToAddress( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(BridgeMintBurnErrors::InvalidToAddress) + } + InvalidToAddress + }, + { + fn ExpectedPause( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(BridgeMintBurnErrors::ExpectedPause) + } + ExpectedPause + }, + { + fn RequestAlreadyProcessed( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(BridgeMintBurnErrors::RequestAlreadyProcessed) + } + RequestAlreadyProcessed + }, + { + fn MirrorTokenNotFound( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(BridgeMintBurnErrors::MirrorTokenNotFound) + } + MirrorTokenNotFound + }, + { + fn DailyLimitExhausted( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(BridgeMintBurnErrors::DailyLimitExhausted) + } + DailyLimitExhausted + }, + { + fn InvalidDepositLog( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(BridgeMintBurnErrors::InvalidDepositLog) + } + InvalidDepositLog + }, + { + fn EnforcedPause( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(BridgeMintBurnErrors::EnforcedPause) + } + EnforcedPause + }, + { + fn AccessControlUnauthorizedAccount( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(BridgeMintBurnErrors::AccessControlUnauthorizedAccount) + } + AccessControlUnauthorizedAccount + }, + { + fn PrecompileCallFailed( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(BridgeMintBurnErrors::PrecompileCallFailed) + } + PrecompileCallFailed + }, + ]; + let Ok(idx) = Self::SELECTORS.binary_search(&selector) else { + return Err( + alloy_sol_types::Error::unknown_selector( + ::NAME, + selector, + ), + ); + }; + DECODE_VALIDATE_SHIMS[idx](data) + } + #[inline] + fn abi_encoded_size(&self) -> usize { + match self { + Self::AccessControlBadConfirmation(inner) => { + ::abi_encoded_size( + inner, + ) + } + Self::AccessControlUnauthorizedAccount(inner) => { + ::abi_encoded_size( + inner, + ) + } + Self::BlockNotFinalized(inner) => { + ::abi_encoded_size( + inner, + ) + } + Self::ContractMigrated(inner) => { + ::abi_encoded_size( + inner, + ) + } + Self::DailyLimitExhausted(inner) => { + ::abi_encoded_size( + inner, + ) + } + Self::Empty(inner) => { + ::abi_encoded_size(inner) + } + Self::EnforcedPause(inner) => { + ::abi_encoded_size(inner) + } + Self::ExpectedPause(inner) => { + ::abi_encoded_size(inner) + } + Self::InvalidBridgeContract(inner) => { + ::abi_encoded_size( + inner, + ) + } + Self::InvalidDepositLog(inner) => { + ::abi_encoded_size( + inner, + ) + } + Self::InvalidNonce(inner) => { + ::abi_encoded_size(inner) + } + Self::InvalidToAddress(inner) => { + ::abi_encoded_size( + inner, + ) + } + Self::InvalidTokenAmount(inner) => { + ::abi_encoded_size( + inner, + ) + } + Self::InvalidTokenConfig(inner) => { + ::abi_encoded_size( + inner, + ) + } + Self::MirrorTokenNotFound(inner) => { + ::abi_encoded_size( + inner, + ) + } + Self::Overflow256(inner) => { + ::abi_encoded_size(inner) + } + Self::PrecompileCallFailed(inner) => { + ::abi_encoded_size( + inner, + ) + } + Self::RequestAlreadyProcessed(inner) => { + ::abi_encoded_size( + inner, + ) + } + } + } + #[inline] + fn abi_encode_raw(&self, out: &mut alloy_sol_types::private::Vec) { + match self { + Self::AccessControlBadConfirmation(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } + Self::AccessControlUnauthorizedAccount(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } + Self::BlockNotFinalized(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } + Self::ContractMigrated(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } + Self::DailyLimitExhausted(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } + Self::Empty(inner) => { + ::abi_encode_raw(inner, out) + } + Self::EnforcedPause(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } + Self::ExpectedPause(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } + Self::InvalidBridgeContract(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } + Self::InvalidDepositLog(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } + Self::InvalidNonce(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } + Self::InvalidToAddress(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } + Self::InvalidTokenAmount(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } + Self::InvalidTokenConfig(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } + Self::MirrorTokenNotFound(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } + Self::Overflow256(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } + Self::PrecompileCallFailed(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } + Self::RequestAlreadyProcessed(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } + } + } + } + ///Container for all the [`BridgeMintBurn`](self) events. + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Debug, PartialEq, Eq, Hash)] + pub enum BridgeMintBurnEvents { + #[allow(missing_docs)] + Claim(Claim), + #[allow(missing_docs)] + ClaimNative(ClaimNative), + #[allow(missing_docs)] + Deposit(Deposit), + #[allow(missing_docs)] + DepositNative(DepositNative), + #[allow(missing_docs)] + Paused(Paused), + #[allow(missing_docs)] + RoleAdminChanged(RoleAdminChanged), + #[allow(missing_docs)] + RoleGranted(RoleGranted), + #[allow(missing_docs)] + RoleRevoked(RoleRevoked), + #[allow(missing_docs)] + Unpaused(Unpaused), + } + #[automatically_derived] + impl BridgeMintBurnEvents { + /// All the selectors of this enum. + /// + /// Note that the selectors might not be in the same order as the variants. + /// No guarantees are made about the order of the selectors. + /// + /// Prefer using `SolInterface` methods instead. + pub const SELECTORS: &'static [[u8; 32usize]] = &[ + [ + 5u8, 229u8, 127u8, 166u8, 45u8, 137u8, 6u8, 3u8, 216u8, 89u8, 68u8, + 201u8, 99u8, 221u8, 199u8, 251u8, 231u8, 124u8, 222u8, 94u8, 166u8, + 156u8, 173u8, 112u8, 51u8, 252u8, 111u8, 118u8, 183u8, 221u8, 210u8, + 171u8, + ], + [ + 47u8, 135u8, 136u8, 17u8, 126u8, 126u8, 255u8, 29u8, 130u8, 233u8, 38u8, + 236u8, 121u8, 73u8, 1u8, 209u8, 124u8, 120u8, 2u8, 74u8, 80u8, 39u8, 9u8, + 64u8, 48u8, 69u8, 64u8, 167u8, 51u8, 101u8, 111u8, 13u8, + ], + [ + 64u8, 53u8, 43u8, 99u8, 208u8, 169u8, 201u8, 41u8, 131u8, 252u8, 241u8, + 157u8, 140u8, 63u8, 194u8, 140u8, 160u8, 188u8, 200u8, 250u8, 159u8, + 254u8, 181u8, 190u8, 40u8, 225u8, 74u8, 63u8, 117u8, 138u8, 179u8, 158u8, + ], + [ + 93u8, 185u8, 238u8, 10u8, 73u8, 91u8, 242u8, 230u8, 255u8, 156u8, 145u8, + 167u8, 131u8, 76u8, 27u8, 164u8, 253u8, 210u8, 68u8, 165u8, 232u8, 170u8, + 78u8, 83u8, 123u8, 211u8, 138u8, 234u8, 228u8, 176u8, 115u8, 170u8, + ], + [ + 98u8, 231u8, 140u8, 234u8, 1u8, 190u8, 227u8, 32u8, 205u8, 78u8, 66u8, + 2u8, 112u8, 181u8, 234u8, 116u8, 0u8, 13u8, 17u8, 176u8, 201u8, 247u8, + 71u8, 84u8, 235u8, 219u8, 252u8, 84u8, 75u8, 5u8, 162u8, 88u8, + ], + [ + 145u8, 49u8, 104u8, 218u8, 7u8, 195u8, 247u8, 245u8, 243u8, 197u8, 35u8, + 147u8, 51u8, 22u8, 50u8, 139u8, 13u8, 6u8, 17u8, 182u8, 39u8, 241u8, + 46u8, 177u8, 28u8, 34u8, 202u8, 68u8, 251u8, 177u8, 157u8, 198u8, + ], + [ + 175u8, 63u8, 26u8, 18u8, 52u8, 75u8, 190u8, 170u8, 185u8, 84u8, 212u8, + 18u8, 232u8, 33u8, 214u8, 182u8, 160u8, 109u8, 92u8, 213u8, 210u8, 123u8, + 226u8, 4u8, 53u8, 59u8, 212u8, 234u8, 155u8, 85u8, 165u8, 4u8, + ], + [ + 189u8, 121u8, 184u8, 111u8, 254u8, 10u8, 184u8, 232u8, 119u8, 97u8, 81u8, + 81u8, 66u8, 23u8, 205u8, 124u8, 172u8, 213u8, 44u8, 144u8, 159u8, 102u8, + 71u8, 92u8, 58u8, 244u8, 78u8, 18u8, 159u8, 11u8, 0u8, 255u8, + ], + [ + 246u8, 57u8, 31u8, 92u8, 50u8, 217u8, 198u8, 157u8, 42u8, 71u8, 234u8, + 103u8, 11u8, 68u8, 41u8, 116u8, 181u8, 57u8, 53u8, 209u8, 237u8, 199u8, + 253u8, 100u8, 235u8, 33u8, 224u8, 71u8, 168u8, 57u8, 23u8, 27u8, + ], + ]; + } + #[automatically_derived] + impl alloy_sol_types::SolEventInterface for BridgeMintBurnEvents { + const NAME: &'static str = "BridgeMintBurnEvents"; + const COUNT: usize = 9usize; + fn decode_raw_log( + topics: &[alloy_sol_types::Word], + data: &[u8], + ) -> alloy_sol_types::Result { + match topics.first().copied() { + Some(::SIGNATURE_HASH) => { + ::decode_raw_log(topics, data) + .map(Self::Claim) + } + Some(::SIGNATURE_HASH) => { + ::decode_raw_log( + topics, + data, + ) + .map(Self::ClaimNative) + } + Some(::SIGNATURE_HASH) => { + ::decode_raw_log(topics, data) + .map(Self::Deposit) + } + Some(::SIGNATURE_HASH) => { + ::decode_raw_log( + topics, + data, + ) + .map(Self::DepositNative) + } + Some(::SIGNATURE_HASH) => { + ::decode_raw_log(topics, data) + .map(Self::Paused) + } + Some(::SIGNATURE_HASH) => { + ::decode_raw_log( + topics, + data, + ) + .map(Self::RoleAdminChanged) + } + Some(::SIGNATURE_HASH) => { + ::decode_raw_log( + topics, + data, + ) + .map(Self::RoleGranted) + } + Some(::SIGNATURE_HASH) => { + ::decode_raw_log( + topics, + data, + ) + .map(Self::RoleRevoked) + } + Some(::SIGNATURE_HASH) => { + ::decode_raw_log(topics, data) + .map(Self::Unpaused) + } + _ => { + alloy_sol_types::private::Err(alloy_sol_types::Error::InvalidLog { + name: ::NAME, + log: alloy_sol_types::private::Box::new( + alloy_sol_types::private::LogData::new_unchecked( + topics.to_vec(), + data.to_vec().into(), + ), + ), + }) + } + } + } + } + #[automatically_derived] + impl alloy_sol_types::private::IntoLogData for BridgeMintBurnEvents { + fn to_log_data(&self) -> alloy_sol_types::private::LogData { + match self { + Self::Claim(inner) => { + alloy_sol_types::private::IntoLogData::to_log_data(inner) + } + Self::ClaimNative(inner) => { + alloy_sol_types::private::IntoLogData::to_log_data(inner) + } + Self::Deposit(inner) => { + alloy_sol_types::private::IntoLogData::to_log_data(inner) + } + Self::DepositNative(inner) => { + alloy_sol_types::private::IntoLogData::to_log_data(inner) + } + Self::Paused(inner) => { + alloy_sol_types::private::IntoLogData::to_log_data(inner) + } + Self::RoleAdminChanged(inner) => { + alloy_sol_types::private::IntoLogData::to_log_data(inner) + } + Self::RoleGranted(inner) => { + alloy_sol_types::private::IntoLogData::to_log_data(inner) + } + Self::RoleRevoked(inner) => { + alloy_sol_types::private::IntoLogData::to_log_data(inner) + } + Self::Unpaused(inner) => { + alloy_sol_types::private::IntoLogData::to_log_data(inner) + } + } + } + fn into_log_data(self) -> alloy_sol_types::private::LogData { + match self { + Self::Claim(inner) => { + alloy_sol_types::private::IntoLogData::into_log_data(inner) + } + Self::ClaimNative(inner) => { + alloy_sol_types::private::IntoLogData::into_log_data(inner) + } + Self::Deposit(inner) => { + alloy_sol_types::private::IntoLogData::into_log_data(inner) + } + Self::DepositNative(inner) => { + alloy_sol_types::private::IntoLogData::into_log_data(inner) + } + Self::Paused(inner) => { + alloy_sol_types::private::IntoLogData::into_log_data(inner) + } + Self::RoleAdminChanged(inner) => { + alloy_sol_types::private::IntoLogData::into_log_data(inner) + } + Self::RoleGranted(inner) => { + alloy_sol_types::private::IntoLogData::into_log_data(inner) + } + Self::RoleRevoked(inner) => { + alloy_sol_types::private::IntoLogData::into_log_data(inner) + } + Self::Unpaused(inner) => { + alloy_sol_types::private::IntoLogData::into_log_data(inner) + } + } + } + } + use alloy::contract as alloy_contract; + /**Creates a new wrapper around an on-chain [`BridgeMintBurn`](self) contract instance. + +See the [wrapper's documentation](`BridgeMintBurnInstance`) for more details.*/ + #[inline] + pub const fn new< + P: alloy_contract::private::Provider, + N: alloy_contract::private::Network, + >( + address: alloy_sol_types::private::Address, + provider: P, + ) -> BridgeMintBurnInstance { + BridgeMintBurnInstance::::new(address, provider) + } + /**A [`BridgeMintBurn`](self) instance. + +Contains type-safe methods for interacting with an on-chain instance of the +[`BridgeMintBurn`](self) contract located at a given `address`, using a given +provider `P`. + +If the contract bytecode is available (see the [`sol!`](alloy_sol_types::sol!) +documentation on how to provide it), the `deploy` and `deploy_builder` methods can +be used to deploy a new instance of the contract. + +See the [module-level documentation](self) for all the available methods.*/ + #[derive(Clone)] + pub struct BridgeMintBurnInstance { + address: alloy_sol_types::private::Address, + provider: P, + _network: ::core::marker::PhantomData, + } + #[automatically_derived] + impl ::core::fmt::Debug for BridgeMintBurnInstance { + #[inline] + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + f.debug_tuple("BridgeMintBurnInstance").field(&self.address).finish() + } + } + /// Instantiation and getters/setters. + #[automatically_derived] + impl< + P: alloy_contract::private::Provider, + N: alloy_contract::private::Network, + > BridgeMintBurnInstance { + /**Creates a new wrapper around an on-chain [`BridgeMintBurn`](self) contract instance. + +See the [wrapper's documentation](`BridgeMintBurnInstance`) for more details.*/ + #[inline] + pub const fn new( + address: alloy_sol_types::private::Address, + provider: P, + ) -> Self { + Self { + address, + provider, + _network: ::core::marker::PhantomData, + } + } + /// Returns a reference to the address. + #[inline] + pub const fn address(&self) -> &alloy_sol_types::private::Address { + &self.address + } + /// Sets the address. + #[inline] + pub fn set_address(&mut self, address: alloy_sol_types::private::Address) { + self.address = address; + } + /// Sets the address and returns `self`. + pub fn at(mut self, address: alloy_sol_types::private::Address) -> Self { + self.set_address(address); + self + } + /// Returns a reference to the provider. + #[inline] + pub const fn provider(&self) -> &P { + &self.provider + } + } + impl BridgeMintBurnInstance<&P, N> { + /// Clones the provider and returns a new instance with the cloned provider. + #[inline] + pub fn with_cloned_provider(self) -> BridgeMintBurnInstance { + BridgeMintBurnInstance { + address: self.address, + provider: ::core::clone::Clone::clone(&self.provider), + _network: ::core::marker::PhantomData, + } + } + } + /// Function calls. + #[automatically_derived] + impl< + P: alloy_contract::private::Provider, + N: alloy_contract::private::Network, + > BridgeMintBurnInstance { + /// Creates a new call builder using this contract instance's provider and address. + /// + /// Note that the call can be any function call, not just those defined in this + /// contract. Prefer using the other methods for building type-safe contract calls. + pub fn call_builder( + &self, + call: &C, + ) -> alloy_contract::SolCallBuilder<&P, C, N> { + alloy_contract::SolCallBuilder::new_sol(&self.provider, &self.address, call) + } + ///Creates a new call builder for the [`DEFAULT_ADMIN_ROLE`] function. + pub fn DEFAULT_ADMIN_ROLE( + &self, + ) -> alloy_contract::SolCallBuilder<&P, DEFAULT_ADMIN_ROLECall, N> { + self.call_builder(&DEFAULT_ADMIN_ROLECall) + } + ///Creates a new call builder for the [`PAUSER_ROLE`] function. + pub fn PAUSER_ROLE( + &self, + ) -> alloy_contract::SolCallBuilder<&P, PAUSER_ROLECall, N> { + self.call_builder(&PAUSER_ROLECall) + } + ///Creates a new call builder for the [`bridgeContract`] function. + pub fn bridgeContract( + &self, + ) -> alloy_contract::SolCallBuilder<&P, bridgeContractCall, N> { + self.call_builder(&bridgeContractCall) + } + ///Creates a new call builder for the [`claim`] function. + pub fn claim( + &self, + id: alloy::sol_types::private::primitives::aliases::U256, + token: alloy::sol_types::private::Address, + blockNumber: alloy::sol_types::private::primitives::aliases::U256, + ) -> alloy_contract::SolCallBuilder<&P, claimCall, N> { + self.call_builder( + &claimCall { + id, + token, + blockNumber, + }, + ) + } + ///Creates a new call builder for the [`claimNative`] function. + pub fn claimNative( + &self, + id: alloy::sol_types::private::primitives::aliases::U256, + blockNumber: alloy::sol_types::private::primitives::aliases::U256, + ) -> alloy_contract::SolCallBuilder<&P, claimNativeCall, N> { + self.call_builder(&claimNativeCall { id, blockNumber }) + } + ///Creates a new call builder for the [`configureToken`] function. + pub fn configureToken( + &self, + token: alloy::sol_types::private::Address, + limits: ::RustType, + ) -> alloy_contract::SolCallBuilder<&P, configureTokenCall, N> { + self.call_builder( + &configureTokenCall { + token, + limits, + }, + ) + } + ///Creates a new call builder for the [`createAndWhitelistMirrorToken`] function. + pub fn createAndWhitelistMirrorToken( + &self, + tokenName: alloy::sol_types::private::String, + tokenSymbol: alloy::sol_types::private::String, + existingToken: alloy::sol_types::private::Address, + mirrorToken: alloy::sol_types::private::Address, + mirrorTokenDecimals: u8, + limits: ::RustType, + ) -> alloy_contract::SolCallBuilder<&P, createAndWhitelistMirrorTokenCall, N> { + self.call_builder( + &createAndWhitelistMirrorTokenCall { + tokenName, + tokenSymbol, + existingToken, + mirrorToken, + mirrorTokenDecimals, + limits, + }, + ) + } + ///Creates a new call builder for the [`deposit`] function. + pub fn deposit( + &self, + token: alloy::sol_types::private::Address, + amount: alloy::sol_types::private::primitives::aliases::U256, + to: alloy::sol_types::private::Address, + ) -> alloy_contract::SolCallBuilder<&P, depositCall, N> { + self.call_builder(&depositCall { token, amount, to }) + } + ///Creates a new call builder for the [`depositNative`] function. + pub fn depositNative( + &self, + to: alloy::sol_types::private::Address, + ) -> alloy_contract::SolCallBuilder<&P, depositNativeCall, N> { + self.call_builder(&depositNativeCall { to }) + } + ///Creates a new call builder for the [`getRoleAdmin`] function. + pub fn getRoleAdmin( + &self, + role: alloy::sol_types::private::FixedBytes<32>, + ) -> alloy_contract::SolCallBuilder<&P, getRoleAdminCall, N> { + self.call_builder(&getRoleAdminCall { role }) + } + ///Creates a new call builder for the [`grantRole`] function. + pub fn grantRole( + &self, + role: alloy::sol_types::private::FixedBytes<32>, + account: alloy::sol_types::private::Address, + ) -> alloy_contract::SolCallBuilder<&P, grantRoleCall, N> { + self.call_builder(&grantRoleCall { role, account }) + } + ///Creates a new call builder for the [`hasRole`] function. + pub fn hasRole( + &self, + role: alloy::sol_types::private::FixedBytes<32>, + account: alloy::sol_types::private::Address, + ) -> alloy_contract::SolCallBuilder<&P, hasRoleCall, N> { + self.call_builder(&hasRoleCall { role, account }) + } + ///Creates a new call builder for the [`migrate`] function. + pub fn migrate( + &self, + _newContract: alloy::sol_types::private::Address, + ) -> alloy_contract::SolCallBuilder<&P, migrateCall, N> { + self.call_builder(&migrateCall { _newContract }) + } + ///Creates a new call builder for the [`migratedContract`] function. + pub fn migratedContract( + &self, + ) -> alloy_contract::SolCallBuilder<&P, migratedContractCall, N> { + self.call_builder(&migratedContractCall) + } + ///Creates a new call builder for the [`mirrorTokens`] function. + pub fn mirrorTokens( + &self, + _0: alloy::sol_types::private::Address, + ) -> alloy_contract::SolCallBuilder<&P, mirrorTokensCall, N> { + self.call_builder(&mirrorTokensCall(_0)) + } + ///Creates a new call builder for the [`pause`] function. + pub fn pause(&self) -> alloy_contract::SolCallBuilder<&P, pauseCall, N> { + self.call_builder(&pauseCall) + } + ///Creates a new call builder for the [`paused`] function. + pub fn paused(&self) -> alloy_contract::SolCallBuilder<&P, pausedCall, N> { + self.call_builder(&pausedCall) + } + ///Creates a new call builder for the [`processedRequests`] function. + pub fn processedRequests( + &self, + _0: alloy::sol_types::private::FixedBytes<32>, + ) -> alloy_contract::SolCallBuilder<&P, processedRequestsCall, N> { + self.call_builder(&processedRequestsCall(_0)) + } + ///Creates a new call builder for the [`renounceRole`] function. + pub fn renounceRole( + &self, + role: alloy::sol_types::private::FixedBytes<32>, + callerConfirmation: alloy::sol_types::private::Address, + ) -> alloy_contract::SolCallBuilder<&P, renounceRoleCall, N> { + self.call_builder( + &renounceRoleCall { + role, + callerConfirmation, + }, + ) + } + ///Creates a new call builder for the [`revokeRole`] function. + pub fn revokeRole( + &self, + role: alloy::sol_types::private::FixedBytes<32>, + account: alloy::sol_types::private::Address, + ) -> alloy_contract::SolCallBuilder<&P, revokeRoleCall, N> { + self.call_builder(&revokeRoleCall { role, account }) + } + ///Creates a new call builder for the [`supportsInterface`] function. + pub fn supportsInterface( + &self, + interfaceId: alloy::sol_types::private::FixedBytes<4>, + ) -> alloy_contract::SolCallBuilder<&P, supportsInterfaceCall, N> { + self.call_builder( + &supportsInterfaceCall { + interfaceId, + }, + ) + } + ///Creates a new call builder for the [`tokenData`] function. + pub fn tokenData( + &self, + _0: alloy::sol_types::private::Address, + ) -> alloy_contract::SolCallBuilder<&P, tokenDataCall, N> { + self.call_builder(&tokenDataCall(_0)) + } + ///Creates a new call builder for the [`unpause`] function. + pub fn unpause(&self) -> alloy_contract::SolCallBuilder<&P, unpauseCall, N> { + self.call_builder(&unpauseCall) + } + ///Creates a new call builder for the [`usedNonces`] function. + pub fn usedNonces( + &self, + _0: alloy::sol_types::private::primitives::aliases::U256, + ) -> alloy_contract::SolCallBuilder<&P, usedNoncesCall, N> { + self.call_builder(&usedNoncesCall(_0)) + } + ///Creates a new call builder for the [`whitelistedTokens`] function. + pub fn whitelistedTokens( + &self, + _0: alloy::sol_types::private::primitives::aliases::U256, + ) -> alloy_contract::SolCallBuilder<&P, whitelistedTokensCall, N> { + self.call_builder(&whitelistedTokensCall(_0)) + } + } + /// Event filters. + #[automatically_derived] + impl< + P: alloy_contract::private::Provider, + N: alloy_contract::private::Network, + > BridgeMintBurnInstance { + /// Creates a new event filter using this contract instance's provider and address. + /// + /// Note that the type can be any event, not just those defined in this contract. + /// Prefer using the other methods for building type-safe event filters. + pub fn event_filter( + &self, + ) -> alloy_contract::Event<&P, E, N> { + alloy_contract::Event::new_sol(&self.provider, &self.address) + } + ///Creates a new event filter for the [`Claim`] event. + pub fn Claim_filter(&self) -> alloy_contract::Event<&P, Claim, N> { + self.event_filter::() + } + ///Creates a new event filter for the [`ClaimNative`] event. + pub fn ClaimNative_filter(&self) -> alloy_contract::Event<&P, ClaimNative, N> { + self.event_filter::() + } + ///Creates a new event filter for the [`Deposit`] event. + pub fn Deposit_filter(&self) -> alloy_contract::Event<&P, Deposit, N> { + self.event_filter::() + } + ///Creates a new event filter for the [`DepositNative`] event. + pub fn DepositNative_filter( + &self, + ) -> alloy_contract::Event<&P, DepositNative, N> { + self.event_filter::() + } + ///Creates a new event filter for the [`Paused`] event. + pub fn Paused_filter(&self) -> alloy_contract::Event<&P, Paused, N> { + self.event_filter::() + } + ///Creates a new event filter for the [`RoleAdminChanged`] event. + pub fn RoleAdminChanged_filter( + &self, + ) -> alloy_contract::Event<&P, RoleAdminChanged, N> { + self.event_filter::() + } + ///Creates a new event filter for the [`RoleGranted`] event. + pub fn RoleGranted_filter(&self) -> alloy_contract::Event<&P, RoleGranted, N> { + self.event_filter::() + } + ///Creates a new event filter for the [`RoleRevoked`] event. + pub fn RoleRevoked_filter(&self) -> alloy_contract::Event<&P, RoleRevoked, N> { + self.event_filter::() + } + ///Creates a new event filter for the [`Unpaused`] event. + pub fn Unpaused_filter(&self) -> alloy_contract::Event<&P, Unpaused, N> { + self.event_filter::() + } + } +} diff --git a/protocol/bindings/src/lib.rs b/protocol/bindings/src/lib.rs new file mode 100644 index 00000000..df99de7f --- /dev/null +++ b/protocol/bindings/src/lib.rs @@ -0,0 +1,7 @@ +#![allow(unused_imports, clippy::all, rustdoc::all)] +//! This module contains the sol! generated bindings for solidity contracts. +//! This is autogenerated code. +//! Do not manually edit these files. +//! These files may be overwritten by the codegen system at any time. +pub mod r#bridge_deposit_withdraw; +pub mod r#bridge_mint_burn; diff --git a/protocol/script/DeployMintBurn.s.sol b/protocol/script/DeployMintBurn.s.sol index 3497babd..3b372c50 100644 --- a/protocol/script/DeployMintBurn.s.sol +++ b/protocol/script/DeployMintBurn.s.sol @@ -15,7 +15,7 @@ contract DeployMintBurn is Script { vm.startBroadcast(); - BridgeMintBurn bridgeMintBurn = new BridgeMintBurn(OTHER_BRIDGE_CONTRACT, nativeTokenLimits); + BridgeMintBurn bridgeMintBurn = new BridgeMintBurn(OTHER_BRIDGE_CONTRACT, nativeTokenLimits, 1); console.log("BridgeMintBurn deployed at:", address(bridgeMintBurn)); vm.stopBroadcast(); diff --git a/protocol/src/BridgeDepositWithdraw.sol b/protocol/src/BridgeDepositWithdraw.sol index f6810563..a48fe8d7 100644 --- a/protocol/src/BridgeDepositWithdraw.sol +++ b/protocol/src/BridgeDepositWithdraw.sol @@ -1,12 +1,12 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.20; -import {IBridgeDepositWithdraw} from "./interfaces/IBridgeDepositWithdraw.sol"; -import {Bridge} from "./abstract/Bridge.sol"; +import {IBridgeDepositWithdraw} from "pod-protocol/interfaces/IBridgeDepositWithdraw.sol"; +import {Bridge} from "pod-protocol/abstract/Bridge.sol"; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import {PodECDSA} from "pod-sdk/verifier/PodECDSA.sol"; -import {IPodRegistry} from "./interfaces/IPodRegistry.sol"; +import {IPodRegistry} from "pod-protocol/interfaces/IPodRegistry.sol"; /** * @title BridgeDepositWithdraw diff --git a/protocol/src/BridgeMintBurn.sol b/protocol/src/BridgeMintBurn.sol index a6335d1e..9c852eeb 100644 --- a/protocol/src/BridgeMintBurn.sol +++ b/protocol/src/BridgeMintBurn.sol @@ -1,13 +1,13 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.20; -import {IBridgeMintBurn} from "./interfaces/IBridgeMintBurn.sol"; -import {Bridge} from "./abstract/Bridge.sol"; +import {IBridgeMintBurn} from "pod-protocol/interfaces/IBridgeMintBurn.sol"; +import {Bridge} from "pod-protocol/abstract/Bridge.sol"; import {IAccessControl} from "@openzeppelin/contracts/access/IAccessControl.sol"; -import {IERC20MintableAndBurnable} from "./interfaces/IERC20MintableAndBurnable.sol"; -import {WrappedToken} from "./WrappedToken.sol"; +import {IERC20MintableAndBurnable} from "pod-protocol/interfaces/IERC20MintableAndBurnable.sol"; +import {WrappedToken} from "pod-protocol/WrappedToken.sol"; import {EthGetLogsTypes} from "pod-sdk/types/EthGetLogsTypes.sol"; -import {PodPrecompileHelper} from "./libraries/PodPrecompileHelper.sol"; +import {PodPrecompileHelper} from "pod-protocol/libraries/PodPrecompileHelper.sol"; /** * @title BridgeMintBurn @@ -24,7 +24,7 @@ contract BridgeMintBurn is Bridge, IBridgeMintBurn { /** * @dev The source chain id. */ - uint96 constant SOURCE_CHAIN_ID = 1; + uint96 immutable SOURCE_CHAIN_ID; /** * @dev "finalized" as bytes @@ -34,9 +34,11 @@ contract BridgeMintBurn is Bridge, IBridgeMintBurn { /** * @dev Constructor. */ - constructor(address _bridgeContract, TokenLimits memory nativeTokenLimits) + constructor(address _bridgeContract, TokenLimits memory nativeTokenLimits, uint96 _sourceChainId) Bridge(_bridgeContract, nativeTokenLimits) - {} + { + SOURCE_CHAIN_ID = _sourceChainId; + } /** * @dev Handles the deposit of tokens. The tokens are burned from the msg.sender. diff --git a/protocol/test/BridgeMintBurn.t.sol b/protocol/test/BridgeMintBurn.t.sol index d24ffa41..1a6744ff 100644 --- a/protocol/test/BridgeMintBurn.t.sol +++ b/protocol/test/BridgeMintBurn.t.sol @@ -2,16 +2,16 @@ pragma solidity ^0.8.20; import {BridgeBehaviorTest} from "./abstract/Bridge.t.sol"; -import {BridgeMintBurn} from "../src/BridgeMintBurn.sol"; -import {IBridgeMintBurn} from "../src/interfaces/IBridgeMintBurn.sol"; -import {IBridge} from "../src/interfaces/IBridge.sol"; -import {Bridge} from "../src/abstract/Bridge.sol"; +import {BridgeMintBurn} from "pod-protocol/BridgeMintBurn.sol"; +import {IBridgeMintBurn} from "pod-protocol/interfaces/IBridgeMintBurn.sol"; +import {IBridge} from "pod-protocol/interfaces/IBridge.sol"; +import {Bridge} from "pod-protocol/abstract/Bridge.sol"; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import {WrappedToken} from "../src/WrappedToken.sol"; +import {WrappedToken} from "pod-protocol/WrappedToken.sol"; import {Pausable} from "@openzeppelin/contracts/utils/Pausable.sol"; import {EthGetLogsTypes} from "pod-sdk/types/EthGetLogsTypes.sol"; import {EthGetBlockByNumberTypes} from "pod-sdk/types/EthGetBlockByNumberTypes.sol"; -import {HexUtils} from "../src/libraries/HexUtils.sol"; +import {HexUtils} from "pod-protocol/libraries/HexUtils.sol"; import {TxInfo} from "pod-sdk/Context.sol"; import {VmSafe} from "forge-std/Vm.sol"; @@ -31,7 +31,7 @@ contract BridgeMintBurnTest is BridgeBehaviorTest { function setUpSuite() public override { vm.startPrank(admin); - _bridge = new BridgeMintBurn(OTHER_BRIDGE_CONTRACT, nativeTokenLimits); + _bridge = new BridgeMintBurn(OTHER_BRIDGE_CONTRACT, nativeTokenLimits, 1); _token = WrappedToken( _bridge.createAndWhitelistMirrorToken( From ed3712e37a8ba58a5f3c7fe185251e522f088c41 Mon Sep 17 00:00:00 2001 From: Jakov Mitrovski Date: Mon, 22 Sep 2025 15:12:41 +0200 Subject: [PATCH 55/64] resolve ci --- .rustfmt.toml | 3 ++- examples/solidity/script/Deploy.s.sol | 12 ++++++------ 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/.rustfmt.toml b/.rustfmt.toml index a50dfef8..55129603 100644 --- a/.rustfmt.toml +++ b/.rustfmt.toml @@ -4,5 +4,6 @@ ignore = [ "examples/optimistic-auction/bindings", "examples/voting/bindings", "examples/auction/bindings", - "examples/notary/bindings" + "examples/notary/bindings", + "protocol/bindings" ] diff --git a/examples/solidity/script/Deploy.s.sol b/examples/solidity/script/Deploy.s.sol index 152afa7e..4aef3bf8 100644 --- a/examples/solidity/script/Deploy.s.sol +++ b/examples/solidity/script/Deploy.s.sol @@ -33,12 +33,6 @@ contract Deployer is BaseDeployer { if (testContracts) { address[] memory initialValidators = getValidatorAddresses(); - address otherBridgeContract = makeAddr("otherBridgeContract"); - IBridge.TokenLimits nativeTokenLimits = - IBridge.TokenLimits({minAmount: 0.01 ether, deposit: 500e18, claim: 400e18}); - BridgeMintBurn bridgeMintBurn = new BridgeMintBurn(otherBridgeContract, nativeTokenLimits); - console.log("BridgeMintBurn deployed at:", address(bridgeMintBurn)); - PodRegistry podRegistry = new PodRegistry(initialValidators); console.log("PodRegistry deployed at:", address(podRegistry)); @@ -49,6 +43,12 @@ contract Deployer is BaseDeployer { TestMintBalancePrecompile testMintBalance = new TestMintBalancePrecompile(); console.log("TestMintBalancePrecompile contract deployed at:", address(testMintBalance)); + + address otherBridgeContract = makeAddr("otherBridgeContract"); + IBridge.TokenLimits memory nativeTokenLimits = + IBridge.TokenLimits({minAmount: 0.01 ether, deposit: 500e18, claim: 400e18}); + BridgeMintBurn bridgeMintBurn = new BridgeMintBurn(otherBridgeContract, nativeTokenLimits); + console.log("BridgeMintBurn deployed at:", address(bridgeMintBurn)); } vm.stopBroadcast(); From dd72a83e53154a52fc50d13a428ad21318306c1e Mon Sep 17 00:00:00 2001 From: Jakov Mitrovski Date: Mon, 22 Sep 2025 15:15:17 +0200 Subject: [PATCH 56/64] upd bridge args --- examples/solidity/script/Deploy.s.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/solidity/script/Deploy.s.sol b/examples/solidity/script/Deploy.s.sol index 4aef3bf8..4f05c91d 100644 --- a/examples/solidity/script/Deploy.s.sol +++ b/examples/solidity/script/Deploy.s.sol @@ -47,7 +47,7 @@ contract Deployer is BaseDeployer { address otherBridgeContract = makeAddr("otherBridgeContract"); IBridge.TokenLimits memory nativeTokenLimits = IBridge.TokenLimits({minAmount: 0.01 ether, deposit: 500e18, claim: 400e18}); - BridgeMintBurn bridgeMintBurn = new BridgeMintBurn(otherBridgeContract, nativeTokenLimits); + BridgeMintBurn bridgeMintBurn = new BridgeMintBurn(otherBridgeContract, nativeTokenLimits, 0); console.log("BridgeMintBurn deployed at:", address(bridgeMintBurn)); } From 53c7f19d5c1108ddc197ea574547f3fd34a6f48c Mon Sep 17 00:00:00 2001 From: Jakov Mitrovski Date: Tue, 23 Sep 2025 18:43:56 +0200 Subject: [PATCH 57/64] bridge updates --- Cargo.lock | 8 + examples/solidity/script/Deploy.s.sol | 15 +- protocol/Makefile | 4 +- protocol/bindings/src/lib.rs | 1 + protocol/bindings/src/wrapped_token.rs | 8164 +++++++++++++++++ protocol/src/BridgeMintBurn.sol | 15 +- protocol/src/abstract/Bridge.sol | 2 +- .../src/libraries/PodPrecompileHelper.sol | 30 +- protocol/test/BridgeMintBurn.t.sol | 19 +- 9 files changed, 8223 insertions(+), 35 deletions(-) create mode 100644 protocol/bindings/src/wrapped_token.rs diff --git a/Cargo.lock b/Cargo.lock index f93cbddd..a2b4cbb2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3479,6 +3479,14 @@ dependencies = [ "serde", ] +[[package]] +name = "pod-protocol" +version = "0.1.0" +dependencies = [ + "alloy", + "serde", +] + [[package]] name = "pod-sdk" version = "0.2.0" diff --git a/examples/solidity/script/Deploy.s.sol b/examples/solidity/script/Deploy.s.sol index 4f05c91d..b9e8cb3c 100644 --- a/examples/solidity/script/Deploy.s.sol +++ b/examples/solidity/script/Deploy.s.sol @@ -44,11 +44,20 @@ contract Deployer is BaseDeployer { TestMintBalancePrecompile testMintBalance = new TestMintBalancePrecompile(); console.log("TestMintBalancePrecompile contract deployed at:", address(testMintBalance)); - address otherBridgeContract = makeAddr("otherBridgeContract"); + address OTHER_BRIDGE_CONTRACT = makeAddr("otherBridgeContract"); IBridge.TokenLimits memory nativeTokenLimits = - IBridge.TokenLimits({minAmount: 0.01 ether, deposit: 500e18, claim: 400e18}); - BridgeMintBurn bridgeMintBurn = new BridgeMintBurn(otherBridgeContract, nativeTokenLimits, 0); + IBridge.TokenLimits({minAmount: 0.01 ether, deposit: 5000000 ether, claim: 4000000 ether}); + + BridgeMintBurn bridgeMintBurn = new BridgeMintBurn(OTHER_BRIDGE_CONTRACT, nativeTokenLimits, 0); console.log("BridgeMintBurn deployed at:", address(bridgeMintBurn)); + + address MIRROR_TOKEN_ADDRESS = makeAddr("mirrorToken"); + + address token = bridgeMintBurn.createAndWhitelistMirrorToken( + "Test Token", "TEST", address(0), address(MIRROR_TOKEN_ADDRESS), 18, nativeTokenLimits + ); + + console.log("Token deployed at:", token); } vm.stopBroadcast(); diff --git a/protocol/Makefile b/protocol/Makefile index 99babe12..8b8301dc 100644 --- a/protocol/Makefile +++ b/protocol/Makefile @@ -1,8 +1,8 @@ generate: - forge bind --crate-name pod-protocol --bindings-path ./bindings --alloy-version 1.0.24 --force --no-metadata --select "^BridgeMintBurn$$" --select "^BridgeDepositWithdraw$$" --overwrite + forge bind --crate-name pod-protocol --bindings-path ./bindings --alloy-version 1.0.24 --force --no-metadata --select "^BridgeMintBurn$$" --select "^BridgeDepositWithdraw$$" --select "^WrappedToken$$" --overwrite check: - forge bind --crate-name pod-protocol --bindings-path ./bindings --alloy-version 1.0.24 --force --no-metadata --select "^BridgeMintBurn$$" --select "^BridgeDepositWithdraw$$" + forge bind --crate-name pod-protocol --bindings-path ./bindings --alloy-version 1.0.24 --force --no-metadata --select "^BridgeMintBurn$$" --select "^BridgeDepositWithdraw$$" --select "^WrappedToken$$" diff --git a/protocol/bindings/src/lib.rs b/protocol/bindings/src/lib.rs index df99de7f..e1205ddd 100644 --- a/protocol/bindings/src/lib.rs +++ b/protocol/bindings/src/lib.rs @@ -5,3 +5,4 @@ //! These files may be overwritten by the codegen system at any time. pub mod r#bridge_deposit_withdraw; pub mod r#bridge_mint_burn; +pub mod r#wrapped_token; diff --git a/protocol/bindings/src/wrapped_token.rs b/protocol/bindings/src/wrapped_token.rs new file mode 100644 index 00000000..70d110b2 --- /dev/null +++ b/protocol/bindings/src/wrapped_token.rs @@ -0,0 +1,8164 @@ +/** + +Generated by the following Solidity interface... +```solidity +interface WrappedToken { + error AccessControlBadConfirmation(); + error AccessControlUnauthorizedAccount(address account, bytes32 neededRole); + error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed); + error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed); + error ERC20InvalidApprover(address approver); + error ERC20InvalidReceiver(address receiver); + error ERC20InvalidSender(address sender); + error ERC20InvalidSpender(address spender); + error EnforcedPause(); + error ExpectedPause(); + + event Approval(address indexed owner, address indexed spender, uint256 value); + event Paused(address account); + event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole); + event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender); + event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender); + event Transfer(address indexed from, address indexed to, uint256 value); + event Unpaused(address account); + + constructor(string name_, string symbol_, uint8 decimals_); + + function DEFAULT_ADMIN_ROLE() external view returns (bytes32); + function MINTER_ROLE() external view returns (bytes32); + function PAUSER_ROLE() external view returns (bytes32); + function allowance(address owner, address spender) external view returns (uint256); + function approve(address spender, uint256 value) external returns (bool); + function balanceOf(address account) external view returns (uint256); + function burn(uint256 value) external; + function burnFrom(address account, uint256 value) external; + function decimals() external view returns (uint8); + function getRoleAdmin(bytes32 role) external view returns (bytes32); + function grantRole(bytes32 role, address account) external; + function hasRole(bytes32 role, address account) external view returns (bool); + function mint(address to, uint256 amount) external; + function name() external view returns (string memory); + function pause() external; + function paused() external view returns (bool); + function renounceRole(bytes32 role, address callerConfirmation) external; + function revokeRole(bytes32 role, address account) external; + function supportsInterface(bytes4 interfaceId) external view returns (bool); + function symbol() external view returns (string memory); + function totalSupply() external view returns (uint256); + function transfer(address to, uint256 value) external returns (bool); + function transferFrom(address from, address to, uint256 value) external returns (bool); + function unpause() external; +} +``` + +...which was generated by the following JSON ABI: +```json +[ + { + "type": "constructor", + "inputs": [ + { + "name": "name_", + "type": "string", + "internalType": "string" + }, + { + "name": "symbol_", + "type": "string", + "internalType": "string" + }, + { + "name": "decimals_", + "type": "uint8", + "internalType": "uint8" + } + ], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "DEFAULT_ADMIN_ROLE", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "bytes32", + "internalType": "bytes32" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "MINTER_ROLE", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "bytes32", + "internalType": "bytes32" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "PAUSER_ROLE", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "bytes32", + "internalType": "bytes32" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "allowance", + "inputs": [ + { + "name": "owner", + "type": "address", + "internalType": "address" + }, + { + "name": "spender", + "type": "address", + "internalType": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "approve", + "inputs": [ + { + "name": "spender", + "type": "address", + "internalType": "address" + }, + { + "name": "value", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [ + { + "name": "", + "type": "bool", + "internalType": "bool" + } + ], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "balanceOf", + "inputs": [ + { + "name": "account", + "type": "address", + "internalType": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "burn", + "inputs": [ + { + "name": "value", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "burnFrom", + "inputs": [ + { + "name": "account", + "type": "address", + "internalType": "address" + }, + { + "name": "value", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "decimals", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint8", + "internalType": "uint8" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getRoleAdmin", + "inputs": [ + { + "name": "role", + "type": "bytes32", + "internalType": "bytes32" + } + ], + "outputs": [ + { + "name": "", + "type": "bytes32", + "internalType": "bytes32" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "grantRole", + "inputs": [ + { + "name": "role", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "account", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "hasRole", + "inputs": [ + { + "name": "role", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "account", + "type": "address", + "internalType": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "bool", + "internalType": "bool" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "mint", + "inputs": [ + { + "name": "to", + "type": "address", + "internalType": "address" + }, + { + "name": "amount", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "name", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "string", + "internalType": "string" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "pause", + "inputs": [], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "paused", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "bool", + "internalType": "bool" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "renounceRole", + "inputs": [ + { + "name": "role", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "callerConfirmation", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "revokeRole", + "inputs": [ + { + "name": "role", + "type": "bytes32", + "internalType": "bytes32" + }, + { + "name": "account", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "supportsInterface", + "inputs": [ + { + "name": "interfaceId", + "type": "bytes4", + "internalType": "bytes4" + } + ], + "outputs": [ + { + "name": "", + "type": "bool", + "internalType": "bool" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "symbol", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "string", + "internalType": "string" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "totalSupply", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "transfer", + "inputs": [ + { + "name": "to", + "type": "address", + "internalType": "address" + }, + { + "name": "value", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [ + { + "name": "", + "type": "bool", + "internalType": "bool" + } + ], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "transferFrom", + "inputs": [ + { + "name": "from", + "type": "address", + "internalType": "address" + }, + { + "name": "to", + "type": "address", + "internalType": "address" + }, + { + "name": "value", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [ + { + "name": "", + "type": "bool", + "internalType": "bool" + } + ], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "unpause", + "inputs": [], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "event", + "name": "Approval", + "inputs": [ + { + "name": "owner", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "spender", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "value", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "Paused", + "inputs": [ + { + "name": "account", + "type": "address", + "indexed": false, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "RoleAdminChanged", + "inputs": [ + { + "name": "role", + "type": "bytes32", + "indexed": true, + "internalType": "bytes32" + }, + { + "name": "previousAdminRole", + "type": "bytes32", + "indexed": true, + "internalType": "bytes32" + }, + { + "name": "newAdminRole", + "type": "bytes32", + "indexed": true, + "internalType": "bytes32" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "RoleGranted", + "inputs": [ + { + "name": "role", + "type": "bytes32", + "indexed": true, + "internalType": "bytes32" + }, + { + "name": "account", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "sender", + "type": "address", + "indexed": true, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "RoleRevoked", + "inputs": [ + { + "name": "role", + "type": "bytes32", + "indexed": true, + "internalType": "bytes32" + }, + { + "name": "account", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "sender", + "type": "address", + "indexed": true, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "Transfer", + "inputs": [ + { + "name": "from", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "to", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "value", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "Unpaused", + "inputs": [ + { + "name": "account", + "type": "address", + "indexed": false, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "type": "error", + "name": "AccessControlBadConfirmation", + "inputs": [] + }, + { + "type": "error", + "name": "AccessControlUnauthorizedAccount", + "inputs": [ + { + "name": "account", + "type": "address", + "internalType": "address" + }, + { + "name": "neededRole", + "type": "bytes32", + "internalType": "bytes32" + } + ] + }, + { + "type": "error", + "name": "ERC20InsufficientAllowance", + "inputs": [ + { + "name": "spender", + "type": "address", + "internalType": "address" + }, + { + "name": "allowance", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "needed", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "type": "error", + "name": "ERC20InsufficientBalance", + "inputs": [ + { + "name": "sender", + "type": "address", + "internalType": "address" + }, + { + "name": "balance", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "needed", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "type": "error", + "name": "ERC20InvalidApprover", + "inputs": [ + { + "name": "approver", + "type": "address", + "internalType": "address" + } + ] + }, + { + "type": "error", + "name": "ERC20InvalidReceiver", + "inputs": [ + { + "name": "receiver", + "type": "address", + "internalType": "address" + } + ] + }, + { + "type": "error", + "name": "ERC20InvalidSender", + "inputs": [ + { + "name": "sender", + "type": "address", + "internalType": "address" + } + ] + }, + { + "type": "error", + "name": "ERC20InvalidSpender", + "inputs": [ + { + "name": "spender", + "type": "address", + "internalType": "address" + } + ] + }, + { + "type": "error", + "name": "EnforcedPause", + "inputs": [] + }, + { + "type": "error", + "name": "ExpectedPause", + "inputs": [] + } +] +```*/ +#[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style, + clippy::empty_structs_with_brackets +)] +pub mod WrappedToken { + use super::*; + use alloy::sol_types as alloy_sol_types; + /// The creation / init bytecode of the contract. + /// + /// ```text + ///0x60a060405234801561000f575f5ffd5b50604051612116380380612116833981810160405281019061003191906103c4565b82828160039081610042919061065c565b508060049081610052919061065c565b5050508060ff1660808160ff16815250506100755f5f1b336100e060201b60201c565b506100a67f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a336100e060201b60201c565b506100d77f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a6336100e060201b60201c565b5050505061072b565b5f6100f183836101d660201b60201c565b6101cc57600160065f8581526020019081526020015f205f015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff02191690831515021790555061016961023a60201b60201c565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a4600190506101d0565b5f90505b92915050565b5f60065f8481526020019081526020015f205f015f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16905092915050565b5f33905090565b5f604051905090565b5f5ffd5b5f5ffd5b5f5ffd5b5f5ffd5b5f601f19601f8301169050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6102a08261025a565b810181811067ffffffffffffffff821117156102bf576102be61026a565b5b80604052505050565b5f6102d1610241565b90506102dd8282610297565b919050565b5f67ffffffffffffffff8211156102fc576102fb61026a565b5b6103058261025a565b9050602081019050919050565b8281835e5f83830152505050565b5f61033261032d846102e2565b6102c8565b90508281526020810184848401111561034e5761034d610256565b5b610359848285610312565b509392505050565b5f82601f83011261037557610374610252565b5b8151610385848260208601610320565b91505092915050565b5f60ff82169050919050565b6103a38161038e565b81146103ad575f5ffd5b50565b5f815190506103be8161039a565b92915050565b5f5f5f606084860312156103db576103da61024a565b5b5f84015167ffffffffffffffff8111156103f8576103f761024e565b5b61040486828701610361565b935050602084015167ffffffffffffffff8111156104255761042461024e565b5b61043186828701610361565b9250506040610442868287016103b0565b9150509250925092565b5f81519050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f600282049050600182168061049a57607f821691505b6020821081036104ad576104ac610456565b5b50919050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f6008830261050f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff826104d4565b61051986836104d4565b95508019841693508086168417925050509392505050565b5f819050919050565b5f819050919050565b5f61055d61055861055384610531565b61053a565b610531565b9050919050565b5f819050919050565b61057683610543565b61058a61058282610564565b8484546104e0565b825550505050565b5f5f905090565b6105a1610592565b6105ac81848461056d565b505050565b5b818110156105cf576105c45f82610599565b6001810190506105b2565b5050565b601f821115610614576105e5816104b3565b6105ee846104c5565b810160208510156105fd578190505b610611610609856104c5565b8301826105b1565b50505b505050565b5f82821c905092915050565b5f6106345f1984600802610619565b1980831691505092915050565b5f61064c8383610625565b9150826002028217905092915050565b6106658261044c565b67ffffffffffffffff81111561067e5761067d61026a565b5b6106888254610483565b6106938282856105d3565b5f60209050601f8311600181146106c4575f84156106b2578287015190505b6106bc8582610641565b865550610723565b601f1984166106d2866104b3565b5f5b828110156106f9578489015182556001820191506020850194506020810190506106d4565b868310156107165784890151610712601f891682610625565b8355505b6001600288020188555050505b505050505050565b6080516119d36107435f395f61062a01526119d35ff3fe608060405234801561000f575f5ffd5b5060043610610156575f3560e01c80635c975abb116100c1578063a217fddf1161007a578063a217fddf146103b0578063a9059cbb146103ce578063d5391393146103fe578063d547741f1461041c578063dd62ed3e14610438578063e63ab1e91461046857610156565b80635c975abb146102ee57806370a082311461030c57806379cc67901461033c5780638456cb591461035857806391d148541461036257806395d89b411461039257610156565b80632f2ff15d116101135780632f2ff15d14610256578063313ce5671461027257806336568abe146102905780633f4ba83a146102ac57806340c10f19146102b657806342966c68146102d257610156565b806301ffc9a71461015a57806306fdde031461018a578063095ea7b3146101a857806318160ddd146101d857806323b872dd146101f6578063248a9ca314610226575b5f5ffd5b610174600480360381019061016f91906114d5565b610486565b604051610181919061151a565b60405180910390f35b6101926104ff565b60405161019f91906115a3565b60405180910390f35b6101c260048036038101906101bd9190611650565b61058f565b6040516101cf919061151a565b60405180910390f35b6101e06105b1565b6040516101ed919061169d565b60405180910390f35b610210600480360381019061020b91906116b6565b6105ba565b60405161021d919061151a565b60405180910390f35b610240600480360381019061023b9190611739565b6105e8565b60405161024d9190611773565b60405180910390f35b610270600480360381019061026b919061178c565b610605565b005b61027a610627565b60405161028791906117e5565b60405180910390f35b6102aa60048036038101906102a5919061178c565b61064e565b005b6102b46106c9565b005b6102d060048036038101906102cb9190611650565b6106e0565b005b6102ec60048036038101906102e791906117fe565b610719565b005b6102f661072d565b604051610303919061151a565b60405180910390f35b61032660048036038101906103219190611829565b610742565b604051610333919061169d565b60405180910390f35b61035660048036038101906103519190611650565b610787565b005b6103606107a7565b005b61037c6004803603810190610377919061178c565b6107dc565b604051610389919061151a565b60405180910390f35b61039a610840565b6040516103a791906115a3565b60405180910390f35b6103b86108d0565b6040516103c59190611773565b60405180910390f35b6103e860048036038101906103e39190611650565b6108d6565b6040516103f5919061151a565b60405180910390f35b6104066108f8565b6040516104139190611773565b60405180910390f35b6104366004803603810190610431919061178c565b61091c565b005b610452600480360381019061044d9190611854565b61093e565b60405161045f919061169d565b60405180910390f35b6104706109c0565b60405161047d9190611773565b60405180910390f35b5f7f7965db0b000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806104f857506104f7826109e4565b5b9050919050565b60606003805461050e906118bf565b80601f016020809104026020016040519081016040528092919081815260200182805461053a906118bf565b80156105855780601f1061055c57610100808354040283529160200191610585565b820191905f5260205f20905b81548152906001019060200180831161056857829003601f168201915b5050505050905090565b5f5f610599610a4d565b90506105a6818585610a54565b600191505092915050565b5f600254905090565b5f5f6105c4610a4d565b90506105d1858285610a66565b6105dc858585610af9565b60019150509392505050565b5f60065f8381526020019081526020015f20600101549050919050565b61060e826105e8565b61061781610be9565b6106218383610bfd565b50505050565b5f7f0000000000000000000000000000000000000000000000000000000000000000905090565b610656610a4d565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146106ba576040517f6697b23200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6106c48282610ce7565b505050565b5f5f1b6106d581610be9565b6106dd610dd1565b50565b7f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a661070a81610be9565b6107148383610e32565b505050565b61072a610724610a4d565b82610eb1565b50565b5f60055f9054906101000a900460ff16905090565b5f5f5f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20549050919050565b61079982610793610a4d565b83610a66565b6107a38282610eb1565b5050565b7f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a6107d181610be9565b6107d9610f30565b50565b5f60065f8481526020019081526020015f205f015f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16905092915050565b60606004805461084f906118bf565b80601f016020809104026020016040519081016040528092919081815260200182805461087b906118bf565b80156108c65780601f1061089d576101008083540402835291602001916108c6565b820191905f5260205f20905b8154815290600101906020018083116108a957829003601f168201915b5050505050905090565b5f5f1b81565b5f5f6108e0610a4d565b90506108ed818585610af9565b600191505092915050565b7f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a681565b610925826105e8565b61092e81610be9565b6109388383610ce7565b50505050565b5f60015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054905092915050565b7f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a81565b5f7f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b5f33905090565b610a618383836001610f92565b505050565b5f610a71848461093e565b90507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff811015610af35781811015610ae4578281836040517ffb8f41b2000000000000000000000000000000000000000000000000000000008152600401610adb939291906118fe565b60405180910390fd5b610af284848484035f610f92565b5b50505050565b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610b69575f6040517f96c6fd1e000000000000000000000000000000000000000000000000000000008152600401610b609190611933565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610bd9575f6040517fec442f05000000000000000000000000000000000000000000000000000000008152600401610bd09190611933565b60405180910390fd5b610be4838383611161565b505050565b610bfa81610bf5610a4d565b611179565b50565b5f610c0883836107dc565b610cdd57600160065f8581526020019081526020015f205f015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff021916908315150217905550610c7a610a4d565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a460019050610ce1565b5f90505b92915050565b5f610cf283836107dc565b15610dc7575f60065f8581526020019081526020015f205f015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff021916908315150217905550610d64610a4d565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16847ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b60405160405180910390a460019050610dcb565b5f90505b92915050565b610dd96111ca565b5f60055f6101000a81548160ff0219169083151502179055507f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa610e1b610a4d565b604051610e289190611933565b60405180910390a1565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610ea2575f6040517fec442f05000000000000000000000000000000000000000000000000000000008152600401610e999190611933565b60405180910390fd5b610ead5f8383611161565b5050565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610f21575f6040517f96c6fd1e000000000000000000000000000000000000000000000000000000008152600401610f189190611933565b60405180910390fd5b610f2c825f83611161565b5050565b610f3861120a565b600160055f6101000a81548160ff0219169083151502179055507f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258610f7b610a4d565b604051610f889190611933565b60405180910390a1565b5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1603611002575f6040517fe602df05000000000000000000000000000000000000000000000000000000008152600401610ff99190611933565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603611072575f6040517f94280d620000000000000000000000000000000000000000000000000000000081526004016110699190611933565b60405180910390fd5b8160015f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2081905550801561115b578273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92584604051611152919061169d565b60405180910390a35b50505050565b61116961120a565b61117483838361124b565b505050565b61118382826107dc565b6111c65780826040517fe2517d3f0000000000000000000000000000000000000000000000000000000081526004016111bd92919061194c565b60405180910390fd5b5050565b6111d261072d565b611208576040517f8dfc202b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b61121261072d565b15611249576040517fd93c066500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b61125361120a565b61125e838383611263565b505050565b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036112b3578060025f8282546112a791906119a0565b92505081905550611381565b5f5f5f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205490508181101561133c578381836040517fe450d38c000000000000000000000000000000000000000000000000000000008152600401611333939291906118fe565b60405180910390fd5b8181035f5f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2081905550505b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036113c8578060025f8282540392505081905550611412565b805f5f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825401925050819055505b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8360405161146f919061169d565b60405180910390a3505050565b5f5ffd5b5f7fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b6114b481611480565b81146114be575f5ffd5b50565b5f813590506114cf816114ab565b92915050565b5f602082840312156114ea576114e961147c565b5b5f6114f7848285016114c1565b91505092915050565b5f8115159050919050565b61151481611500565b82525050565b5f60208201905061152d5f83018461150b565b92915050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f61157582611533565b61157f818561153d565b935061158f81856020860161154d565b6115988161155b565b840191505092915050565b5f6020820190508181035f8301526115bb818461156b565b905092915050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6115ec826115c3565b9050919050565b6115fc816115e2565b8114611606575f5ffd5b50565b5f81359050611617816115f3565b92915050565b5f819050919050565b61162f8161161d565b8114611639575f5ffd5b50565b5f8135905061164a81611626565b92915050565b5f5f604083850312156116665761166561147c565b5b5f61167385828601611609565b92505060206116848582860161163c565b9150509250929050565b6116978161161d565b82525050565b5f6020820190506116b05f83018461168e565b92915050565b5f5f5f606084860312156116cd576116cc61147c565b5b5f6116da86828701611609565b93505060206116eb86828701611609565b92505060406116fc8682870161163c565b9150509250925092565b5f819050919050565b61171881611706565b8114611722575f5ffd5b50565b5f813590506117338161170f565b92915050565b5f6020828403121561174e5761174d61147c565b5b5f61175b84828501611725565b91505092915050565b61176d81611706565b82525050565b5f6020820190506117865f830184611764565b92915050565b5f5f604083850312156117a2576117a161147c565b5b5f6117af85828601611725565b92505060206117c085828601611609565b9150509250929050565b5f60ff82169050919050565b6117df816117ca565b82525050565b5f6020820190506117f85f8301846117d6565b92915050565b5f602082840312156118135761181261147c565b5b5f6118208482850161163c565b91505092915050565b5f6020828403121561183e5761183d61147c565b5b5f61184b84828501611609565b91505092915050565b5f5f6040838503121561186a5761186961147c565b5b5f61187785828601611609565b925050602061188885828601611609565b9150509250929050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f60028204905060018216806118d657607f821691505b6020821081036118e9576118e8611892565b5b50919050565b6118f8816115e2565b82525050565b5f6060820190506119115f8301866118ef565b61191e602083018561168e565b61192b604083018461168e565b949350505050565b5f6020820190506119465f8301846118ef565b92915050565b5f60408201905061195f5f8301856118ef565b61196c6020830184611764565b9392505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f6119aa8261161d565b91506119b58361161d565b92508282019050808211156119cd576119cc611973565b5b9291505056 + /// ``` + #[rustfmt::skip] + #[allow(clippy::all)] + pub static BYTECODE: alloy_sol_types::private::Bytes = alloy_sol_types::private::Bytes::from_static( + b"`\xA0`@R4\x80\x15a\0\x0FW__\xFD[P`@Qa!\x168\x03\x80a!\x16\x839\x81\x81\x01`@R\x81\x01\x90a\x001\x91\x90a\x03\xC4V[\x82\x82\x81`\x03\x90\x81a\0B\x91\x90a\x06\\V[P\x80`\x04\x90\x81a\0R\x91\x90a\x06\\V[PPP\x80`\xFF\x16`\x80\x81`\xFF\x16\x81RPPa\0u__\x1B3a\0\xE0` \x1B` \x1CV[Pa\0\xA6\x7Fe\xD7\xA2\x8E2e\xB3zdt\x92\x9F3e!\xB32\xC1h\x1B\x93?l\xB9\xF37fsD\r\x86*3a\0\xE0` \x1B` \x1CV[Pa\0\xD7\x7F\x9F-\xF0\xFE\xD2\xC7vH\xDEX`\xA4\xCCP\x8C\xD0\x81\x8C\x85\xB8\xB8\xA1\xABL\xEE\xEF\x8D\x98\x1C\x89V\xA63a\0\xE0` \x1B` \x1CV[PPPPa\x07+V[_a\0\xF1\x83\x83a\x01\xD6` \x1B` \x1CV[a\x01\xCCW`\x01`\x06_\x85\x81R` \x01\x90\x81R` \x01_ _\x01_\x84s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01\x90\x81R` \x01_ _a\x01\0\n\x81T\x81`\xFF\x02\x19\x16\x90\x83\x15\x15\x02\x17\x90UPa\x01ia\x02:` \x1B` \x1CV[s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x82s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x84\x7F/\x87\x88\x11~~\xFF\x1D\x82\xE9&\xECyI\x01\xD1|x\x02JP'\t@0E@\xA73eo\r`@Q`@Q\x80\x91\x03\x90\xA4`\x01\x90Pa\x01\xD0V[_\x90P[\x92\x91PPV[_`\x06_\x84\x81R` \x01\x90\x81R` \x01_ _\x01_\x83s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01\x90\x81R` \x01_ _\x90T\x90a\x01\0\n\x90\x04`\xFF\x16\x90P\x92\x91PPV[_3\x90P\x90V[_`@Q\x90P\x90V[__\xFD[__\xFD[__\xFD[__\xFD[_`\x1F\x19`\x1F\x83\x01\x16\x90P\x91\x90PV[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_R`A`\x04R`$_\xFD[a\x02\xA0\x82a\x02ZV[\x81\x01\x81\x81\x10g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x11\x17\x15a\x02\xBFWa\x02\xBEa\x02jV[[\x80`@RPPPV[_a\x02\xD1a\x02AV[\x90Pa\x02\xDD\x82\x82a\x02\x97V[\x91\x90PV[_g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82\x11\x15a\x02\xFCWa\x02\xFBa\x02jV[[a\x03\x05\x82a\x02ZV[\x90P` \x81\x01\x90P\x91\x90PV[\x82\x81\x83^_\x83\x83\x01RPPPV[_a\x032a\x03-\x84a\x02\xE2V[a\x02\xC8V[\x90P\x82\x81R` \x81\x01\x84\x84\x84\x01\x11\x15a\x03NWa\x03Ma\x02VV[[a\x03Y\x84\x82\x85a\x03\x12V[P\x93\x92PPPV[_\x82`\x1F\x83\x01\x12a\x03uWa\x03ta\x02RV[[\x81Qa\x03\x85\x84\x82` \x86\x01a\x03 V[\x91PP\x92\x91PPV[_`\xFF\x82\x16\x90P\x91\x90PV[a\x03\xA3\x81a\x03\x8EV[\x81\x14a\x03\xADW__\xFD[PV[_\x81Q\x90Pa\x03\xBE\x81a\x03\x9AV[\x92\x91PPV[___``\x84\x86\x03\x12\x15a\x03\xDBWa\x03\xDAa\x02JV[[_\x84\x01Qg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\x03\xF8Wa\x03\xF7a\x02NV[[a\x04\x04\x86\x82\x87\x01a\x03aV[\x93PP` \x84\x01Qg\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\x04%Wa\x04$a\x02NV[[a\x041\x86\x82\x87\x01a\x03aV[\x92PP`@a\x04B\x86\x82\x87\x01a\x03\xB0V[\x91PP\x92P\x92P\x92V[_\x81Q\x90P\x91\x90PV[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_R`\"`\x04R`$_\xFD[_`\x02\x82\x04\x90P`\x01\x82\x16\x80a\x04\x9AW`\x7F\x82\x16\x91P[` \x82\x10\x81\x03a\x04\xADWa\x04\xACa\x04VV[[P\x91\x90PV[_\x81\x90P\x81_R` _ \x90P\x91\x90PV[_` `\x1F\x83\x01\x04\x90P\x91\x90PV[_\x82\x82\x1B\x90P\x92\x91PPV[_`\x08\x83\x02a\x05\x0F\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x82a\x04\xD4V[a\x05\x19\x86\x83a\x04\xD4V[\x95P\x80\x19\x84\x16\x93P\x80\x86\x16\x84\x17\x92PPP\x93\x92PPPV[_\x81\x90P\x91\x90PV[_\x81\x90P\x91\x90PV[_a\x05]a\x05Xa\x05S\x84a\x051V[a\x05:V[a\x051V[\x90P\x91\x90PV[_\x81\x90P\x91\x90PV[a\x05v\x83a\x05CV[a\x05\x8Aa\x05\x82\x82a\x05dV[\x84\x84Ta\x04\xE0V[\x82UPPPPV[__\x90P\x90V[a\x05\xA1a\x05\x92V[a\x05\xAC\x81\x84\x84a\x05mV[PPPV[[\x81\x81\x10\x15a\x05\xCFWa\x05\xC4_\x82a\x05\x99V[`\x01\x81\x01\x90Pa\x05\xB2V[PPV[`\x1F\x82\x11\x15a\x06\x14Wa\x05\xE5\x81a\x04\xB3V[a\x05\xEE\x84a\x04\xC5V[\x81\x01` \x85\x10\x15a\x05\xFDW\x81\x90P[a\x06\x11a\x06\t\x85a\x04\xC5V[\x83\x01\x82a\x05\xB1V[PP[PPPV[_\x82\x82\x1C\x90P\x92\x91PPV[_a\x064_\x19\x84`\x08\x02a\x06\x19V[\x19\x80\x83\x16\x91PP\x92\x91PPV[_a\x06L\x83\x83a\x06%V[\x91P\x82`\x02\x02\x82\x17\x90P\x92\x91PPV[a\x06e\x82a\x04LV[g\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x11\x15a\x06~Wa\x06}a\x02jV[[a\x06\x88\x82Ta\x04\x83V[a\x06\x93\x82\x82\x85a\x05\xD3V[_` \x90P`\x1F\x83\x11`\x01\x81\x14a\x06\xC4W_\x84\x15a\x06\xB2W\x82\x87\x01Q\x90P[a\x06\xBC\x85\x82a\x06AV[\x86UPa\x07#V[`\x1F\x19\x84\x16a\x06\xD2\x86a\x04\xB3V[_[\x82\x81\x10\x15a\x06\xF9W\x84\x89\x01Q\x82U`\x01\x82\x01\x91P` \x85\x01\x94P` \x81\x01\x90Pa\x06\xD4V[\x86\x83\x10\x15a\x07\x16W\x84\x89\x01Qa\x07\x12`\x1F\x89\x16\x82a\x06%V[\x83UP[`\x01`\x02\x88\x02\x01\x88UPPP[PPPPPPV[`\x80Qa\x19\xD3a\x07C_9_a\x06*\x01Ra\x19\xD3_\xF3\xFE`\x80`@R4\x80\x15a\0\x0FW__\xFD[P`\x046\x10a\x01VW_5`\xE0\x1C\x80c\\\x97Z\xBB\x11a\0\xC1W\x80c\xA2\x17\xFD\xDF\x11a\0zW\x80c\xA2\x17\xFD\xDF\x14a\x03\xB0W\x80c\xA9\x05\x9C\xBB\x14a\x03\xCEW\x80c\xD59\x13\x93\x14a\x03\xFEW\x80c\xD5Gt\x1F\x14a\x04\x1CW\x80c\xDDb\xED>\x14a\x048W\x80c\xE6:\xB1\xE9\x14a\x04hWa\x01VV[\x80c\\\x97Z\xBB\x14a\x02\xEEW\x80cp\xA0\x821\x14a\x03\x0CW\x80cy\xCCg\x90\x14a\x03V[`@Qa\x04_\x91\x90a\x16\x9DV[`@Q\x80\x91\x03\x90\xF3[a\x04pa\t\xC0V[`@Qa\x04}\x91\x90a\x17sV[`@Q\x80\x91\x03\x90\xF3[_\x7Fye\xDB\x0B\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0{\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x19\x16\x82{\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x19\x16\x14\x80a\x04\xF8WPa\x04\xF7\x82a\t\xE4V[[\x90P\x91\x90PV[```\x03\x80Ta\x05\x0E\x90a\x18\xBFV[\x80`\x1F\x01` \x80\x91\x04\x02` \x01`@Q\x90\x81\x01`@R\x80\x92\x91\x90\x81\x81R` \x01\x82\x80Ta\x05:\x90a\x18\xBFV[\x80\x15a\x05\x85W\x80`\x1F\x10a\x05\\Wa\x01\0\x80\x83T\x04\x02\x83R\x91` \x01\x91a\x05\x85V[\x82\x01\x91\x90_R` _ \x90[\x81T\x81R\x90`\x01\x01\x90` \x01\x80\x83\x11a\x05hW\x82\x90\x03`\x1F\x16\x82\x01\x91[PPPPP\x90P\x90V[__a\x05\x99a\nMV[\x90Pa\x05\xA6\x81\x85\x85a\nTV[`\x01\x91PP\x92\x91PPV[_`\x02T\x90P\x90V[__a\x05\xC4a\nMV[\x90Pa\x05\xD1\x85\x82\x85a\nfV[a\x05\xDC\x85\x85\x85a\n\xF9V[`\x01\x91PP\x93\x92PPPV[_`\x06_\x83\x81R` \x01\x90\x81R` \x01_ `\x01\x01T\x90P\x91\x90PV[a\x06\x0E\x82a\x05\xE8V[a\x06\x17\x81a\x0B\xE9V[a\x06!\x83\x83a\x0B\xFDV[PPPPV[_\x7F\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x90P\x90V[a\x06Va\nMV[s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x06\xBAW`@Q\x7Ff\x97\xB22\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01`@Q\x80\x91\x03\x90\xFD[a\x06\xC4\x82\x82a\x0C\xE7V[PPPV[__\x1Ba\x06\xD5\x81a\x0B\xE9V[a\x06\xDDa\r\xD1V[PV[\x7F\x9F-\xF0\xFE\xD2\xC7vH\xDEX`\xA4\xCCP\x8C\xD0\x81\x8C\x85\xB8\xB8\xA1\xABL\xEE\xEF\x8D\x98\x1C\x89V\xA6a\x07\n\x81a\x0B\xE9V[a\x07\x14\x83\x83a\x0E2V[PPPV[a\x07*a\x07$a\nMV[\x82a\x0E\xB1V[PV[_`\x05_\x90T\x90a\x01\0\n\x90\x04`\xFF\x16\x90P\x90V[___\x83s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01\x90\x81R` \x01_ T\x90P\x91\x90PV[a\x07\x99\x82a\x07\x93a\nMV[\x83a\nfV[a\x07\xA3\x82\x82a\x0E\xB1V[PPV[\x7Fe\xD7\xA2\x8E2e\xB3zdt\x92\x9F3e!\xB32\xC1h\x1B\x93?l\xB9\xF37fsD\r\x86*a\x07\xD1\x81a\x0B\xE9V[a\x07\xD9a\x0F0V[PV[_`\x06_\x84\x81R` \x01\x90\x81R` \x01_ _\x01_\x83s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01\x90\x81R` \x01_ _\x90T\x90a\x01\0\n\x90\x04`\xFF\x16\x90P\x92\x91PPV[```\x04\x80Ta\x08O\x90a\x18\xBFV[\x80`\x1F\x01` \x80\x91\x04\x02` \x01`@Q\x90\x81\x01`@R\x80\x92\x91\x90\x81\x81R` \x01\x82\x80Ta\x08{\x90a\x18\xBFV[\x80\x15a\x08\xC6W\x80`\x1F\x10a\x08\x9DWa\x01\0\x80\x83T\x04\x02\x83R\x91` \x01\x91a\x08\xC6V[\x82\x01\x91\x90_R` _ \x90[\x81T\x81R\x90`\x01\x01\x90` \x01\x80\x83\x11a\x08\xA9W\x82\x90\x03`\x1F\x16\x82\x01\x91[PPPPP\x90P\x90V[__\x1B\x81V[__a\x08\xE0a\nMV[\x90Pa\x08\xED\x81\x85\x85a\n\xF9V[`\x01\x91PP\x92\x91PPV[\x7F\x9F-\xF0\xFE\xD2\xC7vH\xDEX`\xA4\xCCP\x8C\xD0\x81\x8C\x85\xB8\xB8\xA1\xABL\xEE\xEF\x8D\x98\x1C\x89V\xA6\x81V[a\t%\x82a\x05\xE8V[a\t.\x81a\x0B\xE9V[a\t8\x83\x83a\x0C\xE7V[PPPPV[_`\x01_\x84s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01\x90\x81R` \x01_ _\x83s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01\x90\x81R` \x01_ T\x90P\x92\x91PPV[\x7Fe\xD7\xA2\x8E2e\xB3zdt\x92\x9F3e!\xB32\xC1h\x1B\x93?l\xB9\xF37fsD\r\x86*\x81V[_\x7F\x01\xFF\xC9\xA7\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0{\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x19\x16\x82{\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x19\x16\x14\x90P\x91\x90PV[_3\x90P\x90V[a\na\x83\x83\x83`\x01a\x0F\x92V[PPPV[_a\nq\x84\x84a\t>V[\x90P\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x10\x15a\n\xF3W\x81\x81\x10\x15a\n\xE4W\x82\x81\x83`@Q\x7F\xFB\x8FA\xB2\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\n\xDB\x93\x92\x91\x90a\x18\xFEV[`@Q\x80\x91\x03\x90\xFD[a\n\xF2\x84\x84\x84\x84\x03_a\x0F\x92V[[PPPPV[_s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x83s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x03a\x0BiW_`@Q\x7F\x96\xC6\xFD\x1E\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x0B`\x91\x90a\x193V[`@Q\x80\x91\x03\x90\xFD[_s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x82s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x03a\x0B\xD9W_`@Q\x7F\xECD/\x05\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x0B\xD0\x91\x90a\x193V[`@Q\x80\x91\x03\x90\xFD[a\x0B\xE4\x83\x83\x83a\x11aV[PPPV[a\x0B\xFA\x81a\x0B\xF5a\nMV[a\x11yV[PV[_a\x0C\x08\x83\x83a\x07\xDCV[a\x0C\xDDW`\x01`\x06_\x85\x81R` \x01\x90\x81R` \x01_ _\x01_\x84s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01\x90\x81R` \x01_ _a\x01\0\n\x81T\x81`\xFF\x02\x19\x16\x90\x83\x15\x15\x02\x17\x90UPa\x0Cza\nMV[s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x82s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x84\x7F/\x87\x88\x11~~\xFF\x1D\x82\xE9&\xECyI\x01\xD1|x\x02JP'\t@0E@\xA73eo\r`@Q`@Q\x80\x91\x03\x90\xA4`\x01\x90Pa\x0C\xE1V[_\x90P[\x92\x91PPV[_a\x0C\xF2\x83\x83a\x07\xDCV[\x15a\r\xC7W_`\x06_\x85\x81R` \x01\x90\x81R` \x01_ _\x01_\x84s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01\x90\x81R` \x01_ _a\x01\0\n\x81T\x81`\xFF\x02\x19\x16\x90\x83\x15\x15\x02\x17\x90UPa\rda\nMV[s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x82s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x84\x7F\xF69\x1F\\2\xD9\xC6\x9D*G\xEAg\x0BD)t\xB595\xD1\xED\xC7\xFDd\xEB!\xE0G\xA89\x17\x1B`@Q`@Q\x80\x91\x03\x90\xA4`\x01\x90Pa\r\xCBV[_\x90P[\x92\x91PPV[a\r\xD9a\x11\xCAV[_`\x05_a\x01\0\n\x81T\x81`\xFF\x02\x19\x16\x90\x83\x15\x15\x02\x17\x90UP\x7F]\xB9\xEE\nI[\xF2\xE6\xFF\x9C\x91\xA7\x83L\x1B\xA4\xFD\xD2D\xA5\xE8\xAANS{\xD3\x8A\xEA\xE4\xB0s\xAAa\x0E\x1Ba\nMV[`@Qa\x0E(\x91\x90a\x193V[`@Q\x80\x91\x03\x90\xA1V[_s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x82s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x03a\x0E\xA2W_`@Q\x7F\xECD/\x05\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x0E\x99\x91\x90a\x193V[`@Q\x80\x91\x03\x90\xFD[a\x0E\xAD_\x83\x83a\x11aV[PPV[_s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x82s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x03a\x0F!W_`@Q\x7F\x96\xC6\xFD\x1E\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x0F\x18\x91\x90a\x193V[`@Q\x80\x91\x03\x90\xFD[a\x0F,\x82_\x83a\x11aV[PPV[a\x0F8a\x12\nV[`\x01`\x05_a\x01\0\n\x81T\x81`\xFF\x02\x19\x16\x90\x83\x15\x15\x02\x17\x90UP\x7Fb\xE7\x8C\xEA\x01\xBE\xE3 \xCDNB\x02p\xB5\xEAt\0\r\x11\xB0\xC9\xF7GT\xEB\xDB\xFCTK\x05\xA2Xa\x0F{a\nMV[`@Qa\x0F\x88\x91\x90a\x193V[`@Q\x80\x91\x03\x90\xA1V[_s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x84s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x03a\x10\x02W_`@Q\x7F\xE6\x02\xDF\x05\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x0F\xF9\x91\x90a\x193V[`@Q\x80\x91\x03\x90\xFD[_s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x83s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x03a\x10rW_`@Q\x7F\x94(\rb\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x10i\x91\x90a\x193V[`@Q\x80\x91\x03\x90\xFD[\x81`\x01_\x86s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01\x90\x81R` \x01_ _\x85s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01\x90\x81R` \x01_ \x81\x90UP\x80\x15a\x11[W\x82s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x84s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x7F\x8C[\xE1\xE5\xEB\xEC}[\xD1OqB}\x1E\x84\xF3\xDD\x03\x14\xC0\xF7\xB2)\x1E[ \n\xC8\xC7\xC3\xB9%\x84`@Qa\x11R\x91\x90a\x16\x9DV[`@Q\x80\x91\x03\x90\xA3[PPPPV[a\x11ia\x12\nV[a\x11t\x83\x83\x83a\x12KV[PPPV[a\x11\x83\x82\x82a\x07\xDCV[a\x11\xC6W\x80\x82`@Q\x7F\xE2Q}?\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x11\xBD\x92\x91\x90a\x19LV[`@Q\x80\x91\x03\x90\xFD[PPV[a\x11\xD2a\x07-V[a\x12\x08W`@Q\x7F\x8D\xFC +\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01`@Q\x80\x91\x03\x90\xFD[V[a\x12\x12a\x07-V[\x15a\x12IW`@Q\x7F\xD9<\x06e\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01`@Q\x80\x91\x03\x90\xFD[V[a\x12Sa\x12\nV[a\x12^\x83\x83\x83a\x12cV[PPPV[_s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x83s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x03a\x12\xB3W\x80`\x02_\x82\x82Ta\x12\xA7\x91\x90a\x19\xA0V[\x92PP\x81\x90UPa\x13\x81V[___\x85s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01\x90\x81R` \x01_ T\x90P\x81\x81\x10\x15a\x13Wa\x18=a\x14|V[[_a\x18K\x84\x82\x85\x01a\x16\tV[\x91PP\x92\x91PPV[__`@\x83\x85\x03\x12\x15a\x18jWa\x18ia\x14|V[[_a\x18w\x85\x82\x86\x01a\x16\tV[\x92PP` a\x18\x88\x85\x82\x86\x01a\x16\tV[\x91PP\x92P\x92\x90PV[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_R`\"`\x04R`$_\xFD[_`\x02\x82\x04\x90P`\x01\x82\x16\x80a\x18\xD6W`\x7F\x82\x16\x91P[` \x82\x10\x81\x03a\x18\xE9Wa\x18\xE8a\x18\x92V[[P\x91\x90PV[a\x18\xF8\x81a\x15\xE2V[\x82RPPV[_``\x82\x01\x90Pa\x19\x11_\x83\x01\x86a\x18\xEFV[a\x19\x1E` \x83\x01\x85a\x16\x8EV[a\x19+`@\x83\x01\x84a\x16\x8EV[\x94\x93PPPPV[_` \x82\x01\x90Pa\x19F_\x83\x01\x84a\x18\xEFV[\x92\x91PPV[_`@\x82\x01\x90Pa\x19__\x83\x01\x85a\x18\xEFV[a\x19l` \x83\x01\x84a\x17dV[\x93\x92PPPV[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_R`\x11`\x04R`$_\xFD[_a\x19\xAA\x82a\x16\x1DV[\x91Pa\x19\xB5\x83a\x16\x1DV[\x92P\x82\x82\x01\x90P\x80\x82\x11\x15a\x19\xCDWa\x19\xCCa\x19sV[[\x92\x91PPV", + ); + /// The runtime bytecode of the contract, as deployed on the network. + /// + /// ```text + ///0x608060405234801561000f575f5ffd5b5060043610610156575f3560e01c80635c975abb116100c1578063a217fddf1161007a578063a217fddf146103b0578063a9059cbb146103ce578063d5391393146103fe578063d547741f1461041c578063dd62ed3e14610438578063e63ab1e91461046857610156565b80635c975abb146102ee57806370a082311461030c57806379cc67901461033c5780638456cb591461035857806391d148541461036257806395d89b411461039257610156565b80632f2ff15d116101135780632f2ff15d14610256578063313ce5671461027257806336568abe146102905780633f4ba83a146102ac57806340c10f19146102b657806342966c68146102d257610156565b806301ffc9a71461015a57806306fdde031461018a578063095ea7b3146101a857806318160ddd146101d857806323b872dd146101f6578063248a9ca314610226575b5f5ffd5b610174600480360381019061016f91906114d5565b610486565b604051610181919061151a565b60405180910390f35b6101926104ff565b60405161019f91906115a3565b60405180910390f35b6101c260048036038101906101bd9190611650565b61058f565b6040516101cf919061151a565b60405180910390f35b6101e06105b1565b6040516101ed919061169d565b60405180910390f35b610210600480360381019061020b91906116b6565b6105ba565b60405161021d919061151a565b60405180910390f35b610240600480360381019061023b9190611739565b6105e8565b60405161024d9190611773565b60405180910390f35b610270600480360381019061026b919061178c565b610605565b005b61027a610627565b60405161028791906117e5565b60405180910390f35b6102aa60048036038101906102a5919061178c565b61064e565b005b6102b46106c9565b005b6102d060048036038101906102cb9190611650565b6106e0565b005b6102ec60048036038101906102e791906117fe565b610719565b005b6102f661072d565b604051610303919061151a565b60405180910390f35b61032660048036038101906103219190611829565b610742565b604051610333919061169d565b60405180910390f35b61035660048036038101906103519190611650565b610787565b005b6103606107a7565b005b61037c6004803603810190610377919061178c565b6107dc565b604051610389919061151a565b60405180910390f35b61039a610840565b6040516103a791906115a3565b60405180910390f35b6103b86108d0565b6040516103c59190611773565b60405180910390f35b6103e860048036038101906103e39190611650565b6108d6565b6040516103f5919061151a565b60405180910390f35b6104066108f8565b6040516104139190611773565b60405180910390f35b6104366004803603810190610431919061178c565b61091c565b005b610452600480360381019061044d9190611854565b61093e565b60405161045f919061169d565b60405180910390f35b6104706109c0565b60405161047d9190611773565b60405180910390f35b5f7f7965db0b000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806104f857506104f7826109e4565b5b9050919050565b60606003805461050e906118bf565b80601f016020809104026020016040519081016040528092919081815260200182805461053a906118bf565b80156105855780601f1061055c57610100808354040283529160200191610585565b820191905f5260205f20905b81548152906001019060200180831161056857829003601f168201915b5050505050905090565b5f5f610599610a4d565b90506105a6818585610a54565b600191505092915050565b5f600254905090565b5f5f6105c4610a4d565b90506105d1858285610a66565b6105dc858585610af9565b60019150509392505050565b5f60065f8381526020019081526020015f20600101549050919050565b61060e826105e8565b61061781610be9565b6106218383610bfd565b50505050565b5f7f0000000000000000000000000000000000000000000000000000000000000000905090565b610656610a4d565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146106ba576040517f6697b23200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6106c48282610ce7565b505050565b5f5f1b6106d581610be9565b6106dd610dd1565b50565b7f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a661070a81610be9565b6107148383610e32565b505050565b61072a610724610a4d565b82610eb1565b50565b5f60055f9054906101000a900460ff16905090565b5f5f5f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20549050919050565b61079982610793610a4d565b83610a66565b6107a38282610eb1565b5050565b7f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a6107d181610be9565b6107d9610f30565b50565b5f60065f8481526020019081526020015f205f015f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f9054906101000a900460ff16905092915050565b60606004805461084f906118bf565b80601f016020809104026020016040519081016040528092919081815260200182805461087b906118bf565b80156108c65780601f1061089d576101008083540402835291602001916108c6565b820191905f5260205f20905b8154815290600101906020018083116108a957829003601f168201915b5050505050905090565b5f5f1b81565b5f5f6108e0610a4d565b90506108ed818585610af9565b600191505092915050565b7f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a681565b610925826105e8565b61092e81610be9565b6109388383610ce7565b50505050565b5f60015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054905092915050565b7f65d7a28e3265b37a6474929f336521b332c1681b933f6cb9f3376673440d862a81565b5f7f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b5f33905090565b610a618383836001610f92565b505050565b5f610a71848461093e565b90507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff811015610af35781811015610ae4578281836040517ffb8f41b2000000000000000000000000000000000000000000000000000000008152600401610adb939291906118fe565b60405180910390fd5b610af284848484035f610f92565b5b50505050565b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610b69575f6040517f96c6fd1e000000000000000000000000000000000000000000000000000000008152600401610b609190611933565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610bd9575f6040517fec442f05000000000000000000000000000000000000000000000000000000008152600401610bd09190611933565b60405180910390fd5b610be4838383611161565b505050565b610bfa81610bf5610a4d565b611179565b50565b5f610c0883836107dc565b610cdd57600160065f8581526020019081526020015f205f015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff021916908315150217905550610c7a610a4d565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a460019050610ce1565b5f90505b92915050565b5f610cf283836107dc565b15610dc7575f60065f8581526020019081526020015f205f015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f6101000a81548160ff021916908315150217905550610d64610a4d565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16847ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b60405160405180910390a460019050610dcb565b5f90505b92915050565b610dd96111ca565b5f60055f6101000a81548160ff0219169083151502179055507f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa610e1b610a4d565b604051610e289190611933565b60405180910390a1565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610ea2575f6040517fec442f05000000000000000000000000000000000000000000000000000000008152600401610e999190611933565b60405180910390fd5b610ead5f8383611161565b5050565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610f21575f6040517f96c6fd1e000000000000000000000000000000000000000000000000000000008152600401610f189190611933565b60405180910390fd5b610f2c825f83611161565b5050565b610f3861120a565b600160055f6101000a81548160ff0219169083151502179055507f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258610f7b610a4d565b604051610f889190611933565b60405180910390a1565b5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1603611002575f6040517fe602df05000000000000000000000000000000000000000000000000000000008152600401610ff99190611933565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603611072575f6040517f94280d620000000000000000000000000000000000000000000000000000000081526004016110699190611933565b60405180910390fd5b8160015f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2081905550801561115b578273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92584604051611152919061169d565b60405180910390a35b50505050565b61116961120a565b61117483838361124b565b505050565b61118382826107dc565b6111c65780826040517fe2517d3f0000000000000000000000000000000000000000000000000000000081526004016111bd92919061194c565b60405180910390fd5b5050565b6111d261072d565b611208576040517f8dfc202b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b61121261072d565b15611249576040517fd93c066500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b61125361120a565b61125e838383611263565b505050565b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036112b3578060025f8282546112a791906119a0565b92505081905550611381565b5f5f5f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205490508181101561133c578381836040517fe450d38c000000000000000000000000000000000000000000000000000000008152600401611333939291906118fe565b60405180910390fd5b8181035f5f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2081905550505b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036113c8578060025f8282540392505081905550611412565b805f5f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825401925050819055505b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8360405161146f919061169d565b60405180910390a3505050565b5f5ffd5b5f7fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b6114b481611480565b81146114be575f5ffd5b50565b5f813590506114cf816114ab565b92915050565b5f602082840312156114ea576114e961147c565b5b5f6114f7848285016114c1565b91505092915050565b5f8115159050919050565b61151481611500565b82525050565b5f60208201905061152d5f83018461150b565b92915050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f61157582611533565b61157f818561153d565b935061158f81856020860161154d565b6115988161155b565b840191505092915050565b5f6020820190508181035f8301526115bb818461156b565b905092915050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6115ec826115c3565b9050919050565b6115fc816115e2565b8114611606575f5ffd5b50565b5f81359050611617816115f3565b92915050565b5f819050919050565b61162f8161161d565b8114611639575f5ffd5b50565b5f8135905061164a81611626565b92915050565b5f5f604083850312156116665761166561147c565b5b5f61167385828601611609565b92505060206116848582860161163c565b9150509250929050565b6116978161161d565b82525050565b5f6020820190506116b05f83018461168e565b92915050565b5f5f5f606084860312156116cd576116cc61147c565b5b5f6116da86828701611609565b93505060206116eb86828701611609565b92505060406116fc8682870161163c565b9150509250925092565b5f819050919050565b61171881611706565b8114611722575f5ffd5b50565b5f813590506117338161170f565b92915050565b5f6020828403121561174e5761174d61147c565b5b5f61175b84828501611725565b91505092915050565b61176d81611706565b82525050565b5f6020820190506117865f830184611764565b92915050565b5f5f604083850312156117a2576117a161147c565b5b5f6117af85828601611725565b92505060206117c085828601611609565b9150509250929050565b5f60ff82169050919050565b6117df816117ca565b82525050565b5f6020820190506117f85f8301846117d6565b92915050565b5f602082840312156118135761181261147c565b5b5f6118208482850161163c565b91505092915050565b5f6020828403121561183e5761183d61147c565b5b5f61184b84828501611609565b91505092915050565b5f5f6040838503121561186a5761186961147c565b5b5f61187785828601611609565b925050602061188885828601611609565b9150509250929050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f60028204905060018216806118d657607f821691505b6020821081036118e9576118e8611892565b5b50919050565b6118f8816115e2565b82525050565b5f6060820190506119115f8301866118ef565b61191e602083018561168e565b61192b604083018461168e565b949350505050565b5f6020820190506119465f8301846118ef565b92915050565b5f60408201905061195f5f8301856118ef565b61196c6020830184611764565b9392505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f6119aa8261161d565b91506119b58361161d565b92508282019050808211156119cd576119cc611973565b5b9291505056 + /// ``` + #[rustfmt::skip] + #[allow(clippy::all)] + pub static DEPLOYED_BYTECODE: alloy_sol_types::private::Bytes = alloy_sol_types::private::Bytes::from_static( + b"`\x80`@R4\x80\x15a\0\x0FW__\xFD[P`\x046\x10a\x01VW_5`\xE0\x1C\x80c\\\x97Z\xBB\x11a\0\xC1W\x80c\xA2\x17\xFD\xDF\x11a\0zW\x80c\xA2\x17\xFD\xDF\x14a\x03\xB0W\x80c\xA9\x05\x9C\xBB\x14a\x03\xCEW\x80c\xD59\x13\x93\x14a\x03\xFEW\x80c\xD5Gt\x1F\x14a\x04\x1CW\x80c\xDDb\xED>\x14a\x048W\x80c\xE6:\xB1\xE9\x14a\x04hWa\x01VV[\x80c\\\x97Z\xBB\x14a\x02\xEEW\x80cp\xA0\x821\x14a\x03\x0CW\x80cy\xCCg\x90\x14a\x03V[`@Qa\x04_\x91\x90a\x16\x9DV[`@Q\x80\x91\x03\x90\xF3[a\x04pa\t\xC0V[`@Qa\x04}\x91\x90a\x17sV[`@Q\x80\x91\x03\x90\xF3[_\x7Fye\xDB\x0B\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0{\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x19\x16\x82{\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x19\x16\x14\x80a\x04\xF8WPa\x04\xF7\x82a\t\xE4V[[\x90P\x91\x90PV[```\x03\x80Ta\x05\x0E\x90a\x18\xBFV[\x80`\x1F\x01` \x80\x91\x04\x02` \x01`@Q\x90\x81\x01`@R\x80\x92\x91\x90\x81\x81R` \x01\x82\x80Ta\x05:\x90a\x18\xBFV[\x80\x15a\x05\x85W\x80`\x1F\x10a\x05\\Wa\x01\0\x80\x83T\x04\x02\x83R\x91` \x01\x91a\x05\x85V[\x82\x01\x91\x90_R` _ \x90[\x81T\x81R\x90`\x01\x01\x90` \x01\x80\x83\x11a\x05hW\x82\x90\x03`\x1F\x16\x82\x01\x91[PPPPP\x90P\x90V[__a\x05\x99a\nMV[\x90Pa\x05\xA6\x81\x85\x85a\nTV[`\x01\x91PP\x92\x91PPV[_`\x02T\x90P\x90V[__a\x05\xC4a\nMV[\x90Pa\x05\xD1\x85\x82\x85a\nfV[a\x05\xDC\x85\x85\x85a\n\xF9V[`\x01\x91PP\x93\x92PPPV[_`\x06_\x83\x81R` \x01\x90\x81R` \x01_ `\x01\x01T\x90P\x91\x90PV[a\x06\x0E\x82a\x05\xE8V[a\x06\x17\x81a\x0B\xE9V[a\x06!\x83\x83a\x0B\xFDV[PPPPV[_\x7F\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x90P\x90V[a\x06Va\nMV[s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x14a\x06\xBAW`@Q\x7Ff\x97\xB22\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01`@Q\x80\x91\x03\x90\xFD[a\x06\xC4\x82\x82a\x0C\xE7V[PPPV[__\x1Ba\x06\xD5\x81a\x0B\xE9V[a\x06\xDDa\r\xD1V[PV[\x7F\x9F-\xF0\xFE\xD2\xC7vH\xDEX`\xA4\xCCP\x8C\xD0\x81\x8C\x85\xB8\xB8\xA1\xABL\xEE\xEF\x8D\x98\x1C\x89V\xA6a\x07\n\x81a\x0B\xE9V[a\x07\x14\x83\x83a\x0E2V[PPPV[a\x07*a\x07$a\nMV[\x82a\x0E\xB1V[PV[_`\x05_\x90T\x90a\x01\0\n\x90\x04`\xFF\x16\x90P\x90V[___\x83s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01\x90\x81R` \x01_ T\x90P\x91\x90PV[a\x07\x99\x82a\x07\x93a\nMV[\x83a\nfV[a\x07\xA3\x82\x82a\x0E\xB1V[PPV[\x7Fe\xD7\xA2\x8E2e\xB3zdt\x92\x9F3e!\xB32\xC1h\x1B\x93?l\xB9\xF37fsD\r\x86*a\x07\xD1\x81a\x0B\xE9V[a\x07\xD9a\x0F0V[PV[_`\x06_\x84\x81R` \x01\x90\x81R` \x01_ _\x01_\x83s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01\x90\x81R` \x01_ _\x90T\x90a\x01\0\n\x90\x04`\xFF\x16\x90P\x92\x91PPV[```\x04\x80Ta\x08O\x90a\x18\xBFV[\x80`\x1F\x01` \x80\x91\x04\x02` \x01`@Q\x90\x81\x01`@R\x80\x92\x91\x90\x81\x81R` \x01\x82\x80Ta\x08{\x90a\x18\xBFV[\x80\x15a\x08\xC6W\x80`\x1F\x10a\x08\x9DWa\x01\0\x80\x83T\x04\x02\x83R\x91` \x01\x91a\x08\xC6V[\x82\x01\x91\x90_R` _ \x90[\x81T\x81R\x90`\x01\x01\x90` \x01\x80\x83\x11a\x08\xA9W\x82\x90\x03`\x1F\x16\x82\x01\x91[PPPPP\x90P\x90V[__\x1B\x81V[__a\x08\xE0a\nMV[\x90Pa\x08\xED\x81\x85\x85a\n\xF9V[`\x01\x91PP\x92\x91PPV[\x7F\x9F-\xF0\xFE\xD2\xC7vH\xDEX`\xA4\xCCP\x8C\xD0\x81\x8C\x85\xB8\xB8\xA1\xABL\xEE\xEF\x8D\x98\x1C\x89V\xA6\x81V[a\t%\x82a\x05\xE8V[a\t.\x81a\x0B\xE9V[a\t8\x83\x83a\x0C\xE7V[PPPPV[_`\x01_\x84s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01\x90\x81R` \x01_ _\x83s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01\x90\x81R` \x01_ T\x90P\x92\x91PPV[\x7Fe\xD7\xA2\x8E2e\xB3zdt\x92\x9F3e!\xB32\xC1h\x1B\x93?l\xB9\xF37fsD\r\x86*\x81V[_\x7F\x01\xFF\xC9\xA7\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0{\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x19\x16\x82{\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x19\x16\x14\x90P\x91\x90PV[_3\x90P\x90V[a\na\x83\x83\x83`\x01a\x0F\x92V[PPPV[_a\nq\x84\x84a\t>V[\x90P\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x81\x10\x15a\n\xF3W\x81\x81\x10\x15a\n\xE4W\x82\x81\x83`@Q\x7F\xFB\x8FA\xB2\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\n\xDB\x93\x92\x91\x90a\x18\xFEV[`@Q\x80\x91\x03\x90\xFD[a\n\xF2\x84\x84\x84\x84\x03_a\x0F\x92V[[PPPPV[_s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x83s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x03a\x0BiW_`@Q\x7F\x96\xC6\xFD\x1E\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x0B`\x91\x90a\x193V[`@Q\x80\x91\x03\x90\xFD[_s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x82s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x03a\x0B\xD9W_`@Q\x7F\xECD/\x05\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x0B\xD0\x91\x90a\x193V[`@Q\x80\x91\x03\x90\xFD[a\x0B\xE4\x83\x83\x83a\x11aV[PPPV[a\x0B\xFA\x81a\x0B\xF5a\nMV[a\x11yV[PV[_a\x0C\x08\x83\x83a\x07\xDCV[a\x0C\xDDW`\x01`\x06_\x85\x81R` \x01\x90\x81R` \x01_ _\x01_\x84s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01\x90\x81R` \x01_ _a\x01\0\n\x81T\x81`\xFF\x02\x19\x16\x90\x83\x15\x15\x02\x17\x90UPa\x0Cza\nMV[s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x82s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x84\x7F/\x87\x88\x11~~\xFF\x1D\x82\xE9&\xECyI\x01\xD1|x\x02JP'\t@0E@\xA73eo\r`@Q`@Q\x80\x91\x03\x90\xA4`\x01\x90Pa\x0C\xE1V[_\x90P[\x92\x91PPV[_a\x0C\xF2\x83\x83a\x07\xDCV[\x15a\r\xC7W_`\x06_\x85\x81R` \x01\x90\x81R` \x01_ _\x01_\x84s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01\x90\x81R` \x01_ _a\x01\0\n\x81T\x81`\xFF\x02\x19\x16\x90\x83\x15\x15\x02\x17\x90UPa\rda\nMV[s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x82s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x84\x7F\xF69\x1F\\2\xD9\xC6\x9D*G\xEAg\x0BD)t\xB595\xD1\xED\xC7\xFDd\xEB!\xE0G\xA89\x17\x1B`@Q`@Q\x80\x91\x03\x90\xA4`\x01\x90Pa\r\xCBV[_\x90P[\x92\x91PPV[a\r\xD9a\x11\xCAV[_`\x05_a\x01\0\n\x81T\x81`\xFF\x02\x19\x16\x90\x83\x15\x15\x02\x17\x90UP\x7F]\xB9\xEE\nI[\xF2\xE6\xFF\x9C\x91\xA7\x83L\x1B\xA4\xFD\xD2D\xA5\xE8\xAANS{\xD3\x8A\xEA\xE4\xB0s\xAAa\x0E\x1Ba\nMV[`@Qa\x0E(\x91\x90a\x193V[`@Q\x80\x91\x03\x90\xA1V[_s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x82s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x03a\x0E\xA2W_`@Q\x7F\xECD/\x05\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x0E\x99\x91\x90a\x193V[`@Q\x80\x91\x03\x90\xFD[a\x0E\xAD_\x83\x83a\x11aV[PPV[_s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x82s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x03a\x0F!W_`@Q\x7F\x96\xC6\xFD\x1E\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x0F\x18\x91\x90a\x193V[`@Q\x80\x91\x03\x90\xFD[a\x0F,\x82_\x83a\x11aV[PPV[a\x0F8a\x12\nV[`\x01`\x05_a\x01\0\n\x81T\x81`\xFF\x02\x19\x16\x90\x83\x15\x15\x02\x17\x90UP\x7Fb\xE7\x8C\xEA\x01\xBE\xE3 \xCDNB\x02p\xB5\xEAt\0\r\x11\xB0\xC9\xF7GT\xEB\xDB\xFCTK\x05\xA2Xa\x0F{a\nMV[`@Qa\x0F\x88\x91\x90a\x193V[`@Q\x80\x91\x03\x90\xA1V[_s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x84s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x03a\x10\x02W_`@Q\x7F\xE6\x02\xDF\x05\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x0F\xF9\x91\x90a\x193V[`@Q\x80\x91\x03\x90\xFD[_s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x83s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x03a\x10rW_`@Q\x7F\x94(\rb\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x10i\x91\x90a\x193V[`@Q\x80\x91\x03\x90\xFD[\x81`\x01_\x86s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01\x90\x81R` \x01_ _\x85s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01\x90\x81R` \x01_ \x81\x90UP\x80\x15a\x11[W\x82s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x84s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x7F\x8C[\xE1\xE5\xEB\xEC}[\xD1OqB}\x1E\x84\xF3\xDD\x03\x14\xC0\xF7\xB2)\x1E[ \n\xC8\xC7\xC3\xB9%\x84`@Qa\x11R\x91\x90a\x16\x9DV[`@Q\x80\x91\x03\x90\xA3[PPPPV[a\x11ia\x12\nV[a\x11t\x83\x83\x83a\x12KV[PPPV[a\x11\x83\x82\x82a\x07\xDCV[a\x11\xC6W\x80\x82`@Q\x7F\xE2Q}?\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01a\x11\xBD\x92\x91\x90a\x19LV[`@Q\x80\x91\x03\x90\xFD[PPV[a\x11\xD2a\x07-V[a\x12\x08W`@Q\x7F\x8D\xFC +\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01`@Q\x80\x91\x03\x90\xFD[V[a\x12\x12a\x07-V[\x15a\x12IW`@Q\x7F\xD9<\x06e\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x81R`\x04\x01`@Q\x80\x91\x03\x90\xFD[V[a\x12Sa\x12\nV[a\x12^\x83\x83\x83a\x12cV[PPPV[_s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x83s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x03a\x12\xB3W\x80`\x02_\x82\x82Ta\x12\xA7\x91\x90a\x19\xA0V[\x92PP\x81\x90UPa\x13\x81V[___\x85s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16s\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x16\x81R` \x01\x90\x81R` \x01_ T\x90P\x81\x81\x10\x15a\x13Wa\x18=a\x14|V[[_a\x18K\x84\x82\x85\x01a\x16\tV[\x91PP\x92\x91PPV[__`@\x83\x85\x03\x12\x15a\x18jWa\x18ia\x14|V[[_a\x18w\x85\x82\x86\x01a\x16\tV[\x92PP` a\x18\x88\x85\x82\x86\x01a\x16\tV[\x91PP\x92P\x92\x90PV[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_R`\"`\x04R`$_\xFD[_`\x02\x82\x04\x90P`\x01\x82\x16\x80a\x18\xD6W`\x7F\x82\x16\x91P[` \x82\x10\x81\x03a\x18\xE9Wa\x18\xE8a\x18\x92V[[P\x91\x90PV[a\x18\xF8\x81a\x15\xE2V[\x82RPPV[_``\x82\x01\x90Pa\x19\x11_\x83\x01\x86a\x18\xEFV[a\x19\x1E` \x83\x01\x85a\x16\x8EV[a\x19+`@\x83\x01\x84a\x16\x8EV[\x94\x93PPPPV[_` \x82\x01\x90Pa\x19F_\x83\x01\x84a\x18\xEFV[\x92\x91PPV[_`@\x82\x01\x90Pa\x19__\x83\x01\x85a\x18\xEFV[a\x19l` \x83\x01\x84a\x17dV[\x93\x92PPPV[\x7FNH{q\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0_R`\x11`\x04R`$_\xFD[_a\x19\xAA\x82a\x16\x1DV[\x91Pa\x19\xB5\x83a\x16\x1DV[\x92P\x82\x82\x01\x90P\x80\x82\x11\x15a\x19\xCDWa\x19\xCCa\x19sV[[\x92\x91PPV", + ); + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Custom error with signature `AccessControlBadConfirmation()` and selector `0x6697b232`. +```solidity +error AccessControlBadConfirmation(); +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct AccessControlBadConfirmation; + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From + for UnderlyingRustTuple<'_> { + fn from(value: AccessControlBadConfirmation) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> + for AccessControlBadConfirmation { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self + } + } + #[automatically_derived] + impl alloy_sol_types::SolError for AccessControlBadConfirmation { + type Parameters<'a> = UnderlyingSolTuple<'a>; + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "AccessControlBadConfirmation()"; + const SELECTOR: [u8; 4] = [102u8, 151u8, 178u8, 50u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + () + } + #[inline] + fn abi_decode_raw_validate(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(Self::new) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Custom error with signature `AccessControlUnauthorizedAccount(address,bytes32)` and selector `0xe2517d3f`. +```solidity +error AccessControlUnauthorizedAccount(address account, bytes32 neededRole); +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct AccessControlUnauthorizedAccount { + #[allow(missing_docs)] + pub account: alloy::sol_types::private::Address, + #[allow(missing_docs)] + pub neededRole: alloy::sol_types::private::FixedBytes<32>, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[doc(hidden)] + type UnderlyingSolTuple<'a> = ( + alloy::sol_types::sol_data::Address, + alloy::sol_types::sol_data::FixedBytes<32>, + ); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = ( + alloy::sol_types::private::Address, + alloy::sol_types::private::FixedBytes<32>, + ); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From + for UnderlyingRustTuple<'_> { + fn from(value: AccessControlUnauthorizedAccount) -> Self { + (value.account, value.neededRole) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> + for AccessControlUnauthorizedAccount { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { + account: tuple.0, + neededRole: tuple.1, + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolError for AccessControlUnauthorizedAccount { + type Parameters<'a> = UnderlyingSolTuple<'a>; + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "AccessControlUnauthorizedAccount(address,bytes32)"; + const SELECTOR: [u8; 4] = [226u8, 81u8, 125u8, 63u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + ( + ::tokenize( + &self.account, + ), + as alloy_sol_types::SolType>::tokenize(&self.neededRole), + ) + } + #[inline] + fn abi_decode_raw_validate(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(Self::new) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Custom error with signature `ERC20InsufficientAllowance(address,uint256,uint256)` and selector `0xfb8f41b2`. +```solidity +error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed); +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct ERC20InsufficientAllowance { + #[allow(missing_docs)] + pub spender: alloy::sol_types::private::Address, + #[allow(missing_docs)] + pub allowance: alloy::sol_types::private::primitives::aliases::U256, + #[allow(missing_docs)] + pub needed: alloy::sol_types::private::primitives::aliases::U256, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[doc(hidden)] + type UnderlyingSolTuple<'a> = ( + alloy::sol_types::sol_data::Address, + alloy::sol_types::sol_data::Uint<256>, + alloy::sol_types::sol_data::Uint<256>, + ); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = ( + alloy::sol_types::private::Address, + alloy::sol_types::private::primitives::aliases::U256, + alloy::sol_types::private::primitives::aliases::U256, + ); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From + for UnderlyingRustTuple<'_> { + fn from(value: ERC20InsufficientAllowance) -> Self { + (value.spender, value.allowance, value.needed) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> + for ERC20InsufficientAllowance { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { + spender: tuple.0, + allowance: tuple.1, + needed: tuple.2, + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolError for ERC20InsufficientAllowance { + type Parameters<'a> = UnderlyingSolTuple<'a>; + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "ERC20InsufficientAllowance(address,uint256,uint256)"; + const SELECTOR: [u8; 4] = [251u8, 143u8, 65u8, 178u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + ( + ::tokenize( + &self.spender, + ), + as alloy_sol_types::SolType>::tokenize(&self.allowance), + as alloy_sol_types::SolType>::tokenize(&self.needed), + ) + } + #[inline] + fn abi_decode_raw_validate(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(Self::new) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Custom error with signature `ERC20InsufficientBalance(address,uint256,uint256)` and selector `0xe450d38c`. +```solidity +error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed); +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct ERC20InsufficientBalance { + #[allow(missing_docs)] + pub sender: alloy::sol_types::private::Address, + #[allow(missing_docs)] + pub balance: alloy::sol_types::private::primitives::aliases::U256, + #[allow(missing_docs)] + pub needed: alloy::sol_types::private::primitives::aliases::U256, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[doc(hidden)] + type UnderlyingSolTuple<'a> = ( + alloy::sol_types::sol_data::Address, + alloy::sol_types::sol_data::Uint<256>, + alloy::sol_types::sol_data::Uint<256>, + ); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = ( + alloy::sol_types::private::Address, + alloy::sol_types::private::primitives::aliases::U256, + alloy::sol_types::private::primitives::aliases::U256, + ); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From + for UnderlyingRustTuple<'_> { + fn from(value: ERC20InsufficientBalance) -> Self { + (value.sender, value.balance, value.needed) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> + for ERC20InsufficientBalance { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { + sender: tuple.0, + balance: tuple.1, + needed: tuple.2, + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolError for ERC20InsufficientBalance { + type Parameters<'a> = UnderlyingSolTuple<'a>; + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "ERC20InsufficientBalance(address,uint256,uint256)"; + const SELECTOR: [u8; 4] = [228u8, 80u8, 211u8, 140u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + ( + ::tokenize( + &self.sender, + ), + as alloy_sol_types::SolType>::tokenize(&self.balance), + as alloy_sol_types::SolType>::tokenize(&self.needed), + ) + } + #[inline] + fn abi_decode_raw_validate(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(Self::new) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Custom error with signature `ERC20InvalidApprover(address)` and selector `0xe602df05`. +```solidity +error ERC20InvalidApprover(address approver); +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct ERC20InvalidApprover { + #[allow(missing_docs)] + pub approver: alloy::sol_types::private::Address, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (alloy::sol_types::sol_data::Address,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (alloy::sol_types::private::Address,); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: ERC20InvalidApprover) -> Self { + (value.approver,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for ERC20InvalidApprover { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { approver: tuple.0 } + } + } + #[automatically_derived] + impl alloy_sol_types::SolError for ERC20InvalidApprover { + type Parameters<'a> = UnderlyingSolTuple<'a>; + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "ERC20InvalidApprover(address)"; + const SELECTOR: [u8; 4] = [230u8, 2u8, 223u8, 5u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + ( + ::tokenize( + &self.approver, + ), + ) + } + #[inline] + fn abi_decode_raw_validate(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(Self::new) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Custom error with signature `ERC20InvalidReceiver(address)` and selector `0xec442f05`. +```solidity +error ERC20InvalidReceiver(address receiver); +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct ERC20InvalidReceiver { + #[allow(missing_docs)] + pub receiver: alloy::sol_types::private::Address, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (alloy::sol_types::sol_data::Address,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (alloy::sol_types::private::Address,); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: ERC20InvalidReceiver) -> Self { + (value.receiver,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for ERC20InvalidReceiver { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { receiver: tuple.0 } + } + } + #[automatically_derived] + impl alloy_sol_types::SolError for ERC20InvalidReceiver { + type Parameters<'a> = UnderlyingSolTuple<'a>; + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "ERC20InvalidReceiver(address)"; + const SELECTOR: [u8; 4] = [236u8, 68u8, 47u8, 5u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + ( + ::tokenize( + &self.receiver, + ), + ) + } + #[inline] + fn abi_decode_raw_validate(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(Self::new) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Custom error with signature `ERC20InvalidSender(address)` and selector `0x96c6fd1e`. +```solidity +error ERC20InvalidSender(address sender); +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct ERC20InvalidSender { + #[allow(missing_docs)] + pub sender: alloy::sol_types::private::Address, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (alloy::sol_types::sol_data::Address,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (alloy::sol_types::private::Address,); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: ERC20InvalidSender) -> Self { + (value.sender,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for ERC20InvalidSender { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { sender: tuple.0 } + } + } + #[automatically_derived] + impl alloy_sol_types::SolError for ERC20InvalidSender { + type Parameters<'a> = UnderlyingSolTuple<'a>; + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "ERC20InvalidSender(address)"; + const SELECTOR: [u8; 4] = [150u8, 198u8, 253u8, 30u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + ( + ::tokenize( + &self.sender, + ), + ) + } + #[inline] + fn abi_decode_raw_validate(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(Self::new) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Custom error with signature `ERC20InvalidSpender(address)` and selector `0x94280d62`. +```solidity +error ERC20InvalidSpender(address spender); +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct ERC20InvalidSpender { + #[allow(missing_docs)] + pub spender: alloy::sol_types::private::Address, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (alloy::sol_types::sol_data::Address,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (alloy::sol_types::private::Address,); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: ERC20InvalidSpender) -> Self { + (value.spender,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for ERC20InvalidSpender { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { spender: tuple.0 } + } + } + #[automatically_derived] + impl alloy_sol_types::SolError for ERC20InvalidSpender { + type Parameters<'a> = UnderlyingSolTuple<'a>; + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "ERC20InvalidSpender(address)"; + const SELECTOR: [u8; 4] = [148u8, 40u8, 13u8, 98u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + ( + ::tokenize( + &self.spender, + ), + ) + } + #[inline] + fn abi_decode_raw_validate(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(Self::new) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Custom error with signature `EnforcedPause()` and selector `0xd93c0665`. +```solidity +error EnforcedPause(); +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct EnforcedPause; + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: EnforcedPause) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for EnforcedPause { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self + } + } + #[automatically_derived] + impl alloy_sol_types::SolError for EnforcedPause { + type Parameters<'a> = UnderlyingSolTuple<'a>; + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "EnforcedPause()"; + const SELECTOR: [u8; 4] = [217u8, 60u8, 6u8, 101u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + () + } + #[inline] + fn abi_decode_raw_validate(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(Self::new) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Custom error with signature `ExpectedPause()` and selector `0x8dfc202b`. +```solidity +error ExpectedPause(); +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct ExpectedPause; + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: ExpectedPause) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for ExpectedPause { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self + } + } + #[automatically_derived] + impl alloy_sol_types::SolError for ExpectedPause { + type Parameters<'a> = UnderlyingSolTuple<'a>; + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "ExpectedPause()"; + const SELECTOR: [u8; 4] = [141u8, 252u8, 32u8, 43u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + () + } + #[inline] + fn abi_decode_raw_validate(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(Self::new) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Event with signature `Approval(address,address,uint256)` and selector `0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925`. +```solidity +event Approval(address indexed owner, address indexed spender, uint256 value); +```*/ + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + #[derive(Clone)] + pub struct Approval { + #[allow(missing_docs)] + pub owner: alloy::sol_types::private::Address, + #[allow(missing_docs)] + pub spender: alloy::sol_types::private::Address, + #[allow(missing_docs)] + pub value: alloy::sol_types::private::primitives::aliases::U256, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[automatically_derived] + impl alloy_sol_types::SolEvent for Approval { + type DataTuple<'a> = (alloy::sol_types::sol_data::Uint<256>,); + type DataToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + type TopicList = ( + alloy_sol_types::sol_data::FixedBytes<32>, + alloy::sol_types::sol_data::Address, + alloy::sol_types::sol_data::Address, + ); + const SIGNATURE: &'static str = "Approval(address,address,uint256)"; + const SIGNATURE_HASH: alloy_sol_types::private::B256 = alloy_sol_types::private::B256::new([ + 140u8, 91u8, 225u8, 229u8, 235u8, 236u8, 125u8, 91u8, 209u8, 79u8, 113u8, + 66u8, 125u8, 30u8, 132u8, 243u8, 221u8, 3u8, 20u8, 192u8, 247u8, 178u8, + 41u8, 30u8, 91u8, 32u8, 10u8, 200u8, 199u8, 195u8, 185u8, 37u8, + ]); + const ANONYMOUS: bool = false; + #[allow(unused_variables)] + #[inline] + fn new( + topics: ::RustType, + data: as alloy_sol_types::SolType>::RustType, + ) -> Self { + Self { + owner: topics.1, + spender: topics.2, + value: data.0, + } + } + #[inline] + fn check_signature( + topics: &::RustType, + ) -> alloy_sol_types::Result<()> { + if topics.0 != Self::SIGNATURE_HASH { + return Err( + alloy_sol_types::Error::invalid_event_signature_hash( + Self::SIGNATURE, + topics.0, + Self::SIGNATURE_HASH, + ), + ); + } + Ok(()) + } + #[inline] + fn tokenize_body(&self) -> Self::DataToken<'_> { + ( + as alloy_sol_types::SolType>::tokenize(&self.value), + ) + } + #[inline] + fn topics(&self) -> ::RustType { + (Self::SIGNATURE_HASH.into(), self.owner.clone(), self.spender.clone()) + } + #[inline] + fn encode_topics_raw( + &self, + out: &mut [alloy_sol_types::abi::token::WordToken], + ) -> alloy_sol_types::Result<()> { + if out.len() < ::COUNT { + return Err(alloy_sol_types::Error::Overrun); + } + out[0usize] = alloy_sol_types::abi::token::WordToken( + Self::SIGNATURE_HASH, + ); + out[1usize] = ::encode_topic( + &self.owner, + ); + out[2usize] = ::encode_topic( + &self.spender, + ); + Ok(()) + } + } + #[automatically_derived] + impl alloy_sol_types::private::IntoLogData for Approval { + fn to_log_data(&self) -> alloy_sol_types::private::LogData { + From::from(self) + } + fn into_log_data(self) -> alloy_sol_types::private::LogData { + From::from(&self) + } + } + #[automatically_derived] + impl From<&Approval> for alloy_sol_types::private::LogData { + #[inline] + fn from(this: &Approval) -> alloy_sol_types::private::LogData { + alloy_sol_types::SolEvent::encode_log_data(this) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Event with signature `Paused(address)` and selector `0x62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258`. +```solidity +event Paused(address account); +```*/ + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + #[derive(Clone)] + pub struct Paused { + #[allow(missing_docs)] + pub account: alloy::sol_types::private::Address, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[automatically_derived] + impl alloy_sol_types::SolEvent for Paused { + type DataTuple<'a> = (alloy::sol_types::sol_data::Address,); + type DataToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + type TopicList = (alloy_sol_types::sol_data::FixedBytes<32>,); + const SIGNATURE: &'static str = "Paused(address)"; + const SIGNATURE_HASH: alloy_sol_types::private::B256 = alloy_sol_types::private::B256::new([ + 98u8, 231u8, 140u8, 234u8, 1u8, 190u8, 227u8, 32u8, 205u8, 78u8, 66u8, + 2u8, 112u8, 181u8, 234u8, 116u8, 0u8, 13u8, 17u8, 176u8, 201u8, 247u8, + 71u8, 84u8, 235u8, 219u8, 252u8, 84u8, 75u8, 5u8, 162u8, 88u8, + ]); + const ANONYMOUS: bool = false; + #[allow(unused_variables)] + #[inline] + fn new( + topics: ::RustType, + data: as alloy_sol_types::SolType>::RustType, + ) -> Self { + Self { account: data.0 } + } + #[inline] + fn check_signature( + topics: &::RustType, + ) -> alloy_sol_types::Result<()> { + if topics.0 != Self::SIGNATURE_HASH { + return Err( + alloy_sol_types::Error::invalid_event_signature_hash( + Self::SIGNATURE, + topics.0, + Self::SIGNATURE_HASH, + ), + ); + } + Ok(()) + } + #[inline] + fn tokenize_body(&self) -> Self::DataToken<'_> { + ( + ::tokenize( + &self.account, + ), + ) + } + #[inline] + fn topics(&self) -> ::RustType { + (Self::SIGNATURE_HASH.into(),) + } + #[inline] + fn encode_topics_raw( + &self, + out: &mut [alloy_sol_types::abi::token::WordToken], + ) -> alloy_sol_types::Result<()> { + if out.len() < ::COUNT { + return Err(alloy_sol_types::Error::Overrun); + } + out[0usize] = alloy_sol_types::abi::token::WordToken( + Self::SIGNATURE_HASH, + ); + Ok(()) + } + } + #[automatically_derived] + impl alloy_sol_types::private::IntoLogData for Paused { + fn to_log_data(&self) -> alloy_sol_types::private::LogData { + From::from(self) + } + fn into_log_data(self) -> alloy_sol_types::private::LogData { + From::from(&self) + } + } + #[automatically_derived] + impl From<&Paused> for alloy_sol_types::private::LogData { + #[inline] + fn from(this: &Paused) -> alloy_sol_types::private::LogData { + alloy_sol_types::SolEvent::encode_log_data(this) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Event with signature `RoleAdminChanged(bytes32,bytes32,bytes32)` and selector `0xbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff`. +```solidity +event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole); +```*/ + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + #[derive(Clone)] + pub struct RoleAdminChanged { + #[allow(missing_docs)] + pub role: alloy::sol_types::private::FixedBytes<32>, + #[allow(missing_docs)] + pub previousAdminRole: alloy::sol_types::private::FixedBytes<32>, + #[allow(missing_docs)] + pub newAdminRole: alloy::sol_types::private::FixedBytes<32>, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[automatically_derived] + impl alloy_sol_types::SolEvent for RoleAdminChanged { + type DataTuple<'a> = (); + type DataToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + type TopicList = ( + alloy_sol_types::sol_data::FixedBytes<32>, + alloy::sol_types::sol_data::FixedBytes<32>, + alloy::sol_types::sol_data::FixedBytes<32>, + alloy::sol_types::sol_data::FixedBytes<32>, + ); + const SIGNATURE: &'static str = "RoleAdminChanged(bytes32,bytes32,bytes32)"; + const SIGNATURE_HASH: alloy_sol_types::private::B256 = alloy_sol_types::private::B256::new([ + 189u8, 121u8, 184u8, 111u8, 254u8, 10u8, 184u8, 232u8, 119u8, 97u8, 81u8, + 81u8, 66u8, 23u8, 205u8, 124u8, 172u8, 213u8, 44u8, 144u8, 159u8, 102u8, + 71u8, 92u8, 58u8, 244u8, 78u8, 18u8, 159u8, 11u8, 0u8, 255u8, + ]); + const ANONYMOUS: bool = false; + #[allow(unused_variables)] + #[inline] + fn new( + topics: ::RustType, + data: as alloy_sol_types::SolType>::RustType, + ) -> Self { + Self { + role: topics.1, + previousAdminRole: topics.2, + newAdminRole: topics.3, + } + } + #[inline] + fn check_signature( + topics: &::RustType, + ) -> alloy_sol_types::Result<()> { + if topics.0 != Self::SIGNATURE_HASH { + return Err( + alloy_sol_types::Error::invalid_event_signature_hash( + Self::SIGNATURE, + topics.0, + Self::SIGNATURE_HASH, + ), + ); + } + Ok(()) + } + #[inline] + fn tokenize_body(&self) -> Self::DataToken<'_> { + () + } + #[inline] + fn topics(&self) -> ::RustType { + ( + Self::SIGNATURE_HASH.into(), + self.role.clone(), + self.previousAdminRole.clone(), + self.newAdminRole.clone(), + ) + } + #[inline] + fn encode_topics_raw( + &self, + out: &mut [alloy_sol_types::abi::token::WordToken], + ) -> alloy_sol_types::Result<()> { + if out.len() < ::COUNT { + return Err(alloy_sol_types::Error::Overrun); + } + out[0usize] = alloy_sol_types::abi::token::WordToken( + Self::SIGNATURE_HASH, + ); + out[1usize] = as alloy_sol_types::EventTopic>::encode_topic(&self.role); + out[2usize] = as alloy_sol_types::EventTopic>::encode_topic(&self.previousAdminRole); + out[3usize] = as alloy_sol_types::EventTopic>::encode_topic(&self.newAdminRole); + Ok(()) + } + } + #[automatically_derived] + impl alloy_sol_types::private::IntoLogData for RoleAdminChanged { + fn to_log_data(&self) -> alloy_sol_types::private::LogData { + From::from(self) + } + fn into_log_data(self) -> alloy_sol_types::private::LogData { + From::from(&self) + } + } + #[automatically_derived] + impl From<&RoleAdminChanged> for alloy_sol_types::private::LogData { + #[inline] + fn from(this: &RoleAdminChanged) -> alloy_sol_types::private::LogData { + alloy_sol_types::SolEvent::encode_log_data(this) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Event with signature `RoleGranted(bytes32,address,address)` and selector `0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d`. +```solidity +event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender); +```*/ + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + #[derive(Clone)] + pub struct RoleGranted { + #[allow(missing_docs)] + pub role: alloy::sol_types::private::FixedBytes<32>, + #[allow(missing_docs)] + pub account: alloy::sol_types::private::Address, + #[allow(missing_docs)] + pub sender: alloy::sol_types::private::Address, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[automatically_derived] + impl alloy_sol_types::SolEvent for RoleGranted { + type DataTuple<'a> = (); + type DataToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + type TopicList = ( + alloy_sol_types::sol_data::FixedBytes<32>, + alloy::sol_types::sol_data::FixedBytes<32>, + alloy::sol_types::sol_data::Address, + alloy::sol_types::sol_data::Address, + ); + const SIGNATURE: &'static str = "RoleGranted(bytes32,address,address)"; + const SIGNATURE_HASH: alloy_sol_types::private::B256 = alloy_sol_types::private::B256::new([ + 47u8, 135u8, 136u8, 17u8, 126u8, 126u8, 255u8, 29u8, 130u8, 233u8, 38u8, + 236u8, 121u8, 73u8, 1u8, 209u8, 124u8, 120u8, 2u8, 74u8, 80u8, 39u8, 9u8, + 64u8, 48u8, 69u8, 64u8, 167u8, 51u8, 101u8, 111u8, 13u8, + ]); + const ANONYMOUS: bool = false; + #[allow(unused_variables)] + #[inline] + fn new( + topics: ::RustType, + data: as alloy_sol_types::SolType>::RustType, + ) -> Self { + Self { + role: topics.1, + account: topics.2, + sender: topics.3, + } + } + #[inline] + fn check_signature( + topics: &::RustType, + ) -> alloy_sol_types::Result<()> { + if topics.0 != Self::SIGNATURE_HASH { + return Err( + alloy_sol_types::Error::invalid_event_signature_hash( + Self::SIGNATURE, + topics.0, + Self::SIGNATURE_HASH, + ), + ); + } + Ok(()) + } + #[inline] + fn tokenize_body(&self) -> Self::DataToken<'_> { + () + } + #[inline] + fn topics(&self) -> ::RustType { + ( + Self::SIGNATURE_HASH.into(), + self.role.clone(), + self.account.clone(), + self.sender.clone(), + ) + } + #[inline] + fn encode_topics_raw( + &self, + out: &mut [alloy_sol_types::abi::token::WordToken], + ) -> alloy_sol_types::Result<()> { + if out.len() < ::COUNT { + return Err(alloy_sol_types::Error::Overrun); + } + out[0usize] = alloy_sol_types::abi::token::WordToken( + Self::SIGNATURE_HASH, + ); + out[1usize] = as alloy_sol_types::EventTopic>::encode_topic(&self.role); + out[2usize] = ::encode_topic( + &self.account, + ); + out[3usize] = ::encode_topic( + &self.sender, + ); + Ok(()) + } + } + #[automatically_derived] + impl alloy_sol_types::private::IntoLogData for RoleGranted { + fn to_log_data(&self) -> alloy_sol_types::private::LogData { + From::from(self) + } + fn into_log_data(self) -> alloy_sol_types::private::LogData { + From::from(&self) + } + } + #[automatically_derived] + impl From<&RoleGranted> for alloy_sol_types::private::LogData { + #[inline] + fn from(this: &RoleGranted) -> alloy_sol_types::private::LogData { + alloy_sol_types::SolEvent::encode_log_data(this) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Event with signature `RoleRevoked(bytes32,address,address)` and selector `0xf6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b`. +```solidity +event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender); +```*/ + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + #[derive(Clone)] + pub struct RoleRevoked { + #[allow(missing_docs)] + pub role: alloy::sol_types::private::FixedBytes<32>, + #[allow(missing_docs)] + pub account: alloy::sol_types::private::Address, + #[allow(missing_docs)] + pub sender: alloy::sol_types::private::Address, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[automatically_derived] + impl alloy_sol_types::SolEvent for RoleRevoked { + type DataTuple<'a> = (); + type DataToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + type TopicList = ( + alloy_sol_types::sol_data::FixedBytes<32>, + alloy::sol_types::sol_data::FixedBytes<32>, + alloy::sol_types::sol_data::Address, + alloy::sol_types::sol_data::Address, + ); + const SIGNATURE: &'static str = "RoleRevoked(bytes32,address,address)"; + const SIGNATURE_HASH: alloy_sol_types::private::B256 = alloy_sol_types::private::B256::new([ + 246u8, 57u8, 31u8, 92u8, 50u8, 217u8, 198u8, 157u8, 42u8, 71u8, 234u8, + 103u8, 11u8, 68u8, 41u8, 116u8, 181u8, 57u8, 53u8, 209u8, 237u8, 199u8, + 253u8, 100u8, 235u8, 33u8, 224u8, 71u8, 168u8, 57u8, 23u8, 27u8, + ]); + const ANONYMOUS: bool = false; + #[allow(unused_variables)] + #[inline] + fn new( + topics: ::RustType, + data: as alloy_sol_types::SolType>::RustType, + ) -> Self { + Self { + role: topics.1, + account: topics.2, + sender: topics.3, + } + } + #[inline] + fn check_signature( + topics: &::RustType, + ) -> alloy_sol_types::Result<()> { + if topics.0 != Self::SIGNATURE_HASH { + return Err( + alloy_sol_types::Error::invalid_event_signature_hash( + Self::SIGNATURE, + topics.0, + Self::SIGNATURE_HASH, + ), + ); + } + Ok(()) + } + #[inline] + fn tokenize_body(&self) -> Self::DataToken<'_> { + () + } + #[inline] + fn topics(&self) -> ::RustType { + ( + Self::SIGNATURE_HASH.into(), + self.role.clone(), + self.account.clone(), + self.sender.clone(), + ) + } + #[inline] + fn encode_topics_raw( + &self, + out: &mut [alloy_sol_types::abi::token::WordToken], + ) -> alloy_sol_types::Result<()> { + if out.len() < ::COUNT { + return Err(alloy_sol_types::Error::Overrun); + } + out[0usize] = alloy_sol_types::abi::token::WordToken( + Self::SIGNATURE_HASH, + ); + out[1usize] = as alloy_sol_types::EventTopic>::encode_topic(&self.role); + out[2usize] = ::encode_topic( + &self.account, + ); + out[3usize] = ::encode_topic( + &self.sender, + ); + Ok(()) + } + } + #[automatically_derived] + impl alloy_sol_types::private::IntoLogData for RoleRevoked { + fn to_log_data(&self) -> alloy_sol_types::private::LogData { + From::from(self) + } + fn into_log_data(self) -> alloy_sol_types::private::LogData { + From::from(&self) + } + } + #[automatically_derived] + impl From<&RoleRevoked> for alloy_sol_types::private::LogData { + #[inline] + fn from(this: &RoleRevoked) -> alloy_sol_types::private::LogData { + alloy_sol_types::SolEvent::encode_log_data(this) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Event with signature `Transfer(address,address,uint256)` and selector `0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef`. +```solidity +event Transfer(address indexed from, address indexed to, uint256 value); +```*/ + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + #[derive(Clone)] + pub struct Transfer { + #[allow(missing_docs)] + pub from: alloy::sol_types::private::Address, + #[allow(missing_docs)] + pub to: alloy::sol_types::private::Address, + #[allow(missing_docs)] + pub value: alloy::sol_types::private::primitives::aliases::U256, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[automatically_derived] + impl alloy_sol_types::SolEvent for Transfer { + type DataTuple<'a> = (alloy::sol_types::sol_data::Uint<256>,); + type DataToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + type TopicList = ( + alloy_sol_types::sol_data::FixedBytes<32>, + alloy::sol_types::sol_data::Address, + alloy::sol_types::sol_data::Address, + ); + const SIGNATURE: &'static str = "Transfer(address,address,uint256)"; + const SIGNATURE_HASH: alloy_sol_types::private::B256 = alloy_sol_types::private::B256::new([ + 221u8, 242u8, 82u8, 173u8, 27u8, 226u8, 200u8, 155u8, 105u8, 194u8, + 176u8, 104u8, 252u8, 55u8, 141u8, 170u8, 149u8, 43u8, 167u8, 241u8, 99u8, + 196u8, 161u8, 22u8, 40u8, 245u8, 90u8, 77u8, 245u8, 35u8, 179u8, 239u8, + ]); + const ANONYMOUS: bool = false; + #[allow(unused_variables)] + #[inline] + fn new( + topics: ::RustType, + data: as alloy_sol_types::SolType>::RustType, + ) -> Self { + Self { + from: topics.1, + to: topics.2, + value: data.0, + } + } + #[inline] + fn check_signature( + topics: &::RustType, + ) -> alloy_sol_types::Result<()> { + if topics.0 != Self::SIGNATURE_HASH { + return Err( + alloy_sol_types::Error::invalid_event_signature_hash( + Self::SIGNATURE, + topics.0, + Self::SIGNATURE_HASH, + ), + ); + } + Ok(()) + } + #[inline] + fn tokenize_body(&self) -> Self::DataToken<'_> { + ( + as alloy_sol_types::SolType>::tokenize(&self.value), + ) + } + #[inline] + fn topics(&self) -> ::RustType { + (Self::SIGNATURE_HASH.into(), self.from.clone(), self.to.clone()) + } + #[inline] + fn encode_topics_raw( + &self, + out: &mut [alloy_sol_types::abi::token::WordToken], + ) -> alloy_sol_types::Result<()> { + if out.len() < ::COUNT { + return Err(alloy_sol_types::Error::Overrun); + } + out[0usize] = alloy_sol_types::abi::token::WordToken( + Self::SIGNATURE_HASH, + ); + out[1usize] = ::encode_topic( + &self.from, + ); + out[2usize] = ::encode_topic( + &self.to, + ); + Ok(()) + } + } + #[automatically_derived] + impl alloy_sol_types::private::IntoLogData for Transfer { + fn to_log_data(&self) -> alloy_sol_types::private::LogData { + From::from(self) + } + fn into_log_data(self) -> alloy_sol_types::private::LogData { + From::from(&self) + } + } + #[automatically_derived] + impl From<&Transfer> for alloy_sol_types::private::LogData { + #[inline] + fn from(this: &Transfer) -> alloy_sol_types::private::LogData { + alloy_sol_types::SolEvent::encode_log_data(this) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Event with signature `Unpaused(address)` and selector `0x5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa`. +```solidity +event Unpaused(address account); +```*/ + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + #[derive(Clone)] + pub struct Unpaused { + #[allow(missing_docs)] + pub account: alloy::sol_types::private::Address, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + #[automatically_derived] + impl alloy_sol_types::SolEvent for Unpaused { + type DataTuple<'a> = (alloy::sol_types::sol_data::Address,); + type DataToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + type TopicList = (alloy_sol_types::sol_data::FixedBytes<32>,); + const SIGNATURE: &'static str = "Unpaused(address)"; + const SIGNATURE_HASH: alloy_sol_types::private::B256 = alloy_sol_types::private::B256::new([ + 93u8, 185u8, 238u8, 10u8, 73u8, 91u8, 242u8, 230u8, 255u8, 156u8, 145u8, + 167u8, 131u8, 76u8, 27u8, 164u8, 253u8, 210u8, 68u8, 165u8, 232u8, 170u8, + 78u8, 83u8, 123u8, 211u8, 138u8, 234u8, 228u8, 176u8, 115u8, 170u8, + ]); + const ANONYMOUS: bool = false; + #[allow(unused_variables)] + #[inline] + fn new( + topics: ::RustType, + data: as alloy_sol_types::SolType>::RustType, + ) -> Self { + Self { account: data.0 } + } + #[inline] + fn check_signature( + topics: &::RustType, + ) -> alloy_sol_types::Result<()> { + if topics.0 != Self::SIGNATURE_HASH { + return Err( + alloy_sol_types::Error::invalid_event_signature_hash( + Self::SIGNATURE, + topics.0, + Self::SIGNATURE_HASH, + ), + ); + } + Ok(()) + } + #[inline] + fn tokenize_body(&self) -> Self::DataToken<'_> { + ( + ::tokenize( + &self.account, + ), + ) + } + #[inline] + fn topics(&self) -> ::RustType { + (Self::SIGNATURE_HASH.into(),) + } + #[inline] + fn encode_topics_raw( + &self, + out: &mut [alloy_sol_types::abi::token::WordToken], + ) -> alloy_sol_types::Result<()> { + if out.len() < ::COUNT { + return Err(alloy_sol_types::Error::Overrun); + } + out[0usize] = alloy_sol_types::abi::token::WordToken( + Self::SIGNATURE_HASH, + ); + Ok(()) + } + } + #[automatically_derived] + impl alloy_sol_types::private::IntoLogData for Unpaused { + fn to_log_data(&self) -> alloy_sol_types::private::LogData { + From::from(self) + } + fn into_log_data(self) -> alloy_sol_types::private::LogData { + From::from(&self) + } + } + #[automatically_derived] + impl From<&Unpaused> for alloy_sol_types::private::LogData { + #[inline] + fn from(this: &Unpaused) -> alloy_sol_types::private::LogData { + alloy_sol_types::SolEvent::encode_log_data(this) + } + } + }; + /**Constructor`. +```solidity +constructor(string name_, string symbol_, uint8 decimals_); +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct constructorCall { + #[allow(missing_docs)] + pub name_: alloy::sol_types::private::String, + #[allow(missing_docs)] + pub symbol_: alloy::sol_types::private::String, + #[allow(missing_docs)] + pub decimals_: u8, + } + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = ( + alloy::sol_types::sol_data::String, + alloy::sol_types::sol_data::String, + alloy::sol_types::sol_data::Uint<8>, + ); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = ( + alloy::sol_types::private::String, + alloy::sol_types::private::String, + u8, + ); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: constructorCall) -> Self { + (value.name_, value.symbol_, value.decimals_) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for constructorCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { + name_: tuple.0, + symbol_: tuple.1, + decimals_: tuple.2, + } + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolConstructor for constructorCall { + type Parameters<'a> = ( + alloy::sol_types::sol_data::String, + alloy::sol_types::sol_data::String, + alloy::sol_types::sol_data::Uint<8>, + ); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + ( + ::tokenize( + &self.name_, + ), + ::tokenize( + &self.symbol_, + ), + as alloy_sol_types::SolType>::tokenize(&self.decimals_), + ) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Function with signature `DEFAULT_ADMIN_ROLE()` and selector `0xa217fddf`. +```solidity +function DEFAULT_ADMIN_ROLE() external view returns (bytes32); +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct DEFAULT_ADMIN_ROLECall; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + ///Container type for the return parameters of the [`DEFAULT_ADMIN_ROLE()`](DEFAULT_ADMIN_ROLECall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct DEFAULT_ADMIN_ROLEReturn { + #[allow(missing_docs)] + pub _0: alloy::sol_types::private::FixedBytes<32>, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From + for UnderlyingRustTuple<'_> { + fn from(value: DEFAULT_ADMIN_ROLECall) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> + for DEFAULT_ADMIN_ROLECall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self + } + } + } + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (alloy::sol_types::sol_data::FixedBytes<32>,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (alloy::sol_types::private::FixedBytes<32>,); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From + for UnderlyingRustTuple<'_> { + fn from(value: DEFAULT_ADMIN_ROLEReturn) -> Self { + (value._0,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> + for DEFAULT_ADMIN_ROLEReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { _0: tuple.0 } + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for DEFAULT_ADMIN_ROLECall { + type Parameters<'a> = (); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = alloy::sol_types::private::FixedBytes<32>; + type ReturnTuple<'a> = (alloy::sol_types::sol_data::FixedBytes<32>,); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "DEFAULT_ADMIN_ROLE()"; + const SELECTOR: [u8; 4] = [162u8, 23u8, 253u8, 223u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + () + } + #[inline] + fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> { + ( + as alloy_sol_types::SolType>::tokenize(ret), + ) + } + #[inline] + fn abi_decode_returns(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data) + .map(|r| { + let r: DEFAULT_ADMIN_ROLEReturn = r.into(); + r._0 + }) + } + #[inline] + fn abi_decode_returns_validate( + data: &[u8], + ) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(|r| { + let r: DEFAULT_ADMIN_ROLEReturn = r.into(); + r._0 + }) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Function with signature `MINTER_ROLE()` and selector `0xd5391393`. +```solidity +function MINTER_ROLE() external view returns (bytes32); +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct MINTER_ROLECall; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + ///Container type for the return parameters of the [`MINTER_ROLE()`](MINTER_ROLECall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct MINTER_ROLEReturn { + #[allow(missing_docs)] + pub _0: alloy::sol_types::private::FixedBytes<32>, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: MINTER_ROLECall) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for MINTER_ROLECall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self + } + } + } + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (alloy::sol_types::sol_data::FixedBytes<32>,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (alloy::sol_types::private::FixedBytes<32>,); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: MINTER_ROLEReturn) -> Self { + (value._0,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for MINTER_ROLEReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { _0: tuple.0 } + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for MINTER_ROLECall { + type Parameters<'a> = (); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = alloy::sol_types::private::FixedBytes<32>; + type ReturnTuple<'a> = (alloy::sol_types::sol_data::FixedBytes<32>,); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "MINTER_ROLE()"; + const SELECTOR: [u8; 4] = [213u8, 57u8, 19u8, 147u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + () + } + #[inline] + fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> { + ( + as alloy_sol_types::SolType>::tokenize(ret), + ) + } + #[inline] + fn abi_decode_returns(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data) + .map(|r| { + let r: MINTER_ROLEReturn = r.into(); + r._0 + }) + } + #[inline] + fn abi_decode_returns_validate( + data: &[u8], + ) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(|r| { + let r: MINTER_ROLEReturn = r.into(); + r._0 + }) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Function with signature `PAUSER_ROLE()` and selector `0xe63ab1e9`. +```solidity +function PAUSER_ROLE() external view returns (bytes32); +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct PAUSER_ROLECall; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + ///Container type for the return parameters of the [`PAUSER_ROLE()`](PAUSER_ROLECall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct PAUSER_ROLEReturn { + #[allow(missing_docs)] + pub _0: alloy::sol_types::private::FixedBytes<32>, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: PAUSER_ROLECall) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for PAUSER_ROLECall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self + } + } + } + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (alloy::sol_types::sol_data::FixedBytes<32>,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (alloy::sol_types::private::FixedBytes<32>,); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: PAUSER_ROLEReturn) -> Self { + (value._0,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for PAUSER_ROLEReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { _0: tuple.0 } + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for PAUSER_ROLECall { + type Parameters<'a> = (); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = alloy::sol_types::private::FixedBytes<32>; + type ReturnTuple<'a> = (alloy::sol_types::sol_data::FixedBytes<32>,); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "PAUSER_ROLE()"; + const SELECTOR: [u8; 4] = [230u8, 58u8, 177u8, 233u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + () + } + #[inline] + fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> { + ( + as alloy_sol_types::SolType>::tokenize(ret), + ) + } + #[inline] + fn abi_decode_returns(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data) + .map(|r| { + let r: PAUSER_ROLEReturn = r.into(); + r._0 + }) + } + #[inline] + fn abi_decode_returns_validate( + data: &[u8], + ) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(|r| { + let r: PAUSER_ROLEReturn = r.into(); + r._0 + }) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Function with signature `allowance(address,address)` and selector `0xdd62ed3e`. +```solidity +function allowance(address owner, address spender) external view returns (uint256); +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct allowanceCall { + #[allow(missing_docs)] + pub owner: alloy::sol_types::private::Address, + #[allow(missing_docs)] + pub spender: alloy::sol_types::private::Address, + } + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + ///Container type for the return parameters of the [`allowance(address,address)`](allowanceCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct allowanceReturn { + #[allow(missing_docs)] + pub _0: alloy::sol_types::private::primitives::aliases::U256, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = ( + alloy::sol_types::sol_data::Address, + alloy::sol_types::sol_data::Address, + ); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = ( + alloy::sol_types::private::Address, + alloy::sol_types::private::Address, + ); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: allowanceCall) -> Self { + (value.owner, value.spender) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for allowanceCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { + owner: tuple.0, + spender: tuple.1, + } + } + } + } + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (alloy::sol_types::sol_data::Uint<256>,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = ( + alloy::sol_types::private::primitives::aliases::U256, + ); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: allowanceReturn) -> Self { + (value._0,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for allowanceReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { _0: tuple.0 } + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for allowanceCall { + type Parameters<'a> = ( + alloy::sol_types::sol_data::Address, + alloy::sol_types::sol_data::Address, + ); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = alloy::sol_types::private::primitives::aliases::U256; + type ReturnTuple<'a> = (alloy::sol_types::sol_data::Uint<256>,); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "allowance(address,address)"; + const SELECTOR: [u8; 4] = [221u8, 98u8, 237u8, 62u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + ( + ::tokenize( + &self.owner, + ), + ::tokenize( + &self.spender, + ), + ) + } + #[inline] + fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> { + ( + as alloy_sol_types::SolType>::tokenize(ret), + ) + } + #[inline] + fn abi_decode_returns(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data) + .map(|r| { + let r: allowanceReturn = r.into(); + r._0 + }) + } + #[inline] + fn abi_decode_returns_validate( + data: &[u8], + ) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(|r| { + let r: allowanceReturn = r.into(); + r._0 + }) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Function with signature `approve(address,uint256)` and selector `0x095ea7b3`. +```solidity +function approve(address spender, uint256 value) external returns (bool); +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct approveCall { + #[allow(missing_docs)] + pub spender: alloy::sol_types::private::Address, + #[allow(missing_docs)] + pub value: alloy::sol_types::private::primitives::aliases::U256, + } + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + ///Container type for the return parameters of the [`approve(address,uint256)`](approveCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct approveReturn { + #[allow(missing_docs)] + pub _0: bool, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = ( + alloy::sol_types::sol_data::Address, + alloy::sol_types::sol_data::Uint<256>, + ); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = ( + alloy::sol_types::private::Address, + alloy::sol_types::private::primitives::aliases::U256, + ); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: approveCall) -> Self { + (value.spender, value.value) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for approveCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { + spender: tuple.0, + value: tuple.1, + } + } + } + } + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (alloy::sol_types::sol_data::Bool,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (bool,); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: approveReturn) -> Self { + (value._0,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for approveReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { _0: tuple.0 } + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for approveCall { + type Parameters<'a> = ( + alloy::sol_types::sol_data::Address, + alloy::sol_types::sol_data::Uint<256>, + ); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = bool; + type ReturnTuple<'a> = (alloy::sol_types::sol_data::Bool,); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "approve(address,uint256)"; + const SELECTOR: [u8; 4] = [9u8, 94u8, 167u8, 179u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + ( + ::tokenize( + &self.spender, + ), + as alloy_sol_types::SolType>::tokenize(&self.value), + ) + } + #[inline] + fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> { + ( + ::tokenize( + ret, + ), + ) + } + #[inline] + fn abi_decode_returns(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data) + .map(|r| { + let r: approveReturn = r.into(); + r._0 + }) + } + #[inline] + fn abi_decode_returns_validate( + data: &[u8], + ) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(|r| { + let r: approveReturn = r.into(); + r._0 + }) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Function with signature `balanceOf(address)` and selector `0x70a08231`. +```solidity +function balanceOf(address account) external view returns (uint256); +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct balanceOfCall { + #[allow(missing_docs)] + pub account: alloy::sol_types::private::Address, + } + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + ///Container type for the return parameters of the [`balanceOf(address)`](balanceOfCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct balanceOfReturn { + #[allow(missing_docs)] + pub _0: alloy::sol_types::private::primitives::aliases::U256, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (alloy::sol_types::sol_data::Address,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (alloy::sol_types::private::Address,); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: balanceOfCall) -> Self { + (value.account,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for balanceOfCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { account: tuple.0 } + } + } + } + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (alloy::sol_types::sol_data::Uint<256>,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = ( + alloy::sol_types::private::primitives::aliases::U256, + ); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: balanceOfReturn) -> Self { + (value._0,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for balanceOfReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { _0: tuple.0 } + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for balanceOfCall { + type Parameters<'a> = (alloy::sol_types::sol_data::Address,); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = alloy::sol_types::private::primitives::aliases::U256; + type ReturnTuple<'a> = (alloy::sol_types::sol_data::Uint<256>,); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "balanceOf(address)"; + const SELECTOR: [u8; 4] = [112u8, 160u8, 130u8, 49u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + ( + ::tokenize( + &self.account, + ), + ) + } + #[inline] + fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> { + ( + as alloy_sol_types::SolType>::tokenize(ret), + ) + } + #[inline] + fn abi_decode_returns(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data) + .map(|r| { + let r: balanceOfReturn = r.into(); + r._0 + }) + } + #[inline] + fn abi_decode_returns_validate( + data: &[u8], + ) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(|r| { + let r: balanceOfReturn = r.into(); + r._0 + }) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Function with signature `burn(uint256)` and selector `0x42966c68`. +```solidity +function burn(uint256 value) external; +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct burnCall { + #[allow(missing_docs)] + pub value: alloy::sol_types::private::primitives::aliases::U256, + } + ///Container type for the return parameters of the [`burn(uint256)`](burnCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct burnReturn {} + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (alloy::sol_types::sol_data::Uint<256>,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = ( + alloy::sol_types::private::primitives::aliases::U256, + ); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: burnCall) -> Self { + (value.value,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for burnCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { value: tuple.0 } + } + } + } + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: burnReturn) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for burnReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self {} + } + } + } + impl burnReturn { + fn _tokenize( + &self, + ) -> ::ReturnToken<'_> { + () + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for burnCall { + type Parameters<'a> = (alloy::sol_types::sol_data::Uint<256>,); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = burnReturn; + type ReturnTuple<'a> = (); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "burn(uint256)"; + const SELECTOR: [u8; 4] = [66u8, 150u8, 108u8, 104u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + ( + as alloy_sol_types::SolType>::tokenize(&self.value), + ) + } + #[inline] + fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> { + burnReturn::_tokenize(ret) + } + #[inline] + fn abi_decode_returns(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data) + .map(Into::into) + } + #[inline] + fn abi_decode_returns_validate( + data: &[u8], + ) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(Into::into) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Function with signature `burnFrom(address,uint256)` and selector `0x79cc6790`. +```solidity +function burnFrom(address account, uint256 value) external; +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct burnFromCall { + #[allow(missing_docs)] + pub account: alloy::sol_types::private::Address, + #[allow(missing_docs)] + pub value: alloy::sol_types::private::primitives::aliases::U256, + } + ///Container type for the return parameters of the [`burnFrom(address,uint256)`](burnFromCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct burnFromReturn {} + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = ( + alloy::sol_types::sol_data::Address, + alloy::sol_types::sol_data::Uint<256>, + ); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = ( + alloy::sol_types::private::Address, + alloy::sol_types::private::primitives::aliases::U256, + ); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: burnFromCall) -> Self { + (value.account, value.value) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for burnFromCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { + account: tuple.0, + value: tuple.1, + } + } + } + } + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: burnFromReturn) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for burnFromReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self {} + } + } + } + impl burnFromReturn { + fn _tokenize( + &self, + ) -> ::ReturnToken<'_> { + () + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for burnFromCall { + type Parameters<'a> = ( + alloy::sol_types::sol_data::Address, + alloy::sol_types::sol_data::Uint<256>, + ); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = burnFromReturn; + type ReturnTuple<'a> = (); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "burnFrom(address,uint256)"; + const SELECTOR: [u8; 4] = [121u8, 204u8, 103u8, 144u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + ( + ::tokenize( + &self.account, + ), + as alloy_sol_types::SolType>::tokenize(&self.value), + ) + } + #[inline] + fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> { + burnFromReturn::_tokenize(ret) + } + #[inline] + fn abi_decode_returns(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data) + .map(Into::into) + } + #[inline] + fn abi_decode_returns_validate( + data: &[u8], + ) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(Into::into) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Function with signature `decimals()` and selector `0x313ce567`. +```solidity +function decimals() external view returns (uint8); +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct decimalsCall; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + ///Container type for the return parameters of the [`decimals()`](decimalsCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct decimalsReturn { + #[allow(missing_docs)] + pub _0: u8, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: decimalsCall) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for decimalsCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self + } + } + } + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (alloy::sol_types::sol_data::Uint<8>,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (u8,); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: decimalsReturn) -> Self { + (value._0,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for decimalsReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { _0: tuple.0 } + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for decimalsCall { + type Parameters<'a> = (); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = u8; + type ReturnTuple<'a> = (alloy::sol_types::sol_data::Uint<8>,); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "decimals()"; + const SELECTOR: [u8; 4] = [49u8, 60u8, 229u8, 103u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + () + } + #[inline] + fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> { + ( + as alloy_sol_types::SolType>::tokenize(ret), + ) + } + #[inline] + fn abi_decode_returns(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data) + .map(|r| { + let r: decimalsReturn = r.into(); + r._0 + }) + } + #[inline] + fn abi_decode_returns_validate( + data: &[u8], + ) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(|r| { + let r: decimalsReturn = r.into(); + r._0 + }) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Function with signature `getRoleAdmin(bytes32)` and selector `0x248a9ca3`. +```solidity +function getRoleAdmin(bytes32 role) external view returns (bytes32); +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct getRoleAdminCall { + #[allow(missing_docs)] + pub role: alloy::sol_types::private::FixedBytes<32>, + } + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + ///Container type for the return parameters of the [`getRoleAdmin(bytes32)`](getRoleAdminCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct getRoleAdminReturn { + #[allow(missing_docs)] + pub _0: alloy::sol_types::private::FixedBytes<32>, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (alloy::sol_types::sol_data::FixedBytes<32>,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (alloy::sol_types::private::FixedBytes<32>,); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: getRoleAdminCall) -> Self { + (value.role,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for getRoleAdminCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { role: tuple.0 } + } + } + } + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (alloy::sol_types::sol_data::FixedBytes<32>,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (alloy::sol_types::private::FixedBytes<32>,); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: getRoleAdminReturn) -> Self { + (value._0,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for getRoleAdminReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { _0: tuple.0 } + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for getRoleAdminCall { + type Parameters<'a> = (alloy::sol_types::sol_data::FixedBytes<32>,); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = alloy::sol_types::private::FixedBytes<32>; + type ReturnTuple<'a> = (alloy::sol_types::sol_data::FixedBytes<32>,); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "getRoleAdmin(bytes32)"; + const SELECTOR: [u8; 4] = [36u8, 138u8, 156u8, 163u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + ( + as alloy_sol_types::SolType>::tokenize(&self.role), + ) + } + #[inline] + fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> { + ( + as alloy_sol_types::SolType>::tokenize(ret), + ) + } + #[inline] + fn abi_decode_returns(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data) + .map(|r| { + let r: getRoleAdminReturn = r.into(); + r._0 + }) + } + #[inline] + fn abi_decode_returns_validate( + data: &[u8], + ) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(|r| { + let r: getRoleAdminReturn = r.into(); + r._0 + }) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Function with signature `grantRole(bytes32,address)` and selector `0x2f2ff15d`. +```solidity +function grantRole(bytes32 role, address account) external; +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct grantRoleCall { + #[allow(missing_docs)] + pub role: alloy::sol_types::private::FixedBytes<32>, + #[allow(missing_docs)] + pub account: alloy::sol_types::private::Address, + } + ///Container type for the return parameters of the [`grantRole(bytes32,address)`](grantRoleCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct grantRoleReturn {} + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = ( + alloy::sol_types::sol_data::FixedBytes<32>, + alloy::sol_types::sol_data::Address, + ); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = ( + alloy::sol_types::private::FixedBytes<32>, + alloy::sol_types::private::Address, + ); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: grantRoleCall) -> Self { + (value.role, value.account) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for grantRoleCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { + role: tuple.0, + account: tuple.1, + } + } + } + } + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: grantRoleReturn) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for grantRoleReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self {} + } + } + } + impl grantRoleReturn { + fn _tokenize( + &self, + ) -> ::ReturnToken<'_> { + () + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for grantRoleCall { + type Parameters<'a> = ( + alloy::sol_types::sol_data::FixedBytes<32>, + alloy::sol_types::sol_data::Address, + ); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = grantRoleReturn; + type ReturnTuple<'a> = (); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "grantRole(bytes32,address)"; + const SELECTOR: [u8; 4] = [47u8, 47u8, 241u8, 93u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + ( + as alloy_sol_types::SolType>::tokenize(&self.role), + ::tokenize( + &self.account, + ), + ) + } + #[inline] + fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> { + grantRoleReturn::_tokenize(ret) + } + #[inline] + fn abi_decode_returns(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data) + .map(Into::into) + } + #[inline] + fn abi_decode_returns_validate( + data: &[u8], + ) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(Into::into) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Function with signature `hasRole(bytes32,address)` and selector `0x91d14854`. +```solidity +function hasRole(bytes32 role, address account) external view returns (bool); +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct hasRoleCall { + #[allow(missing_docs)] + pub role: alloy::sol_types::private::FixedBytes<32>, + #[allow(missing_docs)] + pub account: alloy::sol_types::private::Address, + } + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + ///Container type for the return parameters of the [`hasRole(bytes32,address)`](hasRoleCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct hasRoleReturn { + #[allow(missing_docs)] + pub _0: bool, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = ( + alloy::sol_types::sol_data::FixedBytes<32>, + alloy::sol_types::sol_data::Address, + ); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = ( + alloy::sol_types::private::FixedBytes<32>, + alloy::sol_types::private::Address, + ); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: hasRoleCall) -> Self { + (value.role, value.account) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for hasRoleCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { + role: tuple.0, + account: tuple.1, + } + } + } + } + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (alloy::sol_types::sol_data::Bool,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (bool,); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: hasRoleReturn) -> Self { + (value._0,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for hasRoleReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { _0: tuple.0 } + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for hasRoleCall { + type Parameters<'a> = ( + alloy::sol_types::sol_data::FixedBytes<32>, + alloy::sol_types::sol_data::Address, + ); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = bool; + type ReturnTuple<'a> = (alloy::sol_types::sol_data::Bool,); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "hasRole(bytes32,address)"; + const SELECTOR: [u8; 4] = [145u8, 209u8, 72u8, 84u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + ( + as alloy_sol_types::SolType>::tokenize(&self.role), + ::tokenize( + &self.account, + ), + ) + } + #[inline] + fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> { + ( + ::tokenize( + ret, + ), + ) + } + #[inline] + fn abi_decode_returns(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data) + .map(|r| { + let r: hasRoleReturn = r.into(); + r._0 + }) + } + #[inline] + fn abi_decode_returns_validate( + data: &[u8], + ) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(|r| { + let r: hasRoleReturn = r.into(); + r._0 + }) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Function with signature `mint(address,uint256)` and selector `0x40c10f19`. +```solidity +function mint(address to, uint256 amount) external; +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct mintCall { + #[allow(missing_docs)] + pub to: alloy::sol_types::private::Address, + #[allow(missing_docs)] + pub amount: alloy::sol_types::private::primitives::aliases::U256, + } + ///Container type for the return parameters of the [`mint(address,uint256)`](mintCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct mintReturn {} + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = ( + alloy::sol_types::sol_data::Address, + alloy::sol_types::sol_data::Uint<256>, + ); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = ( + alloy::sol_types::private::Address, + alloy::sol_types::private::primitives::aliases::U256, + ); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: mintCall) -> Self { + (value.to, value.amount) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for mintCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { + to: tuple.0, + amount: tuple.1, + } + } + } + } + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: mintReturn) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for mintReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self {} + } + } + } + impl mintReturn { + fn _tokenize( + &self, + ) -> ::ReturnToken<'_> { + () + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for mintCall { + type Parameters<'a> = ( + alloy::sol_types::sol_data::Address, + alloy::sol_types::sol_data::Uint<256>, + ); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = mintReturn; + type ReturnTuple<'a> = (); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "mint(address,uint256)"; + const SELECTOR: [u8; 4] = [64u8, 193u8, 15u8, 25u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + ( + ::tokenize( + &self.to, + ), + as alloy_sol_types::SolType>::tokenize(&self.amount), + ) + } + #[inline] + fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> { + mintReturn::_tokenize(ret) + } + #[inline] + fn abi_decode_returns(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data) + .map(Into::into) + } + #[inline] + fn abi_decode_returns_validate( + data: &[u8], + ) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(Into::into) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Function with signature `name()` and selector `0x06fdde03`. +```solidity +function name() external view returns (string memory); +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct nameCall; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + ///Container type for the return parameters of the [`name()`](nameCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct nameReturn { + #[allow(missing_docs)] + pub _0: alloy::sol_types::private::String, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: nameCall) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for nameCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self + } + } + } + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (alloy::sol_types::sol_data::String,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (alloy::sol_types::private::String,); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: nameReturn) -> Self { + (value._0,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for nameReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { _0: tuple.0 } + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for nameCall { + type Parameters<'a> = (); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = alloy::sol_types::private::String; + type ReturnTuple<'a> = (alloy::sol_types::sol_data::String,); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "name()"; + const SELECTOR: [u8; 4] = [6u8, 253u8, 222u8, 3u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + () + } + #[inline] + fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> { + ( + ::tokenize( + ret, + ), + ) + } + #[inline] + fn abi_decode_returns(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data) + .map(|r| { + let r: nameReturn = r.into(); + r._0 + }) + } + #[inline] + fn abi_decode_returns_validate( + data: &[u8], + ) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(|r| { + let r: nameReturn = r.into(); + r._0 + }) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Function with signature `pause()` and selector `0x8456cb59`. +```solidity +function pause() external; +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct pauseCall; + ///Container type for the return parameters of the [`pause()`](pauseCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct pauseReturn {} + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: pauseCall) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for pauseCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self + } + } + } + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: pauseReturn) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for pauseReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self {} + } + } + } + impl pauseReturn { + fn _tokenize( + &self, + ) -> ::ReturnToken<'_> { + () + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for pauseCall { + type Parameters<'a> = (); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = pauseReturn; + type ReturnTuple<'a> = (); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "pause()"; + const SELECTOR: [u8; 4] = [132u8, 86u8, 203u8, 89u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + () + } + #[inline] + fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> { + pauseReturn::_tokenize(ret) + } + #[inline] + fn abi_decode_returns(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data) + .map(Into::into) + } + #[inline] + fn abi_decode_returns_validate( + data: &[u8], + ) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(Into::into) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Function with signature `paused()` and selector `0x5c975abb`. +```solidity +function paused() external view returns (bool); +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct pausedCall; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + ///Container type for the return parameters of the [`paused()`](pausedCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct pausedReturn { + #[allow(missing_docs)] + pub _0: bool, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: pausedCall) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for pausedCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self + } + } + } + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (alloy::sol_types::sol_data::Bool,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (bool,); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: pausedReturn) -> Self { + (value._0,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for pausedReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { _0: tuple.0 } + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for pausedCall { + type Parameters<'a> = (); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = bool; + type ReturnTuple<'a> = (alloy::sol_types::sol_data::Bool,); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "paused()"; + const SELECTOR: [u8; 4] = [92u8, 151u8, 90u8, 187u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + () + } + #[inline] + fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> { + ( + ::tokenize( + ret, + ), + ) + } + #[inline] + fn abi_decode_returns(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data) + .map(|r| { + let r: pausedReturn = r.into(); + r._0 + }) + } + #[inline] + fn abi_decode_returns_validate( + data: &[u8], + ) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(|r| { + let r: pausedReturn = r.into(); + r._0 + }) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Function with signature `renounceRole(bytes32,address)` and selector `0x36568abe`. +```solidity +function renounceRole(bytes32 role, address callerConfirmation) external; +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct renounceRoleCall { + #[allow(missing_docs)] + pub role: alloy::sol_types::private::FixedBytes<32>, + #[allow(missing_docs)] + pub callerConfirmation: alloy::sol_types::private::Address, + } + ///Container type for the return parameters of the [`renounceRole(bytes32,address)`](renounceRoleCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct renounceRoleReturn {} + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = ( + alloy::sol_types::sol_data::FixedBytes<32>, + alloy::sol_types::sol_data::Address, + ); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = ( + alloy::sol_types::private::FixedBytes<32>, + alloy::sol_types::private::Address, + ); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: renounceRoleCall) -> Self { + (value.role, value.callerConfirmation) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for renounceRoleCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { + role: tuple.0, + callerConfirmation: tuple.1, + } + } + } + } + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: renounceRoleReturn) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for renounceRoleReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self {} + } + } + } + impl renounceRoleReturn { + fn _tokenize( + &self, + ) -> ::ReturnToken<'_> { + () + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for renounceRoleCall { + type Parameters<'a> = ( + alloy::sol_types::sol_data::FixedBytes<32>, + alloy::sol_types::sol_data::Address, + ); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = renounceRoleReturn; + type ReturnTuple<'a> = (); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "renounceRole(bytes32,address)"; + const SELECTOR: [u8; 4] = [54u8, 86u8, 138u8, 190u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + ( + as alloy_sol_types::SolType>::tokenize(&self.role), + ::tokenize( + &self.callerConfirmation, + ), + ) + } + #[inline] + fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> { + renounceRoleReturn::_tokenize(ret) + } + #[inline] + fn abi_decode_returns(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data) + .map(Into::into) + } + #[inline] + fn abi_decode_returns_validate( + data: &[u8], + ) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(Into::into) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Function with signature `revokeRole(bytes32,address)` and selector `0xd547741f`. +```solidity +function revokeRole(bytes32 role, address account) external; +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct revokeRoleCall { + #[allow(missing_docs)] + pub role: alloy::sol_types::private::FixedBytes<32>, + #[allow(missing_docs)] + pub account: alloy::sol_types::private::Address, + } + ///Container type for the return parameters of the [`revokeRole(bytes32,address)`](revokeRoleCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct revokeRoleReturn {} + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = ( + alloy::sol_types::sol_data::FixedBytes<32>, + alloy::sol_types::sol_data::Address, + ); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = ( + alloy::sol_types::private::FixedBytes<32>, + alloy::sol_types::private::Address, + ); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: revokeRoleCall) -> Self { + (value.role, value.account) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for revokeRoleCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { + role: tuple.0, + account: tuple.1, + } + } + } + } + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: revokeRoleReturn) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for revokeRoleReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self {} + } + } + } + impl revokeRoleReturn { + fn _tokenize( + &self, + ) -> ::ReturnToken<'_> { + () + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for revokeRoleCall { + type Parameters<'a> = ( + alloy::sol_types::sol_data::FixedBytes<32>, + alloy::sol_types::sol_data::Address, + ); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = revokeRoleReturn; + type ReturnTuple<'a> = (); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "revokeRole(bytes32,address)"; + const SELECTOR: [u8; 4] = [213u8, 71u8, 116u8, 31u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + ( + as alloy_sol_types::SolType>::tokenize(&self.role), + ::tokenize( + &self.account, + ), + ) + } + #[inline] + fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> { + revokeRoleReturn::_tokenize(ret) + } + #[inline] + fn abi_decode_returns(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data) + .map(Into::into) + } + #[inline] + fn abi_decode_returns_validate( + data: &[u8], + ) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(Into::into) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Function with signature `supportsInterface(bytes4)` and selector `0x01ffc9a7`. +```solidity +function supportsInterface(bytes4 interfaceId) external view returns (bool); +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct supportsInterfaceCall { + #[allow(missing_docs)] + pub interfaceId: alloy::sol_types::private::FixedBytes<4>, + } + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + ///Container type for the return parameters of the [`supportsInterface(bytes4)`](supportsInterfaceCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct supportsInterfaceReturn { + #[allow(missing_docs)] + pub _0: bool, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (alloy::sol_types::sol_data::FixedBytes<4>,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (alloy::sol_types::private::FixedBytes<4>,); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From + for UnderlyingRustTuple<'_> { + fn from(value: supportsInterfaceCall) -> Self { + (value.interfaceId,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> + for supportsInterfaceCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { interfaceId: tuple.0 } + } + } + } + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (alloy::sol_types::sol_data::Bool,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (bool,); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From + for UnderlyingRustTuple<'_> { + fn from(value: supportsInterfaceReturn) -> Self { + (value._0,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> + for supportsInterfaceReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { _0: tuple.0 } + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for supportsInterfaceCall { + type Parameters<'a> = (alloy::sol_types::sol_data::FixedBytes<4>,); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = bool; + type ReturnTuple<'a> = (alloy::sol_types::sol_data::Bool,); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "supportsInterface(bytes4)"; + const SELECTOR: [u8; 4] = [1u8, 255u8, 201u8, 167u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + ( + as alloy_sol_types::SolType>::tokenize(&self.interfaceId), + ) + } + #[inline] + fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> { + ( + ::tokenize( + ret, + ), + ) + } + #[inline] + fn abi_decode_returns(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data) + .map(|r| { + let r: supportsInterfaceReturn = r.into(); + r._0 + }) + } + #[inline] + fn abi_decode_returns_validate( + data: &[u8], + ) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(|r| { + let r: supportsInterfaceReturn = r.into(); + r._0 + }) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Function with signature `symbol()` and selector `0x95d89b41`. +```solidity +function symbol() external view returns (string memory); +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct symbolCall; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + ///Container type for the return parameters of the [`symbol()`](symbolCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct symbolReturn { + #[allow(missing_docs)] + pub _0: alloy::sol_types::private::String, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: symbolCall) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for symbolCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self + } + } + } + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (alloy::sol_types::sol_data::String,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (alloy::sol_types::private::String,); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: symbolReturn) -> Self { + (value._0,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for symbolReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { _0: tuple.0 } + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for symbolCall { + type Parameters<'a> = (); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = alloy::sol_types::private::String; + type ReturnTuple<'a> = (alloy::sol_types::sol_data::String,); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "symbol()"; + const SELECTOR: [u8; 4] = [149u8, 216u8, 155u8, 65u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + () + } + #[inline] + fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> { + ( + ::tokenize( + ret, + ), + ) + } + #[inline] + fn abi_decode_returns(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data) + .map(|r| { + let r: symbolReturn = r.into(); + r._0 + }) + } + #[inline] + fn abi_decode_returns_validate( + data: &[u8], + ) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(|r| { + let r: symbolReturn = r.into(); + r._0 + }) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Function with signature `totalSupply()` and selector `0x18160ddd`. +```solidity +function totalSupply() external view returns (uint256); +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct totalSupplyCall; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + ///Container type for the return parameters of the [`totalSupply()`](totalSupplyCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct totalSupplyReturn { + #[allow(missing_docs)] + pub _0: alloy::sol_types::private::primitives::aliases::U256, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: totalSupplyCall) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for totalSupplyCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self + } + } + } + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (alloy::sol_types::sol_data::Uint<256>,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = ( + alloy::sol_types::private::primitives::aliases::U256, + ); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: totalSupplyReturn) -> Self { + (value._0,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for totalSupplyReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { _0: tuple.0 } + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for totalSupplyCall { + type Parameters<'a> = (); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = alloy::sol_types::private::primitives::aliases::U256; + type ReturnTuple<'a> = (alloy::sol_types::sol_data::Uint<256>,); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "totalSupply()"; + const SELECTOR: [u8; 4] = [24u8, 22u8, 13u8, 221u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + () + } + #[inline] + fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> { + ( + as alloy_sol_types::SolType>::tokenize(ret), + ) + } + #[inline] + fn abi_decode_returns(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data) + .map(|r| { + let r: totalSupplyReturn = r.into(); + r._0 + }) + } + #[inline] + fn abi_decode_returns_validate( + data: &[u8], + ) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(|r| { + let r: totalSupplyReturn = r.into(); + r._0 + }) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Function with signature `transfer(address,uint256)` and selector `0xa9059cbb`. +```solidity +function transfer(address to, uint256 value) external returns (bool); +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct transferCall { + #[allow(missing_docs)] + pub to: alloy::sol_types::private::Address, + #[allow(missing_docs)] + pub value: alloy::sol_types::private::primitives::aliases::U256, + } + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + ///Container type for the return parameters of the [`transfer(address,uint256)`](transferCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct transferReturn { + #[allow(missing_docs)] + pub _0: bool, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = ( + alloy::sol_types::sol_data::Address, + alloy::sol_types::sol_data::Uint<256>, + ); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = ( + alloy::sol_types::private::Address, + alloy::sol_types::private::primitives::aliases::U256, + ); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: transferCall) -> Self { + (value.to, value.value) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for transferCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { + to: tuple.0, + value: tuple.1, + } + } + } + } + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (alloy::sol_types::sol_data::Bool,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (bool,); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: transferReturn) -> Self { + (value._0,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for transferReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { _0: tuple.0 } + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for transferCall { + type Parameters<'a> = ( + alloy::sol_types::sol_data::Address, + alloy::sol_types::sol_data::Uint<256>, + ); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = bool; + type ReturnTuple<'a> = (alloy::sol_types::sol_data::Bool,); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "transfer(address,uint256)"; + const SELECTOR: [u8; 4] = [169u8, 5u8, 156u8, 187u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + ( + ::tokenize( + &self.to, + ), + as alloy_sol_types::SolType>::tokenize(&self.value), + ) + } + #[inline] + fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> { + ( + ::tokenize( + ret, + ), + ) + } + #[inline] + fn abi_decode_returns(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data) + .map(|r| { + let r: transferReturn = r.into(); + r._0 + }) + } + #[inline] + fn abi_decode_returns_validate( + data: &[u8], + ) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(|r| { + let r: transferReturn = r.into(); + r._0 + }) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Function with signature `transferFrom(address,address,uint256)` and selector `0x23b872dd`. +```solidity +function transferFrom(address from, address to, uint256 value) external returns (bool); +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct transferFromCall { + #[allow(missing_docs)] + pub from: alloy::sol_types::private::Address, + #[allow(missing_docs)] + pub to: alloy::sol_types::private::Address, + #[allow(missing_docs)] + pub value: alloy::sol_types::private::primitives::aliases::U256, + } + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + ///Container type for the return parameters of the [`transferFrom(address,address,uint256)`](transferFromCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct transferFromReturn { + #[allow(missing_docs)] + pub _0: bool, + } + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = ( + alloy::sol_types::sol_data::Address, + alloy::sol_types::sol_data::Address, + alloy::sol_types::sol_data::Uint<256>, + ); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = ( + alloy::sol_types::private::Address, + alloy::sol_types::private::Address, + alloy::sol_types::private::primitives::aliases::U256, + ); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: transferFromCall) -> Self { + (value.from, value.to, value.value) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for transferFromCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { + from: tuple.0, + to: tuple.1, + value: tuple.2, + } + } + } + } + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (alloy::sol_types::sol_data::Bool,); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (bool,); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: transferFromReturn) -> Self { + (value._0,) + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for transferFromReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self { _0: tuple.0 } + } + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for transferFromCall { + type Parameters<'a> = ( + alloy::sol_types::sol_data::Address, + alloy::sol_types::sol_data::Address, + alloy::sol_types::sol_data::Uint<256>, + ); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = bool; + type ReturnTuple<'a> = (alloy::sol_types::sol_data::Bool,); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "transferFrom(address,address,uint256)"; + const SELECTOR: [u8; 4] = [35u8, 184u8, 114u8, 221u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + ( + ::tokenize( + &self.from, + ), + ::tokenize( + &self.to, + ), + as alloy_sol_types::SolType>::tokenize(&self.value), + ) + } + #[inline] + fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> { + ( + ::tokenize( + ret, + ), + ) + } + #[inline] + fn abi_decode_returns(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data) + .map(|r| { + let r: transferFromReturn = r.into(); + r._0 + }) + } + #[inline] + fn abi_decode_returns_validate( + data: &[u8], + ) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(|r| { + let r: transferFromReturn = r.into(); + r._0 + }) + } + } + }; + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] + /**Function with signature `unpause()` and selector `0x3f4ba83a`. +```solidity +function unpause() external; +```*/ + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct unpauseCall; + ///Container type for the return parameters of the [`unpause()`](unpauseCall) function. + #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] + #[derive(Clone)] + pub struct unpauseReturn {} + #[allow( + non_camel_case_types, + non_snake_case, + clippy::pub_underscore_fields, + clippy::style + )] + const _: () = { + use alloy::sol_types as alloy_sol_types; + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: unpauseCall) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for unpauseCall { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self + } + } + } + { + #[doc(hidden)] + type UnderlyingSolTuple<'a> = (); + #[doc(hidden)] + type UnderlyingRustTuple<'a> = (); + #[cfg(test)] + #[allow(dead_code, unreachable_patterns)] + fn _type_assertion( + _t: alloy_sol_types::private::AssertTypeEq, + ) { + match _t { + alloy_sol_types::private::AssertTypeEq::< + ::RustType, + >(_) => {} + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From for UnderlyingRustTuple<'_> { + fn from(value: unpauseReturn) -> Self { + () + } + } + #[automatically_derived] + #[doc(hidden)] + impl ::core::convert::From> for unpauseReturn { + fn from(tuple: UnderlyingRustTuple<'_>) -> Self { + Self {} + } + } + } + impl unpauseReturn { + fn _tokenize( + &self, + ) -> ::ReturnToken<'_> { + () + } + } + #[automatically_derived] + impl alloy_sol_types::SolCall for unpauseCall { + type Parameters<'a> = (); + type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; + type Return = unpauseReturn; + type ReturnTuple<'a> = (); + type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; + const SIGNATURE: &'static str = "unpause()"; + const SELECTOR: [u8; 4] = [63u8, 75u8, 168u8, 58u8]; + #[inline] + fn new<'a>( + tuple: as alloy_sol_types::SolType>::RustType, + ) -> Self { + tuple.into() + } + #[inline] + fn tokenize(&self) -> Self::Token<'_> { + () + } + #[inline] + fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> { + unpauseReturn::_tokenize(ret) + } + #[inline] + fn abi_decode_returns(data: &[u8]) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence(data) + .map(Into::into) + } + #[inline] + fn abi_decode_returns_validate( + data: &[u8], + ) -> alloy_sol_types::Result { + as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) + .map(Into::into) + } + } + }; + ///Container for all the [`WrappedToken`](self) function calls. + #[derive(serde::Serialize, serde::Deserialize)] + #[derive()] + pub enum WrappedTokenCalls { + #[allow(missing_docs)] + DEFAULT_ADMIN_ROLE(DEFAULT_ADMIN_ROLECall), + #[allow(missing_docs)] + MINTER_ROLE(MINTER_ROLECall), + #[allow(missing_docs)] + PAUSER_ROLE(PAUSER_ROLECall), + #[allow(missing_docs)] + allowance(allowanceCall), + #[allow(missing_docs)] + approve(approveCall), + #[allow(missing_docs)] + balanceOf(balanceOfCall), + #[allow(missing_docs)] + burn(burnCall), + #[allow(missing_docs)] + burnFrom(burnFromCall), + #[allow(missing_docs)] + decimals(decimalsCall), + #[allow(missing_docs)] + getRoleAdmin(getRoleAdminCall), + #[allow(missing_docs)] + grantRole(grantRoleCall), + #[allow(missing_docs)] + hasRole(hasRoleCall), + #[allow(missing_docs)] + mint(mintCall), + #[allow(missing_docs)] + name(nameCall), + #[allow(missing_docs)] + pause(pauseCall), + #[allow(missing_docs)] + paused(pausedCall), + #[allow(missing_docs)] + renounceRole(renounceRoleCall), + #[allow(missing_docs)] + revokeRole(revokeRoleCall), + #[allow(missing_docs)] + supportsInterface(supportsInterfaceCall), + #[allow(missing_docs)] + symbol(symbolCall), + #[allow(missing_docs)] + totalSupply(totalSupplyCall), + #[allow(missing_docs)] + transfer(transferCall), + #[allow(missing_docs)] + transferFrom(transferFromCall), + #[allow(missing_docs)] + unpause(unpauseCall), + } + #[automatically_derived] + impl WrappedTokenCalls { + /// All the selectors of this enum. + /// + /// Note that the selectors might not be in the same order as the variants. + /// No guarantees are made about the order of the selectors. + /// + /// Prefer using `SolInterface` methods instead. + pub const SELECTORS: &'static [[u8; 4usize]] = &[ + [1u8, 255u8, 201u8, 167u8], + [6u8, 253u8, 222u8, 3u8], + [9u8, 94u8, 167u8, 179u8], + [24u8, 22u8, 13u8, 221u8], + [35u8, 184u8, 114u8, 221u8], + [36u8, 138u8, 156u8, 163u8], + [47u8, 47u8, 241u8, 93u8], + [49u8, 60u8, 229u8, 103u8], + [54u8, 86u8, 138u8, 190u8], + [63u8, 75u8, 168u8, 58u8], + [64u8, 193u8, 15u8, 25u8], + [66u8, 150u8, 108u8, 104u8], + [92u8, 151u8, 90u8, 187u8], + [112u8, 160u8, 130u8, 49u8], + [121u8, 204u8, 103u8, 144u8], + [132u8, 86u8, 203u8, 89u8], + [145u8, 209u8, 72u8, 84u8], + [149u8, 216u8, 155u8, 65u8], + [162u8, 23u8, 253u8, 223u8], + [169u8, 5u8, 156u8, 187u8], + [213u8, 57u8, 19u8, 147u8], + [213u8, 71u8, 116u8, 31u8], + [221u8, 98u8, 237u8, 62u8], + [230u8, 58u8, 177u8, 233u8], + ]; + } + #[automatically_derived] + impl alloy_sol_types::SolInterface for WrappedTokenCalls { + const NAME: &'static str = "WrappedTokenCalls"; + const MIN_DATA_LENGTH: usize = 0usize; + const COUNT: usize = 24usize; + #[inline] + fn selector(&self) -> [u8; 4] { + match self { + Self::DEFAULT_ADMIN_ROLE(_) => { + ::SELECTOR + } + Self::MINTER_ROLE(_) => { + ::SELECTOR + } + Self::PAUSER_ROLE(_) => { + ::SELECTOR + } + Self::allowance(_) => { + ::SELECTOR + } + Self::approve(_) => ::SELECTOR, + Self::balanceOf(_) => { + ::SELECTOR + } + Self::burn(_) => ::SELECTOR, + Self::burnFrom(_) => ::SELECTOR, + Self::decimals(_) => ::SELECTOR, + Self::getRoleAdmin(_) => { + ::SELECTOR + } + Self::grantRole(_) => { + ::SELECTOR + } + Self::hasRole(_) => ::SELECTOR, + Self::mint(_) => ::SELECTOR, + Self::name(_) => ::SELECTOR, + Self::pause(_) => ::SELECTOR, + Self::paused(_) => ::SELECTOR, + Self::renounceRole(_) => { + ::SELECTOR + } + Self::revokeRole(_) => { + ::SELECTOR + } + Self::supportsInterface(_) => { + ::SELECTOR + } + Self::symbol(_) => ::SELECTOR, + Self::totalSupply(_) => { + ::SELECTOR + } + Self::transfer(_) => ::SELECTOR, + Self::transferFrom(_) => { + ::SELECTOR + } + Self::unpause(_) => ::SELECTOR, + } + } + #[inline] + fn selector_at(i: usize) -> ::core::option::Option<[u8; 4]> { + Self::SELECTORS.get(i).copied() + } + #[inline] + fn valid_selector(selector: [u8; 4]) -> bool { + Self::SELECTORS.binary_search(&selector).is_ok() + } + #[inline] + #[allow(non_snake_case)] + fn abi_decode_raw( + selector: [u8; 4], + data: &[u8], + ) -> alloy_sol_types::Result { + static DECODE_SHIMS: &[fn( + &[u8], + ) -> alloy_sol_types::Result] = &[ + { + fn supportsInterface( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw( + data, + ) + .map(WrappedTokenCalls::supportsInterface) + } + supportsInterface + }, + { + fn name(data: &[u8]) -> alloy_sol_types::Result { + ::abi_decode_raw(data) + .map(WrappedTokenCalls::name) + } + name + }, + { + fn approve( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw(data) + .map(WrappedTokenCalls::approve) + } + approve + }, + { + fn totalSupply( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw( + data, + ) + .map(WrappedTokenCalls::totalSupply) + } + totalSupply + }, + { + fn transferFrom( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw( + data, + ) + .map(WrappedTokenCalls::transferFrom) + } + transferFrom + }, + { + fn getRoleAdmin( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw( + data, + ) + .map(WrappedTokenCalls::getRoleAdmin) + } + getRoleAdmin + }, + { + fn grantRole( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw(data) + .map(WrappedTokenCalls::grantRole) + } + grantRole + }, + { + fn decimals( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw(data) + .map(WrappedTokenCalls::decimals) + } + decimals + }, + { + fn renounceRole( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw( + data, + ) + .map(WrappedTokenCalls::renounceRole) + } + renounceRole + }, + { + fn unpause( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw(data) + .map(WrappedTokenCalls::unpause) + } + unpause + }, + { + fn mint(data: &[u8]) -> alloy_sol_types::Result { + ::abi_decode_raw(data) + .map(WrappedTokenCalls::mint) + } + mint + }, + { + fn burn(data: &[u8]) -> alloy_sol_types::Result { + ::abi_decode_raw(data) + .map(WrappedTokenCalls::burn) + } + burn + }, + { + fn paused( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw(data) + .map(WrappedTokenCalls::paused) + } + paused + }, + { + fn balanceOf( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw(data) + .map(WrappedTokenCalls::balanceOf) + } + balanceOf + }, + { + fn burnFrom( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw(data) + .map(WrappedTokenCalls::burnFrom) + } + burnFrom + }, + { + fn pause(data: &[u8]) -> alloy_sol_types::Result { + ::abi_decode_raw(data) + .map(WrappedTokenCalls::pause) + } + pause + }, + { + fn hasRole( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw(data) + .map(WrappedTokenCalls::hasRole) + } + hasRole + }, + { + fn symbol( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw(data) + .map(WrappedTokenCalls::symbol) + } + symbol + }, + { + fn DEFAULT_ADMIN_ROLE( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw( + data, + ) + .map(WrappedTokenCalls::DEFAULT_ADMIN_ROLE) + } + DEFAULT_ADMIN_ROLE + }, + { + fn transfer( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw(data) + .map(WrappedTokenCalls::transfer) + } + transfer + }, + { + fn MINTER_ROLE( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw( + data, + ) + .map(WrappedTokenCalls::MINTER_ROLE) + } + MINTER_ROLE + }, + { + fn revokeRole( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw( + data, + ) + .map(WrappedTokenCalls::revokeRole) + } + revokeRole + }, + { + fn allowance( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw(data) + .map(WrappedTokenCalls::allowance) + } + allowance + }, + { + fn PAUSER_ROLE( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw( + data, + ) + .map(WrappedTokenCalls::PAUSER_ROLE) + } + PAUSER_ROLE + }, + ]; + let Ok(idx) = Self::SELECTORS.binary_search(&selector) else { + return Err( + alloy_sol_types::Error::unknown_selector( + ::NAME, + selector, + ), + ); + }; + DECODE_SHIMS[idx](data) + } + #[inline] + #[allow(non_snake_case)] + fn abi_decode_raw_validate( + selector: [u8; 4], + data: &[u8], + ) -> alloy_sol_types::Result { + static DECODE_VALIDATE_SHIMS: &[fn( + &[u8], + ) -> alloy_sol_types::Result] = &[ + { + fn supportsInterface( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(WrappedTokenCalls::supportsInterface) + } + supportsInterface + }, + { + fn name(data: &[u8]) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(WrappedTokenCalls::name) + } + name + }, + { + fn approve( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(WrappedTokenCalls::approve) + } + approve + }, + { + fn totalSupply( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(WrappedTokenCalls::totalSupply) + } + totalSupply + }, + { + fn transferFrom( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(WrappedTokenCalls::transferFrom) + } + transferFrom + }, + { + fn getRoleAdmin( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(WrappedTokenCalls::getRoleAdmin) + } + getRoleAdmin + }, + { + fn grantRole( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(WrappedTokenCalls::grantRole) + } + grantRole + }, + { + fn decimals( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(WrappedTokenCalls::decimals) + } + decimals + }, + { + fn renounceRole( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(WrappedTokenCalls::renounceRole) + } + renounceRole + }, + { + fn unpause( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(WrappedTokenCalls::unpause) + } + unpause + }, + { + fn mint(data: &[u8]) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(WrappedTokenCalls::mint) + } + mint + }, + { + fn burn(data: &[u8]) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(WrappedTokenCalls::burn) + } + burn + }, + { + fn paused( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(WrappedTokenCalls::paused) + } + paused + }, + { + fn balanceOf( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(WrappedTokenCalls::balanceOf) + } + balanceOf + }, + { + fn burnFrom( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(WrappedTokenCalls::burnFrom) + } + burnFrom + }, + { + fn pause(data: &[u8]) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(WrappedTokenCalls::pause) + } + pause + }, + { + fn hasRole( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(WrappedTokenCalls::hasRole) + } + hasRole + }, + { + fn symbol( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(WrappedTokenCalls::symbol) + } + symbol + }, + { + fn DEFAULT_ADMIN_ROLE( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(WrappedTokenCalls::DEFAULT_ADMIN_ROLE) + } + DEFAULT_ADMIN_ROLE + }, + { + fn transfer( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(WrappedTokenCalls::transfer) + } + transfer + }, + { + fn MINTER_ROLE( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(WrappedTokenCalls::MINTER_ROLE) + } + MINTER_ROLE + }, + { + fn revokeRole( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(WrappedTokenCalls::revokeRole) + } + revokeRole + }, + { + fn allowance( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(WrappedTokenCalls::allowance) + } + allowance + }, + { + fn PAUSER_ROLE( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(WrappedTokenCalls::PAUSER_ROLE) + } + PAUSER_ROLE + }, + ]; + let Ok(idx) = Self::SELECTORS.binary_search(&selector) else { + return Err( + alloy_sol_types::Error::unknown_selector( + ::NAME, + selector, + ), + ); + }; + DECODE_VALIDATE_SHIMS[idx](data) + } + #[inline] + fn abi_encoded_size(&self) -> usize { + match self { + Self::DEFAULT_ADMIN_ROLE(inner) => { + ::abi_encoded_size( + inner, + ) + } + Self::MINTER_ROLE(inner) => { + ::abi_encoded_size( + inner, + ) + } + Self::PAUSER_ROLE(inner) => { + ::abi_encoded_size( + inner, + ) + } + Self::allowance(inner) => { + ::abi_encoded_size(inner) + } + Self::approve(inner) => { + ::abi_encoded_size(inner) + } + Self::balanceOf(inner) => { + ::abi_encoded_size(inner) + } + Self::burn(inner) => { + ::abi_encoded_size(inner) + } + Self::burnFrom(inner) => { + ::abi_encoded_size(inner) + } + Self::decimals(inner) => { + ::abi_encoded_size(inner) + } + Self::getRoleAdmin(inner) => { + ::abi_encoded_size( + inner, + ) + } + Self::grantRole(inner) => { + ::abi_encoded_size(inner) + } + Self::hasRole(inner) => { + ::abi_encoded_size(inner) + } + Self::mint(inner) => { + ::abi_encoded_size(inner) + } + Self::name(inner) => { + ::abi_encoded_size(inner) + } + Self::pause(inner) => { + ::abi_encoded_size(inner) + } + Self::paused(inner) => { + ::abi_encoded_size(inner) + } + Self::renounceRole(inner) => { + ::abi_encoded_size( + inner, + ) + } + Self::revokeRole(inner) => { + ::abi_encoded_size(inner) + } + Self::supportsInterface(inner) => { + ::abi_encoded_size( + inner, + ) + } + Self::symbol(inner) => { + ::abi_encoded_size(inner) + } + Self::totalSupply(inner) => { + ::abi_encoded_size( + inner, + ) + } + Self::transfer(inner) => { + ::abi_encoded_size(inner) + } + Self::transferFrom(inner) => { + ::abi_encoded_size( + inner, + ) + } + Self::unpause(inner) => { + ::abi_encoded_size(inner) + } + } + } + #[inline] + fn abi_encode_raw(&self, out: &mut alloy_sol_types::private::Vec) { + match self { + Self::DEFAULT_ADMIN_ROLE(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } + Self::MINTER_ROLE(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } + Self::PAUSER_ROLE(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } + Self::allowance(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } + Self::approve(inner) => { + ::abi_encode_raw(inner, out) + } + Self::balanceOf(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } + Self::burn(inner) => { + ::abi_encode_raw(inner, out) + } + Self::burnFrom(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } + Self::decimals(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } + Self::getRoleAdmin(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } + Self::grantRole(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } + Self::hasRole(inner) => { + ::abi_encode_raw(inner, out) + } + Self::mint(inner) => { + ::abi_encode_raw(inner, out) + } + Self::name(inner) => { + ::abi_encode_raw(inner, out) + } + Self::pause(inner) => { + ::abi_encode_raw(inner, out) + } + Self::paused(inner) => { + ::abi_encode_raw(inner, out) + } + Self::renounceRole(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } + Self::revokeRole(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } + Self::supportsInterface(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } + Self::symbol(inner) => { + ::abi_encode_raw(inner, out) + } + Self::totalSupply(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } + Self::transfer(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } + Self::transferFrom(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } + Self::unpause(inner) => { + ::abi_encode_raw(inner, out) + } + } + } + } + ///Container for all the [`WrappedToken`](self) custom errors. + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Debug, PartialEq, Eq, Hash)] + pub enum WrappedTokenErrors { + #[allow(missing_docs)] + AccessControlBadConfirmation(AccessControlBadConfirmation), + #[allow(missing_docs)] + AccessControlUnauthorizedAccount(AccessControlUnauthorizedAccount), + #[allow(missing_docs)] + ERC20InsufficientAllowance(ERC20InsufficientAllowance), + #[allow(missing_docs)] + ERC20InsufficientBalance(ERC20InsufficientBalance), + #[allow(missing_docs)] + ERC20InvalidApprover(ERC20InvalidApprover), + #[allow(missing_docs)] + ERC20InvalidReceiver(ERC20InvalidReceiver), + #[allow(missing_docs)] + ERC20InvalidSender(ERC20InvalidSender), + #[allow(missing_docs)] + ERC20InvalidSpender(ERC20InvalidSpender), + #[allow(missing_docs)] + EnforcedPause(EnforcedPause), + #[allow(missing_docs)] + ExpectedPause(ExpectedPause), + } + #[automatically_derived] + impl WrappedTokenErrors { + /// All the selectors of this enum. + /// + /// Note that the selectors might not be in the same order as the variants. + /// No guarantees are made about the order of the selectors. + /// + /// Prefer using `SolInterface` methods instead. + pub const SELECTORS: &'static [[u8; 4usize]] = &[ + [102u8, 151u8, 178u8, 50u8], + [141u8, 252u8, 32u8, 43u8], + [148u8, 40u8, 13u8, 98u8], + [150u8, 198u8, 253u8, 30u8], + [217u8, 60u8, 6u8, 101u8], + [226u8, 81u8, 125u8, 63u8], + [228u8, 80u8, 211u8, 140u8], + [230u8, 2u8, 223u8, 5u8], + [236u8, 68u8, 47u8, 5u8], + [251u8, 143u8, 65u8, 178u8], + ]; + } + #[automatically_derived] + impl alloy_sol_types::SolInterface for WrappedTokenErrors { + const NAME: &'static str = "WrappedTokenErrors"; + const MIN_DATA_LENGTH: usize = 0usize; + const COUNT: usize = 10usize; + #[inline] + fn selector(&self) -> [u8; 4] { + match self { + Self::AccessControlBadConfirmation(_) => { + ::SELECTOR + } + Self::AccessControlUnauthorizedAccount(_) => { + ::SELECTOR + } + Self::ERC20InsufficientAllowance(_) => { + ::SELECTOR + } + Self::ERC20InsufficientBalance(_) => { + ::SELECTOR + } + Self::ERC20InvalidApprover(_) => { + ::SELECTOR + } + Self::ERC20InvalidReceiver(_) => { + ::SELECTOR + } + Self::ERC20InvalidSender(_) => { + ::SELECTOR + } + Self::ERC20InvalidSpender(_) => { + ::SELECTOR + } + Self::EnforcedPause(_) => { + ::SELECTOR + } + Self::ExpectedPause(_) => { + ::SELECTOR + } + } + } + #[inline] + fn selector_at(i: usize) -> ::core::option::Option<[u8; 4]> { + Self::SELECTORS.get(i).copied() + } + #[inline] + fn valid_selector(selector: [u8; 4]) -> bool { + Self::SELECTORS.binary_search(&selector).is_ok() + } + #[inline] + #[allow(non_snake_case)] + fn abi_decode_raw( + selector: [u8; 4], + data: &[u8], + ) -> alloy_sol_types::Result { + static DECODE_SHIMS: &[fn( + &[u8], + ) -> alloy_sol_types::Result] = &[ + { + fn AccessControlBadConfirmation( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw( + data, + ) + .map(WrappedTokenErrors::AccessControlBadConfirmation) + } + AccessControlBadConfirmation + }, + { + fn ExpectedPause( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw( + data, + ) + .map(WrappedTokenErrors::ExpectedPause) + } + ExpectedPause + }, + { + fn ERC20InvalidSpender( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw( + data, + ) + .map(WrappedTokenErrors::ERC20InvalidSpender) + } + ERC20InvalidSpender + }, + { + fn ERC20InvalidSender( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw( + data, + ) + .map(WrappedTokenErrors::ERC20InvalidSender) + } + ERC20InvalidSender + }, + { + fn EnforcedPause( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw( + data, + ) + .map(WrappedTokenErrors::EnforcedPause) + } + EnforcedPause + }, + { + fn AccessControlUnauthorizedAccount( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw( + data, + ) + .map(WrappedTokenErrors::AccessControlUnauthorizedAccount) + } + AccessControlUnauthorizedAccount + }, + { + fn ERC20InsufficientBalance( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw( + data, + ) + .map(WrappedTokenErrors::ERC20InsufficientBalance) + } + ERC20InsufficientBalance + }, + { + fn ERC20InvalidApprover( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw( + data, + ) + .map(WrappedTokenErrors::ERC20InvalidApprover) + } + ERC20InvalidApprover + }, + { + fn ERC20InvalidReceiver( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw( + data, + ) + .map(WrappedTokenErrors::ERC20InvalidReceiver) + } + ERC20InvalidReceiver + }, + { + fn ERC20InsufficientAllowance( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw( + data, + ) + .map(WrappedTokenErrors::ERC20InsufficientAllowance) + } + ERC20InsufficientAllowance + }, + ]; + let Ok(idx) = Self::SELECTORS.binary_search(&selector) else { + return Err( + alloy_sol_types::Error::unknown_selector( + ::NAME, + selector, + ), + ); + }; + DECODE_SHIMS[idx](data) + } + #[inline] + #[allow(non_snake_case)] + fn abi_decode_raw_validate( + selector: [u8; 4], + data: &[u8], + ) -> alloy_sol_types::Result { + static DECODE_VALIDATE_SHIMS: &[fn( + &[u8], + ) -> alloy_sol_types::Result] = &[ + { + fn AccessControlBadConfirmation( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(WrappedTokenErrors::AccessControlBadConfirmation) + } + AccessControlBadConfirmation + }, + { + fn ExpectedPause( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(WrappedTokenErrors::ExpectedPause) + } + ExpectedPause + }, + { + fn ERC20InvalidSpender( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(WrappedTokenErrors::ERC20InvalidSpender) + } + ERC20InvalidSpender + }, + { + fn ERC20InvalidSender( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(WrappedTokenErrors::ERC20InvalidSender) + } + ERC20InvalidSender + }, + { + fn EnforcedPause( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(WrappedTokenErrors::EnforcedPause) + } + EnforcedPause + }, + { + fn AccessControlUnauthorizedAccount( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(WrappedTokenErrors::AccessControlUnauthorizedAccount) + } + AccessControlUnauthorizedAccount + }, + { + fn ERC20InsufficientBalance( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(WrappedTokenErrors::ERC20InsufficientBalance) + } + ERC20InsufficientBalance + }, + { + fn ERC20InvalidApprover( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(WrappedTokenErrors::ERC20InvalidApprover) + } + ERC20InvalidApprover + }, + { + fn ERC20InvalidReceiver( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(WrappedTokenErrors::ERC20InvalidReceiver) + } + ERC20InvalidReceiver + }, + { + fn ERC20InsufficientAllowance( + data: &[u8], + ) -> alloy_sol_types::Result { + ::abi_decode_raw_validate( + data, + ) + .map(WrappedTokenErrors::ERC20InsufficientAllowance) + } + ERC20InsufficientAllowance + }, + ]; + let Ok(idx) = Self::SELECTORS.binary_search(&selector) else { + return Err( + alloy_sol_types::Error::unknown_selector( + ::NAME, + selector, + ), + ); + }; + DECODE_VALIDATE_SHIMS[idx](data) + } + #[inline] + fn abi_encoded_size(&self) -> usize { + match self { + Self::AccessControlBadConfirmation(inner) => { + ::abi_encoded_size( + inner, + ) + } + Self::AccessControlUnauthorizedAccount(inner) => { + ::abi_encoded_size( + inner, + ) + } + Self::ERC20InsufficientAllowance(inner) => { + ::abi_encoded_size( + inner, + ) + } + Self::ERC20InsufficientBalance(inner) => { + ::abi_encoded_size( + inner, + ) + } + Self::ERC20InvalidApprover(inner) => { + ::abi_encoded_size( + inner, + ) + } + Self::ERC20InvalidReceiver(inner) => { + ::abi_encoded_size( + inner, + ) + } + Self::ERC20InvalidSender(inner) => { + ::abi_encoded_size( + inner, + ) + } + Self::ERC20InvalidSpender(inner) => { + ::abi_encoded_size( + inner, + ) + } + Self::EnforcedPause(inner) => { + ::abi_encoded_size(inner) + } + Self::ExpectedPause(inner) => { + ::abi_encoded_size(inner) + } + } + } + #[inline] + fn abi_encode_raw(&self, out: &mut alloy_sol_types::private::Vec) { + match self { + Self::AccessControlBadConfirmation(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } + Self::AccessControlUnauthorizedAccount(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } + Self::ERC20InsufficientAllowance(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } + Self::ERC20InsufficientBalance(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } + Self::ERC20InvalidApprover(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } + Self::ERC20InvalidReceiver(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } + Self::ERC20InvalidSender(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } + Self::ERC20InvalidSpender(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } + Self::EnforcedPause(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } + Self::ExpectedPause(inner) => { + ::abi_encode_raw( + inner, + out, + ) + } + } + } + } + ///Container for all the [`WrappedToken`](self) events. + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Debug, PartialEq, Eq, Hash)] + pub enum WrappedTokenEvents { + #[allow(missing_docs)] + Approval(Approval), + #[allow(missing_docs)] + Paused(Paused), + #[allow(missing_docs)] + RoleAdminChanged(RoleAdminChanged), + #[allow(missing_docs)] + RoleGranted(RoleGranted), + #[allow(missing_docs)] + RoleRevoked(RoleRevoked), + #[allow(missing_docs)] + Transfer(Transfer), + #[allow(missing_docs)] + Unpaused(Unpaused), + } + #[automatically_derived] + impl WrappedTokenEvents { + /// All the selectors of this enum. + /// + /// Note that the selectors might not be in the same order as the variants. + /// No guarantees are made about the order of the selectors. + /// + /// Prefer using `SolInterface` methods instead. + pub const SELECTORS: &'static [[u8; 32usize]] = &[ + [ + 47u8, 135u8, 136u8, 17u8, 126u8, 126u8, 255u8, 29u8, 130u8, 233u8, 38u8, + 236u8, 121u8, 73u8, 1u8, 209u8, 124u8, 120u8, 2u8, 74u8, 80u8, 39u8, 9u8, + 64u8, 48u8, 69u8, 64u8, 167u8, 51u8, 101u8, 111u8, 13u8, + ], + [ + 93u8, 185u8, 238u8, 10u8, 73u8, 91u8, 242u8, 230u8, 255u8, 156u8, 145u8, + 167u8, 131u8, 76u8, 27u8, 164u8, 253u8, 210u8, 68u8, 165u8, 232u8, 170u8, + 78u8, 83u8, 123u8, 211u8, 138u8, 234u8, 228u8, 176u8, 115u8, 170u8, + ], + [ + 98u8, 231u8, 140u8, 234u8, 1u8, 190u8, 227u8, 32u8, 205u8, 78u8, 66u8, + 2u8, 112u8, 181u8, 234u8, 116u8, 0u8, 13u8, 17u8, 176u8, 201u8, 247u8, + 71u8, 84u8, 235u8, 219u8, 252u8, 84u8, 75u8, 5u8, 162u8, 88u8, + ], + [ + 140u8, 91u8, 225u8, 229u8, 235u8, 236u8, 125u8, 91u8, 209u8, 79u8, 113u8, + 66u8, 125u8, 30u8, 132u8, 243u8, 221u8, 3u8, 20u8, 192u8, 247u8, 178u8, + 41u8, 30u8, 91u8, 32u8, 10u8, 200u8, 199u8, 195u8, 185u8, 37u8, + ], + [ + 189u8, 121u8, 184u8, 111u8, 254u8, 10u8, 184u8, 232u8, 119u8, 97u8, 81u8, + 81u8, 66u8, 23u8, 205u8, 124u8, 172u8, 213u8, 44u8, 144u8, 159u8, 102u8, + 71u8, 92u8, 58u8, 244u8, 78u8, 18u8, 159u8, 11u8, 0u8, 255u8, + ], + [ + 221u8, 242u8, 82u8, 173u8, 27u8, 226u8, 200u8, 155u8, 105u8, 194u8, + 176u8, 104u8, 252u8, 55u8, 141u8, 170u8, 149u8, 43u8, 167u8, 241u8, 99u8, + 196u8, 161u8, 22u8, 40u8, 245u8, 90u8, 77u8, 245u8, 35u8, 179u8, 239u8, + ], + [ + 246u8, 57u8, 31u8, 92u8, 50u8, 217u8, 198u8, 157u8, 42u8, 71u8, 234u8, + 103u8, 11u8, 68u8, 41u8, 116u8, 181u8, 57u8, 53u8, 209u8, 237u8, 199u8, + 253u8, 100u8, 235u8, 33u8, 224u8, 71u8, 168u8, 57u8, 23u8, 27u8, + ], + ]; + } + #[automatically_derived] + impl alloy_sol_types::SolEventInterface for WrappedTokenEvents { + const NAME: &'static str = "WrappedTokenEvents"; + const COUNT: usize = 7usize; + fn decode_raw_log( + topics: &[alloy_sol_types::Word], + data: &[u8], + ) -> alloy_sol_types::Result { + match topics.first().copied() { + Some(::SIGNATURE_HASH) => { + ::decode_raw_log(topics, data) + .map(Self::Approval) + } + Some(::SIGNATURE_HASH) => { + ::decode_raw_log(topics, data) + .map(Self::Paused) + } + Some(::SIGNATURE_HASH) => { + ::decode_raw_log( + topics, + data, + ) + .map(Self::RoleAdminChanged) + } + Some(::SIGNATURE_HASH) => { + ::decode_raw_log( + topics, + data, + ) + .map(Self::RoleGranted) + } + Some(::SIGNATURE_HASH) => { + ::decode_raw_log( + topics, + data, + ) + .map(Self::RoleRevoked) + } + Some(::SIGNATURE_HASH) => { + ::decode_raw_log(topics, data) + .map(Self::Transfer) + } + Some(::SIGNATURE_HASH) => { + ::decode_raw_log(topics, data) + .map(Self::Unpaused) + } + _ => { + alloy_sol_types::private::Err(alloy_sol_types::Error::InvalidLog { + name: ::NAME, + log: alloy_sol_types::private::Box::new( + alloy_sol_types::private::LogData::new_unchecked( + topics.to_vec(), + data.to_vec().into(), + ), + ), + }) + } + } + } + } + #[automatically_derived] + impl alloy_sol_types::private::IntoLogData for WrappedTokenEvents { + fn to_log_data(&self) -> alloy_sol_types::private::LogData { + match self { + Self::Approval(inner) => { + alloy_sol_types::private::IntoLogData::to_log_data(inner) + } + Self::Paused(inner) => { + alloy_sol_types::private::IntoLogData::to_log_data(inner) + } + Self::RoleAdminChanged(inner) => { + alloy_sol_types::private::IntoLogData::to_log_data(inner) + } + Self::RoleGranted(inner) => { + alloy_sol_types::private::IntoLogData::to_log_data(inner) + } + Self::RoleRevoked(inner) => { + alloy_sol_types::private::IntoLogData::to_log_data(inner) + } + Self::Transfer(inner) => { + alloy_sol_types::private::IntoLogData::to_log_data(inner) + } + Self::Unpaused(inner) => { + alloy_sol_types::private::IntoLogData::to_log_data(inner) + } + } + } + fn into_log_data(self) -> alloy_sol_types::private::LogData { + match self { + Self::Approval(inner) => { + alloy_sol_types::private::IntoLogData::into_log_data(inner) + } + Self::Paused(inner) => { + alloy_sol_types::private::IntoLogData::into_log_data(inner) + } + Self::RoleAdminChanged(inner) => { + alloy_sol_types::private::IntoLogData::into_log_data(inner) + } + Self::RoleGranted(inner) => { + alloy_sol_types::private::IntoLogData::into_log_data(inner) + } + Self::RoleRevoked(inner) => { + alloy_sol_types::private::IntoLogData::into_log_data(inner) + } + Self::Transfer(inner) => { + alloy_sol_types::private::IntoLogData::into_log_data(inner) + } + Self::Unpaused(inner) => { + alloy_sol_types::private::IntoLogData::into_log_data(inner) + } + } + } + } + use alloy::contract as alloy_contract; + /**Creates a new wrapper around an on-chain [`WrappedToken`](self) contract instance. + +See the [wrapper's documentation](`WrappedTokenInstance`) for more details.*/ + #[inline] + pub const fn new< + P: alloy_contract::private::Provider, + N: alloy_contract::private::Network, + >( + address: alloy_sol_types::private::Address, + provider: P, + ) -> WrappedTokenInstance { + WrappedTokenInstance::::new(address, provider) + } + /**Deploys this contract using the given `provider` and constructor arguments, if any. + +Returns a new instance of the contract, if the deployment was successful. + +For more fine-grained control over the deployment process, use [`deploy_builder`] instead.*/ + #[inline] + pub fn deploy< + P: alloy_contract::private::Provider, + N: alloy_contract::private::Network, + >( + provider: P, + name_: alloy::sol_types::private::String, + symbol_: alloy::sol_types::private::String, + decimals_: u8, + ) -> impl ::core::future::Future< + Output = alloy_contract::Result>, + > { + WrappedTokenInstance::::deploy(provider, name_, symbol_, decimals_) + } + /**Creates a `RawCallBuilder` for deploying this contract using the given `provider` +and constructor arguments, if any. + +This is a simple wrapper around creating a `RawCallBuilder` with the data set to +the bytecode concatenated with the constructor's ABI-encoded arguments.*/ + #[inline] + pub fn deploy_builder< + P: alloy_contract::private::Provider, + N: alloy_contract::private::Network, + >( + provider: P, + name_: alloy::sol_types::private::String, + symbol_: alloy::sol_types::private::String, + decimals_: u8, + ) -> alloy_contract::RawCallBuilder { + WrappedTokenInstance::::deploy_builder(provider, name_, symbol_, decimals_) + } + /**A [`WrappedToken`](self) instance. + +Contains type-safe methods for interacting with an on-chain instance of the +[`WrappedToken`](self) contract located at a given `address`, using a given +provider `P`. + +If the contract bytecode is available (see the [`sol!`](alloy_sol_types::sol!) +documentation on how to provide it), the `deploy` and `deploy_builder` methods can +be used to deploy a new instance of the contract. + +See the [module-level documentation](self) for all the available methods.*/ + #[derive(Clone)] + pub struct WrappedTokenInstance { + address: alloy_sol_types::private::Address, + provider: P, + _network: ::core::marker::PhantomData, + } + #[automatically_derived] + impl ::core::fmt::Debug for WrappedTokenInstance { + #[inline] + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + f.debug_tuple("WrappedTokenInstance").field(&self.address).finish() + } + } + /// Instantiation and getters/setters. + #[automatically_derived] + impl< + P: alloy_contract::private::Provider, + N: alloy_contract::private::Network, + > WrappedTokenInstance { + /**Creates a new wrapper around an on-chain [`WrappedToken`](self) contract instance. + +See the [wrapper's documentation](`WrappedTokenInstance`) for more details.*/ + #[inline] + pub const fn new( + address: alloy_sol_types::private::Address, + provider: P, + ) -> Self { + Self { + address, + provider, + _network: ::core::marker::PhantomData, + } + } + /**Deploys this contract using the given `provider` and constructor arguments, if any. + +Returns a new instance of the contract, if the deployment was successful. + +For more fine-grained control over the deployment process, use [`deploy_builder`] instead.*/ + #[inline] + pub async fn deploy( + provider: P, + name_: alloy::sol_types::private::String, + symbol_: alloy::sol_types::private::String, + decimals_: u8, + ) -> alloy_contract::Result> { + let call_builder = Self::deploy_builder(provider, name_, symbol_, decimals_); + let contract_address = call_builder.deploy().await?; + Ok(Self::new(contract_address, call_builder.provider)) + } + /**Creates a `RawCallBuilder` for deploying this contract using the given `provider` +and constructor arguments, if any. + +This is a simple wrapper around creating a `RawCallBuilder` with the data set to +the bytecode concatenated with the constructor's ABI-encoded arguments.*/ + #[inline] + pub fn deploy_builder( + provider: P, + name_: alloy::sol_types::private::String, + symbol_: alloy::sol_types::private::String, + decimals_: u8, + ) -> alloy_contract::RawCallBuilder { + alloy_contract::RawCallBuilder::new_raw_deploy( + provider, + [ + &BYTECODE[..], + &alloy_sol_types::SolConstructor::abi_encode( + &constructorCall { + name_, + symbol_, + decimals_, + }, + )[..], + ] + .concat() + .into(), + ) + } + /// Returns a reference to the address. + #[inline] + pub const fn address(&self) -> &alloy_sol_types::private::Address { + &self.address + } + /// Sets the address. + #[inline] + pub fn set_address(&mut self, address: alloy_sol_types::private::Address) { + self.address = address; + } + /// Sets the address and returns `self`. + pub fn at(mut self, address: alloy_sol_types::private::Address) -> Self { + self.set_address(address); + self + } + /// Returns a reference to the provider. + #[inline] + pub const fn provider(&self) -> &P { + &self.provider + } + } + impl WrappedTokenInstance<&P, N> { + /// Clones the provider and returns a new instance with the cloned provider. + #[inline] + pub fn with_cloned_provider(self) -> WrappedTokenInstance { + WrappedTokenInstance { + address: self.address, + provider: ::core::clone::Clone::clone(&self.provider), + _network: ::core::marker::PhantomData, + } + } + } + /// Function calls. + #[automatically_derived] + impl< + P: alloy_contract::private::Provider, + N: alloy_contract::private::Network, + > WrappedTokenInstance { + /// Creates a new call builder using this contract instance's provider and address. + /// + /// Note that the call can be any function call, not just those defined in this + /// contract. Prefer using the other methods for building type-safe contract calls. + pub fn call_builder( + &self, + call: &C, + ) -> alloy_contract::SolCallBuilder<&P, C, N> { + alloy_contract::SolCallBuilder::new_sol(&self.provider, &self.address, call) + } + ///Creates a new call builder for the [`DEFAULT_ADMIN_ROLE`] function. + pub fn DEFAULT_ADMIN_ROLE( + &self, + ) -> alloy_contract::SolCallBuilder<&P, DEFAULT_ADMIN_ROLECall, N> { + self.call_builder(&DEFAULT_ADMIN_ROLECall) + } + ///Creates a new call builder for the [`MINTER_ROLE`] function. + pub fn MINTER_ROLE( + &self, + ) -> alloy_contract::SolCallBuilder<&P, MINTER_ROLECall, N> { + self.call_builder(&MINTER_ROLECall) + } + ///Creates a new call builder for the [`PAUSER_ROLE`] function. + pub fn PAUSER_ROLE( + &self, + ) -> alloy_contract::SolCallBuilder<&P, PAUSER_ROLECall, N> { + self.call_builder(&PAUSER_ROLECall) + } + ///Creates a new call builder for the [`allowance`] function. + pub fn allowance( + &self, + owner: alloy::sol_types::private::Address, + spender: alloy::sol_types::private::Address, + ) -> alloy_contract::SolCallBuilder<&P, allowanceCall, N> { + self.call_builder(&allowanceCall { owner, spender }) + } + ///Creates a new call builder for the [`approve`] function. + pub fn approve( + &self, + spender: alloy::sol_types::private::Address, + value: alloy::sol_types::private::primitives::aliases::U256, + ) -> alloy_contract::SolCallBuilder<&P, approveCall, N> { + self.call_builder(&approveCall { spender, value }) + } + ///Creates a new call builder for the [`balanceOf`] function. + pub fn balanceOf( + &self, + account: alloy::sol_types::private::Address, + ) -> alloy_contract::SolCallBuilder<&P, balanceOfCall, N> { + self.call_builder(&balanceOfCall { account }) + } + ///Creates a new call builder for the [`burn`] function. + pub fn burn( + &self, + value: alloy::sol_types::private::primitives::aliases::U256, + ) -> alloy_contract::SolCallBuilder<&P, burnCall, N> { + self.call_builder(&burnCall { value }) + } + ///Creates a new call builder for the [`burnFrom`] function. + pub fn burnFrom( + &self, + account: alloy::sol_types::private::Address, + value: alloy::sol_types::private::primitives::aliases::U256, + ) -> alloy_contract::SolCallBuilder<&P, burnFromCall, N> { + self.call_builder(&burnFromCall { account, value }) + } + ///Creates a new call builder for the [`decimals`] function. + pub fn decimals(&self) -> alloy_contract::SolCallBuilder<&P, decimalsCall, N> { + self.call_builder(&decimalsCall) + } + ///Creates a new call builder for the [`getRoleAdmin`] function. + pub fn getRoleAdmin( + &self, + role: alloy::sol_types::private::FixedBytes<32>, + ) -> alloy_contract::SolCallBuilder<&P, getRoleAdminCall, N> { + self.call_builder(&getRoleAdminCall { role }) + } + ///Creates a new call builder for the [`grantRole`] function. + pub fn grantRole( + &self, + role: alloy::sol_types::private::FixedBytes<32>, + account: alloy::sol_types::private::Address, + ) -> alloy_contract::SolCallBuilder<&P, grantRoleCall, N> { + self.call_builder(&grantRoleCall { role, account }) + } + ///Creates a new call builder for the [`hasRole`] function. + pub fn hasRole( + &self, + role: alloy::sol_types::private::FixedBytes<32>, + account: alloy::sol_types::private::Address, + ) -> alloy_contract::SolCallBuilder<&P, hasRoleCall, N> { + self.call_builder(&hasRoleCall { role, account }) + } + ///Creates a new call builder for the [`mint`] function. + pub fn mint( + &self, + to: alloy::sol_types::private::Address, + amount: alloy::sol_types::private::primitives::aliases::U256, + ) -> alloy_contract::SolCallBuilder<&P, mintCall, N> { + self.call_builder(&mintCall { to, amount }) + } + ///Creates a new call builder for the [`name`] function. + pub fn name(&self) -> alloy_contract::SolCallBuilder<&P, nameCall, N> { + self.call_builder(&nameCall) + } + ///Creates a new call builder for the [`pause`] function. + pub fn pause(&self) -> alloy_contract::SolCallBuilder<&P, pauseCall, N> { + self.call_builder(&pauseCall) + } + ///Creates a new call builder for the [`paused`] function. + pub fn paused(&self) -> alloy_contract::SolCallBuilder<&P, pausedCall, N> { + self.call_builder(&pausedCall) + } + ///Creates a new call builder for the [`renounceRole`] function. + pub fn renounceRole( + &self, + role: alloy::sol_types::private::FixedBytes<32>, + callerConfirmation: alloy::sol_types::private::Address, + ) -> alloy_contract::SolCallBuilder<&P, renounceRoleCall, N> { + self.call_builder( + &renounceRoleCall { + role, + callerConfirmation, + }, + ) + } + ///Creates a new call builder for the [`revokeRole`] function. + pub fn revokeRole( + &self, + role: alloy::sol_types::private::FixedBytes<32>, + account: alloy::sol_types::private::Address, + ) -> alloy_contract::SolCallBuilder<&P, revokeRoleCall, N> { + self.call_builder(&revokeRoleCall { role, account }) + } + ///Creates a new call builder for the [`supportsInterface`] function. + pub fn supportsInterface( + &self, + interfaceId: alloy::sol_types::private::FixedBytes<4>, + ) -> alloy_contract::SolCallBuilder<&P, supportsInterfaceCall, N> { + self.call_builder( + &supportsInterfaceCall { + interfaceId, + }, + ) + } + ///Creates a new call builder for the [`symbol`] function. + pub fn symbol(&self) -> alloy_contract::SolCallBuilder<&P, symbolCall, N> { + self.call_builder(&symbolCall) + } + ///Creates a new call builder for the [`totalSupply`] function. + pub fn totalSupply( + &self, + ) -> alloy_contract::SolCallBuilder<&P, totalSupplyCall, N> { + self.call_builder(&totalSupplyCall) + } + ///Creates a new call builder for the [`transfer`] function. + pub fn transfer( + &self, + to: alloy::sol_types::private::Address, + value: alloy::sol_types::private::primitives::aliases::U256, + ) -> alloy_contract::SolCallBuilder<&P, transferCall, N> { + self.call_builder(&transferCall { to, value }) + } + ///Creates a new call builder for the [`transferFrom`] function. + pub fn transferFrom( + &self, + from: alloy::sol_types::private::Address, + to: alloy::sol_types::private::Address, + value: alloy::sol_types::private::primitives::aliases::U256, + ) -> alloy_contract::SolCallBuilder<&P, transferFromCall, N> { + self.call_builder( + &transferFromCall { + from, + to, + value, + }, + ) + } + ///Creates a new call builder for the [`unpause`] function. + pub fn unpause(&self) -> alloy_contract::SolCallBuilder<&P, unpauseCall, N> { + self.call_builder(&unpauseCall) + } + } + /// Event filters. + #[automatically_derived] + impl< + P: alloy_contract::private::Provider, + N: alloy_contract::private::Network, + > WrappedTokenInstance { + /// Creates a new event filter using this contract instance's provider and address. + /// + /// Note that the type can be any event, not just those defined in this contract. + /// Prefer using the other methods for building type-safe event filters. + pub fn event_filter( + &self, + ) -> alloy_contract::Event<&P, E, N> { + alloy_contract::Event::new_sol(&self.provider, &self.address) + } + ///Creates a new event filter for the [`Approval`] event. + pub fn Approval_filter(&self) -> alloy_contract::Event<&P, Approval, N> { + self.event_filter::() + } + ///Creates a new event filter for the [`Paused`] event. + pub fn Paused_filter(&self) -> alloy_contract::Event<&P, Paused, N> { + self.event_filter::() + } + ///Creates a new event filter for the [`RoleAdminChanged`] event. + pub fn RoleAdminChanged_filter( + &self, + ) -> alloy_contract::Event<&P, RoleAdminChanged, N> { + self.event_filter::() + } + ///Creates a new event filter for the [`RoleGranted`] event. + pub fn RoleGranted_filter(&self) -> alloy_contract::Event<&P, RoleGranted, N> { + self.event_filter::() + } + ///Creates a new event filter for the [`RoleRevoked`] event. + pub fn RoleRevoked_filter(&self) -> alloy_contract::Event<&P, RoleRevoked, N> { + self.event_filter::() + } + ///Creates a new event filter for the [`Transfer`] event. + pub fn Transfer_filter(&self) -> alloy_contract::Event<&P, Transfer, N> { + self.event_filter::() + } + ///Creates a new event filter for the [`Unpaused`] event. + pub fn Unpaused_filter(&self) -> alloy_contract::Event<&P, Unpaused, N> { + self.event_filter::() + } + } +} diff --git a/protocol/src/BridgeMintBurn.sol b/protocol/src/BridgeMintBurn.sol index 9c852eeb..779b13ff 100644 --- a/protocol/src/BridgeMintBurn.sol +++ b/protocol/src/BridgeMintBurn.sol @@ -66,7 +66,7 @@ contract BridgeMintBurn is Bridge, IBridgeMintBurn { topics[1] = bytes32(id); topics[2] = bytes32(uint256(uint160(token))); - uint256 finalizedBlockNumber = PodPrecompileHelper.getFinalizedBlockNumber(); + uint256 finalizedBlockNumber = PodPrecompileHelper.getFinalizedBlockNumber(SOURCE_CHAIN_ID); if (blockNumber > finalizedBlockNumber) { revert BlockNotFinalized(); @@ -79,13 +79,14 @@ contract BridgeMintBurn is Bridge, IBridgeMintBurn { if (!_isValidTokenAmount(mirrorToken, decodedAmount, false)) revert InvalidTokenAmount(); - if (processedRequests[requestId]) revert RequestAlreadyProcessed(); + bool isProcessed = processedRequests[requestId]; processedRequests[requestId] = true; - IERC20MintableAndBurnable(mirrorToken).mint(decodedTo, decodedAmount); - - emit Claim(id, mirrorToken, token, decodedAmount, decodedTo); + if (!isProcessed) { + IERC20MintableAndBurnable(mirrorToken).mint(decodedTo, decodedAmount); + emit Claim(id, mirrorToken, token, decodedAmount, decodedTo); + } } function _claim(uint256 id, address token, uint256 blockNumber, bytes32[] memory topics) @@ -113,7 +114,7 @@ contract BridgeMintBurn is Bridge, IBridgeMintBurn { topics[0] = DEPOSIT_NATIVE_TOPIC_0; topics[1] = bytes32(id); - uint256 finalizedBlockNumber = PodPrecompileHelper.getFinalizedBlockNumber(); + uint256 finalizedBlockNumber = PodPrecompileHelper.getFinalizedBlockNumber(SOURCE_CHAIN_ID); if (blockNumber > finalizedBlockNumber) { revert BlockNotFinalized(); @@ -163,7 +164,7 @@ contract BridgeMintBurn is Bridge, IBridgeMintBurn { address mirrorToken, uint8 mirrorTokenDecimals, TokenLimits calldata limits - ) external returns (address token) { + ) external override onlyRole(DEFAULT_ADMIN_ROLE) returns (address token) { token = existingToken == address(0) ? address(new WrappedToken(tokenName, tokenSymbol, mirrorTokenDecimals)) : existingToken; diff --git a/protocol/src/abstract/Bridge.sol b/protocol/src/abstract/Bridge.sol index 9ef586d0..a9e0b24b 100644 --- a/protocol/src/abstract/Bridge.sol +++ b/protocol/src/abstract/Bridge.sol @@ -33,7 +33,7 @@ abstract contract Bridge is IBridge, AccessControl, Pausable { bytes32 constant DEPOSIT_NATIVE_TOPIC_0 = keccak256("DepositNative(uint256,uint256,address)"); /** - * @dev The topic 0 (event signature) of the address for native deposit event. + * @dev The mock address for native deposit. */ address constant MOCK_ADDRESS_FOR_NATIVE_DEPOSIT = address(uint160(uint256(keccak256("MOCK_ADDRESS_FOR_NATIVE_DEPOSIT")))); diff --git a/protocol/src/libraries/PodPrecompileHelper.sol b/protocol/src/libraries/PodPrecompileHelper.sol index b65c3663..383e15d3 100644 --- a/protocol/src/libraries/PodPrecompileHelper.sol +++ b/protocol/src/libraries/PodPrecompileHelper.sol @@ -3,7 +3,7 @@ pragma solidity ^0.8.28; import {EthGetLogsTypes} from "pod-sdk/types/EthGetLogsTypes.sol"; import {EthGetBlockByNumberTypes} from "pod-sdk/types/EthGetBlockByNumberTypes.sol"; -import {TxInfo, getTxInfo} from "pod-sdk/Context.sol"; +import {TxInfo, POD_TX_INFO} from "pod-sdk/Context.sol"; import {HexUtils} from "./HexUtils.sol"; library PodPrecompileHelper { @@ -20,7 +20,7 @@ library PodPrecompileHelper { * @return success Whether the minting was successful. */ function mint(uint256 amount) external view returns (bool) { - (bool success,) = POD_MINT_BALANCE_PRECOMPILE_ADDRESS.staticcall(abi.encode(amount)); + (bool success,) = POD_MINT_BALANCE_PRECOMPILE_ADDRESS.staticcall{gas: gasleft()}(abi.encode(amount)); return success; } @@ -28,13 +28,12 @@ library PodPrecompileHelper { * @dev Gets the finalized block number. * @return blockNumber The finalized block number. */ - function getFinalizedBlockNumber() internal view returns (uint256) { + function getFinalizedBlockNumber(uint256 chainId) internal view returns (uint256) { + EthGetBlockByNumberTypes.PrecompileArgs memory args = EthGetBlockByNumberTypes.PrecompileArgs( + chainId, EthGetBlockByNumberTypes.RpcArgs(hex"66696e616c697a6564", false) + ); (bool success, bytes memory output) = EthGetBlockByNumberTypes.PRECOMPILE_ADDRESS.staticcall( - abi.encode( - EthGetBlockByNumberTypes.PrecompileArgs( - 1, EthGetBlockByNumberTypes.RpcArgs(hex"66696e616c697a6564", false) - ) - ) + abi.encode(args.chainId, args.ethGetBlockByNumberArgs) ); if (!success) revert PrecompileCallFailed(); return HexUtils.uintFromBigEndian(abi.decode(output, (EthGetBlockByNumberTypes.RpcBlock)).number); @@ -53,13 +52,10 @@ library PodPrecompileHelper { returns (EthGetLogsTypes.RpcLog[] memory) { bytes memory n = HexUtils.toBytesMinimal(blockNumber); - (bool success, bytes memory output) = EthGetLogsTypes.PRECOMPILE_ADDRESS.staticcall( - abi.encode( - EthGetLogsTypes.PrecompileArgs( - chainId, EthGetLogsTypes.RpcArgs(n, n, bridgeContract, bytes32(0), topics) - ) - ) - ); + EthGetLogsTypes.PrecompileArgs memory args = + EthGetLogsTypes.PrecompileArgs(chainId, EthGetLogsTypes.RpcArgs(n, n, bridgeContract, bytes32(0), topics)); + (bool success, bytes memory output) = + EthGetLogsTypes.PRECOMPILE_ADDRESS.staticcall{gas: gasleft()}(abi.encode(args.chainId, args.ethGetLogsArgs)); if (!success) revert PrecompileCallFailed(); EthGetLogsTypes.RpcLog[] memory logs = abi.decode(output, (EthGetLogsTypes.RpcLog[])); @@ -68,7 +64,9 @@ library PodPrecompileHelper { } function getTxHash() internal view returns (uint256) { - TxInfo memory txInfo = getTxInfo(); + (bool success, bytes memory output) = POD_TX_INFO.staticcall{gas: gasleft()}(""); + if (!success) revert PrecompileCallFailed(); + TxInfo memory txInfo = abi.decode(output, (TxInfo)); return uint256(txInfo.txHash); } } diff --git a/protocol/test/BridgeMintBurn.t.sol b/protocol/test/BridgeMintBurn.t.sol index 1a6744ff..feb05015 100644 --- a/protocol/test/BridgeMintBurn.t.sol +++ b/protocol/test/BridgeMintBurn.t.sol @@ -14,6 +14,7 @@ import {EthGetBlockByNumberTypes} from "pod-sdk/types/EthGetBlockByNumberTypes.s import {HexUtils} from "pod-protocol/libraries/HexUtils.sol"; import {TxInfo} from "pod-sdk/Context.sol"; import {VmSafe} from "forge-std/Vm.sol"; +import {console} from "forge-std/console.sol"; contract BridgeMintBurnTest is BridgeBehaviorTest { BridgeMintBurn private _bridge; @@ -166,8 +167,13 @@ contract BridgeMintBurnTest is BridgeBehaviorTest { // Mock again with same log so requestId is identical _mockEthGetBlockByNumber(1); _mockEthGetLogs(0, 1, 1, MIRROR_TOKEN_ADDRESS, logs); - vm.expectRevert(abi.encodeWithSelector(IBridge.RequestAlreadyProcessed.selector)); + // record that no logs are emitted + vm.recordLogs(); + vm.prank(recipient); _bridge.claim(0, MIRROR_TOKEN_ADDRESS, 1); + // confirm that nothing happens when the request is already processed + VmSafe.Log[] memory recordedLogs = vm.getRecordedLogs(); + assertEq(recordedLogs.length, 0); } function test_Claim_RevertIfPaused() public { @@ -196,7 +202,7 @@ contract BridgeMintBurnTest is BridgeBehaviorTest { function test_Claim_RevertIfPrecompileCallFails() public { _mockEthGetBlockByNumber(1); EthGetLogsTypes.PrecompileArgs memory args = _buildArgs(0, 1, 1, MIRROR_TOKEN_ADDRESS); - podMockEthGetLogsRevert(abi.encode(args)); + podMockEthGetLogsRevert(abi.encode(args.chainId, args.ethGetLogsArgs)); vm.expectRevert(abi.encodeWithSelector(IBridgeMintBurn.PrecompileCallFailed.selector)); _bridge.claim(0, MIRROR_TOKEN_ADDRESS, 1); @@ -378,7 +384,7 @@ contract BridgeMintBurnTest is BridgeBehaviorTest { EthGetLogsTypes.RpcLog[] memory logs ) internal { EthGetLogsTypes.PrecompileArgs memory args = _buildArgs(id, fromBlock, toBlock, tokenAddr); - podMockEthGetLogs(abi.encode(args), abi.encode(logs)); + podMockEthGetLogs(abi.encode(args.chainId, args.ethGetLogsArgs), abi.encode(logs)); } function _buildTopics(uint256 id, address tokenAddr) internal pure returns (bytes32[] memory topics) { @@ -413,9 +419,10 @@ contract BridgeMintBurnTest is BridgeBehaviorTest { } function _buildEthGetBlockByNumberArgs() internal pure returns (bytes memory) { - return abi.encode( - EthGetBlockByNumberTypes.PrecompileArgs(1, EthGetBlockByNumberTypes.RpcArgs(hex"66696e616c697a6564", false)) - ); + EthGetBlockByNumberTypes.PrecompileArgs memory args = + EthGetBlockByNumberTypes.PrecompileArgs(1, EthGetBlockByNumberTypes.RpcArgs(hex"66696e616c697a6564", false)); + + return abi.encode(args.chainId, args.ethGetBlockByNumberArgs); } function _buildEthGetBlockByNumberRpcBlock(uint256 blockNumber) internal pure returns (bytes memory) { From dceb2c4a349e24257c8cb25e11ed725a9ac9a5b1 Mon Sep 17 00:00:00 2001 From: Jakov Mitrovski Date: Wed, 24 Sep 2025 13:26:54 +0200 Subject: [PATCH 58/64] script updates --- examples/solidity/script/Deploy.s.sol | 13 ++++++++++--- protocol/script/CreateAndWhitelistToken.s.sol | 17 ++++++++++------- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/examples/solidity/script/Deploy.s.sol b/examples/solidity/script/Deploy.s.sol index b9e8cb3c..a8efbc33 100644 --- a/examples/solidity/script/Deploy.s.sol +++ b/examples/solidity/script/Deploy.s.sol @@ -12,6 +12,7 @@ import {PodAuctionConsumer} from "optimistic-auction/PodAuctionConsumer.sol"; import {TestMintBalancePrecompile} from "../src/TestMintBalancePrecompile.sol"; import {BridgeMintBurn} from "pod-protocol/BridgeMintBurn.sol"; import {IBridge} from "pod-protocol/interfaces/IBridge.sol"; +import {WrappedToken} from "pod-protocol/WrappedToken.sol"; contract Deployer is BaseDeployer { function run() public { @@ -53,11 +54,17 @@ contract Deployer is BaseDeployer { address MIRROR_TOKEN_ADDRESS = makeAddr("mirrorToken"); - address token = bridgeMintBurn.createAndWhitelistMirrorToken( - "Test Token", "TEST", address(0), address(MIRROR_TOKEN_ADDRESS), 18, nativeTokenLimits + WrappedToken token = new WrappedToken("Test Token", "TEST", 18); + + console.log("Token deployed at:", address(token)); + + bridgeMintBurn.createAndWhitelistMirrorToken( + "Test Token", "TEST", address(token), address(MIRROR_TOKEN_ADDRESS), 18, nativeTokenLimits ); - console.log("Token deployed at:", token); + token.grantRole(token.MINTER_ROLE(), address(bridgeMintBurn)); + token.grantRole(token.PAUSER_ROLE(), address(bridgeMintBurn)); + token.grantRole(token.DEFAULT_ADMIN_ROLE(), address(bridgeMintBurn)); } vm.stopBroadcast(); diff --git a/protocol/script/CreateAndWhitelistToken.s.sol b/protocol/script/CreateAndWhitelistToken.s.sol index 76a2549f..30df9608 100644 --- a/protocol/script/CreateAndWhitelistToken.s.sol +++ b/protocol/script/CreateAndWhitelistToken.s.sol @@ -4,6 +4,7 @@ pragma solidity ^0.8.20; import {Script} from "forge-std/Script.sol"; import {console} from "forge-std/console.sol"; import {IBridgeMintBurn} from "../src/interfaces/IBridgeMintBurn.sol"; +import {BridgeMintBurn} from "../src/BridgeMintBurn.sol"; import {IBridge} from "../src/interfaces/IBridge.sol"; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import {WrappedToken} from "../src/WrappedToken.sol"; @@ -12,20 +13,22 @@ contract CreateAndWhitelistToken is Script { function run() external { vm.startBroadcast(); - IERC20 testToken = IERC20(vm.envAddress("TEST_ERC")); - WrappedToken mirrorToken = WrappedToken(vm.envAddress("MIRROR_TEST_ERC")); - IBridgeMintBurn bridgeMintBurn = IBridgeMintBurn(vm.envAddress("BRIDGE_MINT_BURN_ADDRESS")); + IBridgeMintBurn bridgeMintBurn = new BridgeMintBurn( + makeAddr("otherBridgeContract"), + IBridge.TokenLimits({minAmount: 1e18, deposit: 10000e18, claim: 10000e18}), + 1 + ); - bridgeMintBurn.createAndWhitelistMirrorToken( + address token = bridgeMintBurn.createAndWhitelistMirrorToken( "Test Token", "TEST", - address(mirrorToken), - address(testToken), + address(0), + address(0x3B1b6FfAC8831f1c1c9a425Bb240Cd1bbF23F146), 18, IBridge.TokenLimits({minAmount: 1e18, deposit: 10000e18, claim: 10000e18}) ); - console.log("Token created and whitelisted"); + console.log("Token created and whitelisted at:", token); vm.stopBroadcast(); } From 12abcb9b359dea94825a6d78fefa439e8857263d Mon Sep 17 00:00:00 2001 From: Jakov Mitrovski Date: Wed, 24 Sep 2025 16:33:27 +0200 Subject: [PATCH 59/64] add bridge deployment scripts + a script that deploys both bridges and test tokens, update bridge to return id --- protocol/.env.example | 6 + .../bindings/src/bridge_deposit_withdraw.rs | 112 +++++++++++------- protocol/bindings/src/bridge_mint_burn.rs | 112 +++++++++++------- protocol/script/CreateAndWhitelistToken.s.sol | 35 ------ protocol/script/DeployAndMintERC.s.sol | 27 ----- protocol/script/DeployDepositWithdraw.s.sol | 64 +++------- protocol/script/DeployMintBurn.s.sol | 34 +++--- protocol/script/DeployToken.s.sol | 22 ++++ protocol/script/Deposit.s.sol | 35 ------ protocol/script/GrantRoles.s.sol | 18 +++ protocol/script/deploy_bridges.bash | 108 +++++++++++++++++ protocol/src/abstract/Bridge.sol | 6 +- protocol/src/interfaces/IBridge.sol | 6 +- protocol/test/BridgeMintBurn.t.sol | 1 - 14 files changed, 343 insertions(+), 243 deletions(-) create mode 100644 protocol/.env.example delete mode 100644 protocol/script/CreateAndWhitelistToken.s.sol delete mode 100644 protocol/script/DeployAndMintERC.s.sol create mode 100644 protocol/script/DeployToken.s.sol delete mode 100644 protocol/script/Deposit.s.sol create mode 100644 protocol/script/GrantRoles.s.sol create mode 100755 protocol/script/deploy_bridges.bash diff --git a/protocol/.env.example b/protocol/.env.example new file mode 100644 index 00000000..abd5303e --- /dev/null +++ b/protocol/.env.example @@ -0,0 +1,6 @@ +PK_SOURCE_CHAIN=0xSourceChainPrivateKey +PK_POD=0xPodPrivateKey +POD_RPC=http://localhost:8545 +SOURCE_CHAIN_RPC=http://localhost:8546 +POD_COMMITTEE_KEYS=0xcc30Ffc732E52fbcF7Ea33915502b2F598BF2a90,0x6931FEd7fD06DDA83f1d5702b729e2E7EaAF6bAB,0x6fE9943790e826e77478B05e740Fc551240221F9,0x135D988A2747A1c61cF90D9492F87AaCeAB8EE2c +USER_ADDRESS=0xYourUserAddress \ No newline at end of file diff --git a/protocol/bindings/src/bridge_deposit_withdraw.rs b/protocol/bindings/src/bridge_deposit_withdraw.rs index 114128ec..2eb0b807 100644 --- a/protocol/bindings/src/bridge_deposit_withdraw.rs +++ b/protocol/bindings/src/bridge_deposit_withdraw.rs @@ -2190,9 +2190,9 @@ interface BridgeDepositWithdraw { function claim(PodECDSA.CertifiedLog memory certifiedLog) external; function claimNative(PodECDSA.CertifiedLog memory certifiedLog) external; function configureToken(address token, IBridge.TokenLimits memory limits) external; - function deposit(address token, uint256 amount, address to) external; + function deposit(address token, uint256 amount, address to) external returns (uint256); function depositIndex() external view returns (uint256); - function depositNative(address to) external payable; + function depositNative(address to) external payable returns (uint256); function getRoleAdmin(bytes32 role) external view returns (bytes32); function grantRole(bytes32 role, address account) external; function hasRole(bytes32 role, address account) external view returns (bool); @@ -2525,7 +2525,13 @@ interface BridgeDepositWithdraw { "internalType": "address" } ], - "outputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], "stateMutability": "nonpayable" }, { @@ -2551,7 +2557,13 @@ interface BridgeDepositWithdraw { "internalType": "address" } ], - "outputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], "stateMutability": "payable" }, { @@ -6562,7 +6574,7 @@ function configureToken(address token, IBridge.TokenLimits memory limits) extern #[derive(Default, Debug, PartialEq, Eq, Hash)] /**Function with signature `deposit(address,uint256,address)` and selector `0xf45346dc`. ```solidity -function deposit(address token, uint256 amount, address to) external; +function deposit(address token, uint256 amount, address to) external returns (uint256); ```*/ #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] #[derive(Clone)] @@ -6574,10 +6586,15 @@ function deposit(address token, uint256 amount, address to) external; #[allow(missing_docs)] pub to: alloy::sol_types::private::Address, } + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] ///Container type for the return parameters of the [`deposit(address,uint256,address)`](depositCall) function. #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] #[derive(Clone)] - pub struct depositReturn {} + pub struct depositReturn { + #[allow(missing_docs)] + pub _0: alloy::sol_types::private::primitives::aliases::U256, + } #[allow( non_camel_case_types, non_snake_case, @@ -6631,9 +6648,11 @@ function deposit(address token, uint256 amount, address to) external; } { #[doc(hidden)] - type UnderlyingSolTuple<'a> = (); + type UnderlyingSolTuple<'a> = (alloy::sol_types::sol_data::Uint<256>,); #[doc(hidden)] - type UnderlyingRustTuple<'a> = (); + type UnderlyingRustTuple<'a> = ( + alloy::sol_types::private::primitives::aliases::U256, + ); #[cfg(test)] #[allow(dead_code, unreachable_patterns)] fn _type_assertion( @@ -6649,24 +6668,17 @@ function deposit(address token, uint256 amount, address to) external; #[doc(hidden)] impl ::core::convert::From for UnderlyingRustTuple<'_> { fn from(value: depositReturn) -> Self { - () + (value._0,) } } #[automatically_derived] #[doc(hidden)] impl ::core::convert::From> for depositReturn { fn from(tuple: UnderlyingRustTuple<'_>) -> Self { - Self {} + Self { _0: tuple.0 } } } } - impl depositReturn { - fn _tokenize( - &self, - ) -> ::ReturnToken<'_> { - () - } - } #[automatically_derived] impl alloy_sol_types::SolCall for depositCall { type Parameters<'a> = ( @@ -6677,8 +6689,8 @@ function deposit(address token, uint256 amount, address to) external; type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; - type Return = depositReturn; - type ReturnTuple<'a> = (); + type Return = alloy::sol_types::private::primitives::aliases::U256; + type ReturnTuple<'a> = (alloy::sol_types::sol_data::Uint<256>,); type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; @@ -6706,14 +6718,21 @@ function deposit(address token, uint256 amount, address to) external; } #[inline] fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> { - depositReturn::_tokenize(ret) + ( + as alloy_sol_types::SolType>::tokenize(ret), + ) } #[inline] fn abi_decode_returns(data: &[u8]) -> alloy_sol_types::Result { as alloy_sol_types::SolType>::abi_decode_sequence(data) - .map(Into::into) + .map(|r| { + let r: depositReturn = r.into(); + r._0 + }) } #[inline] fn abi_decode_returns_validate( @@ -6722,7 +6741,10 @@ function deposit(address token, uint256 amount, address to) external; as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) - .map(Into::into) + .map(|r| { + let r: depositReturn = r.into(); + r._0 + }) } } }; @@ -6875,7 +6897,7 @@ function depositIndex() external view returns (uint256); #[derive(Default, Debug, PartialEq, Eq, Hash)] /**Function with signature `depositNative(address)` and selector `0x33bb7f91`. ```solidity -function depositNative(address to) external payable; +function depositNative(address to) external payable returns (uint256); ```*/ #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] #[derive(Clone)] @@ -6883,10 +6905,15 @@ function depositNative(address to) external payable; #[allow(missing_docs)] pub to: alloy::sol_types::private::Address, } + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] ///Container type for the return parameters of the [`depositNative(address)`](depositNativeCall) function. #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] #[derive(Clone)] - pub struct depositNativeReturn {} + pub struct depositNativeReturn { + #[allow(missing_docs)] + pub _0: alloy::sol_types::private::primitives::aliases::U256, + } #[allow( non_camel_case_types, non_snake_case, @@ -6928,9 +6955,11 @@ function depositNative(address to) external payable; } { #[doc(hidden)] - type UnderlyingSolTuple<'a> = (); + type UnderlyingSolTuple<'a> = (alloy::sol_types::sol_data::Uint<256>,); #[doc(hidden)] - type UnderlyingRustTuple<'a> = (); + type UnderlyingRustTuple<'a> = ( + alloy::sol_types::private::primitives::aliases::U256, + ); #[cfg(test)] #[allow(dead_code, unreachable_patterns)] fn _type_assertion( @@ -6946,32 +6975,25 @@ function depositNative(address to) external payable; #[doc(hidden)] impl ::core::convert::From for UnderlyingRustTuple<'_> { fn from(value: depositNativeReturn) -> Self { - () + (value._0,) } } #[automatically_derived] #[doc(hidden)] impl ::core::convert::From> for depositNativeReturn { fn from(tuple: UnderlyingRustTuple<'_>) -> Self { - Self {} + Self { _0: tuple.0 } } } } - impl depositNativeReturn { - fn _tokenize( - &self, - ) -> ::ReturnToken<'_> { - () - } - } #[automatically_derived] impl alloy_sol_types::SolCall for depositNativeCall { type Parameters<'a> = (alloy::sol_types::sol_data::Address,); type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; - type Return = depositNativeReturn; - type ReturnTuple<'a> = (); + type Return = alloy::sol_types::private::primitives::aliases::U256; + type ReturnTuple<'a> = (alloy::sol_types::sol_data::Uint<256>,); type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; @@ -6993,14 +7015,21 @@ function depositNative(address to) external payable; } #[inline] fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> { - depositNativeReturn::_tokenize(ret) + ( + as alloy_sol_types::SolType>::tokenize(ret), + ) } #[inline] fn abi_decode_returns(data: &[u8]) -> alloy_sol_types::Result { as alloy_sol_types::SolType>::abi_decode_sequence(data) - .map(Into::into) + .map(|r| { + let r: depositNativeReturn = r.into(); + r._0 + }) } #[inline] fn abi_decode_returns_validate( @@ -7009,7 +7038,10 @@ function depositNative(address to) external payable; as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) - .map(Into::into) + .map(|r| { + let r: depositNativeReturn = r.into(); + r._0 + }) } } }; diff --git a/protocol/bindings/src/bridge_mint_burn.rs b/protocol/bindings/src/bridge_mint_burn.rs index 46a78328..96082f93 100644 --- a/protocol/bindings/src/bridge_mint_burn.rs +++ b/protocol/bindings/src/bridge_mint_burn.rs @@ -670,8 +670,8 @@ interface BridgeMintBurn { function claimNative(uint256 id, uint256 blockNumber) external; function configureToken(address token, IBridge.TokenLimits memory limits) external; function createAndWhitelistMirrorToken(string memory tokenName, string memory tokenSymbol, address existingToken, address mirrorToken, uint8 mirrorTokenDecimals, IBridge.TokenLimits memory limits) external returns (address token); - function deposit(address token, uint256 amount, address to) external; - function depositNative(address to) external payable; + function deposit(address token, uint256 amount, address to) external returns (uint256); + function depositNative(address to) external payable returns (uint256); function getRoleAdmin(bytes32 role) external view returns (bytes32); function grantRole(bytes32 role, address account) external; function hasRole(bytes32 role, address account) external view returns (bool); @@ -928,7 +928,13 @@ interface BridgeMintBurn { "internalType": "address" } ], - "outputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], "stateMutability": "nonpayable" }, { @@ -941,7 +947,13 @@ interface BridgeMintBurn { "internalType": "address" } ], - "outputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], "stateMutability": "payable" }, { @@ -5287,7 +5299,7 @@ function createAndWhitelistMirrorToken(string memory tokenName, string memory to #[derive(Default, Debug, PartialEq, Eq, Hash)] /**Function with signature `deposit(address,uint256,address)` and selector `0xf45346dc`. ```solidity -function deposit(address token, uint256 amount, address to) external; +function deposit(address token, uint256 amount, address to) external returns (uint256); ```*/ #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] #[derive(Clone)] @@ -5299,10 +5311,15 @@ function deposit(address token, uint256 amount, address to) external; #[allow(missing_docs)] pub to: alloy::sol_types::private::Address, } + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] ///Container type for the return parameters of the [`deposit(address,uint256,address)`](depositCall) function. #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] #[derive(Clone)] - pub struct depositReturn {} + pub struct depositReturn { + #[allow(missing_docs)] + pub _0: alloy::sol_types::private::primitives::aliases::U256, + } #[allow( non_camel_case_types, non_snake_case, @@ -5356,9 +5373,11 @@ function deposit(address token, uint256 amount, address to) external; } { #[doc(hidden)] - type UnderlyingSolTuple<'a> = (); + type UnderlyingSolTuple<'a> = (alloy::sol_types::sol_data::Uint<256>,); #[doc(hidden)] - type UnderlyingRustTuple<'a> = (); + type UnderlyingRustTuple<'a> = ( + alloy::sol_types::private::primitives::aliases::U256, + ); #[cfg(test)] #[allow(dead_code, unreachable_patterns)] fn _type_assertion( @@ -5374,24 +5393,17 @@ function deposit(address token, uint256 amount, address to) external; #[doc(hidden)] impl ::core::convert::From for UnderlyingRustTuple<'_> { fn from(value: depositReturn) -> Self { - () + (value._0,) } } #[automatically_derived] #[doc(hidden)] impl ::core::convert::From> for depositReturn { fn from(tuple: UnderlyingRustTuple<'_>) -> Self { - Self {} + Self { _0: tuple.0 } } } } - impl depositReturn { - fn _tokenize( - &self, - ) -> ::ReturnToken<'_> { - () - } - } #[automatically_derived] impl alloy_sol_types::SolCall for depositCall { type Parameters<'a> = ( @@ -5402,8 +5414,8 @@ function deposit(address token, uint256 amount, address to) external; type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; - type Return = depositReturn; - type ReturnTuple<'a> = (); + type Return = alloy::sol_types::private::primitives::aliases::U256; + type ReturnTuple<'a> = (alloy::sol_types::sol_data::Uint<256>,); type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; @@ -5431,14 +5443,21 @@ function deposit(address token, uint256 amount, address to) external; } #[inline] fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> { - depositReturn::_tokenize(ret) + ( + as alloy_sol_types::SolType>::tokenize(ret), + ) } #[inline] fn abi_decode_returns(data: &[u8]) -> alloy_sol_types::Result { as alloy_sol_types::SolType>::abi_decode_sequence(data) - .map(Into::into) + .map(|r| { + let r: depositReturn = r.into(); + r._0 + }) } #[inline] fn abi_decode_returns_validate( @@ -5447,7 +5466,10 @@ function deposit(address token, uint256 amount, address to) external; as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) - .map(Into::into) + .map(|r| { + let r: depositReturn = r.into(); + r._0 + }) } } }; @@ -5455,7 +5477,7 @@ function deposit(address token, uint256 amount, address to) external; #[derive(Default, Debug, PartialEq, Eq, Hash)] /**Function with signature `depositNative(address)` and selector `0x33bb7f91`. ```solidity -function depositNative(address to) external payable; +function depositNative(address to) external payable returns (uint256); ```*/ #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] #[derive(Clone)] @@ -5463,10 +5485,15 @@ function depositNative(address to) external payable; #[allow(missing_docs)] pub to: alloy::sol_types::private::Address, } + #[derive(serde::Serialize, serde::Deserialize)] + #[derive(Default, Debug, PartialEq, Eq, Hash)] ///Container type for the return parameters of the [`depositNative(address)`](depositNativeCall) function. #[allow(non_camel_case_types, non_snake_case, clippy::pub_underscore_fields)] #[derive(Clone)] - pub struct depositNativeReturn {} + pub struct depositNativeReturn { + #[allow(missing_docs)] + pub _0: alloy::sol_types::private::primitives::aliases::U256, + } #[allow( non_camel_case_types, non_snake_case, @@ -5508,9 +5535,11 @@ function depositNative(address to) external payable; } { #[doc(hidden)] - type UnderlyingSolTuple<'a> = (); + type UnderlyingSolTuple<'a> = (alloy::sol_types::sol_data::Uint<256>,); #[doc(hidden)] - type UnderlyingRustTuple<'a> = (); + type UnderlyingRustTuple<'a> = ( + alloy::sol_types::private::primitives::aliases::U256, + ); #[cfg(test)] #[allow(dead_code, unreachable_patterns)] fn _type_assertion( @@ -5526,32 +5555,25 @@ function depositNative(address to) external payable; #[doc(hidden)] impl ::core::convert::From for UnderlyingRustTuple<'_> { fn from(value: depositNativeReturn) -> Self { - () + (value._0,) } } #[automatically_derived] #[doc(hidden)] impl ::core::convert::From> for depositNativeReturn { fn from(tuple: UnderlyingRustTuple<'_>) -> Self { - Self {} + Self { _0: tuple.0 } } } } - impl depositNativeReturn { - fn _tokenize( - &self, - ) -> ::ReturnToken<'_> { - () - } - } #[automatically_derived] impl alloy_sol_types::SolCall for depositNativeCall { type Parameters<'a> = (alloy::sol_types::sol_data::Address,); type Token<'a> = as alloy_sol_types::SolType>::Token<'a>; - type Return = depositNativeReturn; - type ReturnTuple<'a> = (); + type Return = alloy::sol_types::private::primitives::aliases::U256; + type ReturnTuple<'a> = (alloy::sol_types::sol_data::Uint<256>,); type ReturnToken<'a> = as alloy_sol_types::SolType>::Token<'a>; @@ -5573,14 +5595,21 @@ function depositNative(address to) external payable; } #[inline] fn tokenize_returns(ret: &Self::Return) -> Self::ReturnToken<'_> { - depositNativeReturn::_tokenize(ret) + ( + as alloy_sol_types::SolType>::tokenize(ret), + ) } #[inline] fn abi_decode_returns(data: &[u8]) -> alloy_sol_types::Result { as alloy_sol_types::SolType>::abi_decode_sequence(data) - .map(Into::into) + .map(|r| { + let r: depositNativeReturn = r.into(); + r._0 + }) } #[inline] fn abi_decode_returns_validate( @@ -5589,7 +5618,10 @@ function depositNative(address to) external payable; as alloy_sol_types::SolType>::abi_decode_sequence_validate(data) - .map(Into::into) + .map(|r| { + let r: depositNativeReturn = r.into(); + r._0 + }) } } }; diff --git a/protocol/script/CreateAndWhitelistToken.s.sol b/protocol/script/CreateAndWhitelistToken.s.sol deleted file mode 100644 index 30df9608..00000000 --- a/protocol/script/CreateAndWhitelistToken.s.sol +++ /dev/null @@ -1,35 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -import {Script} from "forge-std/Script.sol"; -import {console} from "forge-std/console.sol"; -import {IBridgeMintBurn} from "../src/interfaces/IBridgeMintBurn.sol"; -import {BridgeMintBurn} from "../src/BridgeMintBurn.sol"; -import {IBridge} from "../src/interfaces/IBridge.sol"; -import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import {WrappedToken} from "../src/WrappedToken.sol"; - -contract CreateAndWhitelistToken is Script { - function run() external { - vm.startBroadcast(); - - IBridgeMintBurn bridgeMintBurn = new BridgeMintBurn( - makeAddr("otherBridgeContract"), - IBridge.TokenLimits({minAmount: 1e18, deposit: 10000e18, claim: 10000e18}), - 1 - ); - - address token = bridgeMintBurn.createAndWhitelistMirrorToken( - "Test Token", - "TEST", - address(0), - address(0x3B1b6FfAC8831f1c1c9a425Bb240Cd1bbF23F146), - 18, - IBridge.TokenLimits({minAmount: 1e18, deposit: 10000e18, claim: 10000e18}) - ); - - console.log("Token created and whitelisted at:", token); - - vm.stopBroadcast(); - } -} diff --git a/protocol/script/DeployAndMintERC.s.sol b/protocol/script/DeployAndMintERC.s.sol deleted file mode 100644 index d5747dd7..00000000 --- a/protocol/script/DeployAndMintERC.s.sol +++ /dev/null @@ -1,27 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -import {Script} from "forge-std/Script.sol"; -import {console} from "forge-std/console.sol"; -import {WrappedToken} from "../src/WrappedToken.sol"; - -contract DeployAndMintERC is Script { - function run() external { - console.log("=== Minting tokens ==="); - - vm.startBroadcast(); - - address token = vm.envOr("MIRROR_TEST_ERC", address(0)); - - WrappedToken mirrorToken; - if (token == address(0)) { - mirrorToken = new WrappedToken("Test Token", "TEST", 18); - } else { - mirrorToken = WrappedToken(vm.envAddress("MIRROR_TEST_ERC")); - } - - mirrorToken.mint(vm.envAddress("USER_ADDRESS"), 100 * 1e18); - - vm.stopBroadcast(); - } -} diff --git a/protocol/script/DeployDepositWithdraw.s.sol b/protocol/script/DeployDepositWithdraw.s.sol index 16092e03..c63a41c5 100644 --- a/protocol/script/DeployDepositWithdraw.s.sol +++ b/protocol/script/DeployDepositWithdraw.s.sol @@ -1,57 +1,27 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.20; -import {console} from "forge-std/console.sol"; -import {BridgeDepositWithdraw} from "../src/BridgeDepositWithdraw.sol"; -import {PodRegistry} from "../src/PodRegistry.sol"; -import {ERC20Mock} from "@openzeppelin/contracts/mocks/token/ERC20Mock.sol"; -import {IBridge} from "../src/interfaces/IBridge.sol"; import {BaseDeployer} from "./BaseDeployer.s.sol"; +import {console} from "forge-std/console.sol"; +import {BridgeDepositWithdraw} from "pod-protocol/BridgeDepositWithdraw.sol"; +import {IBridge} from "pod-protocol/interfaces/IBridge.sol"; +import {PodRegistry} from "pod-protocol/PodRegistry.sol"; contract DeployDepositWithdraw is BaseDeployer { - uint256 constant CHAIN_ID = 31337; - string constant RPC_URL = "http://localhost:8546"; - address constant OTHER_BRIDGE_CONTRACT = 0x12296f2D128530a834460DF6c36a2895B793F26d; - IBridge.TokenLimits nativeTokenLimits = IBridge.TokenLimits({minAmount: 0.01 ether, deposit: 500e18, claim: 400e18}); - - function run() external { - console.log("=== Deploying BridgeDepositWithdraw to localhost:8546 (chainId 31337) ==="); - - // Create a fork of the deposit/withdraw network - vm.createSelectFork(RPC_URL); - require(block.chainid == CHAIN_ID, "Wrong chain ID for deposit/withdraw network"); - - // Deploy PodRegistry first + function run( + address podBridgeAddr, + IBridge.TokenLimits memory nativeTokenLimits, + address testTokenAddr, + address mirrorTokenAddr + ) external returns (address podRegistry, address depositWithdraw) { address[] memory initialValidators = getValidatorAddresses(); - - PodRegistry podRegistry = new PodRegistry(initialValidators); - console.log("PodRegistry deployed at:", address(podRegistry)); - - BridgeDepositWithdraw bridgeDepositWithdraw = - new BridgeDepositWithdraw(address(podRegistry), OTHER_BRIDGE_CONTRACT, nativeTokenLimits); - console.log("BridgeDepositWithdraw deployed at:", address(bridgeDepositWithdraw)); - - // Deploy some test tokens - ERC20Mock testToken = new ERC20Mock(); - ERC20Mock mirrorToken = new ERC20Mock(); - console.log("Test token deployed at:", address(testToken)); - console.log("Mirror token deployed at:", address(mirrorToken)); - - // Configure the bridge - bridgeDepositWithdraw.whiteListToken( - address(testToken), - address(mirrorToken), - IBridge.TokenLimits({minAmount: 1e18, deposit: 10000e18, claim: 10000e18}) - ); - console.log("Token whitelisted on bridge"); - + vm.startBroadcast(); + PodRegistry reg = new PodRegistry(initialValidators); + BridgeDepositWithdraw bdw = new BridgeDepositWithdraw(address(reg), podBridgeAddr, nativeTokenLimits); + bdw.whiteListToken(testTokenAddr, mirrorTokenAddr, nativeTokenLimits); vm.stopBroadcast(); - - console.log("=== BridgeDepositWithdraw deployment complete ==="); - console.log("Network: localhost:8546 (chainId 1337)"); - console.log("PodRegistry:", address(podRegistry)); - console.log("BridgeDepositWithdraw:", address(bridgeDepositWithdraw)); - console.log("Test Token:", address(testToken)); - console.log("Mirror Token:", address(mirrorToken)); + console.log("PodRegistry deployed at:", address(reg)); + console.log("BridgeDepositWithdraw deployed at:", address(bdw)); + return (address(reg), address(bdw)); } } diff --git a/protocol/script/DeployMintBurn.s.sol b/protocol/script/DeployMintBurn.s.sol index 3b372c50..a3ee2795 100644 --- a/protocol/script/DeployMintBurn.s.sol +++ b/protocol/script/DeployMintBurn.s.sol @@ -3,25 +3,31 @@ pragma solidity ^0.8.20; import {Script} from "forge-std/Script.sol"; import {console} from "forge-std/console.sol"; -import {BridgeMintBurn} from "../src/BridgeMintBurn.sol"; -import {IBridge} from "../src/interfaces/IBridge.sol"; +import {BridgeMintBurn} from "pod-protocol/BridgeMintBurn.sol"; +import {IBridge} from "pod-protocol/interfaces/IBridge.sol"; contract DeployMintBurn is Script { - address constant OTHER_BRIDGE_CONTRACT = 0x12296f2D128530a834460DF6c36a2895B793F26d; - IBridge.TokenLimits nativeTokenLimits = IBridge.TokenLimits({minAmount: 0.01 ether, deposit: 500e18, claim: 400e18}); - - function run() external { - console.log("=== Deploying BridgeMintBurn to localhost:8545 (chainId 1293) ==="); - + function run( + address sourceChainBridgeAddr, + IBridge.TokenLimits memory nativeTokenLimits, + uint96 sourceChainId, + string memory tokenName, + string memory tokenSymbol, + address tokenAddr, + address mirrorTokenAddr, + uint8 tokenDecimals + ) external returns (address bridgeMintBurn) { vm.startBroadcast(); + BridgeMintBurn bmb = new BridgeMintBurn(sourceChainBridgeAddr, nativeTokenLimits, sourceChainId); - BridgeMintBurn bridgeMintBurn = new BridgeMintBurn(OTHER_BRIDGE_CONTRACT, nativeTokenLimits, 1); - console.log("BridgeMintBurn deployed at:", address(bridgeMintBurn)); - + if (tokenAddr != address(0)) { + bmb.createAndWhitelistMirrorToken( + tokenName, tokenSymbol, tokenAddr, mirrorTokenAddr, tokenDecimals, nativeTokenLimits + ); + } vm.stopBroadcast(); + console.log("BridgeMintBurn deployed at:", address(bmb)); - console.log("=== BridgeMintBurn deployment complete ==="); - console.log("Network: localhost:8545 (chainId 1293)"); - console.log("BridgeMintBurn:", address(bridgeMintBurn)); + return address(bmb); } } diff --git a/protocol/script/DeployToken.s.sol b/protocol/script/DeployToken.s.sol new file mode 100644 index 00000000..765498d5 --- /dev/null +++ b/protocol/script/DeployToken.s.sol @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +import {Script} from "forge-std/Script.sol"; +import {console} from "forge-std/console.sol"; +import {WrappedToken} from "pod-protocol/WrappedToken.sol"; + +contract DeployToken is Script { + function run(string memory name, string memory symbol, uint8 decimals, address mintTo, uint256 amount) + external + returns (address token) + { + vm.startBroadcast(); + WrappedToken t = new WrappedToken(name, symbol, decimals); + t.mint(mintTo, amount); + vm.stopBroadcast(); + console.log("Minted amount:", amount); + console.log("Minted to:", mintTo); + console.log("Token deployed at:", address(t)); + return address(t); + } +} diff --git a/protocol/script/Deposit.s.sol b/protocol/script/Deposit.s.sol deleted file mode 100644 index 88dfcd2a..00000000 --- a/protocol/script/Deposit.s.sol +++ /dev/null @@ -1,35 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; - -import {Script} from "forge-std/Script.sol"; -import {console} from "forge-std/console.sol"; -import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import {Bridge} from "../src/abstract/Bridge.sol"; - -contract Deposit is Script { - function run() external { - console.log( - "=== Depositing tokens; needs to be called with the private key of the token holder because of approve ===" - ); - - vm.startBroadcast(); - - address mirrorToken = vm.envAddress("MIRROR_TEST_ERC"); - - Bridge bridge = Bridge(vm.envAddress("BRIDGE_MINT_BURN_ADDRESS")); - - uint256 amount = 1 * 1e18; - - IERC20(mirrorToken).approve(address(bridge), amount); - - vm.stopBroadcast(); - - vm.startBroadcast(); - - address to = vm.envAddress("USER_ADDRESS"); - - bridge.deposit(mirrorToken, amount, to); - - vm.stopBroadcast(); - } -} diff --git a/protocol/script/GrantRoles.s.sol b/protocol/script/GrantRoles.s.sol new file mode 100644 index 00000000..37754045 --- /dev/null +++ b/protocol/script/GrantRoles.s.sol @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +import {Script} from "forge-std/Script.sol"; +import {console} from "forge-std/console.sol"; +import {WrappedToken} from "pod-protocol/WrappedToken.sol"; + +contract GrantRoles is Script { + function run(address token, address admin) external { + vm.startBroadcast(); + WrappedToken t = WrappedToken(token); + t.grantRole(t.MINTER_ROLE(), admin); + t.grantRole(t.PAUSER_ROLE(), admin); + t.grantRole(t.DEFAULT_ADMIN_ROLE(), admin); + vm.stopBroadcast(); + console.log("Granted roles to:", admin); + } +} diff --git a/protocol/script/deploy_bridges.bash b/protocol/script/deploy_bridges.bash new file mode 100755 index 00000000..a79f5488 --- /dev/null +++ b/protocol/script/deploy_bridges.bash @@ -0,0 +1,108 @@ +#!/usr/bin/env bash +set -euo pipefail + +# Usage: +# ./script/deploy_bridges.bash +# ran from protocl folder to grab the .env file + + +source .env +# Required env vars +: "${SOURCE_CHAIN_RPC:?}" # e.g. http://127.0.0.1:8546 or Sepolia RPC +: "${POD_RPC:?}" # Pod RPC +: "${PK_SOURCE_CHAIN:?}" # Anvil/Sepolia deployer private key +: "${PK_POD:?}" # Pod deployer private key +: "${USER_ADDRESS:?}" # Receiver on Anvil/Sepolia for initial mint +: "${POD_COMMITTEE_KEYS:?}" # Pod committee keys + +echo "SOURCE_CHAIN_RPC: $SOURCE_CHAIN_RPC" +echo "POD_RPC: $POD_RPC" +echo "PK_SOURCE_CHAIN: $PK_SOURCE_CHAIN" +echo "PK_POD: $PK_POD" +echo "USER_ADDRESS: $USER_ADDRESS" + +# Optional (defaults) +: "${SOURCE_CHAIN_ID:=31337}" # set to 11155111 for Sepolia + +# Token params +: "${TOKEN_NAME:=Test Token}" +: "${TOKEN_SYMBOL:=TEST}" +: "${MIRROR_SYMBOL:=pwTEST}" +: "${MIRROR_TOKEN_NAME:=Pod Wrapped Test Token}" +: "${DECIMALS:=18}" +: "${MINT_AMOUNT:=100000000000000000000}" # 10e18 + +# Limits +: "${NATIVE_MIN:=10000000000000000}" # 0.01 ether +: "${NATIVE_DEP:=500000000000000000000}" # 500e18 +: "${NATIVE_CLA:=500000000000000000000}" # 500e18 +: "${TOKEN_MIN:=10000000000000000}" # 0.01e18 +: "${TOKEN_DEP:=1000000000000000000000}" # 100e18 +: "${TOKEN_CLA:=1000000000000000000000}" # 100e18 + + +# 1) Deploy test ERC20 on Source chain (Anvil/Sepolia) and mint to user +SOURCE_CHAIN_TOKEN_ADDR=$(forge script ./script/DeployToken.s.sol:DeployToken \ + --rpc-url "$SOURCE_CHAIN_RPC" --private-key "$PK_SOURCE_CHAIN" --broadcast --slow \ + --json \ + --sig "run(string,string,uint8,address,uint256)" \ + "$TOKEN_NAME" "$TOKEN_SYMBOL" "$DECIMALS" "$USER_ADDRESS" "$MINT_AMOUNT" \ + | jq -sr 'map(.returns?.token?.value // empty) | map(select(. != "")) | last') +echo "Source chain token: $SOURCE_CHAIN_TOKEN_ADDR" + +# 2) Deploy Mirror token on Pod +POD_TOKEN_ADDR=$(forge script ./script/DeployToken.s.sol:DeployToken \ + --rpc-url "$POD_RPC" --private-key "$PK_POD" --broadcast --slow \ + --json \ + --sig "run(string,string,uint8,address,uint256)" \ + "$TOKEN_NAME" "$MIRROR_SYMBOL" "$DECIMALS" "$USER_ADDRESS" "$MINT_AMOUNT" \ + | jq -sr 'map(.returns?.token?.value // empty) | map(select(. != "")) | last') +echo "Pod token: $POD_TOKEN_ADDR" + +# Compute addresses for next CREATE +SOURCE_CHAIN_DEPLOYER=$(cast wallet address --private-key "$PK_SOURCE_CHAIN") +POD_DEPLOYER=$(cast wallet address --private-key "$PK_POD") +SOURCE_CHAIN_NONCE=$(cast nonce "$SOURCE_CHAIN_DEPLOYER" --rpc-url "$SOURCE_CHAIN_RPC") +POD_NONCE=$(cast nonce "$POD_DEPLOYER" --rpc-url "$POD_RPC") +SOURCE_CHAIN_BRIDGE_ADDR=$(cast compute-address "$SOURCE_CHAIN_DEPLOYER" --nonce "$SOURCE_CHAIN_NONCE" | grep -oE '0x[0-9a-fA-F]{40}') +POD_BRIDGE_ADDR=$(cast compute-address "$POD_DEPLOYER" --nonce "$POD_NONCE" | grep -oE '0x[0-9a-fA-F]{40}') + +echo "Precomputed:" +echo " Anvil BridgeDepositWithdraw -> $SOURCE_CHAIN_BRIDGE_ADDR" +echo " Pod BridgeMintBurn -> $POD_BRIDGE_ADDR" + +# 3) Deploy BridgeMintBurn on Pod and configure a test token, pointing to precomputed Anvil bridge address +forge script ./script/DeployMintBurn.s.sol:DeployMintBurn \ + --rpc-url "$POD_RPC" --private-key "$PK_POD" --broadcast --slow --skip-simulation \ + --sig "run(address,(uint256,uint256,uint256),uint96,string,string,address,address,uint8)" \ + "$SOURCE_CHAIN_BRIDGE_ADDR" "($NATIVE_MIN,$NATIVE_DEP,$NATIVE_CLA)" "$SOURCE_CHAIN_ID" "$TOKEN_NAME" "$TOKEN_SYMBOL" "$POD_TOKEN_ADDR" "$SOURCE_CHAIN_TOKEN_ADDR" "$DECIMALS" \ + -vvv + +# 4) Deploy BridgeDepositWithdraw on Source chain (Anvil/Sepolia) and configure a test token, pointing to precomputed Pod bridge address. +forge script ./script/DeployDepositWithdraw.s.sol:DeployDepositWithdraw \ + --rpc-url "$SOURCE_CHAIN_RPC" --private-key "$PK_SOURCE_CHAIN" --broadcast --slow --skip-simulation \ + --sig "run(address,(uint256,uint256,uint256),address,address)" \ + "$POD_BRIDGE_ADDR" "($NATIVE_MIN,$NATIVE_DEP,$NATIVE_CLA)" "$SOURCE_CHAIN_TOKEN_ADDR" "$POD_TOKEN_ADDR" \ + -vvv + + +# 5) Grant roles to BridgeMintBurn +forge script ./script/GrantRoles.s.sol:GrantRoles \ + --rpc-url "$POD_RPC" --private-key "$PK_POD" --broadcast --slow --skip-simulation \ + --sig "run(address,address)" \ + "$POD_TOKEN_ADDR" "$POD_BRIDGE_ADDR" \ + -vvv + + +# 5) Show codes to confirm deployment +echo "Codes:" +echo " Source chain BridgeDepositWithdraw code bytes: $(cast code $SOURCE_CHAIN_BRIDGE_ADDR --rpc-url $SOURCE_CHAIN_RPC | wc -c)" +echo " Pod BridgeMintBurn code bytes: $(cast code $POD_BRIDGE_ADDR --rpc-url $POD_RPC | wc -c)" +echo " Source chain Token code bytes: $(cast code $SOURCE_CHAIN_TOKEN_ADDR --rpc-url $SOURCE_CHAIN_RPC | wc -c)" +echo " Pod Mirror Token code bytes: $(cast code $POD_TOKEN_ADDR --rpc-url $POD_RPC | wc -c)" + +echo "Done." +echo "Source chain BridgeDepositWithdraw: $SOURCE_CHAIN_BRIDGE_ADDR" +echo "Pod BridgeMintBurn: $POD_BRIDGE_ADDR" +echo "Source chain token: $SOURCE_CHAIN_TOKEN_ADDR" +echo "Pod mirror token: $POD_TOKEN_ADDR" \ No newline at end of file diff --git a/protocol/src/abstract/Bridge.sol b/protocol/src/abstract/Bridge.sol index a9e0b24b..5b847fc1 100644 --- a/protocol/src/abstract/Bridge.sol +++ b/protocol/src/abstract/Bridge.sol @@ -161,21 +161,23 @@ abstract contract Bridge is IBridge, AccessControl, Pausable { /** * @inheritdoc IBridge */ - function deposit(address token, uint256 amount, address to) external override whenNotPaused { + function deposit(address token, uint256 amount, address to) external override whenNotPaused returns (uint256) { if (!_isValidTokenAmount(token, amount, true)) revert InvalidTokenAmount(); if (to == address(0)) revert InvalidToAddress(); uint256 id = _getDepositId(); handleDeposit(token, amount); emit Deposit(id, token, amount, to); + return id; } /** * @inheritdoc IBridge */ - function depositNative(address to) external payable override whenNotPaused { + function depositNative(address to) external payable override whenNotPaused returns (uint256) { if (!_isValidTokenAmount(MOCK_ADDRESS_FOR_NATIVE_DEPOSIT, msg.value, true)) revert InvalidTokenAmount(); uint256 id = _getDepositId(); emit DepositNative(id, msg.value, to); + return id; } /** diff --git a/protocol/src/interfaces/IBridge.sol b/protocol/src/interfaces/IBridge.sol index ee8a163e..09f32aca 100644 --- a/protocol/src/interfaces/IBridge.sol +++ b/protocol/src/interfaces/IBridge.sol @@ -162,15 +162,17 @@ interface IBridge { * @param token The token to bridge. * @param amount The amount of tokens to bridge. * @param to The address to send the tokens to on the destination chain. + * @return id The request index. */ - function deposit(address token, uint256 amount, address to) external; + function deposit(address token, uint256 amount, address to) external returns (uint256); /** * @dev Deposit native tokens to bridge to the destination chain. * @notice Function used to bridge native tokens to the destination chain. * @param to The address to send the native tokens to on the destination chain. + * @return id The request index. */ - function depositNative(address to) external payable; + function depositNative(address to) external payable returns (uint256); /** * @dev Pauses the contract. diff --git a/protocol/test/BridgeMintBurn.t.sol b/protocol/test/BridgeMintBurn.t.sol index feb05015..2cf8c45f 100644 --- a/protocol/test/BridgeMintBurn.t.sol +++ b/protocol/test/BridgeMintBurn.t.sol @@ -14,7 +14,6 @@ import {EthGetBlockByNumberTypes} from "pod-sdk/types/EthGetBlockByNumberTypes.s import {HexUtils} from "pod-protocol/libraries/HexUtils.sol"; import {TxInfo} from "pod-sdk/Context.sol"; import {VmSafe} from "forge-std/Vm.sol"; -import {console} from "forge-std/console.sol"; contract BridgeMintBurnTest is BridgeBehaviorTest { BridgeMintBurn private _bridge; From c8753437c25caed7f700f6d8786f6b625319cdd9 Mon Sep 17 00:00:00 2001 From: Jakov Mitrovski Date: Thu, 25 Sep 2025 15:11:30 +0200 Subject: [PATCH 60/64] script modifications, block tag for anvil --- protocol/.gitignore | 1 + protocol/script/deploy_bridges.bash | 8 ++++---- protocol/src/BridgeMintBurn.sol | 11 +++++++++-- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/protocol/.gitignore b/protocol/.gitignore index 027d01a8..98c97c73 100644 --- a/protocol/.gitignore +++ b/protocol/.gitignore @@ -7,6 +7,7 @@ out/ /broadcast/*/31337/ /broadcast/**/dry-run/ /broadcast/*/1293/ +/broadcast/*/11155111/ # Docs docs/ diff --git a/protocol/script/deploy_bridges.bash b/protocol/script/deploy_bridges.bash index a79f5488..22ccdd27 100755 --- a/protocol/script/deploy_bridges.bash +++ b/protocol/script/deploy_bridges.bash @@ -64,12 +64,12 @@ SOURCE_CHAIN_DEPLOYER=$(cast wallet address --private-key "$PK_SOURCE_CHAIN") POD_DEPLOYER=$(cast wallet address --private-key "$PK_POD") SOURCE_CHAIN_NONCE=$(cast nonce "$SOURCE_CHAIN_DEPLOYER" --rpc-url "$SOURCE_CHAIN_RPC") POD_NONCE=$(cast nonce "$POD_DEPLOYER" --rpc-url "$POD_RPC") -SOURCE_CHAIN_BRIDGE_ADDR=$(cast compute-address "$SOURCE_CHAIN_DEPLOYER" --nonce "$SOURCE_CHAIN_NONCE" | grep -oE '0x[0-9a-fA-F]{40}') -POD_BRIDGE_ADDR=$(cast compute-address "$POD_DEPLOYER" --nonce "$POD_NONCE" | grep -oE '0x[0-9a-fA-F]{40}') +SOURCE_CHAIN_BRIDGE_ADDR=$(cast compute-address "$SOURCE_CHAIN_DEPLOYER" --nonce "$(($SOURCE_CHAIN_NONCE + 1))" | grep -oE '0x[0-9a-fA-F]{40}') +POD_BRIDGE_ADDR=$(cast compute-address "$POD_DEPLOYER" --nonce "$(($POD_NONCE + 1))" | grep -oE '0x[0-9a-fA-F]{40}') echo "Precomputed:" -echo " Anvil BridgeDepositWithdraw -> $SOURCE_CHAIN_BRIDGE_ADDR" -echo " Pod BridgeMintBurn -> $POD_BRIDGE_ADDR" +echo " Source chain BridgeDepositWithdraw -> $SOURCE_CHAIN_BRIDGE_ADDR" +echo " Pod BridgeMintBurn -> $POD_BRIDGE_ADDR" # 3) Deploy BridgeMintBurn on Pod and configure a test token, pointing to precomputed Anvil bridge address forge script ./script/DeployMintBurn.s.sol:DeployMintBurn \ diff --git a/protocol/src/BridgeMintBurn.sol b/protocol/src/BridgeMintBurn.sol index 779b13ff..6ad4a811 100644 --- a/protocol/src/BridgeMintBurn.sol +++ b/protocol/src/BridgeMintBurn.sol @@ -26,10 +26,12 @@ contract BridgeMintBurn is Bridge, IBridgeMintBurn { */ uint96 immutable SOURCE_CHAIN_ID; + uint256 constant ANVIL_CHAIN_ID = 31337; + /** - * @dev "finalized" as bytes + * @dev "finalized" as bytes, or "latest" for anvil */ - bytes constant FINALIZED_BLOCK_BYTES = hex"66696e616c697a6564"; + bytes block_tag_bytes; /** * @dev Constructor. @@ -38,6 +40,11 @@ contract BridgeMintBurn is Bridge, IBridgeMintBurn { Bridge(_bridgeContract, nativeTokenLimits) { SOURCE_CHAIN_ID = _sourceChainId; + if (SOURCE_CHAIN_ID == ANVIL_CHAIN_ID) { + block_tag_bytes = hex"6c6174657374"; // "latest" because anvil doesn't supporrt "finalized" + } else { + block_tag_bytes = hex"66696e616c697a6564"; + } } /** From 1e6d807c0e43cd1838fde1be836184a6c7a25207 Mon Sep 17 00:00:00 2001 From: Jakov Mitrovski Date: Thu, 25 Sep 2025 15:30:12 +0200 Subject: [PATCH 61/64] update finalized tag handling, script --- protocol/script/deploy_bridges.bash | 4 +++- protocol/src/BridgeMintBurn.sol | 4 ++-- protocol/src/libraries/PodPrecompileHelper.sol | 11 +++++------ 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/protocol/script/deploy_bridges.bash b/protocol/script/deploy_bridges.bash index 22ccdd27..2f90e7b7 100755 --- a/protocol/script/deploy_bridges.bash +++ b/protocol/script/deploy_bridges.bash @@ -59,12 +59,14 @@ POD_TOKEN_ADDR=$(forge script ./script/DeployToken.s.sol:DeployToken \ | jq -sr 'map(.returns?.token?.value // empty) | map(select(. != "")) | last') echo "Pod token: $POD_TOKEN_ADDR" +sleep 1 + # Compute addresses for next CREATE SOURCE_CHAIN_DEPLOYER=$(cast wallet address --private-key "$PK_SOURCE_CHAIN") POD_DEPLOYER=$(cast wallet address --private-key "$PK_POD") SOURCE_CHAIN_NONCE=$(cast nonce "$SOURCE_CHAIN_DEPLOYER" --rpc-url "$SOURCE_CHAIN_RPC") POD_NONCE=$(cast nonce "$POD_DEPLOYER" --rpc-url "$POD_RPC") -SOURCE_CHAIN_BRIDGE_ADDR=$(cast compute-address "$SOURCE_CHAIN_DEPLOYER" --nonce "$(($SOURCE_CHAIN_NONCE + 1))" | grep -oE '0x[0-9a-fA-F]{40}') +SOURCE_CHAIN_BRIDGE_ADDR=$(cast compute-address "$SOURCE_CHAIN_DEPLOYER" --nonce "$(($SOURCE_CHAIN_NONCE + 3))" | grep -oE '0x[0-9a-fA-F]{40}') POD_BRIDGE_ADDR=$(cast compute-address "$POD_DEPLOYER" --nonce "$(($POD_NONCE + 1))" | grep -oE '0x[0-9a-fA-F]{40}') echo "Precomputed:" diff --git a/protocol/src/BridgeMintBurn.sol b/protocol/src/BridgeMintBurn.sol index 6ad4a811..c10f7b00 100644 --- a/protocol/src/BridgeMintBurn.sol +++ b/protocol/src/BridgeMintBurn.sol @@ -73,7 +73,7 @@ contract BridgeMintBurn is Bridge, IBridgeMintBurn { topics[1] = bytes32(id); topics[2] = bytes32(uint256(uint160(token))); - uint256 finalizedBlockNumber = PodPrecompileHelper.getFinalizedBlockNumber(SOURCE_CHAIN_ID); + uint256 finalizedBlockNumber = PodPrecompileHelper.getBlockByBlockTag(SOURCE_CHAIN_ID, block_tag_bytes); if (blockNumber > finalizedBlockNumber) { revert BlockNotFinalized(); @@ -121,7 +121,7 @@ contract BridgeMintBurn is Bridge, IBridgeMintBurn { topics[0] = DEPOSIT_NATIVE_TOPIC_0; topics[1] = bytes32(id); - uint256 finalizedBlockNumber = PodPrecompileHelper.getFinalizedBlockNumber(SOURCE_CHAIN_ID); + uint256 finalizedBlockNumber = PodPrecompileHelper.getBlockByBlockTag(SOURCE_CHAIN_ID, block_tag_bytes); if (blockNumber > finalizedBlockNumber) { revert BlockNotFinalized(); diff --git a/protocol/src/libraries/PodPrecompileHelper.sol b/protocol/src/libraries/PodPrecompileHelper.sol index 383e15d3..c540af3f 100644 --- a/protocol/src/libraries/PodPrecompileHelper.sol +++ b/protocol/src/libraries/PodPrecompileHelper.sol @@ -25,13 +25,12 @@ library PodPrecompileHelper { } /** - * @dev Gets the finalized block number. - * @return blockNumber The finalized block number. + * @dev Gets the block by block tag. + * @return blockNumber The block number. */ - function getFinalizedBlockNumber(uint256 chainId) internal view returns (uint256) { - EthGetBlockByNumberTypes.PrecompileArgs memory args = EthGetBlockByNumberTypes.PrecompileArgs( - chainId, EthGetBlockByNumberTypes.RpcArgs(hex"66696e616c697a6564", false) - ); + function getBlockByBlockTag(uint256 chainId, bytes memory blockTag) internal view returns (uint256) { + EthGetBlockByNumberTypes.PrecompileArgs memory args = + EthGetBlockByNumberTypes.PrecompileArgs(chainId, EthGetBlockByNumberTypes.RpcArgs(blockTag, false)); (bool success, bytes memory output) = EthGetBlockByNumberTypes.PRECOMPILE_ADDRESS.staticcall( abi.encode(args.chainId, args.ethGetBlockByNumberArgs) ); From 47792df77f2c96604da6d4130b28466ccae44316 Mon Sep 17 00:00:00 2001 From: Jakov Mitrovski Date: Fri, 26 Sep 2025 11:46:13 +0200 Subject: [PATCH 62/64] Update deploy bridge script and e2e bridge flow example --- Cargo.lock | 151 +++++- Cargo.toml | 1 + examples/bridge-flow/.env.example | 8 + examples/bridge-flow/.gitignore | 2 + examples/bridge-flow/Cargo.toml | 25 + examples/bridge-flow/src/main.rs | 691 ++++++++++++++++++++++++++++ protocol/.env.example | 3 +- protocol/script/deploy_bridges.bash | 34 +- 8 files changed, 880 insertions(+), 35 deletions(-) create mode 100644 examples/bridge-flow/.env.example create mode 100644 examples/bridge-flow/.gitignore create mode 100644 examples/bridge-flow/Cargo.toml create mode 100644 examples/bridge-flow/src/main.rs diff --git a/Cargo.lock b/Cargo.lock index a2b4cbb2..b65236fa 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -317,6 +317,7 @@ dependencies = [ "derive_arbitrary", "derive_more", "foldhash", + "getrandom 0.3.3", "hashbrown 0.15.2", "indexmap 2.7.0", "itoa", @@ -781,9 +782,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.98" +version = "1.0.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" +checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" [[package]] name = "arbitrary" @@ -991,9 +992,9 @@ dependencies = [ "clap", "futures", "hex", - "pod-examples-solidity", - "pod-sdk", - "pod-types", + "pod-examples-solidity 0.2.0", + "pod-sdk 0.2.0", + "pod-types 0.2.0", "tokio", ] @@ -1271,6 +1272,27 @@ dependencies = [ "zeroize", ] +[[package]] +name = "bridge" +version = "0.1.0" +dependencies = [ + "alloy-contract", + "alloy-network", + "alloy-primitives", + "alloy-provider", + "alloy-signer-local", + "alloy-sol-types", + "anyhow", + "dotenv", + "pod-examples-solidity 0.2.0 (git+https://github.com/podnetwork/pod-sdk.git?rev=7cd15a0c5436182f3ce6f4115d69f2bd257dd8e3)", + "pod-optimistic-auction 0.1.0 (git+https://github.com/podnetwork/pod-sdk.git?rev=7cd15a0c5436182f3ce6f4115d69f2bd257dd8e3)", + "pod-protocol 0.1.0 (git+https://github.com/podnetwork/pod-sdk.git?rev=12abcb9b359dea94825a6d78fefa439e8857263d)", + "pod-sdk 0.2.0 (git+https://github.com/podnetwork/pod-sdk.git?rev=7cd15a0c5436182f3ce6f4115d69f2bd257dd8e3)", + "pod-types 0.2.0 (git+https://github.com/podnetwork/pod-sdk.git?rev=7cd15a0c5436182f3ce6f4115d69f2bd257dd8e3)", + "serde_json", + "tokio", +] + [[package]] name = "bs58" version = "0.5.1" @@ -1293,7 +1315,7 @@ dependencies = [ "config", "hex", "multihash-codetable", - "pod-sdk", + "pod-sdk 0.2.0", "serde", "serde_ipld_dagcbor", "serde_json", @@ -2935,8 +2957,8 @@ dependencies = [ "clap", "futures", "hex", - "pod-sdk", - "pod-types", + "pod-sdk 0.2.0", + "pod-types 0.2.0", "tokio", ] @@ -2951,8 +2973,8 @@ dependencies = [ "hex", "humantime", "notary-bindings", - "pod-sdk", - "pod-types", + "pod-sdk 0.2.0", + "pod-types 0.2.0", "tokio", ] @@ -3242,7 +3264,7 @@ dependencies = [ "futures", "humantime", "op-alloy", - "pod-sdk", + "pod-sdk 0.2.0", "rand 0.9.1", "serde_json", "tokio", @@ -3260,10 +3282,10 @@ dependencies = [ "anyhow", "clap", "dotenv", - "pod-examples-solidity", - "pod-optimistic-auction", - "pod-sdk", - "pod-types", + "pod-examples-solidity 0.2.0", + "pod-optimistic-auction 0.1.0", + "pod-sdk 0.2.0", + "pod-types 0.2.0", "tokio", ] @@ -3471,6 +3493,15 @@ dependencies = [ "serde", ] +[[package]] +name = "pod-examples-solidity" +version = "0.2.0" +source = "git+https://github.com/podnetwork/pod-sdk.git?rev=7cd15a0c5436182f3ce6f4115d69f2bd257dd8e3#7cd15a0c5436182f3ce6f4115d69f2bd257dd8e3" +dependencies = [ + "alloy", + "serde", +] + [[package]] name = "pod-optimistic-auction" version = "0.1.0" @@ -3479,9 +3510,27 @@ dependencies = [ "serde", ] +[[package]] +name = "pod-optimistic-auction" +version = "0.1.0" +source = "git+https://github.com/podnetwork/pod-sdk.git?rev=7cd15a0c5436182f3ce6f4115d69f2bd257dd8e3#7cd15a0c5436182f3ce6f4115d69f2bd257dd8e3" +dependencies = [ + "alloy", + "serde", +] + +[[package]] +name = "pod-protocol" +version = "0.1.0" +dependencies = [ + "alloy", + "serde", +] + [[package]] name = "pod-protocol" version = "0.1.0" +source = "git+https://github.com/podnetwork/pod-sdk.git?rev=12abcb9b359dea94825a6d78fefa439e8857263d#12abcb9b359dea94825a6d78fefa439e8857263d" dependencies = [ "alloy", "serde", @@ -3507,13 +3556,40 @@ dependencies = [ "async-trait", "futures", "hex", - "pod-examples-solidity", - "pod-types", + "pod-examples-solidity 0.2.0", + "pod-types 0.2.0", "serde", "tokio-test", "tracing", ] +[[package]] +name = "pod-sdk" +version = "0.2.0" +source = "git+https://github.com/podnetwork/pod-sdk.git?rev=7cd15a0c5436182f3ce6f4115d69f2bd257dd8e3#7cd15a0c5436182f3ce6f4115d69f2bd257dd8e3" +dependencies = [ + "alloy-consensus", + "alloy-eips", + "alloy-json-rpc", + "alloy-network", + "alloy-primitives", + "alloy-provider", + "alloy-pubsub", + "alloy-rpc-types", + "alloy-signer", + "alloy-signer-local", + "alloy-sol-types", + "alloy-transport", + "anyhow", + "async-trait", + "futures", + "hex", + "pod-examples-solidity 0.2.0 (git+https://github.com/podnetwork/pod-sdk.git?rev=7cd15a0c5436182f3ce6f4115d69f2bd257dd8e3)", + "pod-types 0.2.0 (git+https://github.com/podnetwork/pod-sdk.git?rev=7cd15a0c5436182f3ce6f4115d69f2bd257dd8e3)", + "serde", + "tracing", +] + [[package]] name = "pod-types" version = "0.2.0" @@ -3531,7 +3607,7 @@ dependencies = [ "bytes", "hex", "itertools 0.13.0", - "pod-types", + "pod-types 0.2.0", "rand 0.9.1", "serde", "serde_json", @@ -3542,6 +3618,30 @@ dependencies = [ "utoipa", ] +[[package]] +name = "pod-types" +version = "0.2.0" +source = "git+https://github.com/podnetwork/pod-sdk.git?rev=7cd15a0c5436182f3ce6f4115d69f2bd257dd8e3#7cd15a0c5436182f3ce6f4115d69f2bd257dd8e3" +dependencies = [ + "alloy-consensus", + "alloy-primitives", + "alloy-rpc-types", + "alloy-signer", + "alloy-signer-local", + "alloy-sol-types", + "anyhow", + "base64 0.22.1", + "bytes", + "hex", + "itertools 0.13.0", + "serde", + "serde_with", + "thiserror 2.0.12", + "tokio", + "tracing", + "utoipa", +] + [[package]] name = "powerfmt" version = "0.2.0" @@ -3932,9 +4032,9 @@ dependencies = [ "env_logger", "futures", "hex", - "pod-examples-solidity", - "pod-sdk", - "pod-types", + "pod-examples-solidity 0.2.0", + "pod-sdk 0.2.0", + "pod-types 0.2.0", "tokio", ] @@ -4702,8 +4802,8 @@ dependencies = [ "clap", "futures", "hex", - "pod-sdk", - "pod-types", + "pod-sdk 0.2.0", + "pod-types 0.2.0", "tokio", ] @@ -4722,6 +4822,7 @@ dependencies = [ "signal-hook-registry", "socket2", "tokio-macros", + "tracing", "windows-sys 0.52.0", ] @@ -5134,8 +5235,8 @@ dependencies = [ "clap", "futures", "hex", - "pod-sdk", - "pod-types", + "pod-sdk 0.2.0", + "pod-types 0.2.0", "tokio", "voting-bindings", ] diff --git a/Cargo.toml b/Cargo.toml index 80f81e04..0f360084 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,6 +6,7 @@ members = [ "examples/notary", "examples/optimistic-auction", "examples/auction", + "examples/bridge-flow", "examples/rust", "examples/voting/client", "examples/nfts", diff --git a/examples/bridge-flow/.env.example b/examples/bridge-flow/.env.example new file mode 100644 index 00000000..756b8035 --- /dev/null +++ b/examples/bridge-flow/.env.example @@ -0,0 +1,8 @@ +POD_RPC_URL=http://localhost:8545 +POD_BRIDGE_CONTRACT_ADDRESS=0xpodbridgecontractaddress +POD_TOKEN_CONTRACT_ADDRESS=0xpodtokencontractaddress +SOURCE_CHAIN_RPC_URL=http://localhost:8546 +SOURCE_CHAIN_BRIDGE_CONTRACT_ADDRESS=0xsourcechainbridgecontractaddress +SOURCE_CHAIN_TOKEN_CONTRACT_ADDRESS=0xsourcetokendeployedaddress +USER_ADDRESS=0xuseraddress +USER_PRIVATE_KEY=userprivatekey \ No newline at end of file diff --git a/examples/bridge-flow/.gitignore b/examples/bridge-flow/.gitignore new file mode 100644 index 00000000..0b745e29 --- /dev/null +++ b/examples/bridge-flow/.gitignore @@ -0,0 +1,2 @@ +/target +.env \ No newline at end of file diff --git a/examples/bridge-flow/Cargo.toml b/examples/bridge-flow/Cargo.toml new file mode 100644 index 00000000..3061a085 --- /dev/null +++ b/examples/bridge-flow/Cargo.toml @@ -0,0 +1,25 @@ +[package] +name = "bridge" +version = "0.1.0" +edition = "2024" + +[dependencies] +pod-sdk = { git = "https://github.com/podnetwork/pod-sdk.git", rev = "7cd15a0c5436182f3ce6f4115d69f2bd257dd8e3" } +pod-types = { git = "https://github.com/podnetwork/pod-sdk.git", rev = "7cd15a0c5436182f3ce6f4115d69f2bd257dd8e3" } +alloy-network = "1.0.24" +alloy-primitives = { version = "1.3.0", features = [ + "k256", + "serde", + "getrandom", +] } +alloy-provider = { version = "1.0.24", features = ["pubsub", "ws"] } +alloy-signer-local = "1.0.24" +alloy-contract = { version = "1.0.24" } +alloy-sol-types = "1.3.0" +serde_json = "1.0.132" +pod-examples-solidity = { git = "https://github.com/podnetwork/pod-sdk.git", rev = "7cd15a0c5436182f3ce6f4115d69f2bd257dd8e3" } +pod-optimistic-auction = { git = "https://github.com/podnetwork/pod-sdk.git", rev = "7cd15a0c5436182f3ce6f4115d69f2bd257dd8e3" } +pod-protocol = { git = "https://github.com/podnetwork/pod-sdk.git", rev = "12abcb9b359dea94825a6d78fefa439e8857263d" } +dotenv = "0.15.0" +anyhow = "1.0.100" +tokio = { version = "1.43.1", features = ["full", "tracing"] } diff --git a/examples/bridge-flow/src/main.rs b/examples/bridge-flow/src/main.rs new file mode 100644 index 00000000..1f0a5622 --- /dev/null +++ b/examples/bridge-flow/src/main.rs @@ -0,0 +1,691 @@ +use alloy_sol_types::SolEvent; +use dotenv::dotenv; + +use alloy_network::{Ethereum, EthereumWallet, ReceiptResponse}; +use alloy_primitives::Address; +use alloy_provider::{ + Identity, RootProvider, + fillers::{ + BlobGasFiller, ChainIdFiller, FillProvider, GasFiller, JoinFill, NonceFiller, WalletFiller, + }, +}; +use alloy_signer_local::PrivateKeySigner; + +use anyhow::Result; +use pod_sdk::{ + Provider, ProviderBuilder, U256, + network::PodNetwork, + provider::{PodProvider, PodProviderBuilder}, +}; + +use pod_protocol::{ + bridge_deposit_withdraw::BridgeDepositWithdraw::BridgeDepositWithdrawInstance, + bridge_mint_burn::BridgeMintBurn::{BridgeMintBurnInstance, Deposit, DepositNative}, + wrapped_token::WrappedToken::WrappedTokenInstance, +}; + +use pod_types::{Hashable, ledger::log::VerifiableLog, rpc::filter::LogFilterBuilder}; + +use pod_protocol::bridge_deposit_withdraw::{ + MerkleTree::Proof, + PodECDSA::{ + Certificate as BridgeCertificate, CertifiedLog, CertifiedReceipt, Log as BridgeLog, + }, +}; + +use std::{env, str::FromStr, thread::sleep, time::Duration}; + +type SourceChainProviderType = FillProvider< + JoinFill< + JoinFill< + Identity, + JoinFill>>, + >, + WalletFiller, + >, + RootProvider, + Ethereum, +>; + +type SourceChainContractType = BridgeDepositWithdrawInstance< + FillProvider< + JoinFill< + JoinFill< + Identity, + JoinFill>>, + >, + WalletFiller, + >, + RootProvider, + Ethereum, + >, +>; + +struct PodBridgeClient { + pod_provider: PodProvider, + pod_bridge: BridgeMintBurnInstance, + pod_token_contract: WrappedTokenInstance, +} + +struct SourceChainBridgeClient { + source_chain_provider: SourceChainProviderType, + source_chain_contract: SourceChainContractType, + source_chain_token_contract: WrappedTokenInstance, +} + +fn get_certified_log(log: &VerifiableLog) -> Result { + let proof = log.generate_proof().unwrap(); + let leaf = log.get_leaf(); + + Ok(CertifiedLog { + log: BridgeLog { + addr: log.inner.address(), + topics: log.inner.topics().to_vec(), + data: log.inner.data().data.clone(), + }, + logIndex: U256::from(log.inner.log_index.unwrap()), + certificate: BridgeCertificate { + certifiedReceipt: CertifiedReceipt { + receiptRoot: log.pod_metadata.receipt.hash_custom(), + aggregateSignature: log.aggregate_signatures().into(), + sortedAttestationTimestamps: log.get_sorted_attestation_timestamps_in_seconds(), + }, + leaf, + proof: Proof { path: proof.path }, + }, + }) +} + +impl SourceChainBridgeClient { + pub async fn new( + source_chain_rpc_url: String, + source_chain_contract_address: Address, + source_chain_token_contract_address: Address, + signer: PrivateKeySigner, + ) -> Result { + let wallet = EthereumWallet::from(signer); + + let source_chain_provider = ProviderBuilder::new() + .wallet(wallet.clone()) + .connect_http(source_chain_rpc_url.parse()?); + + let source_chain_contract = BridgeDepositWithdrawInstance::new( + source_chain_contract_address, + source_chain_provider.clone(), + ); + + let source_chain_token_contract = WrappedTokenInstance::new( + source_chain_token_contract_address, + source_chain_provider.clone(), + ); + + Ok(Self { + source_chain_provider, + source_chain_contract, + source_chain_token_contract, + }) + } + + pub async fn deposit_native(&self, to: Address, value: U256) -> Result<(U256, u64)> { + let tx = self + .source_chain_contract + .depositNative(to) + .max_fee_per_gas(1_000_000_000u128) + .max_priority_fee_per_gas(0) + .value(value) + .send() + .await?; + + sleep(Duration::from_millis(100)); + + println!( + "Successfully deposited {:?} native to address: {:?}", + value, to + ); + + let receipt = self + .source_chain_provider + .get_transaction_receipt(*tx.tx_hash()) + .await? + .unwrap(); + + assert!(receipt.status()); + assert!(receipt.logs().len() == 1); + + for log in receipt.logs() { + let event_signature = log.topic0(); + if Some(*event_signature.unwrap()) == Some(DepositNative::SIGNATURE_HASH) { + let request_id = log.topics()[1]; + let block_number = receipt.block_number(); + if block_number.is_some() { + return Ok((request_id.into(), block_number.unwrap())); + } + } + } + + Err(anyhow::anyhow!("Request ID not found")) + } + + pub async fn deposit_token(&self, to: Address, amount: U256) -> Result<(U256, Address, u64)> { + let tx = self + .source_chain_contract + .deposit(*self.source_chain_token_contract.address(), amount, to) + .send() + .await?; + + sleep(Duration::from_millis(1000)); + + let receipt = self + .source_chain_provider + .get_transaction_receipt(*tx.tx_hash()) + .await? + .unwrap(); + + assert!(receipt.status()); + assert!(receipt.logs().len() == 2); + + println!( + "Successfully deposited {:?} token to address: {:?}", + amount, to + ); + + for log in receipt.logs() { + let event_signature = log.topic0(); + if Some(*event_signature.unwrap()) == Some(Deposit::SIGNATURE_HASH) { + let request_id = log.topics()[1]; + let token_address = log.topics()[2]; + let block_number = receipt.block_number(); + if block_number.is_some() { + return Ok(( + request_id.into(), + Address::from_slice(&token_address.0[12..]), + block_number.unwrap(), + )); + } + } + } + + Err(anyhow::anyhow!("Request ID not found")) + } + + pub async fn claim_token(&self, certified_log: CertifiedLog) -> Result<()> { + let tx = self + .source_chain_contract + .claim(certified_log) + .send() + .await?; + + sleep(Duration::from_millis(100)); + + let receipt = self + .source_chain_provider + .get_transaction_receipt(*tx.tx_hash()) + .await? + .unwrap(); + + assert!(receipt.status()); + assert!(receipt.logs().len() == 2); + + println!("Successfully claimed token from source chain",); + + Ok(()) + } + + pub async fn claim_native(&self, certified_log: CertifiedLog) -> Result<()> { + let tx = self + .source_chain_contract + .claimNative(certified_log) + .send() + .await?; + + sleep(Duration::from_millis(100)); + + let receipt = self + .source_chain_provider + .get_transaction_receipt(*tx.tx_hash()) + .await? + .unwrap(); + + assert!(receipt.status()); + assert!(receipt.logs().len() == 1); + + println!("Successfully claimed native from source chain",); + + Ok(()) + } +} + +impl PodBridgeClient { + pub async fn new( + pod_rpc_url: String, + pod_bridge_contract_address: Address, + pod_token_contract_address: Address, + signer: PrivateKeySigner, + ) -> Result { + let wallet = EthereumWallet::from(signer); + + let pod_provider = PodProviderBuilder::with_recommended_settings() + .wallet(wallet.clone()) + .on_url(pod_rpc_url) + .await?; + + let pod_bridge = + BridgeMintBurnInstance::new(pod_bridge_contract_address, pod_provider.clone()); + + let pod_token_contract = + WrappedTokenInstance::new(pod_token_contract_address, pod_provider.clone()); + + Ok(Self { + pod_provider, + pod_bridge, + pod_token_contract, + }) + } + + pub async fn deposit_native(&self, to: Address, value: U256) -> Result { + let tx = self + .pod_bridge + .depositNative(to) + .value(value) + .send() + .await + .unwrap(); + + let receipt = tx.get_receipt().await?; + + assert!(receipt.status()); + assert!(receipt.receipt.logs().len() == 1); + + println!( + "Successfully deposited {:?} native to address: {:?}", + value, to + ); + + for log in receipt.logs() { + let event_signature = log.topic0(); + if Some(*event_signature.unwrap()) == Some(DepositNative::SIGNATURE_HASH) { + let request_id = log.topics()[1]; + return Ok(request_id.into()); + } + } + Err(anyhow::anyhow!("Request ID not found")) + } + + pub async fn deposit_token(&self, to: Address, amount: U256) -> Result<(U256, Address)> { + let tx = self + .pod_bridge + .deposit(*self.pod_token_contract.address(), amount, to) + .max_fee_per_gas(1_000_000_000u128) + .max_priority_fee_per_gas(0) + .send() + .await + .unwrap(); + + let receipt = tx.get_receipt().await?; + + assert!(receipt.status()); + assert!(receipt.logs().len() == 2); + + println!( + "Successfully deposited {:?} token to address: {:?}", + amount, to + ); + + for log in receipt.logs() { + let event_signature = log.topic0(); + if Some(*event_signature.unwrap()) == Some(Deposit::SIGNATURE_HASH) { + let request_id = log.topics()[1]; + let token_address = log.topics()[2]; + return Ok(( + request_id.into(), + Address::from_slice(&token_address.0[12..]), + )); + } + } + Err(anyhow::anyhow!("Request ID not found")) + } + + pub async fn claim_token( + &self, + request_id: U256, + token_address: Address, + block_number: U256, + to: Address, + ) -> Result<()> { + let tx = self + .pod_bridge + .claim(request_id, token_address, block_number) + .send() + .await?; + + let receipt = tx.get_receipt().await?; + + assert!(receipt.status()); + assert!(receipt.logs().len() == 2); + + println!( + "Successfully claimed request id: {:?} by address: {:?}", + request_id, to + ); + + Ok(()) + } + + pub async fn claim_native( + &self, + request_id: U256, + block_number: U256, + to: Address, + ) -> Result<()> { + let prev_balance = self.pod_provider.get_balance(to).await?; + + let tx = self + .pod_bridge + .claimNative(request_id, block_number) + .send() + .await?; + + let receipt = tx.get_receipt().await?; + + assert!(receipt.status()); + assert!(self.pod_provider.get_balance(to).await? > prev_balance); + + println!( + "Successfully claimed request id: {:?} by address: {:?}", + request_id, to + ); + + Ok(()) + } + + pub async fn get_deposit_native_certified_log(&self, request_id: U256) -> Result { + let filter = LogFilterBuilder::new() + .address(Address::from(self.pod_bridge.address().0)) + .event_signature(DepositNative::SIGNATURE_HASH) + .topic1(request_id) + .build(); + + sleep(Duration::from_millis(1000)); + + let logs = self.pod_provider.get_verifiable_logs(&filter).await?; + + assert_eq!(logs.len(), 1); + let log = &logs[0]; + + let certified_log = get_certified_log(log)?; + + println!("Generated certified log for request id: {:?}", request_id); + + Ok(certified_log) + } + + pub async fn get_deposit_token_certified_log( + &self, + request_id: U256, + token_address: Address, + ) -> Result { + let token_address_filter = U256::from_str(&token_address.to_string())?; + let filter = LogFilterBuilder::new() + .address(Address::from(self.pod_bridge.address().0)) + .event_signature(Deposit::SIGNATURE_HASH) + .topic1(request_id) + .topic2(token_address_filter) + .build(); + + sleep(Duration::from_millis(1000)); + + let logs = self.pod_provider.get_verifiable_logs(&filter).await?; + + assert_eq!(logs.len(), 1); + let log = &logs[0]; + + let certified_log = get_certified_log(log)?; + + println!("Generated certified log for request id: {:?}", request_id); + + Ok(certified_log) + } +} + +#[tokio::main] +async fn main() -> Result<()> { + dotenv().ok(); + + let to = env::var("USER_ADDRESS").expect("USER_ADDRESS must be set"); + let to = Address::from_str(&to)?; + + let pod_rpc_url = env::var("POD_RPC_URL").expect("POD_RPC_URL must be set"); + let pod_bridge_contract_address = + env::var("POD_BRIDGE_CONTRACT_ADDRESS").expect("POD_BRIDGE_CONTRACT_ADDRESS must be set"); + let pod_bridge_contract_address = Address::from_str(&pod_bridge_contract_address)?; + let pod_token_contract_address = + env::var("POD_TOKEN_CONTRACT_ADDRESS").expect("POD_TOKEN_CONTRACT_ADDRESS must be set"); + let pod_token_contract_address = Address::from_str(&pod_token_contract_address)?; + + let source_chain_rpc_url = + env::var("SOURCE_CHAIN_RPC_URL").expect("SOURCE_CHAIN_RPC_URL must be set"); + let source_chain_contract_address = env::var("SOURCE_CHAIN_BRIDGE_CONTRACT_ADDRESS") + .expect("SOURCE_CHAIN_BRIDGE_CONTRACT_ADDRESS must be set"); + let source_chain_contract_address = Address::from_str(&source_chain_contract_address)?; + + let source_chain_token_contract_address = env::var("SOURCE_CHAIN_TOKEN_CONTRACT_ADDRESS") + .expect("SOURCE_CHAIN_TOKEN_CONTRACT_ADDRESS must be set"); + let source_chain_token_contract_address = + Address::from_str(&source_chain_token_contract_address)?; + + let user_private_key = env::var("USER_PRIVATE_KEY").expect("USER_PRIVATE_KEY must be set"); + let user_signer: PrivateKeySigner = user_private_key.parse()?; + + let source_chain_bridge_client = SourceChainBridgeClient::new( + source_chain_rpc_url.clone(), + source_chain_contract_address, + source_chain_token_contract_address, + user_signer.clone(), + ) + .await?; + + let pod_bridge_client = PodBridgeClient::new( + pod_rpc_url, + pod_bridge_contract_address, + pod_token_contract_address, + user_signer, + ) + .await?; + + let amount = U256::from(1000000000000000000u128); + + bridge_native_from_source_chain_to_pod( + &source_chain_bridge_client, + &pod_bridge_client, + to, + amount, + ) + .await?; + + bridge_native_from_pod_to_source_chain( + &pod_bridge_client, + &source_chain_bridge_client, + to, + amount, + ) + .await?; + + bridge_token_from_source_chain_to_pod( + &source_chain_bridge_client, + &pod_bridge_client, + to, + amount, + ) + .await?; + + bridge_token_from_pod_to_source_chain( + &pod_bridge_client, + &source_chain_bridge_client, + to, + amount, + ) + .await?; + + Ok(()) +} + +async fn bridge_native_from_source_chain_to_pod( + source_chain_bridge_client: &SourceChainBridgeClient, + pod_bridge_client: &PodBridgeClient, + to: Address, + value: U256, +) -> Result<()> { + let prev_balance_source = source_chain_bridge_client + .source_chain_provider + .get_balance(to) + .await?; + + let prev_balance_pod = pod_bridge_client.pod_provider.get_balance(to).await?; + + let (request_id, source_chain_block_number) = + source_chain_bridge_client.deposit_native(to, value).await?; + + pod_bridge_client + .claim_native(request_id, U256::from(source_chain_block_number), to) + .await?; + + sleep(Duration::from_millis(1000)); + + assert!(pod_bridge_client.pod_provider.get_balance(to).await? > prev_balance_pod); + assert!( + source_chain_bridge_client + .source_chain_provider + .get_balance(to) + .await? + < prev_balance_source + ); + + Ok(()) +} + +async fn bridge_native_from_pod_to_source_chain( + pod_bridge_client: &PodBridgeClient, + source_chain_bridge_client: &SourceChainBridgeClient, + to: Address, + value: U256, +) -> Result<()> { + let prev_balance_pod = pod_bridge_client.pod_provider.get_balance(to).await?; + let prev_balance_source = source_chain_bridge_client + .source_chain_provider + .get_balance(to) + .await?; + + let request_id = pod_bridge_client.deposit_native(to, value).await?; + + let certified_log = pod_bridge_client + .get_deposit_native_certified_log(request_id) + .await?; + + source_chain_bridge_client + .claim_native(certified_log) + .await?; + + assert!(pod_bridge_client.pod_provider.get_balance(to).await? < prev_balance_pod); + assert!( + source_chain_bridge_client + .source_chain_provider + .get_balance(to) + .await? + > prev_balance_source + ); + + Ok(()) +} + +async fn bridge_token_from_source_chain_to_pod( + source_chain_bridge_client: &SourceChainBridgeClient, + pod_bridge_client: &PodBridgeClient, + to: Address, + amount: U256, +) -> Result<()> { + let prev_balance_source = source_chain_bridge_client + .source_chain_token_contract + .balanceOf(to) + .call() + .await?; + let prev_balance_pod = pod_bridge_client + .pod_token_contract + .balanceOf(to) + .call() + .await?; + + let (request_id, token_address, block_number) = + source_chain_bridge_client.deposit_token(to, amount).await?; + + pod_bridge_client + .claim_token(request_id, token_address, U256::from(block_number), to) + .await?; + + assert!( + pod_bridge_client + .pod_token_contract + .balanceOf(to) + .call() + .await? + > prev_balance_pod + ); + + assert!( + source_chain_bridge_client + .source_chain_token_contract + .balanceOf(to) + .call() + .await? + < prev_balance_source + ); + + Ok(()) +} + +async fn bridge_token_from_pod_to_source_chain( + pod_bridge_client: &PodBridgeClient, + source_chain_bridge_client: &SourceChainBridgeClient, + to: Address, + amount: U256, +) -> Result<()> { + let prev_balance_pod = pod_bridge_client + .pod_token_contract + .balanceOf(to) + .call() + .await?; + let prev_balance_source = source_chain_bridge_client + .source_chain_token_contract + .balanceOf(to) + .call() + .await?; + + let (request_id, token_address) = pod_bridge_client.deposit_token(to, amount).await?; + + let certified_log = pod_bridge_client + .get_deposit_token_certified_log(request_id, token_address) + .await?; + + source_chain_bridge_client + .claim_token(certified_log) + .await?; + + assert!( + pod_bridge_client + .pod_token_contract + .balanceOf(to) + .call() + .await? + < prev_balance_pod + ); + + assert!( + source_chain_bridge_client + .source_chain_token_contract + .balanceOf(to) + .call() + .await? + > prev_balance_source + ); + + Ok(()) +} diff --git a/protocol/.env.example b/protocol/.env.example index abd5303e..29057961 100644 --- a/protocol/.env.example +++ b/protocol/.env.example @@ -3,4 +3,5 @@ PK_POD=0xPodPrivateKey POD_RPC=http://localhost:8545 SOURCE_CHAIN_RPC=http://localhost:8546 POD_COMMITTEE_KEYS=0xcc30Ffc732E52fbcF7Ea33915502b2F598BF2a90,0x6931FEd7fD06DDA83f1d5702b729e2E7EaAF6bAB,0x6fE9943790e826e77478B05e740Fc551240221F9,0x135D988A2747A1c61cF90D9492F87AaCeAB8EE2c -USER_ADDRESS=0xYourUserAddress \ No newline at end of file +USER_ADDRESS=0xYourUserAddress +USER_PRIVATE_KEY=0xYourUserPrivateKey \ No newline at end of file diff --git a/protocol/script/deploy_bridges.bash b/protocol/script/deploy_bridges.bash index 2f90e7b7..c628f19c 100755 --- a/protocol/script/deploy_bridges.bash +++ b/protocol/script/deploy_bridges.bash @@ -13,6 +13,7 @@ source .env : "${PK_SOURCE_CHAIN:?}" # Anvil/Sepolia deployer private key : "${PK_POD:?}" # Pod deployer private key : "${USER_ADDRESS:?}" # Receiver on Anvil/Sepolia for initial mint +: "${USER_PRIVATE_KEY:?}" # User private key : "${POD_COMMITTEE_KEYS:?}" # Pod committee keys echo "SOURCE_CHAIN_RPC: $SOURCE_CHAIN_RPC" @@ -96,15 +97,30 @@ forge script ./script/GrantRoles.s.sol:GrantRoles \ -vvv -# 5) Show codes to confirm deployment +# 6) Fund user on Pod and Source chain +cast send --rpc-url "$POD_RPC" --private-key "$PK_POD" --value "$MINT_AMOUNT" "$USER_ADDRESS" +cast send --rpc-url "$SOURCE_CHAIN_RPC" --private-key "$PK_SOURCE_CHAIN" --value "$MINT_AMOUNT" "$USER_ADDRESS" + +# 7) Call approve from user private key on bridge for amount of tokens +cast send $POD_TOKEN_ADDR "approve(address,uint256)" --rpc-url "$POD_RPC" --private-key "$USER_PRIVATE_KEY" "$POD_BRIDGE_ADDR" "$MINT_AMOUNT" +cast send $SOURCE_CHAIN_TOKEN_ADDR "approve(address,uint256)" --rpc-url "$SOURCE_CHAIN_RPC" --private-key "$USER_PRIVATE_KEY" "$SOURCE_CHAIN_BRIDGE_ADDR" "$MINT_AMOUNT" + + +# 8) Show codes to confirm deployment when debugging echo "Codes:" -echo " Source chain BridgeDepositWithdraw code bytes: $(cast code $SOURCE_CHAIN_BRIDGE_ADDR --rpc-url $SOURCE_CHAIN_RPC | wc -c)" -echo " Pod BridgeMintBurn code bytes: $(cast code $POD_BRIDGE_ADDR --rpc-url $POD_RPC | wc -c)" -echo " Source chain Token code bytes: $(cast code $SOURCE_CHAIN_TOKEN_ADDR --rpc-url $SOURCE_CHAIN_RPC | wc -c)" -echo " Pod Mirror Token code bytes: $(cast code $POD_TOKEN_ADDR --rpc-url $POD_RPC | wc -c)" +echo " Source Chain BridgeDepositWithdraw code bytes: $(cast code $SOURCE_CHAIN_BRIDGE_ADDR --rpc-url $SOURCE_CHAIN_RPC | wc -c)" +echo " Pod BridgeMintBurn code bytes: $(cast code $POD_BRIDGE_ADDR --rpc-url $POD_RPC | wc -c)" +echo " Source Chain Token code bytes: $(cast code $SOURCE_CHAIN_TOKEN_ADDR --rpc-url $SOURCE_CHAIN_RPC | wc -c)" +echo " Pod Mirror Token code bytes: $(cast code $POD_TOKEN_ADDR --rpc-url $POD_RPC | wc -c)" + +# Expected values: +# Source Chain BridgeDepositWithdraw code bytes: 26453 +# Pod BridgeMintBurn code bytes: 49063 +# Source Chain Token code bytes: 13225 +# Pod Mirror Token code bytes: 13225 echo "Done." -echo "Source chain BridgeDepositWithdraw: $SOURCE_CHAIN_BRIDGE_ADDR" -echo "Pod BridgeMintBurn: $POD_BRIDGE_ADDR" -echo "Source chain token: $SOURCE_CHAIN_TOKEN_ADDR" -echo "Pod mirror token: $POD_TOKEN_ADDR" \ No newline at end of file +echo "Source Chain BridgeDepositWithdraw: $SOURCE_CHAIN_BRIDGE_ADDR" +echo "Pod BridgeMintBurn: $POD_BRIDGE_ADDR" +echo "Source Chain Token: $SOURCE_CHAIN_TOKEN_ADDR" +echo "Pod Mirror Token: $POD_TOKEN_ADDR" \ No newline at end of file From 9280885bb8ce9c7437fc61d42aef4caba027f094 Mon Sep 17 00:00:00 2001 From: Jakov Mitrovski Date: Fri, 26 Sep 2025 11:55:25 +0200 Subject: [PATCH 63/64] clippy and unused deps --- examples/bridge-flow/Cargo.toml | 4 --- examples/bridge-flow/src/main.rs | 44 ++++++++++---------------------- 2 files changed, 13 insertions(+), 35 deletions(-) diff --git a/examples/bridge-flow/Cargo.toml b/examples/bridge-flow/Cargo.toml index 3061a085..164706eb 100644 --- a/examples/bridge-flow/Cargo.toml +++ b/examples/bridge-flow/Cargo.toml @@ -14,11 +14,7 @@ alloy-primitives = { version = "1.3.0", features = [ ] } alloy-provider = { version = "1.0.24", features = ["pubsub", "ws"] } alloy-signer-local = "1.0.24" -alloy-contract = { version = "1.0.24" } alloy-sol-types = "1.3.0" -serde_json = "1.0.132" -pod-examples-solidity = { git = "https://github.com/podnetwork/pod-sdk.git", rev = "7cd15a0c5436182f3ce6f4115d69f2bd257dd8e3" } -pod-optimistic-auction = { git = "https://github.com/podnetwork/pod-sdk.git", rev = "7cd15a0c5436182f3ce6f4115d69f2bd257dd8e3" } pod-protocol = { git = "https://github.com/podnetwork/pod-sdk.git", rev = "12abcb9b359dea94825a6d78fefa439e8857263d" } dotenv = "0.15.0" anyhow = "1.0.100" diff --git a/examples/bridge-flow/src/main.rs b/examples/bridge-flow/src/main.rs index 1f0a5622..c69fcb81 100644 --- a/examples/bridge-flow/src/main.rs +++ b/examples/bridge-flow/src/main.rs @@ -138,10 +138,7 @@ impl SourceChainBridgeClient { sleep(Duration::from_millis(100)); - println!( - "Successfully deposited {:?} native to address: {:?}", - value, to - ); + println!("Successfully deposited {value} native to address: {to}"); let receipt = self .source_chain_provider @@ -157,8 +154,8 @@ impl SourceChainBridgeClient { if Some(*event_signature.unwrap()) == Some(DepositNative::SIGNATURE_HASH) { let request_id = log.topics()[1]; let block_number = receipt.block_number(); - if block_number.is_some() { - return Ok((request_id.into(), block_number.unwrap())); + if let Some(block_number) = block_number { + return Ok((request_id.into(), block_number)); } } } @@ -184,10 +181,7 @@ impl SourceChainBridgeClient { assert!(receipt.status()); assert!(receipt.logs().len() == 2); - println!( - "Successfully deposited {:?} token to address: {:?}", - amount, to - ); + println!("Successfully deposited {amount} token to address: {to}"); for log in receipt.logs() { let event_signature = log.topic0(); @@ -195,11 +189,11 @@ impl SourceChainBridgeClient { let request_id = log.topics()[1]; let token_address = log.topics()[2]; let block_number = receipt.block_number(); - if block_number.is_some() { + if let Some(block_number) = block_number { return Ok(( request_id.into(), Address::from_slice(&token_address.0[12..]), - block_number.unwrap(), + block_number, )); } } @@ -226,7 +220,7 @@ impl SourceChainBridgeClient { assert!(receipt.status()); assert!(receipt.logs().len() == 2); - println!("Successfully claimed token from source chain",); + println!("Successfully claimed token from source chain"); Ok(()) } @@ -296,10 +290,7 @@ impl PodBridgeClient { assert!(receipt.status()); assert!(receipt.receipt.logs().len() == 1); - println!( - "Successfully deposited {:?} native to address: {:?}", - value, to - ); + println!("Successfully deposited {value} native to address: {to}"); for log in receipt.logs() { let event_signature = log.topic0(); @@ -326,10 +317,7 @@ impl PodBridgeClient { assert!(receipt.status()); assert!(receipt.logs().len() == 2); - println!( - "Successfully deposited {:?} token to address: {:?}", - amount, to - ); + println!("Successfully deposited {amount} token to address: {to}"); for log in receipt.logs() { let event_signature = log.topic0(); @@ -363,10 +351,7 @@ impl PodBridgeClient { assert!(receipt.status()); assert!(receipt.logs().len() == 2); - println!( - "Successfully claimed request id: {:?} by address: {:?}", - request_id, to - ); + println!("Successfully claimed request id: {request_id} by address: {to}"); Ok(()) } @@ -390,10 +375,7 @@ impl PodBridgeClient { assert!(receipt.status()); assert!(self.pod_provider.get_balance(to).await? > prev_balance); - println!( - "Successfully claimed request id: {:?} by address: {:?}", - request_id, to - ); + println!("Successfully claimed request id: {request_id} by address: {to}"); Ok(()) } @@ -414,7 +396,7 @@ impl PodBridgeClient { let certified_log = get_certified_log(log)?; - println!("Generated certified log for request id: {:?}", request_id); + println!("Generated certified log for request id: {request_id}"); Ok(certified_log) } @@ -441,7 +423,7 @@ impl PodBridgeClient { let certified_log = get_certified_log(log)?; - println!("Generated certified log for request id: {:?}", request_id); + println!("Generated certified log for request id: {request_id}"); Ok(certified_log) } From ca6a8d32b18e889046bb7b0747ef9c4f699b413f Mon Sep 17 00:00:00 2001 From: Jakov Mitrovski Date: Fri, 26 Sep 2025 11:56:07 +0200 Subject: [PATCH 64/64] clippy --- Cargo.lock | 15 +-------------- examples/auction/main.rs | 2 +- types/src/pagination.rs | 4 ++-- 3 files changed, 4 insertions(+), 17 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b65236fa..0e81f3c8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1276,7 +1276,6 @@ dependencies = [ name = "bridge" version = "0.1.0" dependencies = [ - "alloy-contract", "alloy-network", "alloy-primitives", "alloy-provider", @@ -1284,12 +1283,9 @@ dependencies = [ "alloy-sol-types", "anyhow", "dotenv", - "pod-examples-solidity 0.2.0 (git+https://github.com/podnetwork/pod-sdk.git?rev=7cd15a0c5436182f3ce6f4115d69f2bd257dd8e3)", - "pod-optimistic-auction 0.1.0 (git+https://github.com/podnetwork/pod-sdk.git?rev=7cd15a0c5436182f3ce6f4115d69f2bd257dd8e3)", "pod-protocol 0.1.0 (git+https://github.com/podnetwork/pod-sdk.git?rev=12abcb9b359dea94825a6d78fefa439e8857263d)", "pod-sdk 0.2.0 (git+https://github.com/podnetwork/pod-sdk.git?rev=7cd15a0c5436182f3ce6f4115d69f2bd257dd8e3)", "pod-types 0.2.0 (git+https://github.com/podnetwork/pod-sdk.git?rev=7cd15a0c5436182f3ce6f4115d69f2bd257dd8e3)", - "serde_json", "tokio", ] @@ -3283,7 +3279,7 @@ dependencies = [ "clap", "dotenv", "pod-examples-solidity 0.2.0", - "pod-optimistic-auction 0.1.0", + "pod-optimistic-auction", "pod-sdk 0.2.0", "pod-types 0.2.0", "tokio", @@ -3510,15 +3506,6 @@ dependencies = [ "serde", ] -[[package]] -name = "pod-optimistic-auction" -version = "0.1.0" -source = "git+https://github.com/podnetwork/pod-sdk.git?rev=7cd15a0c5436182f3ce6f4115d69f2bd257dd8e3#7cd15a0c5436182f3ce6f4115d69f2bd257dd8e3" -dependencies = [ - "alloy", - "serde", -] - [[package]] name = "pod-protocol" version = "0.1.0" diff --git a/examples/auction/main.rs b/examples/auction/main.rs index 251ff29f..510fd2a7 100644 --- a/examples/auction/main.rs +++ b/examples/auction/main.rs @@ -259,7 +259,7 @@ async fn watch(auction_id: U256, deadline: u64, rpc_url: String) -> Result<()> { match result { Ok(Ok(_)) => break, Ok(Err(e)) => return Err(e), - Err(e) => return Err(anyhow::anyhow!("Deadline task failed: {}", e)), + Err(e) => return Err(anyhow::anyhow!("Deadline task failed: {e}")), } } } diff --git a/types/src/pagination.rs b/types/src/pagination.rs index e818c70a..e2907758 100644 --- a/types/src/pagination.rs +++ b/types/src/pagination.rs @@ -79,9 +79,9 @@ impl TryFrom for CursorPagination { Some(cursor) => { let decoded = base64::engine::general_purpose::STANDARD .decode(&cursor) - .map_err(|e| anyhow!("Failed to decode cursor: {}", e))?; + .map_err(|e| anyhow!("Failed to decode cursor: {e}"))?; let decoded_str = String::from_utf8(decoded) - .map_err(|e| anyhow!("Failed to decode cursor as UTF-8: {}", e))?; + .map_err(|e| anyhow!("Failed to decode cursor as UTF-8: {e}"))?; let parts: Vec<&str> = decoded_str.split('|').collect(); if parts.len() != 2 {