ETH Price: $1,913.42 (+4.74%)

Transaction Decoder

Block:
18894895 at Dec-30-2023 12:50:23 AM +UTC
Transaction Fee:
0.005117058701532144 ETH $9.79
Gas Used:
314,152 Gas / 16.288480422 Gwei

Emitted Events:

151 eNear.ConsumedProof( _receiptId=854096901C8855C25AA309BA114D5E6F4B536181C2504848DB8EE5BCC58DD746 )
152 eNear.Transfer( from=0x0000000000000000000000000000000000000000, to=[Sender] 0x324594bdd150e359a2492c2e72533d67b6d1db85, value=246000000000000000000000000 )
153 eNear.NearToEthTransferFinalised( amount=246000000000000000000000000, recipient=[Sender] 0x324594bdd150e359a2492c2e72533d67b6d1db85 )

Account State Difference:

  Address   Before After State Difference Code
0x324594Bd...7b6D1dB85
107.629675774289409174 Eth
Nonce: 390
107.62455871558787703 Eth
Nonce: 391
0.005117058701532144
0x85F17Cf9...bD4B9f6a4
(beaverbuild)
13.735463057225233672 Eth13.735494472425233672 Eth0.0000314152

Execution Trace

eNear.finaliseNearToEthTransfer( proofData=0x040000009B484B3B0AF0BF63B510D6FB270C3B8C720C2A9A8F7FA2DA85785E820B4C1444012EE0A2B5DD3CC51F1A8B6C0724544B0C71E1A1F6CA99D60D2FC838C6FF8AC2B80097D48110DFA9AC7BF9372F8C8DFE9C6BDA1B5FB57D10F811E97C2AA4D7AF3F2E011AC44CE3520650BBD0BB4F3818D6EB4BDD5B68FBF6FE2CF66CAD92ED74F3FF5C002792D21308C1D9FA6EBAEE0BC5EA97BC44920F7C6D22A8712257E6CEB65045761DA07F39EA2D1A606594C61C5EB856A1F6F8F1087622448F845C5D55D71102740000000001000000854096901C8855C25AA309BA114D5E6F4B536181C2504848DB8EE5BCC58DD74610FBB1129E0200000010F903AB4CF2990F000000000000000B000000652D6E6561722E6E656172022500000000000000B658ECB8B8867CCB0000000000324594BDD150E359A2492C2E72533D67B6D1DB8502000000A76E094F6D4A01E6E1988071A3E2D0E474856ADF07EF5F040E51DDCF6A6F180101EB1319D7EE76EE4FAEBE65330345AC47A3F09DEAC3816E4C2D84C46D88E2F52100C958CEFB246970C467481374B08BC009032B8DB9304970BE5BC14492509F4C3A9F5673CC47680221925FE9F9BCB762D91FCE7BE69AAEC730D1366118DA30A906E7DF0D060000000034AA3210244E8E9B12F1ED8B9F977C79A89B88332945F461C83310C8DFF0CECBA32035A4844650D56479FB4FEEF009F390EA836B0EB2D3D26208F000E133280B9634E71ADB75478B74622B8F2374A7ACC08345855B345531F839A7D86C48AC6AE6199D0E4B1CABB4EB07A907769AEB6EABBD1CB7A04271DE8263E0BA7D79ED49048F9E6096B386171E2E9B784B27E69C7D3A19AB77A68A5FD821EB1AD862B4B723D6880DE8D77AC41BF835EBC8ACAF8934C7A8EF2654760D28604C824C86C044D6B78F9390DBFC9A1A000000C958CEFB246970C467481374B08BC009032B8DB9304970BE5BC14492509F4C3A0098E624597AE2754DDA9C4055B224E14CBC7EC8B983893F95FFC551AF289B155901869E87DC6A4D2AC9FD95C9AAFF291761327F8CD818E87212A0E1F55557AFB646010BA183D5E50A732D2B738831228E3779F911E45247055BEDF84C3DA2DF3EEB5601D96C00EAE74452F609706E39F5ED0AEBAE6828073AC2487DF71492D10B07F5FA00CC74A9749115AFED15EAD3221B837BD6621DC3750CD11934A38745082A335BEA0194A054D11C65F6749B46F7C5D7DCDF5CB3ED0014B2A852E89054FE48EB50D6E40062A3600EB24A5F7801A2E5749DAFBAED0F517BE9BDBFAF05C880BAF354FE495F016993966D521E3A284FD798A2079FF078B25CFF52B52A5F5227915A7F5EC998AD00126724B88F90CC7E4203D4FE3E4DFD47396A556494DD3CABF36102125B8996C901FEFCA491CC538FEA0A50FA8744EE03117139CB0D89192CF3772139790B04C33B013767495D76D7D63AD25DE81D32EAF0AD667B58FCA68228F614CECCE4B878F21A012FA6C573FE53C6906A19ABDFBCF1FFF5E5AFA2E5FF2224227DECC7972F7F587201A743AF799571EE2EDB7D672DFFA9A800821933554CAE16AD0F6BDD63D3556B990085DD4713BED410F1529E0783ADEE30201E7147949674A02E3F5B72ACEAB3D09D0060EA375F077DB92A3D850433AA90F86DEF6473D30471E5115ACDBED5AAA8729301CE61BEC753F0C2CFBDDF24D7CA7746C005203764A41CD596142D74E90C2B5F6001458B66EC0E6FDBEB0E468ADE434759EBE03964BE02C7066554DAE460362E067D01E872A35E49FAF05AB92AC3587CF43FE31CBABD69AF797C9F655BD45A6BF6024E0018423638584FC568F497B81094124A093B3DD30D0D69B4FC3AF2F45B94B0FD0101FC3F35291D237F1DCB65EE124A6B963622729408C9A4CD1E5872664A5285FA74002E9669401DC598426BD47F45918D67ACBBDEBD20CB062F78BA848E0BA7F53EC20003A84D735713A0E69AA78A3234E5BE2A21BCA7E0DF9B7AD1B8DCD1D42787A1BF00C31B19250C1479C0F6A372C1464ADBE5B48F8114224902E92F2FBE643160BB8F01129E063AA421F88A829540D9A00AEA80433A755EFAFDFDA35D6760F3E270F25500124BB839A5B9C44856054C6D80BD5229AC2B40FA8A0CD44911629F295B11F08200, proofBlockHeight=109102798 )
  • NearProver.proveOutcome( proofData=0x040000009B484B3B0AF0BF63B510D6FB270C3B8C720C2A9A8F7FA2DA85785E820B4C1444012EE0A2B5DD3CC51F1A8B6C0724544B0C71E1A1F6CA99D60D2FC838C6FF8AC2B80097D48110DFA9AC7BF9372F8C8DFE9C6BDA1B5FB57D10F811E97C2AA4D7AF3F2E011AC44CE3520650BBD0BB4F3818D6EB4BDD5B68FBF6FE2CF66CAD92ED74F3FF5C002792D21308C1D9FA6EBAEE0BC5EA97BC44920F7C6D22A8712257E6CEB65045761DA07F39EA2D1A606594C61C5EB856A1F6F8F1087622448F845C5D55D71102740000000001000000854096901C8855C25AA309BA114D5E6F4B536181C2504848DB8EE5BCC58DD74610FBB1129E0200000010F903AB4CF2990F000000000000000B000000652D6E6561722E6E656172022500000000000000B658ECB8B8867CCB0000000000324594BDD150E359A2492C2E72533D67B6D1DB8502000000A76E094F6D4A01E6E1988071A3E2D0E474856ADF07EF5F040E51DDCF6A6F180101EB1319D7EE76EE4FAEBE65330345AC47A3F09DEAC3816E4C2D84C46D88E2F52100C958CEFB246970C467481374B08BC009032B8DB9304970BE5BC14492509F4C3A9F5673CC47680221925FE9F9BCB762D91FCE7BE69AAEC730D1366118DA30A906E7DF0D060000000034AA3210244E8E9B12F1ED8B9F977C79A89B88332945F461C83310C8DFF0CECBA32035A4844650D56479FB4FEEF009F390EA836B0EB2D3D26208F000E133280B9634E71ADB75478B74622B8F2374A7ACC08345855B345531F839A7D86C48AC6AE6199D0E4B1CABB4EB07A907769AEB6EABBD1CB7A04271DE8263E0BA7D79ED49048F9E6096B386171E2E9B784B27E69C7D3A19AB77A68A5FD821EB1AD862B4B723D6880DE8D77AC41BF835EBC8ACAF8934C7A8EF2654760D28604C824C86C044D6B78F9390DBFC9A1A000000C958CEFB246970C467481374B08BC009032B8DB9304970BE5BC14492509F4C3A0098E624597AE2754DDA9C4055B224E14CBC7EC8B983893F95FFC551AF289B155901869E87DC6A4D2AC9FD95C9AAFF291761327F8CD818E87212A0E1F55557AFB646010BA183D5E50A732D2B738831228E3779F911E45247055BEDF84C3DA2DF3EEB5601D96C00EAE74452F609706E39F5ED0AEBAE6828073AC2487DF71492D10B07F5FA00CC74A9749115AFED15EAD3221B837BD6621DC3750CD11934A38745082A335BEA0194A054D11C65F6749B46F7C5D7DCDF5CB3ED0014B2A852E89054FE48EB50D6E40062A3600EB24A5F7801A2E5749DAFBAED0F517BE9BDBFAF05C880BAF354FE495F016993966D521E3A284FD798A2079FF078B25CFF52B52A5F5227915A7F5EC998AD00126724B88F90CC7E4203D4FE3E4DFD47396A556494DD3CABF36102125B8996C901FEFCA491CC538FEA0A50FA8744EE03117139CB0D89192CF3772139790B04C33B013767495D76D7D63AD25DE81D32EAF0AD667B58FCA68228F614CECCE4B878F21A012FA6C573FE53C6906A19ABDFBCF1FFF5E5AFA2E5FF2224227DECC7972F7F587201A743AF799571EE2EDB7D672DFFA9A800821933554CAE16AD0F6BDD63D3556B990085DD4713BED410F1529E0783ADEE30201E7147949674A02E3F5B72ACEAB3D09D0060EA375F077DB92A3D850433AA90F86DEF6473D30471E5115ACDBED5AAA8729301CE61BEC753F0C2CFBDDF24D7CA7746C005203764A41CD596142D74E90C2B5F6001458B66EC0E6FDBEB0E468ADE434759EBE03964BE02C7066554DAE460362E067D01E872A35E49FAF05AB92AC3587CF43FE31CBABD69AF797C9F655BD45A6BF6024E0018423638584FC568F497B81094124A093B3DD30D0D69B4FC3AF2F45B94B0FD0101FC3F35291D237F1DCB65EE124A6B963622729408C9A4CD1E5872664A5285FA74002E9669401DC598426BD47F45918D67ACBBDEBD20CB062F78BA848E0BA7F53EC20003A84D735713A0E69AA78A3234E5BE2A21BCA7E0DF9B7AD1B8DCD1D42787A1BF00C31B19250C1479C0F6A372C1464ADBE5B48F8114224902E92F2FBE643160BB8F01129E063AA421F88A829540D9A00AEA80433A755EFAFDFDA35D6760F3E270F25500124BB839A5B9C44856054C6D80BD5229AC2B40FA8A0CD44911629F295B11F08200, blockHeight=109102798 ) => ( True )
    • Null: 0x000...002.01000000( )
    • Null: 0x000...002.02000000( )
    • Null: 0x000...002.e7df0d06( )
    • Null: 0x000...002.5a72a7f7( )
    • Null: 0x000...002.47fb831f( )
    • Null: 0x000...002.66a2c5ff( )
    • Null: 0x000...002.2ee0a2b5( )
    • Null: 0x000...002.472fc840( )
    • Null: 0x000...002.1ac44ce3( )
    • Null: 0x000...002.d2c76f0e( )
    • Null: 0x000...002.3ace4c85( )
    • Null: 0x000...002.eb1319d7( )
    • NearBridge.blockMerkleRoots( height=109102798 ) => ( res=BDCD8C698D888DDCC56E0E34503F8B958807AAEC73869A3C1FA86351BD05D737 )
    • Null: 0x000...002.c958cefb( )
    • Null: 0x000...002.c7e376be( )
    • Null: 0x000...002.8d97a235( )
    • Null: 0x000...002.28638247( )
    • Null: 0x000...002.d96c00ea( )
    • Null: 0x000...002.723e26dc( )
    • Null: 0x000...002.94a054d1( )
    • Null: 0x000...002.a36120e9( )
    • Null: 0x000...002.6993966d( )
    • Null: 0x000...002.3e378e1c( )
    • Null: 0x000...002.93a9e8f7( )
    • Null: 0x000...002.5ab780e5( )
    • Null: 0x000...002.e093c223( )
    • Null: 0x000...002.a743af79( )
    • Null: 0x000...002.85dd4713( )
    • Null: 0x000...002.ba548771( )
    • Null: 0x000...002.d31db069( )
    • Null: 0x000...002.085d54aa( )
    • Null: 0x000...002.e872a35e( )
    • Null: 0x000...002.0d663317( )
    • Null: 0x000...002.fc3f3529( )
    • Null: 0x000...002.2e966940( )
    • Null: 0x000...002.03a84d73( )
    • Null: 0x000...002.dc19deea( )
    • Null: 0x000...002.129e063a( )
    • Null: 0x000...002.124bb839( )
    • Null: 0x000...002.01000000( )
    • Null: 0x000...002.02000000( )
    • Null: 0x000...002.e7df0d06( )
    • Null: 0x000...002.5a72a7f7( )
    • Null: 0x000...002.47fb831f( )
      finaliseNearToEthTransfer[eNear (ln:43)]
      File 1 of 3: eNear
      // SPDX-License-Identifier: MIT
      pragma solidity 0.6.12;
      import "rainbow-bridge/contracts/eth/nearprover/contracts/ProofDecoder.sol";
      import "rainbow-bridge/contracts/eth/nearbridge/contracts/Borsh.sol";
      import "rainbow-bridge/contracts/eth/nearbridge/contracts/AdminControlled.sol";
      import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
      import { Bridge, INearProver } from "./Bridge.sol";
      contract eNear is ERC20, Bridge, AdminControlled {
          uint constant PAUSE_FINALISE_FROM_NEAR = 1 << 0;
          uint constant PAUSE_TRANSFER_TO_NEAR = 1 << 1;
          event TransferToNearInitiated (
              address indexed sender,
              uint256 amount,
              string accountId
          );
          event NearToEthTransferFinalised (
              uint128 amount,
              address indexed recipient
          );
          struct BridgeResult {
              uint128 amount;
              address recipient;
          }
          /// @param _tokenName Name given to the token (can be admin updated)
          /// @param _tokenSymbol Symbol given to the token (can be admin updated)
          /// @param _nearConnector Near account ID of the near connector bridge
          /// @param _prover Address of the prover contract on ETH
          /// @param _minBlockAcceptanceHeight The contract will accept proofs from this block onwards
          /// @param _admin Address that can make admin changes to the contract
          /// @param _pausedFlags Flag settings which controls whether certain methods are paused or active
          constructor(
              string memory _tokenName,
              string memory _tokenSymbol,
              bytes memory _nearConnector,
              INearProver _prover,
              uint64 _minBlockAcceptanceHeight,
              address _admin,
              uint256 _pausedFlags
          ) public ERC20(_tokenName, _tokenSymbol) AdminControlled(_admin, _pausedFlags) Bridge(_prover, _nearConnector, _minBlockAcceptanceHeight) {
              // Match yocto Near
              _setupDecimals(24);
          }
          function finaliseNearToEthTransfer(bytes memory proofData, uint64 proofBlockHeight)
          external pausable (PAUSE_FINALISE_FROM_NEAR) {
              ProofDecoder.ExecutionStatus memory status = _parseAndConsumeProof(proofData, proofBlockHeight);
              BridgeResult memory result = _decodeBridgeResult(status.successValue);
              _mint(result.recipient, result.amount);
              emit NearToEthTransferFinalised(result.amount, result.recipient);
          }
          function transferToNear(uint256 _amount, string memory _nearReceiverAccountId)
          external pausable (PAUSE_TRANSFER_TO_NEAR) {
              _burn(msg.sender, _amount);
              emit TransferToNearInitiated(msg.sender, _amount, _nearReceiverAccountId);
          }
          function _decodeBridgeResult(bytes memory data) internal pure returns(BridgeResult memory result) {
              Borsh.Data memory borshData = Borsh.from(data);
              uint8 flag = borshData.decodeU8();
              require(flag == 0, "ERR_NOT_WITHDRAW_RESULT");
              result.amount = borshData.decodeU128();
              bytes20 recipient = borshData.decodeBytes20();
              result.recipient = address(uint160(recipient));
          }
      }
      pragma solidity ^0.6;
      import "../../nearbridge/contracts/Borsh.sol";
      import "../../nearbridge/contracts/NearDecoder.sol";
      library ProofDecoder {
          using Borsh for Borsh.Data;
          using ProofDecoder for Borsh.Data;
          using NearDecoder for Borsh.Data;
          struct FullOutcomeProof {
              ExecutionOutcomeWithIdAndProof outcome_proof;
              MerklePath outcome_root_proof; // TODO: now empty array
              BlockHeaderLight block_header_lite;
              MerklePath block_proof;
          }
          function decodeFullOutcomeProof(Borsh.Data memory data) internal view returns (FullOutcomeProof memory proof) {
              proof.outcome_proof = data.decodeExecutionOutcomeWithIdAndProof();
              proof.outcome_root_proof = data.decodeMerklePath();
              proof.block_header_lite = data.decodeBlockHeaderLight();
              proof.block_proof = data.decodeMerklePath();
          }
          struct BlockHeaderLight {
              bytes32 prev_block_hash;
              bytes32 inner_rest_hash;
              NearDecoder.BlockHeaderInnerLite inner_lite;
              bytes32 hash; // Computable
          }
          function decodeBlockHeaderLight(Borsh.Data memory data) internal view returns (BlockHeaderLight memory header) {
              header.prev_block_hash = data.decodeBytes32();
              header.inner_rest_hash = data.decodeBytes32();
              header.inner_lite = data.decodeBlockHeaderInnerLite();
              header.hash = sha256(
                  abi.encodePacked(
                      sha256(abi.encodePacked(header.inner_lite.hash, header.inner_rest_hash)),
                      header.prev_block_hash
                  )
              );
          }
          struct ExecutionStatus {
              uint8 enumIndex;
              bool unknown;
              bool failed;
              bytes successValue; /// The final action succeeded and returned some value or an empty vec.
              bytes32 successReceiptId; /// The final action of the receipt returned a promise or the signed
              /// transaction was converted to a receipt. Contains the receipt_id of the generated receipt.
          }
          function decodeExecutionStatus(Borsh.Data memory data)
              internal
              pure
              returns (ExecutionStatus memory executionStatus)
          {
              executionStatus.enumIndex = data.decodeU8();
              if (executionStatus.enumIndex == 0) {
                  executionStatus.unknown = true;
              } else if (executionStatus.enumIndex == 1) {
                  //revert("NearDecoder: decodeExecutionStatus failure case not implemented yet");
                  // Can avoid revert since ExecutionStatus is latest field in all parent structures
                  executionStatus.failed = true;
              } else if (executionStatus.enumIndex == 2) {
                  executionStatus.successValue = data.decodeBytes();
              } else if (executionStatus.enumIndex == 3) {
                  executionStatus.successReceiptId = data.decodeBytes32();
              } else {
                  revert("NearDecoder: decodeExecutionStatus index out of range");
              }
          }
          struct ExecutionOutcome {
              bytes[] logs; /// Logs from this transaction or receipt.
              bytes32[] receipt_ids; /// Receipt IDs generated by this transaction or receipt.
              uint64 gas_burnt; /// The amount of the gas burnt by the given transaction or receipt.
              uint128 tokens_burnt; /// The total number of the tokens burnt by the given transaction or receipt.
              bytes executor_id; /// Hash of the transaction or receipt id that produced this outcome.
              ExecutionStatus status; /// Execution status. Contains the result in case of successful execution.
              bytes32[] merkelization_hashes;
          }
          function decodeExecutionOutcome(Borsh.Data memory data) internal view returns (ExecutionOutcome memory outcome) {
              outcome.logs = new bytes[](data.decodeU32());
              for (uint i = 0; i < outcome.logs.length; i++) {
                  outcome.logs[i] = data.decodeBytes();
              }
              uint256 start = data.offset;
              outcome.receipt_ids = new bytes32[](data.decodeU32());
              for (uint i = 0; i < outcome.receipt_ids.length; i++) {
                  outcome.receipt_ids[i] = data.decodeBytes32();
              }
              outcome.gas_burnt = data.decodeU64();
              outcome.tokens_burnt = data.decodeU128();
              outcome.executor_id = data.decodeBytes();
              outcome.status = data.decodeExecutionStatus();
              uint256 stop = data.offset;
              outcome.merkelization_hashes = new bytes32[](1 + outcome.logs.length);
              data.offset = start;
              outcome.merkelization_hashes[0] = data.peekSha256(stop - start);
              data.offset = stop;
              for (uint i = 0; i < outcome.logs.length; i++) {
                  outcome.merkelization_hashes[i + 1] = sha256(outcome.logs[i]);
              }
          }
          struct ExecutionOutcomeWithId {
              bytes32 id; /// The transaction hash or the receipt ID.
              ExecutionOutcome outcome;
              bytes32 hash;
          }
          function decodeExecutionOutcomeWithId(Borsh.Data memory data)
              internal
              view
              returns (ExecutionOutcomeWithId memory outcome)
          {
              outcome.id = data.decodeBytes32();
              outcome.outcome = data.decodeExecutionOutcome();
              uint256 len = 1 + outcome.outcome.merkelization_hashes.length;
              outcome.hash = sha256(
                  abi.encodePacked(
                      uint8((len >> 0) & 0xFF),
                      uint8((len >> 8) & 0xFF),
                      uint8((len >> 16) & 0xFF),
                      uint8((len >> 24) & 0xFF),
                      outcome.id,
                      outcome.outcome.merkelization_hashes
                  )
              );
          }
          struct MerklePathItem {
              bytes32 hash;
              uint8 direction; // 0 = left, 1 = right
          }
          function decodeMerklePathItem(Borsh.Data memory data) internal pure returns (MerklePathItem memory item) {
              item.hash = data.decodeBytes32();
              item.direction = data.decodeU8();
              require(item.direction < 2, "ProofDecoder: MerklePathItem direction should be 0 or 1");
          }
          struct MerklePath {
              MerklePathItem[] items;
          }
          function decodeMerklePath(Borsh.Data memory data) internal pure returns (MerklePath memory path) {
              path.items = new MerklePathItem[](data.decodeU32());
              for (uint i = 0; i < path.items.length; i++) {
                  path.items[i] = data.decodeMerklePathItem();
              }
          }
          struct ExecutionOutcomeWithIdAndProof {
              MerklePath proof;
              bytes32 block_hash;
              ExecutionOutcomeWithId outcome_with_id;
          }
          function decodeExecutionOutcomeWithIdAndProof(Borsh.Data memory data)
              internal
              view
              returns (ExecutionOutcomeWithIdAndProof memory outcome)
          {
              outcome.proof = data.decodeMerklePath();
              outcome.block_hash = data.decodeBytes32();
              outcome.outcome_with_id = data.decodeExecutionOutcomeWithId();
          }
      }
      pragma solidity ^0.6;
      import "@openzeppelin/contracts/math/SafeMath.sol";
      library Borsh {
          using SafeMath for uint256;
          struct Data {
              uint256 offset;
              bytes raw;
          }
          function from(bytes memory data) internal pure returns (Data memory) {
              return Data({offset: 0, raw: data});
          }
          modifier shift(Data memory data, uint256 size) {
              require(data.raw.length >= data.offset + size, "Borsh: Out of range");
              _;
              data.offset += size;
          }
          function finished(Data memory data) internal pure returns (bool) {
              return data.offset == data.raw.length;
          }
          function peekKeccak256(Data memory data, uint256 length) internal pure returns (bytes32 res) {
              return bytesKeccak256(data.raw, data.offset, length);
          }
          function bytesKeccak256(
              bytes memory ptr,
              uint256 offset,
              uint256 length
          ) internal pure returns (bytes32 res) {
              // solium-disable-next-line security/no-inline-assembly
              assembly {
                  res := keccak256(add(add(ptr, 32), offset), length)
              }
          }
          function peekSha256(Data memory data, uint256 length) internal view returns (bytes32) {
              return bytesSha256(data.raw, data.offset, length);
          }
          function bytesSha256(
              bytes memory ptr,
              uint256 offset,
              uint256 length
          ) internal view returns (bytes32) {
              bytes32[1] memory result;
              // solium-disable-next-line security/no-inline-assembly
              assembly {
                  pop(staticcall(gas(), 0x02, add(add(ptr, 32), offset), length, result, 32))
              }
              return result[0];
          }
          function decodeU8(Data memory data) internal pure shift(data, 1) returns (uint8 value) {
              value = uint8(data.raw[data.offset]);
          }
          function decodeI8(Data memory data) internal pure shift(data, 1) returns (int8 value) {
              value = int8(data.raw[data.offset]);
          }
          function decodeU16(Data memory data) internal pure returns (uint16 value) {
              value = uint16(decodeU8(data));
              value |= (uint16(decodeU8(data)) << 8);
          }
          function decodeI16(Data memory data) internal pure returns (int16 value) {
              value = int16(decodeI8(data));
              value |= (int16(decodeI8(data)) << 8);
          }
          function decodeU32(Data memory data) internal pure returns (uint32 value) {
              value = uint32(decodeU16(data));
              value |= (uint32(decodeU16(data)) << 16);
          }
          function decodeI32(Data memory data) internal pure returns (int32 value) {
              value = int32(decodeI16(data));
              value |= (int32(decodeI16(data)) << 16);
          }
          function decodeU64(Data memory data) internal pure returns (uint64 value) {
              value = uint64(decodeU32(data));
              value |= (uint64(decodeU32(data)) << 32);
          }
          function decodeI64(Data memory data) internal pure returns (int64 value) {
              value = int64(decodeI32(data));
              value |= (int64(decodeI32(data)) << 32);
          }
          function decodeU128(Data memory data) internal pure returns (uint128 value) {
              value = uint128(decodeU64(data));
              value |= (uint128(decodeU64(data)) << 64);
          }
          function decodeI128(Data memory data) internal pure returns (int128 value) {
              value = int128(decodeI64(data));
              value |= (int128(decodeI64(data)) << 64);
          }
          function decodeU256(Data memory data) internal pure returns (uint256 value) {
              value = uint256(decodeU128(data));
              value |= (uint256(decodeU128(data)) << 128);
          }
          function decodeI256(Data memory data) internal pure returns (int256 value) {
              value = int256(decodeI128(data));
              value |= (int256(decodeI128(data)) << 128);
          }
          function decodeBool(Data memory data) internal pure returns (bool value) {
              value = (decodeU8(data) != 0);
          }
          function decodeBytes(Data memory data) internal pure returns (bytes memory value) {
              value = new bytes(decodeU32(data));
              for (uint i = 0; i < value.length; i++) {
                  value[i] = byte(decodeU8(data));
              }
          }
          function decodeBytes32(Data memory data) internal pure shift(data, 32) returns (bytes32 value) {
              bytes memory raw = data.raw;
              uint256 offset = data.offset;
              // solium-disable-next-line security/no-inline-assembly
              assembly {
                  value := mload(add(add(raw, 32), offset))
              }
          }
          function decodeBytes20(Data memory data) internal pure returns (bytes20 value) {
              for (uint i = 0; i < 20; i++) {
                  value |= bytes20(byte(decodeU8(data)) & 0xFF) >> (i * 8);
              }
          }
          // Public key
          struct SECP256K1PublicKey {
              uint256 x;
              uint256 y;
          }
          function decodeSECP256K1PublicKey(Borsh.Data memory data) internal pure returns (SECP256K1PublicKey memory key) {
              key.x = decodeU256(data);
              key.y = decodeU256(data);
          }
          struct ED25519PublicKey {
              bytes32 xy;
          }
          function decodeED25519PublicKey(Borsh.Data memory data) internal pure returns (ED25519PublicKey memory key) {
              key.xy = decodeBytes32(data);
          }
          // Signature
          struct SECP256K1Signature {
              bytes32 r;
              bytes32 s;
              uint8 v;
          }
          function decodeSECP256K1Signature(Borsh.Data memory data) internal pure returns (SECP256K1Signature memory sig) {
              sig.r = decodeBytes32(data);
              sig.s = decodeBytes32(data);
              sig.v = decodeU8(data);
          }
          struct ED25519Signature {
              bytes32[2] rs;
          }
          function decodeED25519Signature(Borsh.Data memory data) internal pure returns (ED25519Signature memory sig) {
              sig.rs[0] = decodeBytes32(data);
              sig.rs[1] = decodeBytes32(data);
          }
      }
      pragma solidity ^0.6;
      contract AdminControlled {
          address public admin;
          uint public paused;
          constructor(address _admin, uint flags) public {
              admin = _admin;
              // Add the possibility to set pause flags on the initialization
              paused = flags;
          }
          modifier onlyAdmin {
              require(msg.sender == admin);
              _;
          }
          modifier pausable(uint flag) {
              require((paused & flag) == 0 || msg.sender == admin);
              _;
          }
          function adminPause(uint flags) public onlyAdmin {
              paused = flags;
          }
          function adminSstore(uint key, uint value) public onlyAdmin {
              assembly {
                  sstore(key, value)
              }
          }
          function adminSendEth(address payable destination, uint amount) public onlyAdmin {
              destination.transfer(amount);
          }
          function adminReceiveEth() public payable onlyAdmin {}
          function adminDelegatecall(address target, bytes memory data) public payable onlyAdmin returns (bytes memory) {
              (bool success, bytes memory rdata) = target.delegatecall(data);
              require(success);
              return rdata;
          }
      }
      // SPDX-License-Identifier: MIT
      pragma solidity >=0.6.0 <0.8.0;
      import "../../utils/Context.sol";
      import "./IERC20.sol";
      import "../../math/SafeMath.sol";
      /**
       * @dev Implementation of the {IERC20} interface.
       *
       * This implementation is agnostic to the way tokens are created. This means
       * that a supply mechanism has to be added in a derived contract using {_mint}.
       * For a generic mechanism see {ERC20PresetMinterPauser}.
       *
       * TIP: For a detailed writeup see our guide
       * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How
       * to implement supply mechanisms].
       *
       * We have followed general OpenZeppelin guidelines: functions revert instead
       * of returning `false` on failure. This behavior is nonetheless conventional
       * and does not conflict with the expectations of ERC20 applications.
       *
       * Additionally, an {Approval} event is emitted on calls to {transferFrom}.
       * This allows applications to reconstruct the allowance for all accounts just
       * by listening to said events. Other implementations of the EIP may not emit
       * these events, as it isn't required by the specification.
       *
       * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}
       * functions have been added to mitigate the well-known issues around setting
       * allowances. See {IERC20-approve}.
       */
      contract ERC20 is Context, IERC20 {
          using SafeMath for uint256;
          mapping (address => uint256) private _balances;
          mapping (address => mapping (address => uint256)) private _allowances;
          uint256 private _totalSupply;
          string private _name;
          string private _symbol;
          uint8 private _decimals;
          /**
           * @dev Sets the values for {name} and {symbol}, initializes {decimals} with
           * a default value of 18.
           *
           * To select a different value for {decimals}, use {_setupDecimals}.
           *
           * All three of these values are immutable: they can only be set once during
           * construction.
           */
          constructor (string memory name_, string memory symbol_) public {
              _name = name_;
              _symbol = symbol_;
              _decimals = 18;
          }
          /**
           * @dev Returns the name of the token.
           */
          function name() public view virtual returns (string memory) {
              return _name;
          }
          /**
           * @dev Returns the symbol of the token, usually a shorter version of the
           * name.
           */
          function symbol() public view virtual returns (string memory) {
              return _symbol;
          }
          /**
           * @dev Returns the number of decimals used to get its user representation.
           * For example, if `decimals` equals `2`, a balance of `505` tokens should
           * be displayed to a user as `5,05` (`505 / 10 ** 2`).
           *
           * Tokens usually opt for a value of 18, imitating the relationship between
           * Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is
           * called.
           *
           * NOTE: This information is only used for _display_ purposes: it in
           * no way affects any of the arithmetic of the contract, including
           * {IERC20-balanceOf} and {IERC20-transfer}.
           */
          function decimals() public view virtual returns (uint8) {
              return _decimals;
          }
          /**
           * @dev See {IERC20-totalSupply}.
           */
          function totalSupply() public view virtual override returns (uint256) {
              return _totalSupply;
          }
          /**
           * @dev See {IERC20-balanceOf}.
           */
          function balanceOf(address account) public view virtual override returns (uint256) {
              return _balances[account];
          }
          /**
           * @dev See {IERC20-transfer}.
           *
           * Requirements:
           *
           * - `recipient` cannot be the zero address.
           * - the caller must have a balance of at least `amount`.
           */
          function transfer(address recipient, uint256 amount) public virtual override returns (bool) {
              _transfer(_msgSender(), recipient, amount);
              return true;
          }
          /**
           * @dev See {IERC20-allowance}.
           */
          function allowance(address owner, address spender) public view virtual override returns (uint256) {
              return _allowances[owner][spender];
          }
          /**
           * @dev See {IERC20-approve}.
           *
           * Requirements:
           *
           * - `spender` cannot be the zero address.
           */
          function approve(address spender, uint256 amount) public virtual override returns (bool) {
              _approve(_msgSender(), spender, amount);
              return true;
          }
          /**
           * @dev See {IERC20-transferFrom}.
           *
           * Emits an {Approval} event indicating the updated allowance. This is not
           * required by the EIP. See the note at the beginning of {ERC20}.
           *
           * Requirements:
           *
           * - `sender` and `recipient` cannot be the zero address.
           * - `sender` must have a balance of at least `amount`.
           * - the caller must have allowance for ``sender``'s tokens of at least
           * `amount`.
           */
          function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {
              _transfer(sender, recipient, amount);
              _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance"));
              return true;
          }
          /**
           * @dev Atomically increases the allowance granted to `spender` by the caller.
           *
           * This is an alternative to {approve} that can be used as a mitigation for
           * problems described in {IERC20-approve}.
           *
           * Emits an {Approval} event indicating the updated allowance.
           *
           * Requirements:
           *
           * - `spender` cannot be the zero address.
           */
          function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
              _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue));
              return true;
          }
          /**
           * @dev Atomically decreases the allowance granted to `spender` by the caller.
           *
           * This is an alternative to {approve} that can be used as a mitigation for
           * problems described in {IERC20-approve}.
           *
           * Emits an {Approval} event indicating the updated allowance.
           *
           * Requirements:
           *
           * - `spender` cannot be the zero address.
           * - `spender` must have allowance for the caller of at least
           * `subtractedValue`.
           */
          function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
              _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero"));
              return true;
          }
          /**
           * @dev Moves tokens `amount` from `sender` to `recipient`.
           *
           * This is internal function is equivalent to {transfer}, and can be used to
           * e.g. implement automatic token fees, slashing mechanisms, etc.
           *
           * Emits a {Transfer} event.
           *
           * Requirements:
           *
           * - `sender` cannot be the zero address.
           * - `recipient` cannot be the zero address.
           * - `sender` must have a balance of at least `amount`.
           */
          function _transfer(address sender, address recipient, uint256 amount) internal virtual {
              require(sender != address(0), "ERC20: transfer from the zero address");
              require(recipient != address(0), "ERC20: transfer to the zero address");
              _beforeTokenTransfer(sender, recipient, amount);
              _balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance");
              _balances[recipient] = _balances[recipient].add(amount);
              emit Transfer(sender, recipient, amount);
          }
          /** @dev Creates `amount` tokens and assigns them to `account`, increasing
           * the total supply.
           *
           * Emits a {Transfer} event with `from` set to the zero address.
           *
           * Requirements:
           *
           * - `to` cannot be the zero address.
           */
          function _mint(address account, uint256 amount) internal virtual {
              require(account != address(0), "ERC20: mint to the zero address");
              _beforeTokenTransfer(address(0), account, amount);
              _totalSupply = _totalSupply.add(amount);
              _balances[account] = _balances[account].add(amount);
              emit Transfer(address(0), account, amount);
          }
          /**
           * @dev Destroys `amount` tokens from `account`, reducing the
           * total supply.
           *
           * Emits a {Transfer} event with `to` set to the zero address.
           *
           * Requirements:
           *
           * - `account` cannot be the zero address.
           * - `account` must have at least `amount` tokens.
           */
          function _burn(address account, uint256 amount) internal virtual {
              require(account != address(0), "ERC20: burn from the zero address");
              _beforeTokenTransfer(account, address(0), amount);
              _balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance");
              _totalSupply = _totalSupply.sub(amount);
              emit Transfer(account, address(0), amount);
          }
          /**
           * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.
           *
           * This internal function is equivalent to `approve`, and can be used to
           * e.g. set automatic allowances for certain subsystems, etc.
           *
           * Emits an {Approval} event.
           *
           * Requirements:
           *
           * - `owner` cannot be the zero address.
           * - `spender` cannot be the zero address.
           */
          function _approve(address owner, address spender, uint256 amount) internal virtual {
              require(owner != address(0), "ERC20: approve from the zero address");
              require(spender != address(0), "ERC20: approve to the zero address");
              _allowances[owner][spender] = amount;
              emit Approval(owner, spender, amount);
          }
          /**
           * @dev Sets {decimals} to a value other than the default one of 18.
           *
           * WARNING: This function should only be called from the constructor. Most
           * applications that interact with token contracts will not expect
           * {decimals} to ever change, and may work incorrectly if it does.
           */
          function _setupDecimals(uint8 decimals_) internal virtual {
              _decimals = decimals_;
          }
          /**
           * @dev Hook that is called before any transfer of tokens. This includes
           * minting and burning.
           *
           * Calling conditions:
           *
           * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
           * will be to transferred to `to`.
           * - when `from` is zero, `amount` tokens will be minted for `to`.
           * - when `to` is zero, `amount` of ``from``'s tokens will be burned.
           * - `from` and `to` are never both zero.
           *
           * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
           */
          function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { }
      }
      // SPDX-License-Identifier: MIT
      pragma solidity 0.6.12;
      import "rainbow-bridge/contracts/eth/nearprover/contracts/INearProver.sol";
      import "rainbow-bridge/contracts/eth/nearprover/contracts/ProofDecoder.sol";
      import "rainbow-bridge/contracts/eth/nearbridge/contracts/Borsh.sol";
      contract Bridge {
          using Borsh for Borsh.Data;
          using ProofDecoder for Borsh.Data;
          event ConsumedProof(bytes32 indexed _receiptId);
          INearProver public prover;
          bytes public nearConnector;
          /// Proofs from blocks that are below the acceptance height will be rejected.
          // If `minBlockAcceptanceHeight` value is zero - proofs from block with any height are accepted.
          uint64 public minBlockAcceptanceHeight;
          // OutcomeRecieptId -> Used
          mapping(bytes32 => bool) public usedProofs;
          constructor(INearProver _prover, bytes memory _nearConnector, uint64 _minBlockAcceptanceHeight) public {
              prover = _prover;
              nearConnector = _nearConnector;
              minBlockAcceptanceHeight = _minBlockAcceptanceHeight;
          }
          /// Parses the provided proof and consumes it if it's not already used.
          /// The consumed event cannot be reused for future calls.
          function _parseAndConsumeProof(bytes memory proofData, uint64 proofBlockHeight)
          internal
          returns (ProofDecoder.ExecutionStatus memory result)
          {
              require(prover.proveOutcome(proofData, proofBlockHeight), "Proof should be valid");
              // Unpack the proof and extract the execution outcome.
              Borsh.Data memory borshData = Borsh.from(proofData);
              ProofDecoder.FullOutcomeProof memory fullOutcomeProof = borshData.decodeFullOutcomeProof();
              require(
                  fullOutcomeProof.block_header_lite.inner_lite.height >= minBlockAcceptanceHeight,
                  "Proof is from the ancient block"
              );
              require(borshData.finished(), "Argument should be exact borsh serialization");
              bytes32 receiptId = fullOutcomeProof.outcome_proof.outcome_with_id.outcome.receipt_ids[0];
              require(!usedProofs[receiptId], "The burn event proof cannot be reused");
              usedProofs[receiptId] = true;
              require(keccak256(fullOutcomeProof.outcome_proof.outcome_with_id.outcome.executor_id)
                  == keccak256(nearConnector),
                  "Can only unlock tokens from the linked proof producer on Near blockchain");
              result = fullOutcomeProof.outcome_proof.outcome_with_id.outcome.status;
              require(!result.failed, "Cannot use failed execution outcome for unlocking the tokens");
              require(!result.unknown, "Cannot use unknown execution outcome for unlocking the tokens");
              emit ConsumedProof(receiptId);
          }
      }
      pragma solidity ^0.6;
      import "@openzeppelin/contracts/math/SafeMath.sol";
      import "./Borsh.sol";
      library NearDecoder {
          using Borsh for Borsh.Data;
          using NearDecoder for Borsh.Data;
          struct PublicKey {
              uint8 enumIndex;
              Borsh.ED25519PublicKey ed25519;
              Borsh.SECP256K1PublicKey secp256k1;
          }
          function decodePublicKey(Borsh.Data memory data) internal pure returns (PublicKey memory key) {
              key.enumIndex = data.decodeU8();
              if (key.enumIndex == 0) {
                  key.ed25519 = data.decodeED25519PublicKey();
              } else if (key.enumIndex == 1) {
                  key.secp256k1 = data.decodeSECP256K1PublicKey();
              } else {
                  revert("NearBridge: Only ED25519 and SECP256K1 public keys are supported");
              }
          }
          struct ValidatorStake {
              string account_id;
              PublicKey public_key;
              uint128 stake;
          }
          function decodeValidatorStake(Borsh.Data memory data) internal pure returns (ValidatorStake memory validatorStake) {
              validatorStake.account_id = string(data.decodeBytes());
              validatorStake.public_key = data.decodePublicKey();
              validatorStake.stake = data.decodeU128();
          }
          struct OptionalValidatorStakes {
              bool none;
              ValidatorStake[] validatorStakes;
              bytes32 hash; // Additional computable element
          }
          function decodeOptionalValidatorStakes(Borsh.Data memory data)
              internal
              view
              returns (OptionalValidatorStakes memory stakes)
          {
              stakes.none = (data.decodeU8() == 0);
              if (!stakes.none) {
                  uint256 start = data.offset;
                  stakes.validatorStakes = new ValidatorStake[](data.decodeU32());
                  for (uint i = 0; i < stakes.validatorStakes.length; i++) {
                      stakes.validatorStakes[i] = data.decodeValidatorStake();
                  }
                  uint256 stop = data.offset;
                  data.offset = start;
                  stakes.hash = data.peekSha256(stop - start);
                  data.offset = stop;
              }
          }
          struct Signature {
              uint8 enumIndex;
              Borsh.ED25519Signature ed25519;
              Borsh.SECP256K1Signature secp256k1;
          }
          function decodeSignature(Borsh.Data memory data) internal pure returns (Signature memory sig) {
              sig.enumIndex = data.decodeU8();
              if (sig.enumIndex == 0) {
                  sig.ed25519 = data.decodeED25519Signature();
              } else if (sig.enumIndex == 1) {
                  sig.secp256k1 = data.decodeSECP256K1Signature();
              } else {
                  revert("NearBridge: Only ED25519 and SECP256K1 signatures are supported");
              }
          }
          struct OptionalSignature {
              bool none;
              Signature signature;
          }
          function decodeOptionalSignature(Borsh.Data memory data) internal pure returns (OptionalSignature memory sig) {
              sig.none = (data.decodeU8() == 0);
              if (!sig.none) {
                  sig.signature = data.decodeSignature();
              }
          }
          struct LightClientBlock {
              bytes32 prev_block_hash;
              bytes32 next_block_inner_hash;
              BlockHeaderInnerLite inner_lite;
              bytes32 inner_rest_hash;
              OptionalValidatorStakes next_bps;
              OptionalSignature[] approvals_after_next;
              bytes32 hash;
              bytes32 next_hash;
          }
          struct InitialValidators {
              ValidatorStake[] validator_stakes;
          }
          function decodeInitialValidators(Borsh.Data memory data)
              internal
              view
              returns (InitialValidators memory validators)
          {
              validators.validator_stakes = new ValidatorStake[](data.decodeU32());
              for (uint i = 0; i < validators.validator_stakes.length; i++) {
                  validators.validator_stakes[i] = data.decodeValidatorStake();
              }
          }
          function decodeLightClientBlock(Borsh.Data memory data) internal view returns (LightClientBlock memory header) {
              header.prev_block_hash = data.decodeBytes32();
              header.next_block_inner_hash = data.decodeBytes32();
              header.inner_lite = data.decodeBlockHeaderInnerLite();
              header.inner_rest_hash = data.decodeBytes32();
              header.next_bps = data.decodeOptionalValidatorStakes();
              header.approvals_after_next = new OptionalSignature[](data.decodeU32());
              for (uint i = 0; i < header.approvals_after_next.length; i++) {
                  header.approvals_after_next[i] = data.decodeOptionalSignature();
              }
              header.hash = sha256(
                  abi.encodePacked(
                      sha256(abi.encodePacked(header.inner_lite.hash, header.inner_rest_hash)),
                      header.prev_block_hash
                  )
              );
              header.next_hash = sha256(abi.encodePacked(header.next_block_inner_hash, header.hash));
          }
          struct BlockHeaderInnerLite {
              uint64 height; /// Height of this block since the genesis block (height 0).
              bytes32 epoch_id; /// Epoch start hash of this block's epoch. Used for retrieving validator information
              bytes32 next_epoch_id;
              bytes32 prev_state_root; /// Root hash of the state at the previous block.
              bytes32 outcome_root; /// Root of the outcomes of transactions and receipts.
              uint64 timestamp; /// Timestamp at which the block was built.
              bytes32 next_bp_hash; /// Hash of the next epoch block producers set
              bytes32 block_merkle_root;
              bytes32 hash; // Additional computable element
          }
          function decodeBlockHeaderInnerLite(Borsh.Data memory data)
              internal
              view
              returns (BlockHeaderInnerLite memory header)
          {
              header.hash = data.peekSha256(208);
              header.height = data.decodeU64();
              header.epoch_id = data.decodeBytes32();
              header.next_epoch_id = data.decodeBytes32();
              header.prev_state_root = data.decodeBytes32();
              header.outcome_root = data.decodeBytes32();
              header.timestamp = data.decodeU64();
              header.next_bp_hash = data.decodeBytes32();
              header.block_merkle_root = data.decodeBytes32();
          }
      }
      // SPDX-License-Identifier: MIT
      pragma solidity >=0.6.0 <0.8.0;
      /**
       * @dev Wrappers over Solidity's arithmetic operations with added overflow
       * checks.
       *
       * Arithmetic operations in Solidity wrap on overflow. This can easily result
       * in bugs, because programmers usually assume that an overflow raises an
       * error, which is the standard behavior in high level programming languages.
       * `SafeMath` restores this intuition by reverting the transaction when an
       * operation overflows.
       *
       * Using this library instead of the unchecked operations eliminates an entire
       * class of bugs, so it's recommended to use it always.
       */
      library SafeMath {
          /**
           * @dev Returns the addition of two unsigned integers, with an overflow flag.
           *
           * _Available since v3.4._
           */
          function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
              uint256 c = a + b;
              if (c < a) return (false, 0);
              return (true, c);
          }
          /**
           * @dev Returns the substraction of two unsigned integers, with an overflow flag.
           *
           * _Available since v3.4._
           */
          function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
              if (b > a) return (false, 0);
              return (true, a - b);
          }
          /**
           * @dev Returns the multiplication of two unsigned integers, with an overflow flag.
           *
           * _Available since v3.4._
           */
          function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
              // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
              // benefit is lost if 'b' is also tested.
              // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
              if (a == 0) return (true, 0);
              uint256 c = a * b;
              if (c / a != b) return (false, 0);
              return (true, c);
          }
          /**
           * @dev Returns the division of two unsigned integers, with a division by zero flag.
           *
           * _Available since v3.4._
           */
          function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
              if (b == 0) return (false, 0);
              return (true, a / b);
          }
          /**
           * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
           *
           * _Available since v3.4._
           */
          function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
              if (b == 0) return (false, 0);
              return (true, a % b);
          }
          /**
           * @dev Returns the addition of two unsigned integers, reverting on
           * overflow.
           *
           * Counterpart to Solidity's `+` operator.
           *
           * Requirements:
           *
           * - Addition cannot overflow.
           */
          function add(uint256 a, uint256 b) internal pure returns (uint256) {
              uint256 c = a + b;
              require(c >= a, "SafeMath: addition overflow");
              return c;
          }
          /**
           * @dev Returns the subtraction of two unsigned integers, reverting on
           * overflow (when the result is negative).
           *
           * Counterpart to Solidity's `-` operator.
           *
           * Requirements:
           *
           * - Subtraction cannot overflow.
           */
          function sub(uint256 a, uint256 b) internal pure returns (uint256) {
              require(b <= a, "SafeMath: subtraction overflow");
              return a - b;
          }
          /**
           * @dev Returns the multiplication of two unsigned integers, reverting on
           * overflow.
           *
           * Counterpart to Solidity's `*` operator.
           *
           * Requirements:
           *
           * - Multiplication cannot overflow.
           */
          function mul(uint256 a, uint256 b) internal pure returns (uint256) {
              if (a == 0) return 0;
              uint256 c = a * b;
              require(c / a == b, "SafeMath: multiplication overflow");
              return c;
          }
          /**
           * @dev Returns the integer division of two unsigned integers, reverting on
           * division by zero. The result is rounded towards zero.
           *
           * Counterpart to Solidity's `/` operator. Note: this function uses a
           * `revert` opcode (which leaves remaining gas untouched) while Solidity
           * uses an invalid opcode to revert (consuming all remaining gas).
           *
           * Requirements:
           *
           * - The divisor cannot be zero.
           */
          function div(uint256 a, uint256 b) internal pure returns (uint256) {
              require(b > 0, "SafeMath: division by zero");
              return a / b;
          }
          /**
           * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
           * reverting when dividing by zero.
           *
           * Counterpart to Solidity's `%` operator. This function uses a `revert`
           * opcode (which leaves remaining gas untouched) while Solidity uses an
           * invalid opcode to revert (consuming all remaining gas).
           *
           * Requirements:
           *
           * - The divisor cannot be zero.
           */
          function mod(uint256 a, uint256 b) internal pure returns (uint256) {
              require(b > 0, "SafeMath: modulo by zero");
              return a % b;
          }
          /**
           * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
           * overflow (when the result is negative).
           *
           * CAUTION: This function is deprecated because it requires allocating memory for the error
           * message unnecessarily. For custom revert reasons use {trySub}.
           *
           * Counterpart to Solidity's `-` operator.
           *
           * Requirements:
           *
           * - Subtraction cannot overflow.
           */
          function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
              require(b <= a, errorMessage);
              return a - b;
          }
          /**
           * @dev Returns the integer division of two unsigned integers, reverting with custom message on
           * division by zero. The result is rounded towards zero.
           *
           * CAUTION: This function is deprecated because it requires allocating memory for the error
           * message unnecessarily. For custom revert reasons use {tryDiv}.
           *
           * Counterpart to Solidity's `/` operator. Note: this function uses a
           * `revert` opcode (which leaves remaining gas untouched) while Solidity
           * uses an invalid opcode to revert (consuming all remaining gas).
           *
           * Requirements:
           *
           * - The divisor cannot be zero.
           */
          function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
              require(b > 0, errorMessage);
              return a / b;
          }
          /**
           * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
           * reverting with custom message when dividing by zero.
           *
           * CAUTION: This function is deprecated because it requires allocating memory for the error
           * message unnecessarily. For custom revert reasons use {tryMod}.
           *
           * Counterpart to Solidity's `%` operator. This function uses a `revert`
           * opcode (which leaves remaining gas untouched) while Solidity uses an
           * invalid opcode to revert (consuming all remaining gas).
           *
           * Requirements:
           *
           * - The divisor cannot be zero.
           */
          function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
              require(b > 0, errorMessage);
              return a % b;
          }
      }
      // SPDX-License-Identifier: MIT
      pragma solidity >=0.6.0 <0.8.0;
      /*
       * @dev Provides information about the current execution context, including the
       * sender of the transaction and its data. While these are generally available
       * via msg.sender and msg.data, they should not be accessed in such a direct
       * manner, since when dealing with GSN meta-transactions the account sending and
       * paying for execution may not be the actual sender (as far as an application
       * is concerned).
       *
       * This contract is only required for intermediate, library-like contracts.
       */
      abstract contract Context {
          function _msgSender() internal view virtual returns (address payable) {
              return msg.sender;
          }
          function _msgData() internal view virtual returns (bytes memory) {
              this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
              return msg.data;
          }
      }
      // SPDX-License-Identifier: MIT
      pragma solidity >=0.6.0 <0.8.0;
      /**
       * @dev Interface of the ERC20 standard as defined in the EIP.
       */
      interface IERC20 {
          /**
           * @dev Returns the amount of tokens in existence.
           */
          function totalSupply() external view returns (uint256);
          /**
           * @dev Returns the amount of tokens owned by `account`.
           */
          function balanceOf(address account) external view returns (uint256);
          /**
           * @dev Moves `amount` tokens from the caller's account to `recipient`.
           *
           * Returns a boolean value indicating whether the operation succeeded.
           *
           * Emits a {Transfer} event.
           */
          function transfer(address recipient, uint256 amount) external returns (bool);
          /**
           * @dev Returns the remaining number of tokens that `spender` will be
           * allowed to spend on behalf of `owner` through {transferFrom}. This is
           * zero by default.
           *
           * This value changes when {approve} or {transferFrom} are called.
           */
          function allowance(address owner, address spender) external view returns (uint256);
          /**
           * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
           *
           * Returns a boolean value indicating whether the operation succeeded.
           *
           * IMPORTANT: Beware that changing an allowance with this method brings the risk
           * that someone may use both the old and the new allowance by unfortunate
           * transaction ordering. One possible solution to mitigate this race
           * condition is to first reduce the spender's allowance to 0 and set the
           * desired value afterwards:
           * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
           *
           * Emits an {Approval} event.
           */
          function approve(address spender, uint256 amount) external returns (bool);
          /**
           * @dev Moves `amount` tokens from `sender` to `recipient` using the
           * allowance mechanism. `amount` is then deducted from the caller's
           * allowance.
           *
           * Returns a boolean value indicating whether the operation succeeded.
           *
           * Emits a {Transfer} event.
           */
          function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
          /**
           * @dev Emitted when `value` tokens are moved from one account (`from`) to
           * another (`to`).
           *
           * Note that `value` may be zero.
           */
          event Transfer(address indexed from, address indexed to, uint256 value);
          /**
           * @dev Emitted when the allowance of a `spender` for an `owner` is set by
           * a call to {approve}. `value` is the new allowance.
           */
          event Approval(address indexed owner, address indexed spender, uint256 value);
      }
      pragma solidity ^0.6;
      interface INearProver {
          function proveOutcome(bytes calldata proofData, uint64 blockHeight) external view returns (bool);
      }
      

      File 2 of 3: NearProver
      // File: @openzeppelin/contracts/math/SafeMath.sol
      
      
      pragma solidity >=0.6.0 <0.8.0;
      
      /**
       * @dev Wrappers over Solidity's arithmetic operations with added overflow
       * checks.
       *
       * Arithmetic operations in Solidity wrap on overflow. This can easily result
       * in bugs, because programmers usually assume that an overflow raises an
       * error, which is the standard behavior in high level programming languages.
       * `SafeMath` restores this intuition by reverting the transaction when an
       * operation overflows.
       *
       * Using this library instead of the unchecked operations eliminates an entire
       * class of bugs, so it's recommended to use it always.
       */
      library SafeMath {
          /**
           * @dev Returns the addition of two unsigned integers, with an overflow flag.
           *
           * _Available since v3.4._
           */
          function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
              uint256 c = a + b;
              if (c < a) return (false, 0);
              return (true, c);
          }
      
          /**
           * @dev Returns the substraction of two unsigned integers, with an overflow flag.
           *
           * _Available since v3.4._
           */
          function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
              if (b > a) return (false, 0);
              return (true, a - b);
          }
      
          /**
           * @dev Returns the multiplication of two unsigned integers, with an overflow flag.
           *
           * _Available since v3.4._
           */
          function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
              // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
              // benefit is lost if 'b' is also tested.
              // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
              if (a == 0) return (true, 0);
              uint256 c = a * b;
              if (c / a != b) return (false, 0);
              return (true, c);
          }
      
          /**
           * @dev Returns the division of two unsigned integers, with a division by zero flag.
           *
           * _Available since v3.4._
           */
          function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
              if (b == 0) return (false, 0);
              return (true, a / b);
          }
      
          /**
           * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
           *
           * _Available since v3.4._
           */
          function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
              if (b == 0) return (false, 0);
              return (true, a % b);
          }
      
          /**
           * @dev Returns the addition of two unsigned integers, reverting on
           * overflow.
           *
           * Counterpart to Solidity's `+` operator.
           *
           * Requirements:
           *
           * - Addition cannot overflow.
           */
          function add(uint256 a, uint256 b) internal pure returns (uint256) {
              uint256 c = a + b;
              require(c >= a, "SafeMath: addition overflow");
              return c;
          }
      
          /**
           * @dev Returns the subtraction of two unsigned integers, reverting on
           * overflow (when the result is negative).
           *
           * Counterpart to Solidity's `-` operator.
           *
           * Requirements:
           *
           * - Subtraction cannot overflow.
           */
          function sub(uint256 a, uint256 b) internal pure returns (uint256) {
              require(b <= a, "SafeMath: subtraction overflow");
              return a - b;
          }
      
          /**
           * @dev Returns the multiplication of two unsigned integers, reverting on
           * overflow.
           *
           * Counterpart to Solidity's `*` operator.
           *
           * Requirements:
           *
           * - Multiplication cannot overflow.
           */
          function mul(uint256 a, uint256 b) internal pure returns (uint256) {
              if (a == 0) return 0;
              uint256 c = a * b;
              require(c / a == b, "SafeMath: multiplication overflow");
              return c;
          }
      
          /**
           * @dev Returns the integer division of two unsigned integers, reverting on
           * division by zero. The result is rounded towards zero.
           *
           * Counterpart to Solidity's `/` operator. Note: this function uses a
           * `revert` opcode (which leaves remaining gas untouched) while Solidity
           * uses an invalid opcode to revert (consuming all remaining gas).
           *
           * Requirements:
           *
           * - The divisor cannot be zero.
           */
          function div(uint256 a, uint256 b) internal pure returns (uint256) {
              require(b > 0, "SafeMath: division by zero");
              return a / b;
          }
      
          /**
           * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
           * reverting when dividing by zero.
           *
           * Counterpart to Solidity's `%` operator. This function uses a `revert`
           * opcode (which leaves remaining gas untouched) while Solidity uses an
           * invalid opcode to revert (consuming all remaining gas).
           *
           * Requirements:
           *
           * - The divisor cannot be zero.
           */
          function mod(uint256 a, uint256 b) internal pure returns (uint256) {
              require(b > 0, "SafeMath: modulo by zero");
              return a % b;
          }
      
          /**
           * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
           * overflow (when the result is negative).
           *
           * CAUTION: This function is deprecated because it requires allocating memory for the error
           * message unnecessarily. For custom revert reasons use {trySub}.
           *
           * Counterpart to Solidity's `-` operator.
           *
           * Requirements:
           *
           * - Subtraction cannot overflow.
           */
          function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
              require(b <= a, errorMessage);
              return a - b;
          }
      
          /**
           * @dev Returns the integer division of two unsigned integers, reverting with custom message on
           * division by zero. The result is rounded towards zero.
           *
           * CAUTION: This function is deprecated because it requires allocating memory for the error
           * message unnecessarily. For custom revert reasons use {tryDiv}.
           *
           * Counterpart to Solidity's `/` operator. Note: this function uses a
           * `revert` opcode (which leaves remaining gas untouched) while Solidity
           * uses an invalid opcode to revert (consuming all remaining gas).
           *
           * Requirements:
           *
           * - The divisor cannot be zero.
           */
          function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
              require(b > 0, errorMessage);
              return a / b;
          }
      
          /**
           * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
           * reverting with custom message when dividing by zero.
           *
           * CAUTION: This function is deprecated because it requires allocating memory for the error
           * message unnecessarily. For custom revert reasons use {tryMod}.
           *
           * Counterpart to Solidity's `%` operator. This function uses a `revert`
           * opcode (which leaves remaining gas untouched) while Solidity uses an
           * invalid opcode to revert (consuming all remaining gas).
           *
           * Requirements:
           *
           * - The divisor cannot be zero.
           */
          function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
              require(b > 0, errorMessage);
              return a % b;
          }
      }
      
      // File: contracts/bridge/AdminControlled.sol
      
      pragma solidity ^0.6;
      
      contract AdminControlled {
          address public admin;
          uint public paused;
      
          constructor(address _admin, uint flags) public {
              admin = _admin;
              paused = flags;
          }
      
          modifier onlyAdmin {
              require(msg.sender == admin);
              _;
          }
      
          modifier pausable(uint flag) {
              require((paused & flag) == 0 || msg.sender == admin);
              _;
          }
      
          function adminPause(uint flags) public onlyAdmin {
              paused = flags;
          }
      
          function adminSstore(uint key, uint value) public onlyAdmin {
              assembly {
                  sstore(key, value)
              }
          }
      
          function adminSstoreWithMask(
              uint key,
              uint value,
              uint mask
          ) public onlyAdmin {
              assembly {
                  let oldval := sload(key)
                  sstore(key, xor(and(xor(value, oldval), mask), oldval))
              }
          }
      
          function adminSendEth(address payable destination, uint amount) public onlyAdmin {
              destination.transfer(amount);
          }
      
          function adminReceiveEth() public payable onlyAdmin {}
      
          function adminDelegatecall(address target, bytes memory data) public payable onlyAdmin returns (bytes memory) {
              (bool success, bytes memory rdata) = target.delegatecall(data);
              require(success);
              return rdata;
          }
      }
      
      // File: contracts/bridge/INearBridge.sol
      
      pragma solidity ^0.6;
      
      interface INearBridge {
          event BlockHashAdded(uint64 indexed height, bytes32 blockHash);
      
          event BlockHashReverted(uint64 indexed height, bytes32 blockHash);
      
          function blockHashes(uint64 blockNumber) external view returns (bytes32);
      
          function blockMerkleRoots(uint64 blockNumber) external view returns (bytes32);
      
          function balanceOf(address wallet) external view returns (uint256);
      
          function deposit() external payable;
      
          function withdraw() external;
      
          function initWithValidators(bytes calldata initialValidators) external;
      
          function initWithBlock(bytes calldata data) external;
      
          function addLightClientBlock(bytes calldata data) external;
      
          function challenge(address payable receiver, uint256 signatureIndex) external;
      
          function checkBlockProducerSignatureInHead(uint256 signatureIndex) external view returns (bool);
      }
      
      // File: contracts/bridge/Borsh.sol
      
      pragma solidity ^0.6;
      
      
      library Borsh {
          using SafeMath for uint256;
      
          struct Data {
              uint256 offset;
              bytes raw;
          }
      
          function from(bytes memory data) internal pure returns (Data memory) {
              return Data({offset: 0, raw: data});
          }
      
          modifier shift(Data memory data, uint256 size) {
              require(data.raw.length >= data.offset + size, "Borsh: Out of range");
              _;
              data.offset += size;
          }
      
          function finished(Data memory data) internal pure returns (bool) {
              return data.offset == data.raw.length;
          }
      
          function peekKeccak256(Data memory data, uint256 length) internal pure returns (bytes32 res) {
              return bytesKeccak256(data.raw, data.offset, length);
          }
      
          function bytesKeccak256(
              bytes memory ptr,
              uint256 offset,
              uint256 length
          ) internal pure returns (bytes32 res) {
              // solium-disable-next-line security/no-inline-assembly
              assembly {
                  res := keccak256(add(add(ptr, 32), offset), length)
              }
          }
      
          function peekSha256(Data memory data, uint256 length) internal view returns (bytes32) {
              return bytesSha256(data.raw, data.offset, length);
          }
      
          function bytesSha256(
              bytes memory ptr,
              uint256 offset,
              uint256 length
          ) internal view returns (bytes32) {
              bytes32[1] memory result;
              // solium-disable-next-line security/no-inline-assembly
              assembly {
                  pop(staticcall(gas(), 0x02, add(add(ptr, 32), offset), length, result, 32))
              }
              return result[0];
          }
      
          function decodeU8(Data memory data) internal pure shift(data, 1) returns (uint8 value) {
              value = uint8(data.raw[data.offset]);
          }
      
          function decodeI8(Data memory data) internal pure shift(data, 1) returns (int8 value) {
              value = int8(data.raw[data.offset]);
          }
      
          function decodeU16(Data memory data) internal pure returns (uint16 value) {
              value = uint16(decodeU8(data));
              value |= (uint16(decodeU8(data)) << 8);
          }
      
          function decodeI16(Data memory data) internal pure returns (int16 value) {
              value = int16(decodeI8(data));
              value |= (int16(decodeI8(data)) << 8);
          }
      
          function decodeU32(Data memory data) internal pure returns (uint32 value) {
              value = uint32(decodeU16(data));
              value |= (uint32(decodeU16(data)) << 16);
          }
      
          function decodeI32(Data memory data) internal pure returns (int32 value) {
              value = int32(decodeI16(data));
              value |= (int32(decodeI16(data)) << 16);
          }
      
          function decodeU64(Data memory data) internal pure returns (uint64 value) {
              value = uint64(decodeU32(data));
              value |= (uint64(decodeU32(data)) << 32);
          }
      
          function decodeI64(Data memory data) internal pure returns (int64 value) {
              value = int64(decodeI32(data));
              value |= (int64(decodeI32(data)) << 32);
          }
      
          function decodeU128(Data memory data) internal pure returns (uint128 value) {
              value = uint128(decodeU64(data));
              value |= (uint128(decodeU64(data)) << 64);
          }
      
          function decodeI128(Data memory data) internal pure returns (int128 value) {
              value = int128(decodeI64(data));
              value |= (int128(decodeI64(data)) << 64);
          }
      
          function decodeU256(Data memory data) internal pure returns (uint256 value) {
              value = uint256(decodeU128(data));
              value |= (uint256(decodeU128(data)) << 128);
          }
      
          function decodeI256(Data memory data) internal pure returns (int256 value) {
              value = int256(decodeI128(data));
              value |= (int256(decodeI128(data)) << 128);
          }
      
          function decodeBool(Data memory data) internal pure returns (bool value) {
              value = (decodeU8(data) != 0);
          }
      
          function decodeBytes(Data memory data) internal pure returns (bytes memory value) {
              value = new bytes(decodeU32(data));
              for (uint i = 0; i < value.length; i++) {
                  value[i] = byte(decodeU8(data));
              }
          }
      
          function decodeBytes32(Data memory data) internal pure shift(data, 32) returns (bytes32 value) {
              bytes memory raw = data.raw;
              uint256 offset = data.offset;
              // solium-disable-next-line security/no-inline-assembly
              assembly {
                  value := mload(add(add(raw, 32), offset))
              }
          }
      
          function decodeBytes20(Data memory data) internal pure returns (bytes20 value) {
              for (uint i = 0; i < 20; i++) {
                  value |= bytes20(byte(decodeU8(data)) & 0xFF) >> (i * 8);
              }
          }
      
          // Public key
      
          struct SECP256K1PublicKey {
              uint256 x;
              uint256 y;
          }
      
          function decodeSECP256K1PublicKey(Borsh.Data memory data) internal pure returns (SECP256K1PublicKey memory key) {
              key.x = decodeU256(data);
              key.y = decodeU256(data);
          }
      
          struct ED25519PublicKey {
              bytes32 xy;
          }
      
          function decodeED25519PublicKey(Borsh.Data memory data) internal pure returns (ED25519PublicKey memory key) {
              key.xy = decodeBytes32(data);
          }
      
          // Signature
      
          struct SECP256K1Signature {
              bytes32 r;
              bytes32 s;
              uint8 v;
          }
      
          function decodeSECP256K1Signature(Borsh.Data memory data) internal pure returns (SECP256K1Signature memory sig) {
              sig.r = decodeBytes32(data);
              sig.s = decodeBytes32(data);
              sig.v = decodeU8(data);
          }
      
          struct ED25519Signature {
              bytes32[2] rs;
          }
      
          function decodeED25519Signature(Borsh.Data memory data) internal pure returns (ED25519Signature memory sig) {
              sig.rs[0] = decodeBytes32(data);
              sig.rs[1] = decodeBytes32(data);
          }
      }
      
      // File: contracts/bridge/NearDecoder.sol
      
      pragma solidity ^0.6;
      
      
      
      library NearDecoder {
          using Borsh for Borsh.Data;
          using NearDecoder for Borsh.Data;
      
          struct PublicKey {
              uint8 enumIndex;
              Borsh.ED25519PublicKey ed25519;
              Borsh.SECP256K1PublicKey secp256k1;
          }
      
          function decodePublicKey(Borsh.Data memory data) internal pure returns (PublicKey memory key) {
              key.enumIndex = data.decodeU8();
      
              if (key.enumIndex == 0) {
                  key.ed25519 = data.decodeED25519PublicKey();
              } else if (key.enumIndex == 1) {
                  key.secp256k1 = data.decodeSECP256K1PublicKey();
              } else {
                  revert("NearBridge: Only ED25519 and SECP256K1 public keys are supported");
              }
          }
      
          struct ValidatorStake {
              string account_id;
              PublicKey public_key;
              uint128 stake;
          }
      
          function decodeValidatorStake(Borsh.Data memory data) internal pure returns (ValidatorStake memory validatorStake) {
              validatorStake.account_id = string(data.decodeBytes());
              validatorStake.public_key = data.decodePublicKey();
              validatorStake.stake = data.decodeU128();
          }
      
          struct OptionalValidatorStakes {
              bool none;
              ValidatorStake[] validatorStakes;
              bytes32 hash; // Additional computable element
          }
      
          function decodeOptionalValidatorStakes(Borsh.Data memory data)
              internal
              view
              returns (OptionalValidatorStakes memory stakes)
          {
              stakes.none = (data.decodeU8() == 0);
              if (!stakes.none) {
                  uint256 start = data.offset;
      
                  stakes.validatorStakes = new ValidatorStake[](data.decodeU32());
                  for (uint i = 0; i < stakes.validatorStakes.length; i++) {
                      stakes.validatorStakes[i] = data.decodeValidatorStake();
                  }
      
                  uint256 stop = data.offset;
                  data.offset = start;
                  stakes.hash = data.peekSha256(stop - start);
                  data.offset = stop;
              }
          }
      
          struct Signature {
              uint8 enumIndex;
              Borsh.ED25519Signature ed25519;
              Borsh.SECP256K1Signature secp256k1;
          }
      
          function decodeSignature(Borsh.Data memory data) internal pure returns (Signature memory sig) {
              sig.enumIndex = data.decodeU8();
      
              if (sig.enumIndex == 0) {
                  sig.ed25519 = data.decodeED25519Signature();
              } else if (sig.enumIndex == 1) {
                  sig.secp256k1 = data.decodeSECP256K1Signature();
              } else {
                  revert("NearBridge: Only ED25519 and SECP256K1 signatures are supported");
              }
          }
      
          struct OptionalSignature {
              bool none;
              Signature signature;
          }
      
          function decodeOptionalSignature(Borsh.Data memory data) internal pure returns (OptionalSignature memory sig) {
              sig.none = (data.decodeU8() == 0);
              if (!sig.none) {
                  sig.signature = data.decodeSignature();
              }
          }
      
          struct LightClientBlock {
              bytes32 prev_block_hash;
              bytes32 next_block_inner_hash;
              BlockHeaderInnerLite inner_lite;
              bytes32 inner_rest_hash;
              OptionalValidatorStakes next_bps;
              OptionalSignature[] approvals_after_next;
              bytes32 hash;
              bytes32 next_hash;
          }
      
          struct InitialValidators {
              ValidatorStake[] validator_stakes;
          }
      
          function decodeInitialValidators(Borsh.Data memory data)
              internal
              view
              returns (InitialValidators memory validators)
          {
              validators.validator_stakes = new ValidatorStake[](data.decodeU32());
              for (uint i = 0; i < validators.validator_stakes.length; i++) {
                  validators.validator_stakes[i] = data.decodeValidatorStake();
              }
          }
      
          function decodeLightClientBlock(Borsh.Data memory data) internal view returns (LightClientBlock memory header) {
              header.prev_block_hash = data.decodeBytes32();
              header.next_block_inner_hash = data.decodeBytes32();
              header.inner_lite = data.decodeBlockHeaderInnerLite();
              header.inner_rest_hash = data.decodeBytes32();
              header.next_bps = data.decodeOptionalValidatorStakes();
      
              header.approvals_after_next = new OptionalSignature[](data.decodeU32());
              for (uint i = 0; i < header.approvals_after_next.length; i++) {
                  header.approvals_after_next[i] = data.decodeOptionalSignature();
              }
      
              header.hash = sha256(
                  abi.encodePacked(
                      sha256(abi.encodePacked(header.inner_lite.hash, header.inner_rest_hash)),
                      header.prev_block_hash
                  )
              );
      
              header.next_hash = sha256(abi.encodePacked(header.next_block_inner_hash, header.hash));
          }
      
          struct BlockHeaderInnerLite {
              uint64 height; /// Height of this block since the genesis block (height 0).
              bytes32 epoch_id; /// Epoch start hash of this block's epoch. Used for retrieving validator information
              bytes32 next_epoch_id;
              bytes32 prev_state_root; /// Root hash of the state at the previous block.
              bytes32 outcome_root; /// Root of the outcomes of transactions and receipts.
              uint64 timestamp; /// Timestamp at which the block was built.
              bytes32 next_bp_hash; /// Hash of the next epoch block producers set
              bytes32 block_merkle_root;
              bytes32 hash; // Additional computable element
          }
      
          function decodeBlockHeaderInnerLite(Borsh.Data memory data)
              internal
              view
              returns (BlockHeaderInnerLite memory header)
          {
              header.hash = data.peekSha256(208);
              header.height = data.decodeU64();
              header.epoch_id = data.decodeBytes32();
              header.next_epoch_id = data.decodeBytes32();
              header.prev_state_root = data.decodeBytes32();
              header.outcome_root = data.decodeBytes32();
              header.timestamp = data.decodeU64();
              header.next_bp_hash = data.decodeBytes32();
              header.block_merkle_root = data.decodeBytes32();
          }
      }
      
      // File: contracts/ProofDecoder.sol
      
      pragma solidity ^0.6;
      
      
      
      library ProofDecoder {
          using Borsh for Borsh.Data;
          using ProofDecoder for Borsh.Data;
          using NearDecoder for Borsh.Data;
      
          struct FullOutcomeProof {
              ExecutionOutcomeWithIdAndProof outcome_proof;
              MerklePath outcome_root_proof; // TODO: now empty array
              BlockHeaderLight block_header_lite;
              MerklePath block_proof;
          }
      
          function decodeFullOutcomeProof(Borsh.Data memory data) internal view returns (FullOutcomeProof memory proof) {
              proof.outcome_proof = data.decodeExecutionOutcomeWithIdAndProof();
              proof.outcome_root_proof = data.decodeMerklePath();
              proof.block_header_lite = data.decodeBlockHeaderLight();
              proof.block_proof = data.decodeMerklePath();
          }
      
          struct BlockHeaderLight {
              bytes32 prev_block_hash;
              bytes32 inner_rest_hash;
              NearDecoder.BlockHeaderInnerLite inner_lite;
              bytes32 hash; // Computable
          }
      
          function decodeBlockHeaderLight(Borsh.Data memory data) internal view returns (BlockHeaderLight memory header) {
              header.prev_block_hash = data.decodeBytes32();
              header.inner_rest_hash = data.decodeBytes32();
              header.inner_lite = data.decodeBlockHeaderInnerLite();
      
              header.hash = sha256(
                  abi.encodePacked(
                      sha256(abi.encodePacked(header.inner_lite.hash, header.inner_rest_hash)),
                      header.prev_block_hash
                  )
              );
          }
      
          struct ExecutionStatus {
              uint8 enumIndex;
              bool unknown;
              bool failed;
              bytes successValue; /// The final action succeeded and returned some value or an empty vec.
              bytes32 successReceiptId; /// The final action of the receipt returned a promise or the signed
              /// transaction was converted to a receipt. Contains the receipt_id of the generated receipt.
          }
      
          function decodeExecutionStatus(Borsh.Data memory data)
              internal
              pure
              returns (ExecutionStatus memory executionStatus)
          {
              executionStatus.enumIndex = data.decodeU8();
              if (executionStatus.enumIndex == 0) {
                  executionStatus.unknown = true;
              } else if (executionStatus.enumIndex == 1) {
                  //revert("NearDecoder: decodeExecutionStatus failure case not implemented yet");
                  // Can avoid revert since ExecutionStatus is latest field in all parent structures
                  executionStatus.failed = true;
              } else if (executionStatus.enumIndex == 2) {
                  executionStatus.successValue = data.decodeBytes();
              } else if (executionStatus.enumIndex == 3) {
                  executionStatus.successReceiptId = data.decodeBytes32();
              } else {
                  revert("NearDecoder: decodeExecutionStatus index out of range");
              }
          }
      
          struct ExecutionOutcome {
              bytes[] logs; /// Logs from this transaction or receipt.
              bytes32[] receipt_ids; /// Receipt IDs generated by this transaction or receipt.
              uint64 gas_burnt; /// The amount of the gas burnt by the given transaction or receipt.
              uint128 tokens_burnt; /// The total number of the tokens burnt by the given transaction or receipt.
              bytes executor_id; /// Hash of the transaction or receipt id that produced this outcome.
              ExecutionStatus status; /// Execution status. Contains the result in case of successful execution.
              bytes32[] merkelization_hashes;
          }
      
          function decodeExecutionOutcome(Borsh.Data memory data) internal view returns (ExecutionOutcome memory outcome) {
              outcome.logs = new bytes[](data.decodeU32());
              for (uint i = 0; i < outcome.logs.length; i++) {
                  outcome.logs[i] = data.decodeBytes();
              }
      
              uint256 start = data.offset;
              outcome.receipt_ids = new bytes32[](data.decodeU32());
              for (uint i = 0; i < outcome.receipt_ids.length; i++) {
                  outcome.receipt_ids[i] = data.decodeBytes32();
              }
              outcome.gas_burnt = data.decodeU64();
              outcome.tokens_burnt = data.decodeU128();
              outcome.executor_id = data.decodeBytes();
              outcome.status = data.decodeExecutionStatus();
              uint256 stop = data.offset;
      
              outcome.merkelization_hashes = new bytes32[](1 + outcome.logs.length);
              data.offset = start;
              outcome.merkelization_hashes[0] = data.peekSha256(stop - start);
              data.offset = stop;
              for (uint i = 0; i < outcome.logs.length; i++) {
                  outcome.merkelization_hashes[i + 1] = sha256(outcome.logs[i]);
              }
          }
      
          struct ExecutionOutcomeWithId {
              bytes32 id; /// The transaction hash or the receipt ID.
              ExecutionOutcome outcome;
              bytes32 hash;
          }
      
          function decodeExecutionOutcomeWithId(Borsh.Data memory data)
              internal
              view
              returns (ExecutionOutcomeWithId memory outcome)
          {
              outcome.id = data.decodeBytes32();
              outcome.outcome = data.decodeExecutionOutcome();
      
              uint256 len = 1 + outcome.outcome.merkelization_hashes.length;
              outcome.hash = sha256(
                  abi.encodePacked(
                      uint8((len >> 0) & 0xFF),
                      uint8((len >> 8) & 0xFF),
                      uint8((len >> 16) & 0xFF),
                      uint8((len >> 24) & 0xFF),
                      outcome.id,
                      outcome.outcome.merkelization_hashes
                  )
              );
          }
      
          struct MerklePathItem {
              bytes32 hash;
              uint8 direction; // 0 = left, 1 = right
          }
      
          function decodeMerklePathItem(Borsh.Data memory data) internal pure returns (MerklePathItem memory item) {
              item.hash = data.decodeBytes32();
              item.direction = data.decodeU8();
              require(item.direction < 2, "ProofDecoder: MerklePathItem direction should be 0 or 1");
          }
      
          struct MerklePath {
              MerklePathItem[] items;
          }
      
          function decodeMerklePath(Borsh.Data memory data) internal pure returns (MerklePath memory path) {
              path.items = new MerklePathItem[](data.decodeU32());
              for (uint i = 0; i < path.items.length; i++) {
                  path.items[i] = data.decodeMerklePathItem();
              }
          }
      
          struct ExecutionOutcomeWithIdAndProof {
              MerklePath proof;
              bytes32 block_hash;
              ExecutionOutcomeWithId outcome_with_id;
          }
      
          function decodeExecutionOutcomeWithIdAndProof(Borsh.Data memory data)
              internal
              view
              returns (ExecutionOutcomeWithIdAndProof memory outcome)
          {
              outcome.proof = data.decodeMerklePath();
              outcome.block_hash = data.decodeBytes32();
              outcome.outcome_with_id = data.decodeExecutionOutcomeWithId();
          }
      }
      
      // File: contracts/INearProver.sol
      
      pragma solidity ^0.6;
      
      interface INearProver {
          function proveOutcome(bytes calldata proofData, uint64 blockHeight) external view returns (bool);
      }
      
      // File: contracts/NearProver.sol
      
      pragma solidity ^0.6;
      
      
      
      
      
      
      
      contract NearProver is INearProver, AdminControlled {
          using SafeMath for uint256;
          using Borsh for Borsh.Data;
          using NearDecoder for Borsh.Data;
          using ProofDecoder for Borsh.Data;
      
          INearBridge public bridge;
      
          constructor(
              INearBridge _bridge,
              address _admin,
              uint _pausedFlags
          ) public AdminControlled(_admin, _pausedFlags) {
              bridge = _bridge;
          }
      
          uint constant UNPAUSE_ALL = 0;
          uint constant PAUSED_VERIFY = 1;
      
          function proveOutcome(bytes memory proofData, uint64 blockHeight)
              public
              view
              override
              pausable(PAUSED_VERIFY)
              returns (bool)
          {
              Borsh.Data memory borshData = Borsh.from(proofData);
              ProofDecoder.FullOutcomeProof memory fullOutcomeProof = borshData.decodeFullOutcomeProof();
              require(borshData.finished(), "NearProver: argument should be exact borsh serialization");
      
              bytes32 hash =
                  _computeRoot(fullOutcomeProof.outcome_proof.outcome_with_id.hash, fullOutcomeProof.outcome_proof.proof);
      
              hash = sha256(abi.encodePacked(hash));
      
              hash = _computeRoot(hash, fullOutcomeProof.outcome_root_proof);
      
              require(
                  hash == fullOutcomeProof.block_header_lite.inner_lite.outcome_root,
                  "NearProver: outcome merkle proof is not valid"
              );
      
              bytes32 expectedBlockMerkleRoot = bridge.blockMerkleRoots(blockHeight);
      
              require(
                  _computeRoot(fullOutcomeProof.block_header_lite.hash, fullOutcomeProof.block_proof) ==
                      expectedBlockMerkleRoot,
                  "NearProver: block proof is not valid"
              );
      
              return true;
          }
      
          function _computeRoot(bytes32 node, ProofDecoder.MerklePath memory proof) internal pure returns (bytes32 hash) {
              hash = node;
              for (uint i = 0; i < proof.items.length; i++) {
                  ProofDecoder.MerklePathItem memory item = proof.items[i];
                  if (item.direction == 0) {
                      hash = sha256(abi.encodePacked(item.hash, hash));
                  } else {
                      hash = sha256(abi.encodePacked(hash, item.hash));
                  }
              }
          }
      }

      File 3 of 3: NearBridge
      {"AdminControlled.sol":{"content":"// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity ^0.8;\n\ncontract AdminControlled {\n    address public admin;\n    uint public paused;\n\n    constructor(address _admin, uint flags) {\n        admin = _admin;\n        paused = flags;\n    }\n\n    modifier onlyAdmin {\n        require(msg.sender == admin);\n        _;\n    }\n\n    modifier pausable(uint flag) {\n        require((paused \u0026 flag) == 0 || msg.sender == admin);\n        _;\n    }\n\n    function adminPause(uint flags) public onlyAdmin {\n        paused = flags;\n    }\n\n    function adminSstore(uint key, uint value) public onlyAdmin {\n        assembly {\n            sstore(key, value)\n        }\n    }\n\n    function adminSstoreWithMask(\n        uint key,\n        uint value,\n        uint mask\n    ) public onlyAdmin {\n        assembly {\n            let oldval := sload(key)\n            sstore(key, xor(and(xor(value, oldval), mask), oldval))\n        }\n    }\n\n    function adminSendEth(address payable destination, uint amount) public onlyAdmin {\n        destination.transfer(amount);\n    }\n\n    function adminReceiveEth() public payable onlyAdmin {}\n\n    function adminDelegatecall(address target, bytes memory data) public payable onlyAdmin returns (bytes memory) {\n        (bool success, bytes memory rdata) = target.delegatecall(data);\n        require(success);\n        return rdata;\n    }\n}\n"},"Borsh.sol":{"content":"// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity ^0.8;\n\nimport \"./Utils.sol\";\n\nlibrary Borsh {\n    using Borsh for Data;\n\n    struct Data {\n        uint ptr;\n        uint end;\n    }\n\n    function from(bytes memory data) internal pure returns (Data memory res) {\n        uint ptr;\n        assembly {\n            ptr := data\n        }\n        unchecked {\n            res.ptr = ptr + 32;\n            res.end = res.ptr + Utils.readMemory(ptr);\n        }\n    }\n\n    // This function assumes that length is reasonably small, so that data.ptr + length will not overflow. In the current code, length is always less than 2^32.\n    function requireSpace(Data memory data, uint length) internal pure {\n        unchecked {\n            require(data.ptr + length \u003c= data.end, \"Parse error: unexpected EOI\");\n        }\n    }\n\n    function read(Data memory data, uint length) internal pure returns (bytes32 res) {\n        data.requireSpace(length);\n        res = bytes32(Utils.readMemory(data.ptr));\n        unchecked {\n            data.ptr += length;\n        }\n        return res;\n    }\n\n    function done(Data memory data) internal pure {\n        require(data.ptr == data.end, \"Parse error: EOI expected\");\n    }\n\n    // Same considerations as for requireSpace.\n    function peekKeccak256(Data memory data, uint length) internal pure returns (bytes32) {\n        data.requireSpace(length);\n        return Utils.keccak256Raw(data.ptr, length);\n    }\n\n    // Same considerations as for requireSpace.\n    function peekSha256(Data memory data, uint length) internal view returns (bytes32) {\n        data.requireSpace(length);\n        return Utils.sha256Raw(data.ptr, length);\n    }\n\n    function decodeU8(Data memory data) internal pure returns (uint8) {\n        return uint8(bytes1(data.read(1)));\n    }\n\n    function decodeU16(Data memory data) internal pure returns (uint16) {\n        return Utils.swapBytes2(uint16(bytes2(data.read(2))));\n    }\n\n    function decodeU32(Data memory data) internal pure returns (uint32) {\n        return Utils.swapBytes4(uint32(bytes4(data.read(4))));\n    }\n\n    function decodeU64(Data memory data) internal pure returns (uint64) {\n        return Utils.swapBytes8(uint64(bytes8(data.read(8))));\n    }\n\n    function decodeU128(Data memory data) internal pure returns (uint128) {\n        return Utils.swapBytes16(uint128(bytes16(data.read(16))));\n    }\n\n    function decodeU256(Data memory data) internal pure returns (uint256) {\n        return Utils.swapBytes32(uint256(data.read(32)));\n    }\n\n    function decodeBytes20(Data memory data) internal pure returns (bytes20) {\n        return bytes20(data.read(20));\n    }\n\n    function decodeBytes32(Data memory data) internal pure returns (bytes32) {\n        return data.read(32);\n    }\n\n    function decodeBool(Data memory data) internal pure returns (bool) {\n        uint8 res = data.decodeU8();\n        require(res \u003c= 1, \"Parse error: invalid bool\");\n        return res != 0;\n    }\n\n    function skipBytes(Data memory data) internal pure {\n        uint length = data.decodeU32();\n        data.requireSpace(length);\n        unchecked {\n            data.ptr += length;\n        }\n    }\n\n    function decodeBytes(Data memory data) internal pure returns (bytes memory res) {\n        uint length = data.decodeU32();\n        data.requireSpace(length);\n        res = Utils.memoryToBytes(data.ptr, length);\n        unchecked {\n            data.ptr += length;\n        }\n    }\n}\n"},"Ed25519.sol":{"content":"// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity ^0.8;\n\ncontract Ed25519 {\n    // Computes (v^(2^250-1), v^11) mod p\n    function pow22501(uint256 v) private pure returns (uint256 p22501, uint256 p11) {\n        p11 = mulmod(v, v, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        p22501 = mulmod(p11, p11, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        p22501 = mulmod(\n            mulmod(p22501, p22501, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed),\n            v,\n            0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed\n        );\n        p11 = mulmod(p22501, p11, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        p22501 = mulmod(\n            mulmod(p11, p11, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed),\n            p22501,\n            0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed\n        );\n        uint256 a = mulmod(p22501, p22501, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        p22501 = mulmod(p22501, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(p22501, p22501, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(p22501, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        uint256 b = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        p22501 = mulmod(p22501, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(p22501, p22501, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(p22501, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        b = mulmod(b, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, b, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        a = mulmod(a, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n        p22501 = mulmod(p22501, a, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n    }\n\n    function check(\n        bytes32 k,\n        bytes32 r,\n        bytes32 s,\n        bytes32 m1,\n        bytes9 m2\n    ) public pure returns (bool) {\n        unchecked {\n            uint256 hh;\n            // Step 1: compute SHA-512(R, A, M)\n            {\n                uint256[5][16] memory kk = [\n                    [\n                        uint256(0x428a2f98_d728ae22),\n                        uint256(0xe49b69c1_9ef14ad2),\n                        uint256(0x27b70a85_46d22ffc),\n                        uint256(0x19a4c116_b8d2d0c8),\n                        uint256(0xca273ece_ea26619c)\n                    ],\n                    [\n                        uint256(0x71374491_23ef65cd),\n                        uint256(0xefbe4786_384f25e3),\n                        uint256(0x2e1b2138_5c26c926),\n                        uint256(0x1e376c08_5141ab53),\n                        uint256(0xd186b8c7_21c0c207)\n                    ],\n                    [\n                        uint256(0xb5c0fbcf_ec4d3b2f),\n                        uint256(0xfc19dc6_8b8cd5b5),\n                        uint256(0x4d2c6dfc_5ac42aed),\n                        uint256(0x2748774c_df8eeb99),\n                        uint256(0xeada7dd6_cde0eb1e)\n                    ],\n                    [\n                        uint256(0xe9b5dba5_8189dbbc),\n                        uint256(0x240ca1cc_77ac9c65),\n                        uint256(0x53380d13_9d95b3df),\n                        uint256(0x34b0bcb5_e19b48a8),\n                        uint256(0xf57d4f7f_ee6ed178)\n                    ],\n                    [\n                        uint256(0x3956c25b_f348b538),\n                        uint256(0x2de92c6f_592b0275),\n                        uint256(0x650a7354_8baf63de),\n                        uint256(0x391c0cb3_c5c95a63),\n                        uint256(0x6f067aa_72176fba)\n                    ],\n                    [\n                        uint256(0x59f111f1_b605d019),\n                        uint256(0x4a7484aa_6ea6e483),\n                        uint256(0x766a0abb_3c77b2a8),\n                        uint256(0x4ed8aa4a_e3418acb),\n                        uint256(0xa637dc5_a2c898a6)\n                    ],\n                    [\n                        uint256(0x923f82a4_af194f9b),\n                        uint256(0x5cb0a9dc_bd41fbd4),\n                        uint256(0x81c2c92e_47edaee6),\n                        uint256(0x5b9cca4f_7763e373),\n                        uint256(0x113f9804_bef90dae)\n                    ],\n                    [\n                        uint256(0xab1c5ed5_da6d8118),\n                        uint256(0x76f988da_831153b5),\n                        uint256(0x92722c85_1482353b),\n                        uint256(0x682e6ff3_d6b2b8a3),\n                        uint256(0x1b710b35_131c471b)\n                    ],\n                    [\n                        uint256(0xd807aa98_a3030242),\n                        uint256(0x983e5152_ee66dfab),\n                        uint256(0xa2bfe8a1_4cf10364),\n                        uint256(0x748f82ee_5defb2fc),\n                        uint256(0x28db77f5_23047d84)\n                    ],\n                    [\n                        uint256(0x12835b01_45706fbe),\n                        uint256(0xa831c66d_2db43210),\n                        uint256(0xa81a664b_bc423001),\n                        uint256(0x78a5636f_43172f60),\n                        uint256(0x32caab7b_40c72493)\n                    ],\n                    [\n                        uint256(0x243185be_4ee4b28c),\n                        uint256(0xb00327c8_98fb213f),\n                        uint256(0xc24b8b70_d0f89791),\n                        uint256(0x84c87814_a1f0ab72),\n                        uint256(0x3c9ebe0a_15c9bebc)\n                    ],\n                    [\n                        uint256(0x550c7dc3_d5ffb4e2),\n                        uint256(0xbf597fc7_beef0ee4),\n                        uint256(0xc76c51a3_0654be30),\n                        uint256(0x8cc70208_1a6439ec),\n                        uint256(0x431d67c4_9c100d4c)\n                    ],\n                    [\n                        uint256(0x72be5d74_f27b896f),\n                        uint256(0xc6e00bf3_3da88fc2),\n                        uint256(0xd192e819_d6ef5218),\n                        uint256(0x90befffa_23631e28),\n                        uint256(0x4cc5d4be_cb3e42b6)\n                    ],\n                    [\n                        uint256(0x80deb1fe_3b1696b1),\n                        uint256(0xd5a79147_930aa725),\n                        uint256(0xd6990624_5565a910),\n                        uint256(0xa4506ceb_de82bde9),\n                        uint256(0x597f299c_fc657e2a)\n                    ],\n                    [\n                        uint256(0x9bdc06a7_25c71235),\n                        uint256(0x6ca6351_e003826f),\n                        uint256(0xf40e3585_5771202a),\n                        uint256(0xbef9a3f7_b2c67915),\n                        uint256(0x5fcb6fab_3ad6faec)\n                    ],\n                    [\n                        uint256(0xc19bf174_cf692694),\n                        uint256(0x14292967_0a0e6e70),\n                        uint256(0x106aa070_32bbd1b8),\n                        uint256(0xc67178f2_e372532b),\n                        uint256(0x6c44198c_4a475817)\n                    ]\n                ];\n                uint256 w0 = (uint256(r) \u0026 0xffffffff_ffffffff_00000000_00000000_00000000_00000000_ffffffff_ffffffff) |\n                    ((uint256(r) \u0026 0xffffffff_ffffffff_00000000_00000000_00000000_00000000) \u003e\u003e 64) |\n                    ((uint256(r) \u0026 0xffffffff_ffffffff_00000000_00000000) \u003c\u003c 64);\n                uint256 w1 = (uint256(k) \u0026 0xffffffff_ffffffff_00000000_00000000_00000000_00000000_ffffffff_ffffffff) |\n                    ((uint256(k) \u0026 0xffffffff_ffffffff_00000000_00000000_00000000_00000000) \u003e\u003e 64) |\n                    ((uint256(k) \u0026 0xffffffff_ffffffff_00000000_00000000) \u003c\u003c 64);\n                uint256 w2 = (uint256(m1) \u0026 0xffffffff_ffffffff_00000000_00000000_00000000_00000000_ffffffff_ffffffff) |\n                    ((uint256(m1) \u0026 0xffffffff_ffffffff_00000000_00000000_00000000_00000000) \u003e\u003e 64) |\n                    ((uint256(m1) \u0026 0xffffffff_ffffffff_00000000_00000000) \u003c\u003c 64);\n                uint256 w3 = (uint256(bytes32(m2)) \u0026\n                    0xffffffff_ffffffff_00000000_00000000_00000000_00000000_00000000_00000000) |\n                    ((uint256(bytes32(m2)) \u0026 0xffffffff_ffffffff_00000000_00000000_00000000_00000000) \u003e\u003e 64) |\n                    0x800000_00000000_00000000_00000348;\n                uint256 a = 0x6a09e667_f3bcc908;\n                uint256 b = 0xbb67ae85_84caa73b;\n                uint256 c = 0x3c6ef372_fe94f82b;\n                uint256 d = 0xa54ff53a_5f1d36f1;\n                uint256 e = 0x510e527f_ade682d1;\n                uint256 f = 0x9b05688c_2b3e6c1f;\n                uint256 g = 0x1f83d9ab_fb41bd6b;\n                uint256 h = 0x5be0cd19_137e2179;\n                for (uint256 i = 0; ; i++) {\n                    // Round 16 * i\n                    {\n                        uint256 temp1;\n                        uint256 temp2;\n                        e \u0026= 0xffffffff_ffffffff;\n                        {\n                            uint256 ss = e | (e \u003c\u003c 64);\n                            uint256 s1 = (ss \u003e\u003e 14) ^ (ss \u003e\u003e 18) ^ (ss \u003e\u003e 41);\n                            uint256 ch = (e \u0026 (f ^ g)) ^ g;\n                            temp1 = h + s1 + ch;\n                        }\n                        temp1 += kk[0][i];\n                        temp1 += w0 \u003e\u003e 192;\n                        a \u0026= 0xffffffff_ffffffff;\n                        {\n                            uint256 ss = a | (a \u003c\u003c 64);\n                            uint256 s0 = (ss \u003e\u003e 28) ^ (ss \u003e\u003e 34) ^ (ss \u003e\u003e 39);\n                            uint256 maj = (a \u0026 (b | c)) | (b \u0026 c);\n                            temp2 = s0 + maj;\n                        }\n                        h = g;\n                        g = f;\n                        f = e;\n                        e = d + temp1;\n                        d = c;\n                        c = b;\n                        b = a;\n                        a = temp1 + temp2;\n                    }\n                    // Round 16 * i + 1\n                    {\n                        uint256 temp1;\n                        uint256 temp2;\n                        e \u0026= 0xffffffff_ffffffff;\n                        {\n                            uint256 ss = e | (e \u003c\u003c 64);\n                            uint256 s1 = (ss \u003e\u003e 14) ^ (ss \u003e\u003e 18) ^ (ss \u003e\u003e 41);\n                            uint256 ch = (e \u0026 (f ^ g)) ^ g;\n                            temp1 = h + s1 + ch;\n                        }\n                        temp1 += kk[1][i];\n                        temp1 += w0 \u003e\u003e 64;\n                        a \u0026= 0xffffffff_ffffffff;\n                        {\n                            uint256 ss = a | (a \u003c\u003c 64);\n                            uint256 s0 = (ss \u003e\u003e 28) ^ (ss \u003e\u003e 34) ^ (ss \u003e\u003e 39);\n                            uint256 maj = (a \u0026 (b | c)) | (b \u0026 c);\n                            temp2 = s0 + maj;\n                        }\n                        h = g;\n                        g = f;\n                        f = e;\n                        e = d + temp1;\n                        d = c;\n                        c = b;\n                        b = a;\n                        a = temp1 + temp2;\n                    }\n                    // Round 16 * i + 2\n                    {\n                        uint256 temp1;\n                        uint256 temp2;\n                        e \u0026= 0xffffffff_ffffffff;\n                        {\n                            uint256 ss = e | (e \u003c\u003c 64);\n                            uint256 s1 = (ss \u003e\u003e 14) ^ (ss \u003e\u003e 18) ^ (ss \u003e\u003e 41);\n                            uint256 ch = (e \u0026 (f ^ g)) ^ g;\n                            temp1 = h + s1 + ch;\n                        }\n                        temp1 += kk[2][i];\n                        temp1 += w0 \u003e\u003e 128;\n                        a \u0026= 0xffffffff_ffffffff;\n                        {\n                            uint256 ss = a | (a \u003c\u003c 64);\n                            uint256 s0 = (ss \u003e\u003e 28) ^ (ss \u003e\u003e 34) ^ (ss \u003e\u003e 39);\n                            uint256 maj = (a \u0026 (b | c)) | (b \u0026 c);\n                            temp2 = s0 + maj;\n                        }\n                        h = g;\n                        g = f;\n                        f = e;\n                        e = d + temp1;\n                        d = c;\n                        c = b;\n                        b = a;\n                        a = temp1 + temp2;\n                    }\n                    // Round 16 * i + 3\n                    {\n                        uint256 temp1;\n                        uint256 temp2;\n                        e \u0026= 0xffffffff_ffffffff;\n                        {\n                            uint256 ss = e | (e \u003c\u003c 64);\n                            uint256 s1 = (ss \u003e\u003e 14) ^ (ss \u003e\u003e 18) ^ (ss \u003e\u003e 41);\n                            uint256 ch = (e \u0026 (f ^ g)) ^ g;\n                            temp1 = h + s1 + ch;\n                        }\n                        temp1 += kk[3][i];\n                        temp1 += w0;\n                        a \u0026= 0xffffffff_ffffffff;\n                        {\n                            uint256 ss = a | (a \u003c\u003c 64);\n                            uint256 s0 = (ss \u003e\u003e 28) ^ (ss \u003e\u003e 34) ^ (ss \u003e\u003e 39);\n                            uint256 maj = (a \u0026 (b | c)) | (b \u0026 c);\n                            temp2 = s0 + maj;\n                        }\n                        h = g;\n                        g = f;\n                        f = e;\n                        e = d + temp1;\n                        d = c;\n                        c = b;\n                        b = a;\n                        a = temp1 + temp2;\n                    }\n                    // Round 16 * i + 4\n                    {\n                        uint256 temp1;\n                        uint256 temp2;\n                        e \u0026= 0xffffffff_ffffffff;\n                        {\n                            uint256 ss = e | (e \u003c\u003c 64);\n                            uint256 s1 = (ss \u003e\u003e 14) ^ (ss \u003e\u003e 18) ^ (ss \u003e\u003e 41);\n                            uint256 ch = (e \u0026 (f ^ g)) ^ g;\n                            temp1 = h + s1 + ch;\n                        }\n                        temp1 += kk[4][i];\n                        temp1 += w1 \u003e\u003e 192;\n                        a \u0026= 0xffffffff_ffffffff;\n                        {\n                            uint256 ss = a | (a \u003c\u003c 64);\n                            uint256 s0 = (ss \u003e\u003e 28) ^ (ss \u003e\u003e 34) ^ (ss \u003e\u003e 39);\n                            uint256 maj = (a \u0026 (b | c)) | (b \u0026 c);\n                            temp2 = s0 + maj;\n                        }\n                        h = g;\n                        g = f;\n                        f = e;\n                        e = d + temp1;\n                        d = c;\n                        c = b;\n                        b = a;\n                        a = temp1 + temp2;\n                    }\n                    // Round 16 * i + 5\n                    {\n                        uint256 temp1;\n                        uint256 temp2;\n                        e \u0026= 0xffffffff_ffffffff;\n                        {\n                            uint256 ss = e | (e \u003c\u003c 64);\n                            uint256 s1 = (ss \u003e\u003e 14) ^ (ss \u003e\u003e 18) ^ (ss \u003e\u003e 41);\n                            uint256 ch = (e \u0026 (f ^ g)) ^ g;\n                            temp1 = h + s1 + ch;\n                        }\n                        temp1 += kk[5][i];\n                        temp1 += w1 \u003e\u003e 64;\n                        a \u0026= 0xffffffff_ffffffff;\n                        {\n                            uint256 ss = a | (a \u003c\u003c 64);\n                            uint256 s0 = (ss \u003e\u003e 28) ^ (ss \u003e\u003e 34) ^ (ss \u003e\u003e 39);\n                            uint256 maj = (a \u0026 (b | c)) | (b \u0026 c);\n                            temp2 = s0 + maj;\n                        }\n                        h = g;\n                        g = f;\n                        f = e;\n                        e = d + temp1;\n                        d = c;\n                        c = b;\n                        b = a;\n                        a = temp1 + temp2;\n                    }\n                    // Round 16 * i + 6\n                    {\n                        uint256 temp1;\n                        uint256 temp2;\n                        e \u0026= 0xffffffff_ffffffff;\n                        {\n                            uint256 ss = e | (e \u003c\u003c 64);\n                            uint256 s1 = (ss \u003e\u003e 14) ^ (ss \u003e\u003e 18) ^ (ss \u003e\u003e 41);\n                            uint256 ch = (e \u0026 (f ^ g)) ^ g;\n                            temp1 = h + s1 + ch;\n                        }\n                        temp1 += kk[6][i];\n                        temp1 += w1 \u003e\u003e 128;\n                        a \u0026= 0xffffffff_ffffffff;\n                        {\n                            uint256 ss = a | (a \u003c\u003c 64);\n                            uint256 s0 = (ss \u003e\u003e 28) ^ (ss \u003e\u003e 34) ^ (ss \u003e\u003e 39);\n                            uint256 maj = (a \u0026 (b | c)) | (b \u0026 c);\n                            temp2 = s0 + maj;\n                        }\n                        h = g;\n                        g = f;\n                        f = e;\n                        e = d + temp1;\n                        d = c;\n                        c = b;\n                        b = a;\n                        a = temp1 + temp2;\n                    }\n                    // Round 16 * i + 7\n                    {\n                        uint256 temp1;\n                        uint256 temp2;\n                        e \u0026= 0xffffffff_ffffffff;\n                        {\n                            uint256 ss = e | (e \u003c\u003c 64);\n                            uint256 s1 = (ss \u003e\u003e 14) ^ (ss \u003e\u003e 18) ^ (ss \u003e\u003e 41);\n                            uint256 ch = (e \u0026 (f ^ g)) ^ g;\n                            temp1 = h + s1 + ch;\n                        }\n                        temp1 += kk[7][i];\n                        temp1 += w1;\n                        a \u0026= 0xffffffff_ffffffff;\n                        {\n                            uint256 ss = a | (a \u003c\u003c 64);\n                            uint256 s0 = (ss \u003e\u003e 28) ^ (ss \u003e\u003e 34) ^ (ss \u003e\u003e 39);\n                            uint256 maj = (a \u0026 (b | c)) | (b \u0026 c);\n                            temp2 = s0 + maj;\n                        }\n                        h = g;\n                        g = f;\n                        f = e;\n                        e = d + temp1;\n                        d = c;\n                        c = b;\n                        b = a;\n                        a = temp1 + temp2;\n                    }\n                    // Round 16 * i + 8\n                    {\n                        uint256 temp1;\n                        uint256 temp2;\n                        e \u0026= 0xffffffff_ffffffff;\n                        {\n                            uint256 ss = e | (e \u003c\u003c 64);\n                            uint256 s1 = (ss \u003e\u003e 14) ^ (ss \u003e\u003e 18) ^ (ss \u003e\u003e 41);\n                            uint256 ch = (e \u0026 (f ^ g)) ^ g;\n                            temp1 = h + s1 + ch;\n                        }\n                        temp1 += kk[8][i];\n                        temp1 += w2 \u003e\u003e 192;\n                        a \u0026= 0xffffffff_ffffffff;\n                        {\n                            uint256 ss = a | (a \u003c\u003c 64);\n                            uint256 s0 = (ss \u003e\u003e 28) ^ (ss \u003e\u003e 34) ^ (ss \u003e\u003e 39);\n                            uint256 maj = (a \u0026 (b | c)) | (b \u0026 c);\n                            temp2 = s0 + maj;\n                        }\n                        h = g;\n                        g = f;\n                        f = e;\n                        e = d + temp1;\n                        d = c;\n                        c = b;\n                        b = a;\n                        a = temp1 + temp2;\n                    }\n                    // Round 16 * i + 9\n                    {\n                        uint256 temp1;\n                        uint256 temp2;\n                        e \u0026= 0xffffffff_ffffffff;\n                        {\n                            uint256 ss = e | (e \u003c\u003c 64);\n                            uint256 s1 = (ss \u003e\u003e 14) ^ (ss \u003e\u003e 18) ^ (ss \u003e\u003e 41);\n                            uint256 ch = (e \u0026 (f ^ g)) ^ g;\n                            temp1 = h + s1 + ch;\n                        }\n                        temp1 += kk[9][i];\n                        temp1 += w2 \u003e\u003e 64;\n                        a \u0026= 0xffffffff_ffffffff;\n                        {\n                            uint256 ss = a | (a \u003c\u003c 64);\n                            uint256 s0 = (ss \u003e\u003e 28) ^ (ss \u003e\u003e 34) ^ (ss \u003e\u003e 39);\n                            uint256 maj = (a \u0026 (b | c)) | (b \u0026 c);\n                            temp2 = s0 + maj;\n                        }\n                        h = g;\n                        g = f;\n                        f = e;\n                        e = d + temp1;\n                        d = c;\n                        c = b;\n                        b = a;\n                        a = temp1 + temp2;\n                    }\n                    // Round 16 * i + 10\n                    {\n                        uint256 temp1;\n                        uint256 temp2;\n                        e \u0026= 0xffffffff_ffffffff;\n                        {\n                            uint256 ss = e | (e \u003c\u003c 64);\n                            uint256 s1 = (ss \u003e\u003e 14) ^ (ss \u003e\u003e 18) ^ (ss \u003e\u003e 41);\n                            uint256 ch = (e \u0026 (f ^ g)) ^ g;\n                            temp1 = h + s1 + ch;\n                        }\n                        temp1 += kk[10][i];\n                        temp1 += w2 \u003e\u003e 128;\n                        a \u0026= 0xffffffff_ffffffff;\n                        {\n                            uint256 ss = a | (a \u003c\u003c 64);\n                            uint256 s0 = (ss \u003e\u003e 28) ^ (ss \u003e\u003e 34) ^ (ss \u003e\u003e 39);\n                            uint256 maj = (a \u0026 (b | c)) | (b \u0026 c);\n                            temp2 = s0 + maj;\n                        }\n                        h = g;\n                        g = f;\n                        f = e;\n                        e = d + temp1;\n                        d = c;\n                        c = b;\n                        b = a;\n                        a = temp1 + temp2;\n                    }\n                    // Round 16 * i + 11\n                    {\n                        uint256 temp1;\n                        uint256 temp2;\n                        e \u0026= 0xffffffff_ffffffff;\n                        {\n                            uint256 ss = e | (e \u003c\u003c 64);\n                            uint256 s1 = (ss \u003e\u003e 14) ^ (ss \u003e\u003e 18) ^ (ss \u003e\u003e 41);\n                            uint256 ch = (e \u0026 (f ^ g)) ^ g;\n                            temp1 = h + s1 + ch;\n                        }\n                        temp1 += kk[11][i];\n                        temp1 += w2;\n                        a \u0026= 0xffffffff_ffffffff;\n                        {\n                            uint256 ss = a | (a \u003c\u003c 64);\n                            uint256 s0 = (ss \u003e\u003e 28) ^ (ss \u003e\u003e 34) ^ (ss \u003e\u003e 39);\n                            uint256 maj = (a \u0026 (b | c)) | (b \u0026 c);\n                            temp2 = s0 + maj;\n                        }\n                        h = g;\n                        g = f;\n                        f = e;\n                        e = d + temp1;\n                        d = c;\n                        c = b;\n                        b = a;\n                        a = temp1 + temp2;\n                    }\n                    // Round 16 * i + 12\n                    {\n                        uint256 temp1;\n                        uint256 temp2;\n                        e \u0026= 0xffffffff_ffffffff;\n                        {\n                            uint256 ss = e | (e \u003c\u003c 64);\n                            uint256 s1 = (ss \u003e\u003e 14) ^ (ss \u003e\u003e 18) ^ (ss \u003e\u003e 41);\n                            uint256 ch = (e \u0026 (f ^ g)) ^ g;\n                            temp1 = h + s1 + ch;\n                        }\n                        temp1 += kk[12][i];\n                        temp1 += w3 \u003e\u003e 192;\n                        a \u0026= 0xffffffff_ffffffff;\n                        {\n                            uint256 ss = a | (a \u003c\u003c 64);\n                            uint256 s0 = (ss \u003e\u003e 28) ^ (ss \u003e\u003e 34) ^ (ss \u003e\u003e 39);\n                            uint256 maj = (a \u0026 (b | c)) | (b \u0026 c);\n                            temp2 = s0 + maj;\n                        }\n                        h = g;\n                        g = f;\n                        f = e;\n                        e = d + temp1;\n                        d = c;\n                        c = b;\n                        b = a;\n                        a = temp1 + temp2;\n                    }\n                    // Round 16 * i + 13\n                    {\n                        uint256 temp1;\n                        uint256 temp2;\n                        e \u0026= 0xffffffff_ffffffff;\n                        {\n                            uint256 ss = e | (e \u003c\u003c 64);\n                            uint256 s1 = (ss \u003e\u003e 14) ^ (ss \u003e\u003e 18) ^ (ss \u003e\u003e 41);\n                            uint256 ch = (e \u0026 (f ^ g)) ^ g;\n                            temp1 = h + s1 + ch;\n                        }\n                        temp1 += kk[13][i];\n                        temp1 += w3 \u003e\u003e 64;\n                        a \u0026= 0xffffffff_ffffffff;\n                        {\n                            uint256 ss = a | (a \u003c\u003c 64);\n                            uint256 s0 = (ss \u003e\u003e 28) ^ (ss \u003e\u003e 34) ^ (ss \u003e\u003e 39);\n                            uint256 maj = (a \u0026 (b | c)) | (b \u0026 c);\n                            temp2 = s0 + maj;\n                        }\n                        h = g;\n                        g = f;\n                        f = e;\n                        e = d + temp1;\n                        d = c;\n                        c = b;\n                        b = a;\n                        a = temp1 + temp2;\n                    }\n                    // Round 16 * i + 14\n                    {\n                        uint256 temp1;\n                        uint256 temp2;\n                        e \u0026= 0xffffffff_ffffffff;\n                        {\n                            uint256 ss = e | (e \u003c\u003c 64);\n                            uint256 s1 = (ss \u003e\u003e 14) ^ (ss \u003e\u003e 18) ^ (ss \u003e\u003e 41);\n                            uint256 ch = (e \u0026 (f ^ g)) ^ g;\n                            temp1 = h + s1 + ch;\n                        }\n                        temp1 += kk[14][i];\n                        temp1 += w3 \u003e\u003e 128;\n                        a \u0026= 0xffffffff_ffffffff;\n                        {\n                            uint256 ss = a | (a \u003c\u003c 64);\n                            uint256 s0 = (ss \u003e\u003e 28) ^ (ss \u003e\u003e 34) ^ (ss \u003e\u003e 39);\n                            uint256 maj = (a \u0026 (b | c)) | (b \u0026 c);\n                            temp2 = s0 + maj;\n                        }\n                        h = g;\n                        g = f;\n                        f = e;\n                        e = d + temp1;\n                        d = c;\n                        c = b;\n                        b = a;\n                        a = temp1 + temp2;\n                    }\n                    // Round 16 * i + 15\n                    {\n                        uint256 temp1;\n                        uint256 temp2;\n                        e \u0026= 0xffffffff_ffffffff;\n                        {\n                            uint256 ss = e | (e \u003c\u003c 64);\n                            uint256 s1 = (ss \u003e\u003e 14) ^ (ss \u003e\u003e 18) ^ (ss \u003e\u003e 41);\n                            uint256 ch = (e \u0026 (f ^ g)) ^ g;\n                            temp1 = h + s1 + ch;\n                        }\n                        temp1 += kk[15][i];\n                        temp1 += w3;\n                        a \u0026= 0xffffffff_ffffffff;\n                        {\n                            uint256 ss = a | (a \u003c\u003c 64);\n                            uint256 s0 = (ss \u003e\u003e 28) ^ (ss \u003e\u003e 34) ^ (ss \u003e\u003e 39);\n                            uint256 maj = (a \u0026 (b | c)) | (b \u0026 c);\n                            temp2 = s0 + maj;\n                        }\n                        h = g;\n                        g = f;\n                        f = e;\n                        e = d + temp1;\n                        d = c;\n                        c = b;\n                        b = a;\n                        a = temp1 + temp2;\n                    }\n                    if (i == 4) {\n                        break;\n                    }\n                    // Message expansion\n                    uint256 t0 = w0;\n                    uint256 t1 = w1;\n                    {\n                        uint256 t2 = w2;\n                        uint256 t3 = w3;\n                        {\n                            uint256 n1 = t0 \u0026 0xffffffff_ffffffff_00000000_00000000_ffffffff_ffffffff_00000000_00000000;\n                            n1 +=\n                                ((t2 \u0026 0xffffffff_ffffffff_00000000_00000000) \u003c\u003c 128) |\n                                ((t2 \u0026 0xffffffff_ffffffff_00000000_00000000_00000000_00000000) \u003e\u003e 64);\n                            {\n                                uint256 u1 = ((t0 \u0026 0xffffffff_ffffffff_00000000_00000000) \u003c\u003c 64) |\n                                    ((t0 \u0026 0xffffffff_ffffffff_00000000_00000000_00000000_00000000) \u003e\u003e 128);\n                                uint256 uu1 = u1 | (u1 \u003c\u003c 64);\n                                n1 +=\n                                    ((uu1 \u003c\u003c 63) ^ (uu1 \u003c\u003c 56) ^ (u1 \u003c\u003c 57)) \u0026\n                                    0xffffffff_ffffffff_00000000_00000000_ffffffff_ffffffff_00000000_00000000;\n                            }\n                            {\n                                uint256 v1 = t3 \u0026 0xffffffff_ffffffff_00000000_00000000_ffffffff_ffffffff;\n                                uint256 vv1 = v1 | (v1 \u003c\u003c 64);\n                                n1 +=\n                                    ((vv1 \u003c\u003c 45) ^ (vv1 \u003c\u003c 3) ^ (v1 \u003c\u003c 58)) \u0026\n                                    0xffffffff_ffffffff_00000000_00000000_ffffffff_ffffffff_00000000_00000000;\n                            }\n                            n1 \u0026= 0xffffffff_ffffffff_00000000_00000000_ffffffff_ffffffff_00000000_00000000;\n                            uint256 n2 = t0 \u0026 0xffffffff_ffffffff_00000000_00000000_ffffffff_ffffffff;\n                            n2 += ((t2 \u0026 0xffffffff_ffffffff) \u003c\u003c 128) | (t3 \u003e\u003e 192);\n                            {\n                                uint256 u2 = ((t0 \u0026 0xffffffff_ffffffff) \u003c\u003c 128) | (t1 \u003e\u003e 192);\n                                uint256 uu2 = u2 | (u2 \u003c\u003c 64);\n                                n2 +=\n                                    ((uu2 \u003e\u003e 1) ^ (uu2 \u003e\u003e 8) ^ (u2 \u003e\u003e 7)) \u0026\n                                    0xffffffff_ffffffff_00000000_00000000_ffffffff_ffffffff;\n                            }\n                            {\n                                uint256 vv2 = n1 | (n1 \u003e\u003e 64);\n                                n2 +=\n                                    ((vv2 \u003e\u003e 19) ^ (vv2 \u003e\u003e 61) ^ (n1 \u003e\u003e 70)) \u0026\n                                    0xffffffff_ffffffff_00000000_00000000_ffffffff_ffffffff;\n                            }\n                            n2 \u0026= 0xffffffff_ffffffff_00000000_00000000_ffffffff_ffffffff;\n                            t0 = n1 | n2;\n                        }\n                        {\n                            uint256 n1 = t1 \u0026 0xffffffff_ffffffff_00000000_00000000_ffffffff_ffffffff_00000000_00000000;\n                            n1 +=\n                                ((t3 \u0026 0xffffffff_ffffffff_00000000_00000000) \u003c\u003c 128) |\n                                ((t3 \u0026 0xffffffff_ffffffff_00000000_00000000_00000000_00000000) \u003e\u003e 64);\n                            {\n                                uint256 u1 = ((t1 \u0026 0xffffffff_ffffffff_00000000_00000000) \u003c\u003c 64) |\n                                    ((t1 \u0026 0xffffffff_ffffffff_00000000_00000000_00000000_00000000) \u003e\u003e 128);\n                                uint256 uu1 = u1 | (u1 \u003c\u003c 64);\n                                n1 +=\n                                    ((uu1 \u003c\u003c 63) ^ (uu1 \u003c\u003c 56) ^ (u1 \u003c\u003c 57)) \u0026\n                                    0xffffffff_ffffffff_00000000_00000000_ffffffff_ffffffff_00000000_00000000;\n                            }\n                            {\n                                uint256 v1 = t0 \u0026 0xffffffff_ffffffff_00000000_00000000_ffffffff_ffffffff;\n                                uint256 vv1 = v1 | (v1 \u003c\u003c 64);\n                                n1 +=\n                                    ((vv1 \u003c\u003c 45) ^ (vv1 \u003c\u003c 3) ^ (v1 \u003c\u003c 58)) \u0026\n                                    0xffffffff_ffffffff_00000000_00000000_ffffffff_ffffffff_00000000_00000000;\n                            }\n                            n1 \u0026= 0xffffffff_ffffffff_00000000_00000000_ffffffff_ffffffff_00000000_00000000;\n                            uint256 n2 = t1 \u0026 0xffffffff_ffffffff_00000000_00000000_ffffffff_ffffffff;\n                            n2 += ((t3 \u0026 0xffffffff_ffffffff) \u003c\u003c 128) | (t0 \u003e\u003e 192);\n                            {\n                                uint256 u2 = ((t1 \u0026 0xffffffff_ffffffff) \u003c\u003c 128) | (t2 \u003e\u003e 192);\n                                uint256 uu2 = u2 | (u2 \u003c\u003c 64);\n                                n2 +=\n                                    ((uu2 \u003e\u003e 1) ^ (uu2 \u003e\u003e 8) ^ (u2 \u003e\u003e 7)) \u0026\n                                    0xffffffff_ffffffff_00000000_00000000_ffffffff_ffffffff;\n                            }\n                            {\n                                uint256 vv2 = n1 | (n1 \u003e\u003e 64);\n                                n2 +=\n                                    ((vv2 \u003e\u003e 19) ^ (vv2 \u003e\u003e 61) ^ (n1 \u003e\u003e 70)) \u0026\n                                    0xffffffff_ffffffff_00000000_00000000_ffffffff_ffffffff;\n                            }\n                            n2 \u0026= 0xffffffff_ffffffff_00000000_00000000_ffffffff_ffffffff;\n                            t1 = n1 | n2;\n                        }\n                        {\n                            uint256 n1 = t2 \u0026 0xffffffff_ffffffff_00000000_00000000_ffffffff_ffffffff_00000000_00000000;\n                            n1 +=\n                                ((t0 \u0026 0xffffffff_ffffffff_00000000_00000000) \u003c\u003c 128) |\n                                ((t0 \u0026 0xffffffff_ffffffff_00000000_00000000_00000000_00000000) \u003e\u003e 64);\n                            {\n                                uint256 u1 = ((t2 \u0026 0xffffffff_ffffffff_00000000_00000000) \u003c\u003c 64) |\n                                    ((t2 \u0026 0xffffffff_ffffffff_00000000_00000000_00000000_00000000) \u003e\u003e 128);\n                                uint256 uu1 = u1 | (u1 \u003c\u003c 64);\n                                n1 +=\n                                    ((uu1 \u003c\u003c 63) ^ (uu1 \u003c\u003c 56) ^ (u1 \u003c\u003c 57)) \u0026\n                                    0xffffffff_ffffffff_00000000_00000000_ffffffff_ffffffff_00000000_00000000;\n                            }\n                            {\n                                uint256 v1 = t1 \u0026 0xffffffff_ffffffff_00000000_00000000_ffffffff_ffffffff;\n                                uint256 vv1 = v1 | (v1 \u003c\u003c 64);\n                                n1 +=\n                                    ((vv1 \u003c\u003c 45) ^ (vv1 \u003c\u003c 3) ^ (v1 \u003c\u003c 58)) \u0026\n                                    0xffffffff_ffffffff_00000000_00000000_ffffffff_ffffffff_00000000_00000000;\n                            }\n                            n1 \u0026= 0xffffffff_ffffffff_00000000_00000000_ffffffff_ffffffff_00000000_00000000;\n                            uint256 n2 = t2 \u0026 0xffffffff_ffffffff_00000000_00000000_ffffffff_ffffffff;\n                            n2 += ((t0 \u0026 0xffffffff_ffffffff) \u003c\u003c 128) | (t1 \u003e\u003e 192);\n                            {\n                                uint256 u2 = ((t2 \u0026 0xffffffff_ffffffff) \u003c\u003c 128) | (t3 \u003e\u003e 192);\n                                uint256 uu2 = u2 | (u2 \u003c\u003c 64);\n                                n2 +=\n                                    ((uu2 \u003e\u003e 1) ^ (uu2 \u003e\u003e 8) ^ (u2 \u003e\u003e 7)) \u0026\n                                    0xffffffff_ffffffff_00000000_00000000_ffffffff_ffffffff;\n                            }\n                            {\n                                uint256 vv2 = n1 | (n1 \u003e\u003e 64);\n                                n2 +=\n                                    ((vv2 \u003e\u003e 19) ^ (vv2 \u003e\u003e 61) ^ (n1 \u003e\u003e 70)) \u0026\n                                    0xffffffff_ffffffff_00000000_00000000_ffffffff_ffffffff;\n                            }\n                            n2 \u0026= 0xffffffff_ffffffff_00000000_00000000_ffffffff_ffffffff;\n                            t2 = n1 | n2;\n                        }\n                        {\n                            uint256 n1 = t3 \u0026 0xffffffff_ffffffff_00000000_00000000_ffffffff_ffffffff_00000000_00000000;\n                            n1 +=\n                                ((t1 \u0026 0xffffffff_ffffffff_00000000_00000000) \u003c\u003c 128) |\n                                ((t1 \u0026 0xffffffff_ffffffff_00000000_00000000_00000000_00000000) \u003e\u003e 64);\n                            {\n                                uint256 u1 = ((t3 \u0026 0xffffffff_ffffffff_00000000_00000000) \u003c\u003c 64) |\n                                    ((t3 \u0026 0xffffffff_ffffffff_00000000_00000000_00000000_00000000) \u003e\u003e 128);\n                                uint256 uu1 = u1 | (u1 \u003c\u003c 64);\n                                n1 +=\n                                    ((uu1 \u003c\u003c 63) ^ (uu1 \u003c\u003c 56) ^ (u1 \u003c\u003c 57)) \u0026\n                                    0xffffffff_ffffffff_00000000_00000000_ffffffff_ffffffff_00000000_00000000;\n                            }\n                            {\n                                uint256 v1 = t2 \u0026 0xffffffff_ffffffff_00000000_00000000_ffffffff_ffffffff;\n                                uint256 vv1 = v1 | (v1 \u003c\u003c 64);\n                                n1 +=\n                                    ((vv1 \u003c\u003c 45) ^ (vv1 \u003c\u003c 3) ^ (v1 \u003c\u003c 58)) \u0026\n                                    0xffffffff_ffffffff_00000000_00000000_ffffffff_ffffffff_00000000_00000000;\n                            }\n                            n1 \u0026= 0xffffffff_ffffffff_00000000_00000000_ffffffff_ffffffff_00000000_00000000;\n                            uint256 n2 = t3 \u0026 0xffffffff_ffffffff_00000000_00000000_ffffffff_ffffffff;\n                            n2 += ((t1 \u0026 0xffffffff_ffffffff) \u003c\u003c 128) | (t2 \u003e\u003e 192);\n                            {\n                                uint256 u2 = ((t3 \u0026 0xffffffff_ffffffff) \u003c\u003c 128) | (t0 \u003e\u003e 192);\n                                uint256 uu2 = u2 | (u2 \u003c\u003c 64);\n                                n2 +=\n                                    ((uu2 \u003e\u003e 1) ^ (uu2 \u003e\u003e 8) ^ (u2 \u003e\u003e 7)) \u0026\n                                    0xffffffff_ffffffff_00000000_00000000_ffffffff_ffffffff;\n                            }\n                            {\n                                uint256 vv2 = n1 | (n1 \u003e\u003e 64);\n                                n2 +=\n                                    ((vv2 \u003e\u003e 19) ^ (vv2 \u003e\u003e 61) ^ (n1 \u003e\u003e 70)) \u0026\n                                    0xffffffff_ffffffff_00000000_00000000_ffffffff_ffffffff;\n                            }\n                            n2 \u0026= 0xffffffff_ffffffff_00000000_00000000_ffffffff_ffffffff;\n                            t3 = n1 | n2;\n                        }\n                        w3 = t3;\n                        w2 = t2;\n                    }\n                    w1 = t1;\n                    w0 = t0;\n                }\n                uint256 h0 = ((a + 0x6a09e667_f3bcc908) \u0026 0xffffffff_ffffffff) |\n                    (((b + 0xbb67ae85_84caa73b) \u0026 0xffffffff_ffffffff) \u003c\u003c 64) |\n                    (((c + 0x3c6ef372_fe94f82b) \u0026 0xffffffff_ffffffff) \u003c\u003c 128) |\n                    ((d + 0xa54ff53a_5f1d36f1) \u003c\u003c 192);\n                h0 =\n                    ((h0 \u0026 0xff00ff_00ff00ff_00ff00ff_00ff00ff_00ff00ff_00ff00ff_00ff00ff_00ff00ff) \u003c\u003c 8) |\n                    ((h0 \u0026 0xff00ff00_ff00ff00_ff00ff00_ff00ff00_ff00ff00_ff00ff00_ff00ff00_ff00ff00) \u003e\u003e 8);\n                h0 =\n                    ((h0 \u0026 0xffff_0000ffff_0000ffff_0000ffff_0000ffff_0000ffff_0000ffff_0000ffff) \u003c\u003c 16) |\n                    ((h0 \u0026 0xffff0000_ffff0000_ffff0000_ffff0000_ffff0000_ffff0000_ffff0000_ffff0000) \u003e\u003e 16);\n                h0 =\n                    ((h0 \u0026 0xffffffff_00000000_ffffffff_00000000_ffffffff_00000000_ffffffff) \u003c\u003c 32) |\n                    ((h0 \u0026 0xffffffff_00000000_ffffffff_00000000_ffffffff_00000000_ffffffff_00000000) \u003e\u003e 32);\n                uint256 h1 = ((e + 0x510e527f_ade682d1) \u0026 0xffffffff_ffffffff) |\n                    (((f + 0x9b05688c_2b3e6c1f) \u0026 0xffffffff_ffffffff) \u003c\u003c 64) |\n                    (((g + 0x1f83d9ab_fb41bd6b) \u0026 0xffffffff_ffffffff) \u003c\u003c 128) |\n                    ((h + 0x5be0cd19_137e2179) \u003c\u003c 192);\n                h1 =\n                    ((h1 \u0026 0xff00ff_00ff00ff_00ff00ff_00ff00ff_00ff00ff_00ff00ff_00ff00ff_00ff00ff) \u003c\u003c 8) |\n                    ((h1 \u0026 0xff00ff00_ff00ff00_ff00ff00_ff00ff00_ff00ff00_ff00ff00_ff00ff00_ff00ff00) \u003e\u003e 8);\n                h1 =\n                    ((h1 \u0026 0xffff_0000ffff_0000ffff_0000ffff_0000ffff_0000ffff_0000ffff_0000ffff) \u003c\u003c 16) |\n                    ((h1 \u0026 0xffff0000_ffff0000_ffff0000_ffff0000_ffff0000_ffff0000_ffff0000_ffff0000) \u003e\u003e 16);\n                h1 =\n                    ((h1 \u0026 0xffffffff_00000000_ffffffff_00000000_ffffffff_00000000_ffffffff) \u003c\u003c 32) |\n                    ((h1 \u0026 0xffffffff_00000000_ffffffff_00000000_ffffffff_00000000_ffffffff_00000000) \u003e\u003e 32);\n                hh = addmod(\n                    h0,\n                    mulmod(\n                        h1,\n                        0xfffffff_ffffffff_ffffffff_fffffffe_c6ef5bf4_737dcf70_d6ec3174_8d98951d,\n                        0x10000000_00000000_00000000_00000000_14def9de_a2f79cd6_5812631a_5cf5d3ed\n                    ),\n                    0x10000000_00000000_00000000_00000000_14def9de_a2f79cd6_5812631a_5cf5d3ed\n                );\n            }\n            // Step 2: unpack k\n            k = bytes32(\n                ((uint256(k) \u0026 0xff00ff_00ff00ff_00ff00ff_00ff00ff_00ff00ff_00ff00ff_00ff00ff_00ff00ff) \u003c\u003c 8) |\n                    ((uint256(k) \u0026 0xff00ff00_ff00ff00_ff00ff00_ff00ff00_ff00ff00_ff00ff00_ff00ff00_ff00ff00) \u003e\u003e 8)\n            );\n            k = bytes32(\n                ((uint256(k) \u0026 0xffff_0000ffff_0000ffff_0000ffff_0000ffff_0000ffff_0000ffff_0000ffff) \u003c\u003c 16) |\n                    ((uint256(k) \u0026 0xffff0000_ffff0000_ffff0000_ffff0000_ffff0000_ffff0000_ffff0000_ffff0000) \u003e\u003e 16)\n            );\n            k = bytes32(\n                ((uint256(k) \u0026 0xffffffff_00000000_ffffffff_00000000_ffffffff_00000000_ffffffff) \u003c\u003c 32) |\n                    ((uint256(k) \u0026 0xffffffff_00000000_ffffffff_00000000_ffffffff_00000000_ffffffff_00000000) \u003e\u003e 32)\n            );\n            k = bytes32(\n                ((uint256(k) \u0026 0xffffffff_ffffffff_00000000_00000000_ffffffff_ffffffff) \u003c\u003c 64) |\n                    ((uint256(k) \u0026 0xffffffff_ffffffff_00000000_00000000_ffffffff_ffffffff_00000000_00000000) \u003e\u003e 64)\n            );\n            k = bytes32((uint256(k) \u003c\u003c 128) | (uint256(k) \u003e\u003e 128));\n            uint256 ky = uint256(k) \u0026 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff;\n            uint256 kx;\n            {\n                uint256 ky2 = mulmod(ky, ky, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n                uint256 u = addmod(\n                    ky2,\n                    0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffec,\n                    0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed\n                );\n                uint256 v = mulmod(\n                    ky2,\n                    0x52036cee_2b6ffe73_8cc74079_7779e898_00700a4d_4141d8ab_75eb4dca_135978a3,\n                    0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed\n                ) + 1;\n                uint256 t = mulmod(u, v, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n                (kx, ) = pow22501(t);\n                kx = mulmod(kx, kx, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n                kx = mulmod(\n                    u,\n                    mulmod(\n                        mulmod(kx, kx, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed),\n                        t,\n                        0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed\n                    ),\n                    0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed\n                );\n                t = mulmod(\n                    mulmod(kx, kx, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed),\n                    v,\n                    0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed\n                );\n                if (t != u) {\n                    if (t != 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed - u) {\n                        return false;\n                    }\n                    kx = mulmod(\n                        kx,\n                        0x2b832480_4fc1df0b_2b4d0099_3dfbd7a7_2f431806_ad2fe478_c4ee1b27_4a0ea0b0,\n                        0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed\n                    );\n                }\n            }\n            if ((kx \u0026 1) != uint256(k) \u003e\u003e 255) {\n                kx = 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed - kx;\n            }\n            // Verify s\n            s = bytes32(\n                ((uint256(s) \u0026 0xff00ff_00ff00ff_00ff00ff_00ff00ff_00ff00ff_00ff00ff_00ff00ff_00ff00ff) \u003c\u003c 8) |\n                    ((uint256(s) \u0026 0xff00ff00_ff00ff00_ff00ff00_ff00ff00_ff00ff00_ff00ff00_ff00ff00_ff00ff00) \u003e\u003e 8)\n            );\n            s = bytes32(\n                ((uint256(s) \u0026 0xffff_0000ffff_0000ffff_0000ffff_0000ffff_0000ffff_0000ffff_0000ffff) \u003c\u003c 16) |\n                    ((uint256(s) \u0026 0xffff0000_ffff0000_ffff0000_ffff0000_ffff0000_ffff0000_ffff0000_ffff0000) \u003e\u003e 16)\n            );\n            s = bytes32(\n                ((uint256(s) \u0026 0xffffffff_00000000_ffffffff_00000000_ffffffff_00000000_ffffffff) \u003c\u003c 32) |\n                    ((uint256(s) \u0026 0xffffffff_00000000_ffffffff_00000000_ffffffff_00000000_ffffffff_00000000) \u003e\u003e 32)\n            );\n            s = bytes32(\n                ((uint256(s) \u0026 0xffffffff_ffffffff_00000000_00000000_ffffffff_ffffffff) \u003c\u003c 64) |\n                    ((uint256(s) \u0026 0xffffffff_ffffffff_00000000_00000000_ffffffff_ffffffff_00000000_00000000) \u003e\u003e 64)\n            );\n            s = bytes32((uint256(s) \u003c\u003c 128) | (uint256(s) \u003e\u003e 128));\n            if (uint256(s) \u003e= 0x10000000_00000000_00000000_00000000_14def9de_a2f79cd6_5812631a_5cf5d3ed) {\n                return false;\n            }\n            uint256 vx;\n            uint256 vu;\n            uint256 vy;\n            uint256 vv;\n            // Step 3: compute multiples of k\n            uint256[8][3][2] memory tables;\n            {\n                uint256 ks = ky + kx;\n                uint256 kd = ky + 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed - kx;\n                uint256 k2dt = mulmod(\n                    mulmod(kx, ky, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed),\n                    0x2406d9dc_56dffce7_198e80f2_eef3d130_00e0149a_8283b156_ebd69b94_26b2f159,\n                    0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed\n                );\n                uint256 kky = ky;\n                uint256 kkx = kx;\n                uint256 kku = 1;\n                uint256 kkv = 1;\n                {\n                    uint256 xx = mulmod(\n                        kkx,\n                        kkv,\n                        0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed\n                    );\n                    uint256 yy = mulmod(\n                        kky,\n                        kku,\n                        0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed\n                    );\n                    uint256 zz = mulmod(\n                        kku,\n                        kkv,\n                        0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed\n                    );\n                    uint256 xx2 = mulmod(\n                        xx,\n                        xx,\n                        0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed\n                    );\n                    uint256 yy2 = mulmod(\n                        yy,\n                        yy,\n                        0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed\n                    );\n                    uint256 xxyy = mulmod(\n                        xx,\n                        yy,\n                        0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed\n                    );\n                    uint256 zz2 = mulmod(\n                        zz,\n                        zz,\n                        0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed\n                    );\n                    kkx = xxyy + xxyy;\n                    kku = yy2 - xx2 + 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed;\n                    kky = xx2 + yy2;\n                    kkv = addmod(\n                        zz2 + zz2,\n                        0xffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffda - kku,\n                        0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed\n                    );\n                }\n                {\n                    uint256 xx = mulmod(\n                        kkx,\n                        kkv,\n                        0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed\n                    );\n                    uint256 yy = mulmod(\n                        kky,\n                        kku,\n                        0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed\n                    );\n                    uint256 zz = mulmod(\n                        kku,\n                        kkv,\n                        0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed\n                    );\n                    uint256 xx2 = mulmod(\n                        xx,\n                        xx,\n                        0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed\n                    );\n                    uint256 yy2 = mulmod(\n                        yy,\n                        yy,\n                        0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed\n                    );\n                    uint256 xxyy = mulmod(\n                        xx,\n                        yy,\n                        0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed\n                    );\n                    uint256 zz2 = mulmod(\n                        zz,\n                        zz,\n                        0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed\n                    );\n                    kkx = xxyy + xxyy;\n                    kku = yy2 - xx2 + 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed;\n                    kky = xx2 + yy2;\n                    kkv = addmod(\n                        zz2 + zz2,\n                        0xffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffda - kku,\n                        0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed\n                    );\n                }\n                {\n                    uint256 xx = mulmod(\n                        kkx,\n                        kkv,\n                        0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed\n                    );\n                    uint256 yy = mulmod(\n                        kky,\n                        kku,\n                        0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed\n                    );\n                    uint256 zz = mulmod(\n                        kku,\n                        kkv,\n                        0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed\n                    );\n                    uint256 xx2 = mulmod(\n                        xx,\n                        xx,\n                        0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed\n                    );\n                    uint256 yy2 = mulmod(\n                        yy,\n                        yy,\n                        0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed\n                    );\n                    uint256 xxyy = mulmod(\n                        xx,\n                        yy,\n                        0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed\n                    );\n                    uint256 zz2 = mulmod(\n                        zz,\n                        zz,\n                        0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed\n                    );\n                    kkx = xxyy + xxyy;\n                    kku = yy2 - xx2 + 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed;\n                    kky = xx2 + yy2;\n                    kkv = addmod(\n                        zz2 + zz2,\n                        0xffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffda - kku,\n                        0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed\n                    );\n                }\n                uint256 cprod = 1;\n                uint256[8][3][2] memory tables_ = tables;\n                for (uint256 i = 0; ; i++) {\n                    uint256 cs;\n                    uint256 cd;\n                    uint256 ct;\n                    uint256 c2z;\n                    {\n                        uint256 cx = mulmod(\n                            kkx,\n                            kkv,\n                            0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed\n                        );\n                        uint256 cy = mulmod(\n                            kky,\n                            kku,\n                            0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed\n                        );\n                        uint256 cz = mulmod(\n                            kku,\n                            kkv,\n                            0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed\n                        );\n                        ct = mulmod(\n                            kkx,\n                            kky,\n                            0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed\n                        );\n                        cs = cy + cx;\n                        cd = cy - cx + 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed;\n                        c2z = cz + cz;\n                    }\n                    tables_[1][0][i] = cs;\n                    tables_[1][1][i] = cd;\n                    tables_[1][2][i] = mulmod(\n                        ct,\n                        0x2406d9dc_56dffce7_198e80f2_eef3d130_00e0149a_8283b156_ebd69b94_26b2f159,\n                        0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed\n                    );\n                    tables_[0][0][i] = c2z;\n                    tables_[0][1][i] = cprod;\n                    cprod = mulmod(\n                        cprod,\n                        c2z,\n                        0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed\n                    );\n                    if (i == 7) {\n                        break;\n                    }\n                    uint256 ab = mulmod(\n                        cs,\n                        ks,\n                        0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed\n                    );\n                    uint256 aa = mulmod(\n                        cd,\n                        kd,\n                        0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed\n                    );\n                    uint256 ac = mulmod(\n                        ct,\n                        k2dt,\n                        0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed\n                    );\n                    kkx = ab - aa + 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed;\n                    kku = addmod(c2z, ac, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n                    kky = ab + aa;\n                    kkv = addmod(\n                        c2z,\n                        0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed - ac,\n                        0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed\n                    );\n                }\n                uint256 t;\n                (cprod, t) = pow22501(cprod);\n                cprod = mulmod(cprod, cprod, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n                cprod = mulmod(cprod, cprod, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n                cprod = mulmod(cprod, cprod, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n                cprod = mulmod(cprod, cprod, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n                cprod = mulmod(cprod, cprod, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n                cprod = mulmod(cprod, t, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n                for (uint256 i = 7; ; i--) {\n                    uint256 cinv = mulmod(\n                        cprod,\n                        tables_[0][1][i],\n                        0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed\n                    );\n                    tables_[1][0][i] = mulmod(\n                        tables_[1][0][i],\n                        cinv,\n                        0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed\n                    );\n                    tables_[1][1][i] = mulmod(\n                        tables_[1][1][i],\n                        cinv,\n                        0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed\n                    );\n                    tables_[1][2][i] = mulmod(\n                        tables_[1][2][i],\n                        cinv,\n                        0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed\n                    );\n                    if (i == 0) {\n                        break;\n                    }\n                    cprod = mulmod(\n                        cprod,\n                        tables_[0][0][i],\n                        0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed\n                    );\n                }\n                tables_[0] = [\n                    [\n                        0x43e7ce9d_19ea5d32_9385a44c_321ea161_67c996e3_7dc6070c_97de49e3_7ac61db9,\n                        0x40cff344_25d8ec30_a3bb74ba_58cd5854_fa1e3818_6ad0d31e_bc8ae251_ceb2c97e,\n                        0x459bd270_46e8dd45_aea7008d_b87a5a8f_79067792_53d64523_58951859_9fdfbf4b,\n                        0x69fdd1e2_8c23cc38_94d0c8ff_90e76f6d_5b6e4c2e_620136d0_4dd83c4a_51581ab9,\n                        0x54dceb34_13ce5cfa_11196dfc_960b6eda_f4b380c6_d4d23784_19cc0279_ba49c5f3,\n                        0x4e24184d_d71a3d77_eef3729f_7f8cf7c1_7224cf40_aa7b9548_b9942f3c_5084ceed,\n                        0x5a0e5aab_20262674_ae117576_1cbf5e88_9b52a55f_d7ac5027_c228cebd_c8d2360a,\n                        0x26239334_073e9b38_c6285955_6d451c3d_cc8d30e8_4b361174_f488eadd_e2cf17d9\n                    ],\n                    [\n                        0x227e97c9_4c7c0933_d2e0c21a_3447c504_fe9ccf82_e8a05f59_ce881c82_eba0489f,\n                        0x226a3e0e_cc4afec6_fd0d2884_13014a9d_bddecf06_c1a2f0bb_702ba77c_613d8209,\n                        0x34d7efc8_51d45c5e_71efeb0f_235b7946_91de6228_877569b3_a8d52bf0_58b8a4a0,\n                        0x3c1f5fb3_ca7166fc_e1471c9b_752b6d28_c56301ad_7b65e845_1b2c8c55_26726e12,\n                        0x6102416c_f02f02ff_5be75275_f55f28db_89b2a9d2_456b860c_e22fc0e5_031f7cc5,\n                        0x40adf677_f1bfdae0_57f0fd17_9c126179_18ddaa28_91a6530f_b1a4294f_a8665490,\n                        0x61936f3c_41560904_6187b8ba_a978cbc9_b4789336_3ae5a3cc_7d909f36_35ae7f48,\n                        0x562a9662_b6ec47f9_e979d473_c02b51e4_42336823_8c58ddb5_2f0e5c6a_180e6410\n                    ],\n                    [\n                        0x3788bdb4_4f8632d4_2d0dbee5_eea1acc6_136cf411_e655624f_55e48902_c3bd5534,\n                        0x6190cf2c_2a7b5ad7_69d594a8_2844f23b_4167fa7c_8ac30e51_aa6cfbeb_dcd4b945,\n                        0x65f77870_96be9204_123a71f3_ac88a87b_e1513217_737d6a1e_2f3a13a4_3d7e3a9a,\n                        0x23af32d_bfa67975_536479a7_a7ce74a0_2142147f_ac048018_7f1f1334_9cda1f2d,\n                        0x64fc44b7_fc6841bd_db0ced8b_8b0fe675_9137ef87_ee966512_15fc1dbc_d25c64dc,\n                        0x1434aa37_48b701d5_b69df3d7_d340c1fe_3f6b9c1e_fc617484_caadb47e_382f4475,\n                        0x457a6da8_c962ef35_f2b21742_3e5844e9_d2353452_7e8ea429_0d24e3dd_f21720c6,\n                        0x63b9540c_eb60ccb5_1e4d989d_956e053c_f2511837_efb79089_d2ff4028_4202c53d\n                    ]\n                ];\n            }\n            // Step 4: compute s*G - h*A\n            {\n                uint256 ss = uint256(s) \u003c\u003c 3;\n                uint256 hhh = hh + 0x80000000_00000000_00000000_00000000_a6f7cef5_17bce6b2_c09318d2_e7ae9f60;\n                uint256 vvx = 0;\n                uint256 vvu = 1;\n                uint256 vvy = 1;\n                uint256 vvv = 1;\n                for (uint256 i = 252; ; i--) {\n                    uint256 bit = 8 \u003c\u003c i;\n                    if ((ss \u0026 bit) != 0) {\n                        uint256 ws;\n                        uint256 wd;\n                        uint256 wz;\n                        uint256 wt;\n                        {\n                            uint256 wx = mulmod(\n                                vvx,\n                                vvv,\n                                0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed\n                            );\n                            uint256 wy = mulmod(\n                                vvy,\n                                vvu,\n                                0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed\n                            );\n                            ws = wy + wx;\n                            wd = wy - wx + 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed;\n                            wz = mulmod(\n                                vvu,\n                                vvv,\n                                0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed\n                            );\n                            wt = mulmod(\n                                vvx,\n                                vvy,\n                                0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed\n                            );\n                        }\n                        uint256 j = (ss \u003e\u003e i) \u0026 7;\n                        ss \u0026= ~(7 \u003c\u003c i);\n                        uint256[8][3][2] memory tables_ = tables;\n                        uint256 aa = mulmod(\n                            wd,\n                            tables_[0][1][j],\n                            0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed\n                        );\n                        uint256 ab = mulmod(\n                            ws,\n                            tables_[0][0][j],\n                            0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed\n                        );\n                        uint256 ac = mulmod(\n                            wt,\n                            tables_[0][2][j],\n                            0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed\n                        );\n                        vvx = ab - aa + 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed;\n                        vvu = wz + ac;\n                        vvy = ab + aa;\n                        vvv = wz - ac + 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed;\n                    }\n                    if ((hhh \u0026 bit) != 0) {\n                        uint256 ws;\n                        uint256 wd;\n                        uint256 wz;\n                        uint256 wt;\n                        {\n                            uint256 wx = mulmod(\n                                vvx,\n                                vvv,\n                                0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed\n                            );\n                            uint256 wy = mulmod(\n                                vvy,\n                                vvu,\n                                0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed\n                            );\n                            ws = wy + wx;\n                            wd = wy - wx + 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed;\n                            wz = mulmod(\n                                vvu,\n                                vvv,\n                                0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed\n                            );\n                            wt = mulmod(\n                                vvx,\n                                vvy,\n                                0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed\n                            );\n                        }\n                        uint256 j = (hhh \u003e\u003e i) \u0026 7;\n                        hhh \u0026= ~(7 \u003c\u003c i);\n                        uint256[8][3][2] memory tables_ = tables;\n                        uint256 aa = mulmod(\n                            wd,\n                            tables_[1][0][j],\n                            0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed\n                        );\n                        uint256 ab = mulmod(\n                            ws,\n                            tables_[1][1][j],\n                            0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed\n                        );\n                        uint256 ac = mulmod(\n                            wt,\n                            tables_[1][2][j],\n                            0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed\n                        );\n                        vvx = ab - aa + 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed;\n                        vvu = wz - ac + 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed;\n                        vvy = ab + aa;\n                        vvv = wz + ac;\n                    }\n                    if (i == 0) {\n                        uint256 ws;\n                        uint256 wd;\n                        uint256 wz;\n                        uint256 wt;\n                        {\n                            uint256 wx = mulmod(\n                                vvx,\n                                vvv,\n                                0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed\n                            );\n                            uint256 wy = mulmod(\n                                vvy,\n                                vvu,\n                                0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed\n                            );\n                            ws = wy + wx;\n                            wd = wy - wx + 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed;\n                            wz = mulmod(\n                                vvu,\n                                vvv,\n                                0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed\n                            );\n                            wt = mulmod(\n                                vvx,\n                                vvy,\n                                0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed\n                            );\n                        }\n                        uint256 j = hhh \u0026 7;\n                        uint256[8][3][2] memory tables_ = tables;\n                        uint256 aa = mulmod(\n                            wd,\n                            tables_[1][0][j],\n                            0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed\n                        );\n                        uint256 ab = mulmod(\n                            ws,\n                            tables_[1][1][j],\n                            0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed\n                        );\n                        uint256 ac = mulmod(\n                            wt,\n                            tables_[1][2][j],\n                            0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed\n                        );\n                        vvx = ab - aa + 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed;\n                        vvu = wz - ac + 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed;\n                        vvy = ab + aa;\n                        vvv = wz + ac;\n                        break;\n                    }\n                    {\n                        uint256 xx = mulmod(\n                            vvx,\n                            vvv,\n                            0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed\n                        );\n                        uint256 yy = mulmod(\n                            vvy,\n                            vvu,\n                            0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed\n                        );\n                        uint256 zz = mulmod(\n                            vvu,\n                            vvv,\n                            0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed\n                        );\n                        uint256 xx2 = mulmod(\n                            xx,\n                            xx,\n                            0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed\n                        );\n                        uint256 yy2 = mulmod(\n                            yy,\n                            yy,\n                            0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed\n                        );\n                        uint256 xxyy = mulmod(\n                            xx,\n                            yy,\n                            0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed\n                        );\n                        uint256 zz2 = mulmod(\n                            zz,\n                            zz,\n                            0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed\n                        );\n                        vvx = xxyy + xxyy;\n                        vvu = yy2 - xx2 + 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed;\n                        vvy = xx2 + yy2;\n                        vvv = addmod(\n                            zz2 + zz2,\n                            0xffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffda - vvu,\n                            0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed\n                        );\n                    }\n                }\n                vx = vvx;\n                vu = vvu;\n                vy = vvy;\n                vv = vvv;\n            }\n            // Step 5: compare the points\n            (uint256 vi, uint256 vj) = pow22501(\n                mulmod(vu, vv, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed)\n            );\n            vi = mulmod(vi, vi, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n            vi = mulmod(vi, vi, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n            vi = mulmod(vi, vi, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n            vi = mulmod(vi, vi, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n            vi = mulmod(vi, vi, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n            vi = mulmod(vi, vj, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed);\n            vx = mulmod(\n                vx,\n                mulmod(vi, vv, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed),\n                0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed\n            );\n            vy = mulmod(\n                vy,\n                mulmod(vi, vu, 0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed),\n                0x7fffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffff_ffffffed\n            );\n            bytes32 vr = bytes32(vy | (vx \u003c\u003c 255));\n            vr = bytes32(\n                ((uint256(vr) \u0026 0xff00ff_00ff00ff_00ff00ff_00ff00ff_00ff00ff_00ff00ff_00ff00ff_00ff00ff) \u003c\u003c 8) |\n                    ((uint256(vr) \u0026 0xff00ff00_ff00ff00_ff00ff00_ff00ff00_ff00ff00_ff00ff00_ff00ff00_ff00ff00) \u003e\u003e 8)\n            );\n            vr = bytes32(\n                ((uint256(vr) \u0026 0xffff_0000ffff_0000ffff_0000ffff_0000ffff_0000ffff_0000ffff_0000ffff) \u003c\u003c 16) |\n                    ((uint256(vr) \u0026 0xffff0000_ffff0000_ffff0000_ffff0000_ffff0000_ffff0000_ffff0000_ffff0000) \u003e\u003e 16)\n            );\n            vr = bytes32(\n                ((uint256(vr) \u0026 0xffffffff_00000000_ffffffff_00000000_ffffffff_00000000_ffffffff) \u003c\u003c 32) |\n                    ((uint256(vr) \u0026 0xffffffff_00000000_ffffffff_00000000_ffffffff_00000000_ffffffff_00000000) \u003e\u003e 32)\n            );\n            vr = bytes32(\n                ((uint256(vr) \u0026 0xffffffff_ffffffff_00000000_00000000_ffffffff_ffffffff) \u003c\u003c 64) |\n                    ((uint256(vr) \u0026 0xffffffff_ffffffff_00000000_00000000_ffffffff_ffffffff_00000000_00000000) \u003e\u003e 64)\n            );\n            vr = bytes32((uint256(vr) \u003c\u003c 128) | (uint256(vr) \u003e\u003e 128));\n            return vr == r;\n        }\n    }\n}\n"},"INearBridge.sol":{"content":"// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity ^0.8;\n\ninterface INearBridge {\n    event BlockHashAdded(uint64 indexed height, bytes32 blockHash);\n\n    event BlockHashReverted(uint64 indexed height, bytes32 blockHash);\n\n    function blockHashes(uint64 blockNumber) external view returns (bytes32);\n\n    function blockMerkleRoots(uint64 blockNumber) external view returns (bytes32);\n\n    function balanceOf(address wallet) external view returns (uint256);\n\n    function deposit() external payable;\n\n    function withdraw() external;\n\n    function initWithValidators(bytes calldata initialValidators) external;\n\n    function initWithBlock(bytes calldata data) external;\n\n    function addLightClientBlock(bytes calldata data) external;\n\n    function challenge(address payable receiver, uint256 signatureIndex) external;\n\n    function checkBlockProducerSignatureInHead(uint256 signatureIndex) external view returns (bool);\n}\n"},"NearBridge.sol":{"content":"// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity ^0.8;\n\nimport \"./AdminControlled.sol\";\nimport \"./INearBridge.sol\";\nimport \"./NearDecoder.sol\";\nimport \"./Ed25519.sol\";\n\ncontract NearBridge is INearBridge, AdminControlled {\n    using Borsh for Borsh.Data;\n    using NearDecoder for Borsh.Data;\n\n    // Assumed to be even and to not exceed 256.\n    uint constant MAX_BLOCK_PRODUCERS = 100;\n\n    struct Epoch {\n        bytes32 epochId;\n        uint numBPs;\n        bytes32[MAX_BLOCK_PRODUCERS] keys;\n        bytes32[MAX_BLOCK_PRODUCERS / 2] packedStakes;\n        uint256 stakeThreshold;\n    }\n\n    // Whether the contract was initialized.\n    bool public initialized;\n    uint256 public lockEthAmount;\n    // lockDuration and replaceDuration shouldn\u0027t be extremely big, so adding them to an uint64 timestamp should not overflow uint256.\n    uint256 public lockDuration;\n    // replaceDuration is in nanoseconds, because it is a difference between NEAR timestamps.\n    uint256 public replaceDuration;\n    Ed25519 immutable edwards;\n\n    Epoch[3] epochs;\n    uint curEpoch;\n    uint64 curHeight;\n\n    // The most recently added block. May still be in its challenge period, so should not be trusted.\n    uint64 untrustedHeight;\n    uint256 untrustedTimestamp;\n    bool untrustedNextEpoch;\n    bytes32 untrustedHash;\n    bytes32 untrustedMerkleRoot;\n    bytes32 untrustedNextHash;\n    uint256 untrustedSignatureSet;\n    NearDecoder.Signature[MAX_BLOCK_PRODUCERS] untrustedSignatures;\n\n    // Address of the account which submitted the last block.\n    address lastSubmitter;\n    // End of challenge period. If zero, untrusted* fields and lastSubmitter are not meaningful.\n    uint public lastValidAt;\n\n    mapping(uint64 =\u003e bytes32) blockHashes_;\n    mapping(uint64 =\u003e bytes32) blockMerkleRoots_;\n    mapping(address =\u003e uint256) public override balanceOf;\n\n    constructor(\n        Ed25519 ed,\n        uint256 lockEthAmount_,\n        uint256 lockDuration_,\n        uint256 replaceDuration_,\n        address admin_,\n        uint256 pausedFlags_\n    ) AdminControlled(admin_, pausedFlags_) {\n        require(replaceDuration_ \u003e lockDuration_ * 1000000000);\n        edwards = ed;\n        lockEthAmount = lockEthAmount_;\n        lockDuration = lockDuration_;\n        replaceDuration = replaceDuration_;\n    }\n\n    uint constant UNPAUSE_ALL = 0;\n    uint constant PAUSED_DEPOSIT = 1;\n    uint constant PAUSED_WITHDRAW = 2;\n    uint constant PAUSED_ADD_BLOCK = 4;\n    uint constant PAUSED_CHALLENGE = 8;\n    uint constant PAUSED_VERIFY = 16;\n\n    function deposit() public payable override pausable(PAUSED_DEPOSIT) {\n        require(msg.value == lockEthAmount \u0026\u0026 balanceOf[msg.sender] == 0);\n        balanceOf[msg.sender] = msg.value;\n    }\n\n    function withdraw() public override pausable(PAUSED_WITHDRAW) {\n        require(msg.sender != lastSubmitter || block.timestamp \u003e= lastValidAt);\n        uint amount = balanceOf[msg.sender];\n        require(amount != 0);\n        balanceOf[msg.sender] = 0;\n        payable(msg.sender).transfer(amount);\n    }\n\n    function challenge(address payable receiver, uint signatureIndex) public override pausable(PAUSED_CHALLENGE) {\n        require(block.timestamp \u003c lastValidAt, \"No block can be challenged at this time\");\n        require(!checkBlockProducerSignatureInHead(signatureIndex), \"Can\u0027t challenge valid signature\");\n\n        balanceOf[lastSubmitter] = balanceOf[lastSubmitter] - lockEthAmount;\n        receiver.transfer(lockEthAmount / 2);\n        lastValidAt = 0;\n    }\n\n    function checkBlockProducerSignatureInHead(uint signatureIndex) public view override returns (bool) {\n        // Shifting by a number \u003e= 256 returns zero.\n        require((untrustedSignatureSet \u0026 (1 \u003c\u003c signatureIndex)) != 0, \"No such signature\");\n        unchecked {\n            Epoch storage untrustedEpoch = epochs[untrustedNextEpoch ? (curEpoch + 1) % 3 : curEpoch];\n            NearDecoder.Signature storage signature = untrustedSignatures[signatureIndex];\n            bytes memory message = abi.encodePacked(\n                uint8(0),\n                untrustedNextHash,\n                Utils.swapBytes8(untrustedHeight + 2),\n                bytes23(0)\n            );\n            (bytes32 arg1, bytes9 arg2) = abi.decode(message, (bytes32, bytes9));\n            return edwards.check(untrustedEpoch.keys[signatureIndex], signature.r, signature.s, arg1, arg2);\n        }\n    }\n\n    // The first part of initialization -- setting the validators of the current epoch.\n    function initWithValidators(bytes memory data) public override onlyAdmin {\n        require(!initialized \u0026\u0026 epochs[0].numBPs == 0, \"Wrong initialization stage\");\n\n        Borsh.Data memory borsh = Borsh.from(data);\n        NearDecoder.BlockProducer[] memory initialValidators = borsh.decodeBlockProducers();\n        borsh.done();\n\n        setBlockProducers(initialValidators, epochs[0]);\n    }\n\n    // The second part of the initialization -- setting the current head.\n    function initWithBlock(bytes memory data) public override onlyAdmin {\n        require(!initialized \u0026\u0026 epochs[0].numBPs != 0, \"Wrong initialization stage\");\n        initialized = true;\n\n        Borsh.Data memory borsh = Borsh.from(data);\n        NearDecoder.LightClientBlock memory nearBlock = borsh.decodeLightClientBlock();\n        borsh.done();\n\n        require(nearBlock.next_bps.some, \"Initialization block must contain next_bps\");\n\n        curHeight = nearBlock.inner_lite.height;\n        epochs[0].epochId = nearBlock.inner_lite.epoch_id;\n        epochs[1].epochId = nearBlock.inner_lite.next_epoch_id;\n        blockHashes_[nearBlock.inner_lite.height] = nearBlock.hash;\n        blockMerkleRoots_[nearBlock.inner_lite.height] = nearBlock.inner_lite.block_merkle_root;\n        setBlockProducers(nearBlock.next_bps.blockProducers, epochs[1]);\n    }\n\n    struct BridgeState {\n        uint currentHeight; // Height of the current confirmed block\n        // If there is currently no unconfirmed block, the last three fields are zero.\n        uint nextTimestamp; // Timestamp of the current unconfirmed block\n        uint nextValidAt; // Timestamp when the current unconfirmed block will be confirmed\n        uint numBlockProducers; // Number of block producers for the current unconfirmed block\n    }\n\n    function bridgeState() public view returns (BridgeState memory res) {\n        if (block.timestamp \u003c lastValidAt) {\n            res.currentHeight = curHeight;\n            res.nextTimestamp = untrustedTimestamp;\n            res.nextValidAt = lastValidAt;\n            unchecked {\n                res.numBlockProducers = epochs[untrustedNextEpoch ? (curEpoch + 1) % 3 : curEpoch].numBPs;\n            }\n        } else {\n            res.currentHeight = lastValidAt == 0 ? curHeight : untrustedHeight;\n        }\n    }\n\n    function addLightClientBlock(bytes memory data) public override pausable(PAUSED_ADD_BLOCK) {\n        require(initialized, \"Contract is not initialized\");\n        require(balanceOf[msg.sender] \u003e= lockEthAmount, \"Balance is not enough\");\n\n        Borsh.Data memory borsh = Borsh.from(data);\n        NearDecoder.LightClientBlock memory nearBlock = borsh.decodeLightClientBlock();\n        borsh.done();\n\n        unchecked {\n            // Commit the previous block, or make sure that it is OK to replace it.\n            if (block.timestamp \u003c lastValidAt) {\n                require(\n                    nearBlock.inner_lite.timestamp \u003e= untrustedTimestamp + replaceDuration,\n                    \"Can only replace with a sufficiently newer block\"\n                );\n            } else if (lastValidAt != 0) {\n                curHeight = untrustedHeight;\n                if (untrustedNextEpoch) {\n                    curEpoch = (curEpoch + 1) % 3;\n                }\n                lastValidAt = 0;\n\n                blockHashes_[curHeight] = untrustedHash;\n                blockMerkleRoots_[curHeight] = untrustedMerkleRoot;\n            }\n\n            // Check that the new block\u0027s height is greater than the current one\u0027s.\n            require(nearBlock.inner_lite.height \u003e curHeight, \"New block must have higher height\");\n\n            // Check that the new block is from the same epoch as the current one, or from the next one.\n            bool fromNextEpoch;\n            if (nearBlock.inner_lite.epoch_id == epochs[curEpoch].epochId) {\n                fromNextEpoch = false;\n            } else if (nearBlock.inner_lite.epoch_id == epochs[(curEpoch + 1) % 3].epochId) {\n                fromNextEpoch = true;\n            } else {\n                revert(\"Epoch id of the block is not valid\");\n            }\n\n            // Check that the new block is signed by more than 2/3 of the validators.\n            Epoch storage thisEpoch = epochs[fromNextEpoch ? (curEpoch + 1) % 3 : curEpoch];\n            // Last block in the epoch might contain extra approvals that light client can ignore.\n            require(nearBlock.approvals_after_next.length \u003e= thisEpoch.numBPs, \"Approval list is too short\");\n            // The sum of uint128 values cannot overflow.\n            uint256 votedFor = 0;\n            for ((uint i, uint cnt) = (0, thisEpoch.numBPs); i != cnt; ++i) {\n                bytes32 stakes = thisEpoch.packedStakes[i \u003e\u003e 1];\n                if (nearBlock.approvals_after_next[i].some) {\n                    votedFor += uint128(bytes16(stakes));\n                }\n                if (++i == cnt) {\n                    break;\n                }\n                if (nearBlock.approvals_after_next[i].some) {\n                    votedFor += uint128(uint256(stakes));\n                }\n            }\n            require(votedFor \u003e thisEpoch.stakeThreshold, \"Too few approvals\");\n\n            // If the block is from the next epoch, make sure that next_bps is supplied and has a correct hash.\n            if (fromNextEpoch) {\n                require(nearBlock.next_bps.some, \"Next next_bps should not be None\");\n                require(\n                    nearBlock.next_bps.hash == nearBlock.inner_lite.next_bp_hash,\n                    \"Hash of block producers does not match\"\n                );\n            }\n\n            untrustedHeight = nearBlock.inner_lite.height;\n            untrustedTimestamp = nearBlock.inner_lite.timestamp;\n            untrustedHash = nearBlock.hash;\n            untrustedMerkleRoot = nearBlock.inner_lite.block_merkle_root;\n            untrustedNextHash = nearBlock.next_hash;\n\n            uint256 signatureSet = 0;\n            for ((uint i, uint cnt) = (0, thisEpoch.numBPs); i \u003c cnt; i++) {\n                NearDecoder.OptionalSignature memory approval = nearBlock.approvals_after_next[i];\n                if (approval.some) {\n                    signatureSet |= 1 \u003c\u003c i;\n                    untrustedSignatures[i] = approval.signature;\n                }\n            }\n            untrustedSignatureSet = signatureSet;\n            untrustedNextEpoch = fromNextEpoch;\n            if (fromNextEpoch) {\n                Epoch storage nextEpoch = epochs[(curEpoch + 2) % 3];\n                nextEpoch.epochId = nearBlock.inner_lite.next_epoch_id;\n                setBlockProducers(nearBlock.next_bps.blockProducers, nextEpoch);\n            }\n            lastSubmitter = msg.sender;\n            lastValidAt = block.timestamp + lockDuration;\n        }\n    }\n\n    function setBlockProducers(NearDecoder.BlockProducer[] memory src, Epoch storage epoch) internal {\n        uint cnt = src.length;\n        require(cnt \u003c= MAX_BLOCK_PRODUCERS, \"It is not expected having that many block producers for the provided block\");\n        epoch.numBPs = cnt;\n        unchecked {\n            for (uint i = 0; i \u003c cnt; i++) {\n                epoch.keys[i] = src[i].publicKey.k;\n            }\n            uint256 totalStake = 0; // Sum of uint128, can\u0027t be too big.\n            for (uint i = 0; i != cnt; ++i) {\n                uint128 stake1 = src[i].stake;\n                totalStake += stake1;\n                if (++i == cnt) {\n                    epoch.packedStakes[i \u003e\u003e 1] = bytes32(bytes16(stake1));\n                    break;\n                }\n                uint128 stake2 = src[i].stake;\n                totalStake += stake2;\n                epoch.packedStakes[i \u003e\u003e 1] = bytes32(uint256(bytes32(bytes16(stake1))) + stake2);\n            }\n            epoch.stakeThreshold = (totalStake * 2) / 3;\n        }\n    }\n\n    function blockHashes(uint64 height) public view override pausable(PAUSED_VERIFY) returns (bytes32 res) {\n        res = blockHashes_[height];\n        if (res == 0 \u0026\u0026 block.timestamp \u003e= lastValidAt \u0026\u0026 lastValidAt != 0 \u0026\u0026 height == untrustedHeight) {\n            res = untrustedHash;\n        }\n    }\n\n    function blockMerkleRoots(uint64 height) public view override pausable(PAUSED_VERIFY) returns (bytes32 res) {\n        res = blockMerkleRoots_[height];\n        if (res == 0 \u0026\u0026 block.timestamp \u003e= lastValidAt \u0026\u0026 lastValidAt != 0 \u0026\u0026 height == untrustedHeight) {\n            res = untrustedMerkleRoot;\n        }\n    }\n}\n"},"NearDecoder.sol":{"content":"// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity ^0.8;\n\nimport \"./Borsh.sol\";\n\nlibrary NearDecoder {\n    using Borsh for Borsh.Data;\n    using NearDecoder for Borsh.Data;\n\n    uint8 constant VALIDATOR_V1 = 0;\n    uint8 constant VALIDATOR_V2 = 1;\n\n    struct PublicKey {\n        bytes32 k;\n    }\n\n    function decodePublicKey(Borsh.Data memory data) internal pure returns (PublicKey memory res) {\n        require(data.decodeU8() == 0, \"Parse error: invalid key type\");\n        res.k = data.decodeBytes32();\n    }\n\n    struct Signature {\n        bytes32 r;\n        bytes32 s;\n    }\n\n    function decodeSignature(Borsh.Data memory data) internal pure returns (Signature memory res) {\n        require(data.decodeU8() == 0, \"Parse error: invalid signature type\");\n        res.r = data.decodeBytes32();\n        res.s = data.decodeBytes32();\n    }\n\n    struct BlockProducer {\n        PublicKey publicKey;\n        uint128 stake;\n        // Flag indicating if this validator proposed to be a chunk-only producer (i.e. cannot become a block producer).\n        bool isChunkOnly;\n    }\n\n    function decodeBlockProducer(Borsh.Data memory data) internal pure returns (BlockProducer memory res) {\n        uint8 validator_version = data.decodeU8();\n        data.skipBytes();\n        res.publicKey = data.decodePublicKey();\n        res.stake = data.decodeU128();\n        if (validator_version == VALIDATOR_V2) {\n            res.isChunkOnly = data.decodeU8() != 0;\n        } else {\n            res.isChunkOnly = false;\n        }\n    }\n\n    function decodeBlockProducers(Borsh.Data memory data) internal pure returns (BlockProducer[] memory res) {\n        uint length = data.decodeU32();\n        res = new BlockProducer[](length);\n        for (uint i = 0; i \u003c length; i++) {\n            res[i] = data.decodeBlockProducer();\n        }\n    }\n\n    struct OptionalBlockProducers {\n        bool some;\n        BlockProducer[] blockProducers;\n        bytes32 hash; // Additional computable element\n    }\n\n    function decodeOptionalBlockProducers(Borsh.Data memory data)\n        internal\n        view\n        returns (OptionalBlockProducers memory res)\n    {\n        res.some = data.decodeBool();\n        if (res.some) {\n            uint start = data.ptr;\n            res.blockProducers = data.decodeBlockProducers();\n            res.hash = Utils.sha256Raw(start, data.ptr - start);\n        }\n    }\n\n    struct OptionalSignature {\n        bool some;\n        Signature signature;\n    }\n\n    function decodeOptionalSignature(Borsh.Data memory data) internal pure returns (OptionalSignature memory res) {\n        res.some = data.decodeBool();\n        if (res.some) {\n            res.signature = data.decodeSignature();\n        }\n    }\n\n    struct BlockHeaderInnerLite {\n        uint64 height; // Height of this block since the genesis block (height 0).\n        bytes32 epoch_id; // Epoch start hash of this block\u0027s epoch. Used for retrieving validator information\n        bytes32 next_epoch_id;\n        bytes32 prev_state_root; // Root hash of the state at the previous block.\n        bytes32 outcome_root; // Root of the outcomes of transactions and receipts.\n        uint64 timestamp; // Timestamp at which the block was built.\n        bytes32 next_bp_hash; // Hash of the next epoch block producers set\n        bytes32 block_merkle_root;\n        bytes32 hash; // Additional computable element\n    }\n\n    function decodeBlockHeaderInnerLite(Borsh.Data memory data)\n        internal\n        view\n        returns (BlockHeaderInnerLite memory res)\n    {\n        res.hash = data.peekSha256(208);\n        res.height = data.decodeU64();\n        res.epoch_id = data.decodeBytes32();\n        res.next_epoch_id = data.decodeBytes32();\n        res.prev_state_root = data.decodeBytes32();\n        res.outcome_root = data.decodeBytes32();\n        res.timestamp = data.decodeU64();\n        res.next_bp_hash = data.decodeBytes32();\n        res.block_merkle_root = data.decodeBytes32();\n    }\n\n    struct LightClientBlock {\n        bytes32 prev_block_hash;\n        bytes32 next_block_inner_hash;\n        BlockHeaderInnerLite inner_lite;\n        bytes32 inner_rest_hash;\n        OptionalBlockProducers next_bps;\n        OptionalSignature[] approvals_after_next;\n        bytes32 hash;\n        bytes32 next_hash;\n    }\n\n    function decodeLightClientBlock(Borsh.Data memory data) internal view returns (LightClientBlock memory res) {\n        res.prev_block_hash = data.decodeBytes32();\n        res.next_block_inner_hash = data.decodeBytes32();\n        res.inner_lite = data.decodeBlockHeaderInnerLite();\n        res.inner_rest_hash = data.decodeBytes32();\n        res.next_bps = data.decodeOptionalBlockProducers();\n\n        uint length = data.decodeU32();\n        res.approvals_after_next = new OptionalSignature[](length);\n        for (uint i = 0; i \u003c length; i++) {\n            res.approvals_after_next[i] = data.decodeOptionalSignature();\n        }\n\n        res.hash = sha256(\n            abi.encodePacked(sha256(abi.encodePacked(res.inner_lite.hash, res.inner_rest_hash)), res.prev_block_hash)\n        );\n\n        res.next_hash = sha256(abi.encodePacked(res.next_block_inner_hash, res.hash));\n    }\n}\n"},"Utils.sol":{"content":"// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity ^0.8;\n\nlibrary Utils {\n    function swapBytes2(uint16 v) internal pure returns (uint16) {\n        return (v \u003c\u003c 8) | (v \u003e\u003e 8);\n    }\n\n    function swapBytes4(uint32 v) internal pure returns (uint32) {\n        v = ((v \u0026 0x00ff00ff) \u003c\u003c 8) | ((v \u0026 0xff00ff00) \u003e\u003e 8);\n        return (v \u003c\u003c 16) | (v \u003e\u003e 16);\n    }\n\n    function swapBytes8(uint64 v) internal pure returns (uint64) {\n        v = ((v \u0026 0x00ff00ff00ff00ff) \u003c\u003c 8) | ((v \u0026 0xff00ff00ff00ff00) \u003e\u003e 8);\n        v = ((v \u0026 0x0000ffff0000ffff) \u003c\u003c 16) | ((v \u0026 0xffff0000ffff0000) \u003e\u003e 16);\n        return (v \u003c\u003c 32) | (v \u003e\u003e 32);\n    }\n\n    function swapBytes16(uint128 v) internal pure returns (uint128) {\n        v = ((v \u0026 0x00ff00ff00ff00ff00ff00ff00ff00ff) \u003c\u003c 8) | ((v \u0026 0xff00ff00ff00ff00ff00ff00ff00ff00) \u003e\u003e 8);\n        v = ((v \u0026 0x0000ffff0000ffff0000ffff0000ffff) \u003c\u003c 16) | ((v \u0026 0xffff0000ffff0000ffff0000ffff0000) \u003e\u003e 16);\n        v = ((v \u0026 0x00000000ffffffff00000000ffffffff) \u003c\u003c 32) | ((v \u0026 0xffffffff00000000ffffffff00000000) \u003e\u003e 32);\n        return (v \u003c\u003c 64) | (v \u003e\u003e 64);\n    }\n\n    function swapBytes32(uint256 v) internal pure returns (uint256) {\n        v =\n            ((v \u0026 0x00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff) \u003c\u003c 8) |\n            ((v \u0026 0xff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00) \u003e\u003e 8);\n        v =\n            ((v \u0026 0x0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff) \u003c\u003c 16) |\n            ((v \u0026 0xffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000) \u003e\u003e 16);\n        v =\n            ((v \u0026 0x00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff) \u003c\u003c 32) |\n            ((v \u0026 0xffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000) \u003e\u003e 32);\n        v =\n            ((v \u0026 0x0000000000000000ffffffffffffffff0000000000000000ffffffffffffffff) \u003c\u003c 64) |\n            ((v \u0026 0xffffffffffffffff0000000000000000ffffffffffffffff0000000000000000) \u003e\u003e 64);\n        return (v \u003c\u003c 128) | (v \u003e\u003e 128);\n    }\n\n    function readMemory(uint ptr) internal pure returns (uint res) {\n        assembly {\n            res := mload(ptr)\n        }\n    }\n\n    function writeMemory(uint ptr, uint value) internal pure {\n        assembly {\n            mstore(ptr, value)\n        }\n    }\n\n    function memoryToBytes(uint ptr, uint length) internal pure returns (bytes memory res) {\n        if (length != 0) {\n            assembly {\n                // 0x40 is the address of free memory pointer.\n                res := mload(0x40)\n                let end := add(\n                    res,\n                    and(add(length, 63), 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0)\n                )\n                // end = res + 32 + 32 * ceil(length / 32).\n                mstore(0x40, end)\n                mstore(res, length)\n                let destPtr := add(res, 32)\n                // prettier-ignore\n                for { } 1 { } {\n                    mstore(destPtr, mload(ptr))\n                    destPtr := add(destPtr, 32)\n                    if eq(destPtr, end) {\n                        break\n                    }\n                    ptr := add(ptr, 32)\n                }\n            }\n        }\n    }\n\n    function keccak256Raw(uint ptr, uint length) internal pure returns (bytes32 res) {\n        assembly {\n            res := keccak256(ptr, length)\n        }\n    }\n\n    function sha256Raw(uint ptr, uint length) internal view returns (bytes32 res) {\n        assembly {\n            // 2 is the address of SHA256 precompiled contract.\n            // First 64 bytes of memory can be used as scratch space.\n            let ret := staticcall(gas(), 2, ptr, length, 0, 32)\n            // If the call to SHA256 precompile ran out of gas, burn any gas that remains.\n            // prettier-ignore\n            for { } iszero(ret) { } { }\n            res := mload(0)\n        }\n    }\n}\n"}}