Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
- Contract name:
- BettingLib
- Optimization enabled
- false
- Compiler version
- v0.8.28+commit.7893614a
- EVM Version
- Verified at
- 2026-08-20T06:39:05.203954Z
Constructor Arguments
contracts/lib/BettingLib.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.28;
import {Hand, Action, CannotCheck, NothingToCall, FacingABet, OpponentAllIn,
BadAmount, BetBelowMin, NotReopened, RaiseTooSmall, BetTooLarge,
RaiseBelowMin, BadParam} from "../GameTypes.sol";
/// @title BettingLib — heads-up NLHE betting transitions
/// @notice The exact on-chain mirror of web/js/betting.mjs (the executable
/// betting spec, cross-checked by shared vectors and integration
/// tests). Deployed as an external library to keep the main contract
/// under the EIP-170 size limit.
library BettingLib {
uint8 internal constant OUT_TURN = 0; // turn passed to opponent
uint8 internal constant OUT_CLOSED = 1; // street closed
uint8 internal constant OUT_FOLDED = 2; // actor folded (street closed too)
/// @notice Initialize per-hand betting state and auto-post the blinds.
function initHand(Hand storage h, uint8 btn, uint32 sbChips, uint32 bbChips) public {
h.btn = btn;
h.folded = 255;
h.riverAggressor = 255;
h.pendBy = 255;
h.board = [255, 255, 255, 255, 255];
h.inc = bbChips;
h.reopen = true;
h.bbOption = true;
h.street = 0;
uint8 opp = 1 - btn;
uint32 sbPost = _min32(sbChips, h.stack[btn]);
uint32 bbPost = _min32(bbChips, h.stack[opp]);
h.stack[btn] -= sbPost;
h.streetBet[btn] = sbPost;
h.stack[opp] -= bbPost;
h.streetBet[opp] = bbPost;
h.currentBet = sbPost > bbPost ? sbPost : bbPost;
h.toAct = btn;
h.firstToAct = btn;
if (_shouldAutoClose(h)) closeStreet(h);
}
/// @notice Apply one betting action for seat `me`; reverts if illegal.
/// @return outcome OUT_TURN / OUT_CLOSED / OUT_FOLDED
function applyAction(Hand storage h, uint8 me, Action action, uint32 amount, uint32 bbNominal)
public returns (uint8 outcome)
{
uint8 opp = 1 - me;
uint32 facing = h.currentBet - h.streetBet[me];
if (h.street == 0 && me == 1 - h.btn) h.bbOption = false; // BB is acting
if (action == Action.FOLD) {
h.folded = me;
closeStreet(h);
return OUT_FOLDED;
}
if (action == Action.CHECK) {
if (facing != 0) revert CannotCheck();
if (me != h.firstToAct) {
closeStreet(h);
return OUT_CLOSED;
}
h.toAct = opp;
if (_shouldAutoClose(h)) { closeStreet(h); return OUT_CLOSED; }
return OUT_TURN;
}
if (action == Action.CALL) {
if (facing == 0) revert NothingToCall();
uint32 pay = _min32(facing, h.stack[me]);
h.stack[me] -= pay;
h.streetBet[me] += pay;
// preflop limp: BB is still owed the option to check or raise
if (h.street == 0 && me == h.btn && h.bbOption) {
h.bbOption = false;
h.toAct = opp;
if (_shouldAutoClose(h)) { closeStreet(h); return OUT_CLOSED; }
return OUT_TURN;
}
closeStreet(h);
return OUT_CLOSED;
}
if (action == Action.BET) {
if (h.currentBet != 0) revert FacingABet();
if (h.stack[opp] == 0) revert OpponentAllIn();
if (amount == 0 || amount > h.stack[me]) revert BadAmount();
if (amount < bbNominal && amount != h.stack[me]) revert BetBelowMin();
h.stack[me] -= amount;
h.streetBet[me] = amount;
h.currentBet = amount;
// short all-in bet does not reopen raising for the opponent
if (amount >= bbNominal) { h.inc = amount; h.reopen = true; }
else { h.reopen = false; }
if (h.street == 3) h.riverAggressor = me;
h.toAct = opp;
if (_shouldAutoClose(h)) { closeStreet(h); return OUT_CLOSED; }
return OUT_TURN;
}
if (action == Action.RAISE) {
if (h.currentBet == 0) revert FacingABet();
if (!h.reopen) revert NotReopened();
if (h.stack[opp] == 0) revert OpponentAllIn();
if (amount <= h.currentBet) revert RaiseTooSmall();
uint32 newMoney = amount - h.streetBet[me];
if (newMoney > h.stack[me]) revert BetTooLarge();
uint32 minTo = h.currentBet + h.inc;
bool isAllIn = newMoney == h.stack[me];
if (amount < minTo && !isAllIn) revert RaiseBelowMin();
h.stack[me] -= newMoney;
h.streetBet[me] = amount;
if (amount >= minTo) { h.inc = amount - h.currentBet; h.reopen = true; }
else { h.reopen = false; } // short all-in raise: call/fold only
h.currentBet = amount;
if (h.street == 3) h.riverAggressor = me;
if (h.street == 0) h.bbOption = false;
h.toAct = opp;
if (_shouldAutoClose(h)) { closeStreet(h); return OUT_CLOSED; }
return OUT_TURN;
}
revert BadParam();
}
/// @notice Open the next street's betting round (after a board reveal).
function openStreet(Hand storage h, uint32 bbNominal) public {
h.currentBet = 0;
h.inc = bbNominal;
h.reopen = true;
h.firstToAct = 1 - h.btn;
h.toAct = h.firstToAct;
}
/// @notice Return the uncalled portion, move matched chips to the pot.
function closeStreet(Hand storage h) public {
uint32 m = _min32(h.streetBet[0], h.streetBet[1]);
h.stack[0] += h.streetBet[0] - m;
h.stack[1] += h.streetBet[1] - m;
h.pot += 2 * m;
h.streetBet[0] = 0;
h.streetBet[1] = 0;
if (h.stack[0] == 0 || h.stack[1] == 0) h.allIn = true;
}
/// @dev Nobody can act: actor is all-in, or opponent is all-in with
/// nothing left to call.
function _shouldAutoClose(Hand storage h) private view returns (bool) {
return h.stack[h.toAct] == 0
|| (h.stack[1 - h.toAct] == 0 && h.streetBet[h.toAct] == h.currentBet);
}
function _min32(uint32 a, uint32 b) private pure returns (uint32) {
return a < b ? a : b;
}
}
contracts/GameTypes.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.28;
/// @title GameTypes — shared structs, enums and errors for PLSHoldem
/// @notice File-level definitions so the main contract and external game
/// libraries share one source of truth.
enum TableStatus { NONE, OPEN, PLAYING, SETTLED, CANCELLED }
enum Phase {
NONE, // between hands: waiting for creator to post D1
SHUF1, // (never stored: D1 post transitions NONE->SHUF2)
SHUF2, // joiner must post D2
LOCK1, // creator must post D3
LOCK2, // joiner must post D4
DEAL, // both must post hole-card exponents
BET_PREFLOP,
REVEAL_FLOP,
BET_FLOP,
REVEAL_TURN,
BET_TURN,
REVEAL_RIVER,
BET_RIVER,
SHOWDOWN_1, // first revealer must show
SHOWDOWN_2, // second player shows or mucks
BLAME_J, // joiner must submit blame data
BLAME_C // creator must submit blame data
}
enum Action { FOLD, CHECK, CALL, BET, RAISE }
struct Table {
address creator;
uint96 chipValue; // wei per chip
address joiner;
uint8 status; // TableStatus
uint8 creatorAvatar;
uint8 joinerAvatar;
uint16 rakeBps;
uint32 buyInChips;
uint32 sbChips;
uint32 bbChips;
uint32 penaltyChips;
uint32 actTimeout; // seconds, betting actions
uint32 cryptoTimeout; // seconds, crypto steps / reveals / next hand
uint32 handId; // next / current hand number
uint32 rakeChips; // accrued rake
uint32 stackC; // creator session stack (between hands)
uint32 stackJ; // joiner session stack
uint64 lastSettleTime; // anchor for the next-hand (no-show) clock
}
struct Hand {
uint8 phase; // Phase
uint8 btn; // 0 = creator has the button, 1 = joiner
uint64 deadline; // current actor(s) must move before this
// betting state (mirrors web/js/betting.mjs)
uint32[2] stack; // chips behind, [creator, joiner]
uint32[2] streetBet;
uint32 pot;
uint32 currentBet;
uint32 inc; // last full raise increment
uint8 street; // 0..3
uint8 toAct;
uint8 firstToAct;
bool reopen;
bool bbOption;
bool allIn;
uint8 folded; // 255 = none
uint8 riverAggressor; // 255 = none
// dealing / reveals
bytes32[4] roots; // D1..D4 Merkle roots
uint256[4] holeExp; // per-card exps for positions 0..3 (0,1 by J; 2,3 by C)
uint8 dealMask; // bit0 = joiner posted, bit1 = creator posted
uint8[5] board; // card indices, 255 = unset
uint256[3] pendExp; // first poster's exps for the current reveal
uint8 pendBy; // 255 = none
// showdown
uint8 firstShower;
uint8 shownMask; // bit per seat
uint256[2][2] shownExp; // [seat][slot]
uint8[2][2] shownCards; // [seat][slot]
uint32[2] shownScore;
// blame
uint8 blamePos;
uint8 blameClaimIdx; // disputed claimed card (255 = "garbage" claim)
uint8 blameClaimBy; // seat whose claim/accusation opened blame
uint256 blameGJ; // J's pinned global exponent
uint256 blameCJ; // J's pinned per-card exponent
uint256 blamePostedC; // C's per-card exponent as posted during play
uint256 blamePostedJ; // J's per-card exponent as posted during play
bytes32[4] blameVals; // keccak of Merkle-proven D1[j], D2..D4[pos]
}
// Custom errors (compact reverts), shared by contract + libraries
error AlreadyPosted();
error BadAmount();
error BadData();
error BadInverse();
error BadParam();
error BadPhase();
error BadProof();
error BadScalar();
error BetBelowMin();
error BetTooLarge();
error Bust();
error CannotCheck();
error CardMismatch();
error FacingABet();
error NotAPlayer();
error NotCreator();
error NotExpired();
error NotJoiner();
error NotOpen();
error NotOwner();
error NotPlaying();
error NotReopened();
error NotYourHole();
error NotYourReveal();
error NotYourTurn();
error NothingToCall();
error NothingToDo();
error NothingToRaise();
error OpponentAllIn();
error PostYoursFirst();
error RaiseBelowMin();
error RaiseTooSmall();
error RakeCap();
error TransferFailed();
error WrongDeposit();
error WrongHand();
error YouAreTheStaller();
Compiler Settings
{"viaIR":true,"outputSelection":{"*":{"*":["abi","evm.bytecode","evm.deployedBytecode","evm.methodIdentifiers","metadata"],"":["ast"]}},"optimizer":{"runs":1,"enabled":true},"libraries":{},"evmVersion":"paris"}
Contract ABI
[{"type":"error","name":"BadAmount","inputs":[]},{"type":"error","name":"BadParam","inputs":[]},{"type":"error","name":"BetBelowMin","inputs":[]},{"type":"error","name":"BetTooLarge","inputs":[]},{"type":"error","name":"CannotCheck","inputs":[]},{"type":"error","name":"FacingABet","inputs":[]},{"type":"error","name":"NotReopened","inputs":[]},{"type":"error","name":"NothingToCall","inputs":[]},{"type":"error","name":"OpponentAllIn","inputs":[]},{"type":"error","name":"RaiseBelowMin","inputs":[]},{"type":"error","name":"RaiseTooSmall","inputs":[]}]
Contract Creation Code
0x60808060405234601b57610cf790816100218239308160080152f35b600080fdfe608080604052307f00000000000000000000000000000000000000000000000000000000000000001490600436101561003757600080fd5b60003560e01c908163074bdbe5146101655750806320cf45de146101495780638824e3f6146100cc5763e100fb0e1461006f57600080fd5b6100c75760a03660031901126100c757610087610370565b6044359060058210156100c75761009c610380565b6084359063ffffffff821682036100c7576020936100bc93600435610631565b60ff60405191168152f35b600080fd5b506100c75760403660031901126100c75760043560243563ffffffff811681036100c75761013961013360ff84610118600361014797019563ffffffff60201b198754168755866103b0565b8454607883901b1916600160781b1785555460081c166103d3565b826104a1565b60ff815460701c1690610484565b005b506100c75760203660031901126100c7576101476004356104d8565b826100c75760803660031901126100c757600435610181610370565b6044359263ffffffff841684036100c75761019a610380565b835461ff001916600884901b61ff001617845560038401805461ffff60901b61ffff60901b1990911617815560118501805460ff191660ff1790559160a081016001600160401b0381118282101761035a5760405260ff815260ff602082015260ff604082015260ff606082015260ff608082015260009060005b600581106103365750506102ab60026102ea876102df6102e5896102e56102bb8a8f61024f6103179f9e9d8e6103089e600d8c01556103b0565b8c5464ffff0000ff60601b191661010160781b178d5561026e856103d3565b9586926102df61029960018c019463ffffffff61028b8b886103fa565b90549060031b1c1690610c04565b9d8e9263ffffffff61028b88886103fa565b9c8d9b6102d76102bb8b886103fa565b6102d18763ffffffff84548460031b1c1661042c565b91610446565b0197886103fa565b90610446565b6103fa565b63ffffffff811663ffffffff83161160001461032f57505b82610461565b6103128282610484565b6104a1565b61032081610c24565b61032657005b610147906104d8565b9050610302565b9091602060019160ff8551169060ff8560031b92831b921b19161793019101610215565b634e487b7160e01b600052604160045260246000fd5b6024359060ff821682036100c757565b6064359063ffffffff821682036100c757565b805460ff60981b191660989290921b60ff60981b16919091179055565b805463ffffffff60401b191660409290921b63ffffffff60401b16919091179055565b60ff166001039060ff82116103e457565b634e487b7160e01b600052601160045260246000fd5b919091600283101561041657601c908360031c019260021b1690565b634e487b7160e01b600052603260045260246000fd5b9063ffffffff8091169116039063ffffffff82116103e457565b919063ffffffff8084549260031b9316831b921b1916179055565b805463ffffffff60201b191660209290921b63ffffffff60201b16919091179055565b805460ff60681b191660689290921b60ff60681b16919091179055565b805460ff60701b191660709290921b60ff60701b16919091179055565b9063ffffffff8091169116019063ffffffff82116103e457565b6002810180546000916004916104fb9063ffffffff602082901c81169116610c04565b9061050d8263ffffffff83541661042c565b91610523600187019363ffffffff8554166104be565b90835463ffffffff8760031b9316831b9063ffffffff841b191617845561057561056e61055c8363ffffffff87548a60031b1c1661042c565b63ffffffff87548960031b1c166104be565b8686610446565b60011b956401fffffffe63fffffffe88169716870361061e5791849160036105d894019763ffffffff6105ac8a54928284166104be565b169063ffffffff191617885563ffffffff8254911b191681559063ffffffff82549160031b1b19169055565b63ffffffff81541615928315610606575b5050506105f35750565b805460ff60881b1916600160881b179055565b63ffffffff935050549060031b1c16153880806105e9565b634e487b7160e01b865260118552602486fd5b9392919061063e816103d3565b926003860192835495600288019661067563ffffffff61065e878b6103fa565b90549060031b1c1663ffffffff8360201c1661042c565b9060ff8160601c161580610be7575b610bd8575b506005831015610bc2578215610b9057600060018414610b49575060028314610a6d5750600090600383146108f65750506004146106d25763de17a3af60e01b60005260046000fd5b82549063ffffffff8260201c169182156108e55760ff8160781c16156108d457600188019263ffffffff61070688866103fa565b90549060031b1c16156108c35763ffffffff8316818111156108b35761074263ffffffff610734888c6103fa565b90549060031b1c168561042c565b9163ffffffff61075288886103fa565b90549060031b1c169363ffffffff84169485116108a25763ffffffff918261077e9260401c16906104be565b938161078a89896103fa565b90549060031b1c161493161180928193610899575b5061088857826102df866108389a6102e56107d9956102d16107c4856108129c6103fa565b91909263ffffffff84548460031b1c1661042c565b610878576107fa6107f463ffffffff865460201c168361042c565b856103b0565b835460ff60781b1916600160781b1784555b83610461565b600360ff835460601c1614610868575b50805460ff8160601c1615610859575b50610484565b61084181610c24565b61084b5750600090565b610854906104d8565b600190565b60ff60801b1916815538610832565b6108729082610393565b38610822565b835460ff60781b1916845561080c565b630cc665eb60e41b60005260046000fd5b9050153861079f565b63508bf05560e11b60005260046000fd5b627b085160e71b60005260046000fd5b637099596f60e01b60005260046000fd5b634878610160e01b60005260046000fd5b6308ce497360e31b60005260046000fd5b9096989795949392915063ffffffff845460201c16610a5e576001860163ffffffff61092287836103fa565b90549060031b1c1615610a4f5763ffffffff83169182158015610a30575b610a215763ffffffff16821080928193610a00575b506109f157826102df856109b5999a9b9c6102e56102bb83610976976103fa565b6109808285610461565b6109e05761098e90836103b0565b815460ff60781b1916600160781b1782555b600360ff835460601c16146109d05750610484565b6109be81610c24565b6109c6575090565b61085491506104d8565b6109da9082610393565b38610832565b50815460ff60781b191682556109a0565b6338cded6760e11b8852600488fd5b905063ffffffff610a1186846103fa565b90549060031b1c16141538610955565b63749b593960e01b8952600489fd5b5063ffffffff610a4086846103fa565b90549060031b1c168311610940565b637099596f60e01b8852600488fd5b6308ce497360e31b8752600487fd5b9250505063ffffffff81969592961615610b38576102d1610ac687610adb946102e5610ab083610aaa60018d019863ffffffff61028b848c6103fa565b976103fa565b6102d18863ffffffff84548460031b1c1661042c565b91909263ffffffff84548460031b1c166104be565b80549360ff8560601c16159081610b24575b5080610b17575b610b0457505061085491506104d8565b610838929360ff60801b19168155610484565b5060ff8460801c16610af4565b905060ff80855460081c1691161438610aed565b634af78cfb60e01b60005260046000fd5b98975091505063ffffffff915016610b815760ff80835460701c16911603610b7557906109b591610484565b505061085491506104d8565b630f0565e560e31b8552600485fd5b5050835460ff60901b191660909390931b60ff60901b169290921790925550610bbd9392506104d8915050565b600290565b634e487b7160e01b600052602160045260246000fd5b60ff60801b1916865538610689565b5060ff610bf9818c5460081c166103d3565b1660ff871614610684565b9063ffffffff811663ffffffff831610600014610c1f575090565b905090565b6001810190600381015460ff8160681c1663ffffffff610c4482866103fa565b90549060031b1c1615938415610c5c575b5050505090565b8192939450610c7990610c7363ffffffff936103d3565b906103fa565b90549060031b1c16159283610c95575b50505038808080610c55565b63ffffffff92935082916002610cab92016103fa565b90549060031b1c169160201c1614388080610c8956fea2646970667358221220176a18dfe82bdc284321e351b2435cd0a45d9b5349fcfdcae40459880e71ea1864736f6c634300081c0033
Deployed ByteCode
0x608080604052307f000000000000000000000000ecfafd597d0ffe9d9ba32feaa2f12f12f2bb86dc1490600436101561003757600080fd5b60003560e01c908163074bdbe5146101655750806320cf45de146101495780638824e3f6146100cc5763e100fb0e1461006f57600080fd5b6100c75760a03660031901126100c757610087610370565b6044359060058210156100c75761009c610380565b6084359063ffffffff821682036100c7576020936100bc93600435610631565b60ff60405191168152f35b600080fd5b506100c75760403660031901126100c75760043560243563ffffffff811681036100c75761013961013360ff84610118600361014797019563ffffffff60201b198754168755866103b0565b8454607883901b1916600160781b1785555460081c166103d3565b826104a1565b60ff815460701c1690610484565b005b506100c75760203660031901126100c7576101476004356104d8565b826100c75760803660031901126100c757600435610181610370565b6044359263ffffffff841684036100c75761019a610380565b835461ff001916600884901b61ff001617845560038401805461ffff60901b61ffff60901b1990911617815560118501805460ff191660ff1790559160a081016001600160401b0381118282101761035a5760405260ff815260ff602082015260ff604082015260ff606082015260ff608082015260009060005b600581106103365750506102ab60026102ea876102df6102e5896102e56102bb8a8f61024f6103179f9e9d8e6103089e600d8c01556103b0565b8c5464ffff0000ff60601b191661010160781b178d5561026e856103d3565b9586926102df61029960018c019463ffffffff61028b8b886103fa565b90549060031b1c1690610c04565b9d8e9263ffffffff61028b88886103fa565b9c8d9b6102d76102bb8b886103fa565b6102d18763ffffffff84548460031b1c1661042c565b91610446565b0197886103fa565b90610446565b6103fa565b63ffffffff811663ffffffff83161160001461032f57505b82610461565b6103128282610484565b6104a1565b61032081610c24565b61032657005b610147906104d8565b9050610302565b9091602060019160ff8551169060ff8560031b92831b921b19161793019101610215565b634e487b7160e01b600052604160045260246000fd5b6024359060ff821682036100c757565b6064359063ffffffff821682036100c757565b805460ff60981b191660989290921b60ff60981b16919091179055565b805463ffffffff60401b191660409290921b63ffffffff60401b16919091179055565b60ff166001039060ff82116103e457565b634e487b7160e01b600052601160045260246000fd5b919091600283101561041657601c908360031c019260021b1690565b634e487b7160e01b600052603260045260246000fd5b9063ffffffff8091169116039063ffffffff82116103e457565b919063ffffffff8084549260031b9316831b921b1916179055565b805463ffffffff60201b191660209290921b63ffffffff60201b16919091179055565b805460ff60681b191660689290921b60ff60681b16919091179055565b805460ff60701b191660709290921b60ff60701b16919091179055565b9063ffffffff8091169116019063ffffffff82116103e457565b6002810180546000916004916104fb9063ffffffff602082901c81169116610c04565b9061050d8263ffffffff83541661042c565b91610523600187019363ffffffff8554166104be565b90835463ffffffff8760031b9316831b9063ffffffff841b191617845561057561056e61055c8363ffffffff87548a60031b1c1661042c565b63ffffffff87548960031b1c166104be565b8686610446565b60011b956401fffffffe63fffffffe88169716870361061e5791849160036105d894019763ffffffff6105ac8a54928284166104be565b169063ffffffff191617885563ffffffff8254911b191681559063ffffffff82549160031b1b19169055565b63ffffffff81541615928315610606575b5050506105f35750565b805460ff60881b1916600160881b179055565b63ffffffff935050549060031b1c16153880806105e9565b634e487b7160e01b865260118552602486fd5b9392919061063e816103d3565b926003860192835495600288019661067563ffffffff61065e878b6103fa565b90549060031b1c1663ffffffff8360201c1661042c565b9060ff8160601c161580610be7575b610bd8575b506005831015610bc2578215610b9057600060018414610b49575060028314610a6d5750600090600383146108f65750506004146106d25763de17a3af60e01b60005260046000fd5b82549063ffffffff8260201c169182156108e55760ff8160781c16156108d457600188019263ffffffff61070688866103fa565b90549060031b1c16156108c35763ffffffff8316818111156108b35761074263ffffffff610734888c6103fa565b90549060031b1c168561042c565b9163ffffffff61075288886103fa565b90549060031b1c169363ffffffff84169485116108a25763ffffffff918261077e9260401c16906104be565b938161078a89896103fa565b90549060031b1c161493161180928193610899575b5061088857826102df866108389a6102e56107d9956102d16107c4856108129c6103fa565b91909263ffffffff84548460031b1c1661042c565b610878576107fa6107f463ffffffff865460201c168361042c565b856103b0565b835460ff60781b1916600160781b1784555b83610461565b600360ff835460601c1614610868575b50805460ff8160601c1615610859575b50610484565b61084181610c24565b61084b5750600090565b610854906104d8565b600190565b60ff60801b1916815538610832565b6108729082610393565b38610822565b835460ff60781b1916845561080c565b630cc665eb60e41b60005260046000fd5b9050153861079f565b63508bf05560e11b60005260046000fd5b627b085160e71b60005260046000fd5b637099596f60e01b60005260046000fd5b634878610160e01b60005260046000fd5b6308ce497360e31b60005260046000fd5b9096989795949392915063ffffffff845460201c16610a5e576001860163ffffffff61092287836103fa565b90549060031b1c1615610a4f5763ffffffff83169182158015610a30575b610a215763ffffffff16821080928193610a00575b506109f157826102df856109b5999a9b9c6102e56102bb83610976976103fa565b6109808285610461565b6109e05761098e90836103b0565b815460ff60781b1916600160781b1782555b600360ff835460601c16146109d05750610484565b6109be81610c24565b6109c6575090565b61085491506104d8565b6109da9082610393565b38610832565b50815460ff60781b191682556109a0565b6338cded6760e11b8852600488fd5b905063ffffffff610a1186846103fa565b90549060031b1c16141538610955565b63749b593960e01b8952600489fd5b5063ffffffff610a4086846103fa565b90549060031b1c168311610940565b637099596f60e01b8852600488fd5b6308ce497360e31b8752600487fd5b9250505063ffffffff81969592961615610b38576102d1610ac687610adb946102e5610ab083610aaa60018d019863ffffffff61028b848c6103fa565b976103fa565b6102d18863ffffffff84548460031b1c1661042c565b91909263ffffffff84548460031b1c166104be565b80549360ff8560601c16159081610b24575b5080610b17575b610b0457505061085491506104d8565b610838929360ff60801b19168155610484565b5060ff8460801c16610af4565b905060ff80855460081c1691161438610aed565b634af78cfb60e01b60005260046000fd5b98975091505063ffffffff915016610b815760ff80835460701c16911603610b7557906109b591610484565b505061085491506104d8565b630f0565e560e31b8552600485fd5b5050835460ff60901b191660909390931b60ff60901b169290921790925550610bbd9392506104d8915050565b600290565b634e487b7160e01b600052602160045260246000fd5b60ff60801b1916865538610689565b5060ff610bf9818c5460081c166103d3565b1660ff871614610684565b9063ffffffff811663ffffffff831610600014610c1f575090565b905090565b6001810190600381015460ff8160681c1663ffffffff610c4482866103fa565b90549060031b1c1615938415610c5c575b5050505090565b8192939450610c7990610c7363ffffffff936103d3565b906103fa565b90549060031b1c16159283610c95575b50505038808080610c55565b63ffffffff92935082916002610cab92016103fa565b90549060031b1c169160201c1614388080610c8956fea2646970667358221220176a18dfe82bdc284321e351b2435cd0a45d9b5349fcfdcae40459880e71ea1864736f6c634300081c0033