// SPDX-License-Identifier: MIT
pragma solidity 0.8.28;
import { SafeTransferLib } from "./libraries/SafeTransferLib.sol";
import { RaffleTypes } from "./RaffleTypes.sol";
interface IArbSys {
function arbBlockNumber() external view returns (uint256);
function arbBlockHash(uint256 arbBlockNum) external view returns (bytes32);
}
/// @dev Copied, never imported. Any adapter satisfying `sinjoh-randomness/SPEC.md` may be used.
/// The name matches the adapter package's declaration so the two read identically.
interface ISinjohRandomness {
function requestRandomness(uint64 roundId) external returns (bytes32 requestId);
}
/// @dev Copied, never imported. Execution components satisfy the fee-router interfaces.
interface ISinjohSwapAdapter {
function swap(
address assetIn,
address assetOut,
uint256 amountIn,
uint256 minAmountOut,
bytes calldata routeData
) external payable;
}
interface ISinjohPriceGuard {
function minimumOutput(
address subject,
address assetIn,
address assetOut,
uint256 amountIn,
bytes32 routeHash,
bytes calldata guardData
) external view returns (uint256 minOut, uint48 validUntil);
}
/// @notice One immutable raffle for one subject token. Holders never sign, approve, or register.
/// @dev Clone-initialized once; every parameter is frozen afterwards. No owner, upgrade, sweep,
/// rescue, arbitrary call, or configuration setter exists.
contract SinjohRaffleRewards {
using SafeTransferLib for address;
uint16 public constant BPS = 10_000;
uint16 public constant PROTOCOL_FEE_BPS = 100;
uint16 public constant MAX_PAYOUT_TAX_BPS = 5_000;
uint8 public constant MAX_WINNERS_PER_ROUND = 16;
uint8 public constant MAX_PENDING_ROUNDS = 4;
uint8 public constant MAX_EXCLUSIONS = 32;
uint8 public constant MAX_STOCK_REWARDS = 16;
uint8 public constant MAX_PROOF_LENGTH = 64;
uint16 public constant MAX_ROUTE_DATA_LENGTH = 1_024;
uint32 public constant MIN_ROUND_INTERVAL = 600;
uint32 public constant MAX_ROUND_INTERVAL = 604_800;
uint32 public constant MAX_WEIGHT_WINDOW_BLOCKS = 1_000_000;
uint32 public constant MIN_RANDOMNESS_TIMEOUT = 900;
uint32 public constant MAX_RANDOMNESS_TIMEOUT = 86_400;
uint32 public constant MIN_CLAIM_WINDOW = 3_600;
uint32 public constant MAX_CLAIM_WINDOW = 2_592_000;
/// @dev The final `claimWindow / STOCK_FALLBACK_DIVISOR` of a stock raffle's claim window is
/// also settleable in the funding asset. See `claimFunding`.
uint32 public constant STOCK_FALLBACK_DIVISOR = 4;
address public constant ARBSYS = address(0x64);
address public constant BURN_ADDRESS = 0x000000000000000000000000000000000000dEaD;
bytes32 public constant LEAF_DOMAIN = keccak256("SINJOH_RAFFLE_LEAF_V1");
bytes32 public constant NODE_DOMAIN = keccak256("SINJOH_RAFFLE_NODE_V1");
bytes32 public constant EMPTY_DOMAIN = keccak256("SINJOH_RAFFLE_EMPTY_V1");
bytes32 public constant SLOT_DOMAIN = keccak256("SINJOH_RAFFLE_SLOT_V1");
bytes32 public constant STOCK_DOMAIN = keccak256("SINJOH_RAFFLE_STOCK_V1");
error AlreadyInitialized();
error NotInitialized();
error Unauthorized();
error OnlySelf();
error Reentrancy();
error InvalidAddress();
error InvalidAmount();
error InvalidValue();
error InvalidConfiguration();
error ConfigurationMismatch();
error NonCanonicalConfiguration();
error SubjectNotBound();
error SubjectAlreadyBound();
error InvalidRound();
error InvalidSnapshot();
error InvalidRoot();
error TooManyPendingRounds();
error RoundTooSoon();
error PrizeBelowFloor();
error InvalidRequest();
error InvalidSeed();
error InvalidSlot();
error SlotAlreadyPaid();
error ClaimWindowClosed();
error ClaimWindowOpen();
error RandomnessPending();
error InvalidProof();
error NotWinningLeaf();
error ExcludedHolder();
error NothingOwed();
error Insolvent();
error UnexpectedBalanceDelta(uint256 expected, uint256 actual);
error QuoteExpired();
error InsufficientOutput(uint256 minimum, uint256 actual);
error FallbackUnavailable();
error InvariantViolation();
event RaffleInitialized(
bytes32 indexed configHash, RaffleTypes.Settings configuration, address[] exclusions
);
event SubjectBound(address indexed subject);
event Deposited(
address indexed source, uint256 gross, uint256 fee, uint256 net, bool attributed
);
event RoundCommitted(
uint64 indexed roundId,
uint64 snapshotBlock,
bytes32 snapshotBlockHash,
bytes32 rootHash,
uint256 totalTickets,
uint256 prize,
uint8 winnersPerRound,
bytes32 requestId
);
event RandomnessReceived(uint64 indexed roundId, bytes32 requestId, uint256 seed);
event PrizePaid(
uint64 indexed roundId,
uint8 indexed slot,
address indexed holder,
uint256 gross,
uint256 recipientTax,
uint256 recycleTax,
uint256 net
);
event PaymentDeferred(
uint64 indexed roundId,
uint8 indexed slot,
address indexed holder,
uint256 gross,
uint256 recipientTax,
uint256 recycleTax,
uint256 net,
bytes reason
);
event StockRewardConfigured(
uint8 indexed index,
address indexed asset,
address swapAdapter,
address priceGuard,
bytes routeData,
bytes guardData
);
event StockPrizePaid(
uint64 indexed roundId,
uint8 indexed slot,
address indexed holder,
uint256 gross,
uint256 recipientTax,
uint256 recycleTax,
uint256 fundingSpent,
address payoutAsset,
uint256 payoutAmount
);
event StockPaymentDeferred(
uint64 indexed roundId,
uint8 indexed slot,
address indexed holder,
uint256 gross,
uint256 recipientTax,
uint256 recycleTax,
uint256 fundingSpent,
address payoutAsset,
uint256 payoutAmount,
bytes reason
);
event OwedDelivered(address indexed holder, uint256 amount, address indexed caller);
event StockOwedDelivered(
address indexed holder, address indexed asset, uint256 amount, address indexed caller
);
event RoundExpired(uint64 indexed roundId, uint256 returned);
event RoundAbandoned(uint64 indexed roundId, uint256 returned);
event ProtocolFeeSent(address indexed recipient, uint256 amount, address indexed caller);
event TaxSent(address indexed recipient, uint256 amount, address indexed caller);
/// @dev Not `public`: the generated 20-value getter is unencodable without via-IR, which
/// blocks coverage instrumentation. `configuration()` returns the same data as one struct.
RaffleTypes.Settings internal settings;
bytes32 public configHash;
address public subject;
bool public initialized;
uint64 public latestRoundId;
uint64 public latestSnapshotBlock;
uint64 public lastCommitAt;
uint8 public pendingRounds;
uint256 public availablePool;
uint256 public totalReserved;
uint256 public totalOwed;
uint256 public protocolOwed;
uint256 public taxOwed;
uint256 public totalIntake;
uint16 private _feeRemainder;
mapping(uint64 roundId => RaffleTypes.Round round) public rounds;
mapping(bytes32 requestId => uint64 roundId) public roundOfRequest;
mapping(address holder => bool excluded) public isExcluded;
mapping(address holder => uint256 amount) public owed;
mapping(address holder => mapping(address asset => uint256 amount)) public stockOwed;
mapping(address asset => uint256 amount) public totalStockOwed;
RaffleTypes.StockReward[] private _stockRewards;
uint256 private _reentrancyState = 1;
/// @dev The factory deploys this contract once as clone bytecode. Locking that deployment's
/// storage does not affect clone storage, but prevents anyone from initializing and operating
/// the implementation as an untracked raffle.
constructor() {
initialized = true;
}
modifier nonReentrant() {
if (_reentrancyState == 2) revert Reentrancy();
_reentrancyState = 2;
_;
_reentrancyState = 1;
}
modifier onlyAttestor() {
if (msg.sender != settings.attestor) revert Unauthorized();
_;
}
/// @notice Native prize assets accept unattributed deposits; `sync()` credits them.
receive() external payable {
if (settings.prizeAsset != address(0)) revert InvalidValue();
}
// --------------------------------------------------------------------------------
// Initialization
// --------------------------------------------------------------------------------
/// @notice Freezes every parameter. Called by the factory inside the deployment transaction.
function initialize(RaffleTypes.Config calldata config) external {
if (initialized) revert AlreadyInitialized();
_validate(config);
initialized = true;
configHash = keccak256(abi.encode(config));
RaffleTypes.Settings memory frozen = RaffleTypes.Settings({
creator: config.creator,
attestor: config.attestor,
randomness: config.randomness,
prizeAsset: config.prizeAsset,
protocolFeeRecipient: config.protocolFeeRecipient,
taxRecipient: config.taxRecipient,
tokensPerTicket: config.tokensPerTicket,
maxTicketsPerHolder: config.maxTicketsPerHolder,
minPrize: config.minPrize,
maxPrize: config.maxPrize,
prizeBps: config.prizeBps,
recipientTaxBps: config.recipientTaxBps,
recycleTaxBps: config.recycleTaxBps,
minConfirmations: config.minConfirmations,
winnersPerRound: config.winnersPerRound,
minRoundInterval: config.minRoundInterval,
weightWindowBlocks: config.weightWindowBlocks,
randomnessTimeout: config.randomnessTimeout,
claimWindow: config.claimWindow,
basis: config.basis
});
settings = frozen;
uint256 exclusionLength = config.exclusions.length;
for (uint256 i; i < exclusionLength; ++i) {
isExcluded[config.exclusions[i]] = true;
}
uint256 stockRewardLength = config.stockRewards.length;
for (uint256 i; i < stockRewardLength; ++i) {
RaffleTypes.StockReward calldata reward = config.stockRewards[i];
_stockRewards.push(reward);
emit StockRewardConfigured(
// The list is validated at no more than 16 entries.
// forge-lint: disable-next-line(unsafe-typecast)
uint8(i),
reward.asset,
reward.swapAdapter,
reward.priceGuard,
reward.routeData,
reward.guardData
);
}
isExcluded[address(0)] = true;
isExcluded[BURN_ADDRESS] = true;
isExcluded[address(this)] = true;
emit RaffleInitialized(configHash, frozen, config.exclusions);
}
/// @notice Binds the subject token once. The raffle address exists before the token does.
function bind(address subject_) external {
if (!initialized) revert NotInitialized();
if (msg.sender != settings.creator) revert Unauthorized();
if (subject != address(0)) revert SubjectAlreadyBound();
if (
subject_ == address(0) || subject_ == address(this) || subject_ == settings.prizeAsset
|| subject_.code.length == 0
) revert InvalidAddress();
uint256 stockRewardLength = _stockRewards.length;
for (uint256 i; i < stockRewardLength; ++i) {
if (subject_ == _stockRewards[i].asset) revert InvalidAddress();
}
subject = subject_;
isExcluded[subject_] = true;
emit SubjectBound(subject_);
}
// --------------------------------------------------------------------------------
// Deposits
// --------------------------------------------------------------------------------
/// @notice Atomic sink funding. `msg.sender` is measured, never trusted.
function fund(address subject_, address asset, uint256 amount, bytes calldata configData)
external
payable
nonReentrant
returns (uint256 received)
{
address boundSubject = subject;
if (boundSubject == address(0)) revert SubjectNotBound();
if (subject_ != boundSubject) revert InvalidAddress();
address prizeAsset = settings.prizeAsset;
if (asset != prizeAsset) revert InvalidAddress();
if (amount == 0) revert InvalidAmount();
if (configData.length != 0 && keccak256(configData) != configHash) {
revert ConfigurationMismatch();
}
if (prizeAsset == address(0)) {
if (msg.value != amount) revert InvalidValue();
received = amount;
} else {
if (msg.value != 0) revert InvalidValue();
uint256 beforeBalance = prizeAsset.safeBalanceOf(address(this));
prizeAsset.safeTransferFrom(msg.sender, address(this), amount);
uint256 afterBalance = prizeAsset.safeBalanceOf(address(this));
received = afterBalance >= beforeBalance ? afterBalance - beforeBalance : 0;
if (received != amount) revert UnexpectedBalanceDelta(amount, received);
}
(uint256 fee, uint256 net) = _credit(received);
_assertSolvent();
emit Deposited(msg.sender, received, fee, net, true);
}
/// @notice Credits every unaccounted unit held by the raffle into the prize pool.
/// @dev This is the deposit account for platform fees and donations. Value that is already
/// a liability can never be re-credited.
function sync() external nonReentrant returns (uint256 credited, uint256 fee) {
if (!initialized) revert NotInitialized();
uint256 currentLiabilities = _liabilities();
uint256 balance = _balance();
if (balance <= currentLiabilities) return (0, 0);
uint256 gross = balance - currentLiabilities;
uint256 net;
(fee, net) = _credit(gross);
credited = gross;
_assertSolvent();
emit Deposited(msg.sender, gross, fee, net, false);
}
function sendProtocolFee(uint256 amount) external nonReentrant {
if (amount == 0 || amount > protocolOwed) revert InvalidAmount();
protocolOwed -= amount;
address recipient = settings.protocolFeeRecipient;
_sendExactAsset(settings.prizeAsset, recipient, amount);
_assertSolvent();
emit ProtocolFeeSent(recipient, amount, msg.sender);
}
function sendTax(uint256 amount) external nonReentrant {
if (amount == 0 || amount > taxOwed) revert InvalidAmount();
taxOwed -= amount;
address recipient = settings.taxRecipient;
_sendExactAsset(settings.prizeAsset, recipient, amount);
_assertSolvent();
emit TaxSent(recipient, amount, msg.sender);
}
// --------------------------------------------------------------------------------
// Rounds
// --------------------------------------------------------------------------------
/// @notice Commits one snapshot and requests randomness for it in the same transaction.
/// @dev The prize is reserved here, before any seed exists.
function commitRound(
uint64 roundId,
uint64 snapshotBlock,
bytes32 snapshotBlockHash,
bytes32 rootHash,
uint256 totalTickets
) external onlyAttestor nonReentrant returns (uint256 prize) {
if (subject == address(0)) revert SubjectNotBound();
if (roundId != latestRoundId + 1) revert InvalidRound();
if (snapshotBlock <= latestSnapshotBlock) revert InvalidSnapshot();
if (rootHash == bytes32(0) || totalTickets == 0) revert InvalidRoot();
if (pendingRounds >= MAX_PENDING_ROUNDS) revert TooManyPendingRounds();
// The cadence is measured from the previous commitment; the first round is not gated.
// Second-level sequencer drift cannot shorten an hour-scale window materially.
if (lastCommitAt != 0) {
// forge-lint: disable-next-line(block-timestamp)
if (block.timestamp < uint256(lastCommitAt) + settings.minRoundInterval) {
revert RoundTooSoon();
}
}
uint256 currentL2Block = IArbSys(ARBSYS).arbBlockNumber();
if (currentL2Block < uint256(snapshotBlock) + settings.minConfirmations) {
revert InvalidSnapshot();
}
if (currentL2Block > uint256(snapshotBlock) + 255) revert InvalidSnapshot();
if (IArbSys(ARBSYS).arbBlockHash(snapshotBlock) != snapshotBlockHash) {
revert InvalidSnapshot();
}
prize = _prizeFor(availablePool);
if (prize < settings.minPrize) revert PrizeBelowFloor();
availablePool -= prize;
totalReserved += prize;
latestRoundId = roundId;
latestSnapshotBlock = snapshotBlock;
// forge-lint: disable-next-line(unsafe-typecast)
lastCommitAt = uint64(block.timestamp);
pendingRounds += 1;
bytes32 requestId = ISinjohRandomness(settings.randomness).requestRandomness(roundId);
if (requestId == bytes32(0) || roundOfRequest[requestId] != 0) revert InvalidRequest();
roundOfRequest[requestId] = roundId;
RaffleTypes.Round storage round = rounds[roundId];
round.rootHash = rootHash;
round.requestId = requestId;
round.totalTickets = totalTickets;
round.prize = prize;
round.snapshotBlock = snapshotBlock;
// forge-lint: disable-next-line(unsafe-typecast)
round.committedAt = uint64(block.timestamp);
round.state = RaffleTypes.RoundState.COMMITTED;
_assertSolvent();
emit RoundCommitted(
roundId,
snapshotBlock,
snapshotBlockHash,
rootHash,
totalTickets,
prize,
settings.winnersPerRound,
requestId
);
}
/// @notice Randomness delivery. Performs no transfer and calls nothing external.
/// @dev Guarded even though it moves no value. `commitRound` calls out to the adapter while
/// holding the guard, and a hostile adapter could otherwise re-enter here mid-commit to
/// settle an earlier round. No honest adapter delivers during a request.
function receiveRandomness(bytes32 requestId, uint256 seed) external nonReentrant {
if (msg.sender != settings.randomness) revert Unauthorized();
if (seed == 0) revert InvalidSeed();
uint64 roundId = roundOfRequest[requestId];
if (roundId == 0) revert InvalidRequest();
RaffleTypes.Round storage round = rounds[roundId];
if (round.state != RaffleTypes.RoundState.COMMITTED) revert InvalidRound();
round.seed = seed;
// forge-lint: disable-next-line(unsafe-typecast)
round.drawnAt = uint64(block.timestamp);
round.state = RaffleTypes.RoundState.DRAWN;
pendingRounds -= 1;
emit RandomnessReceived(roundId, requestId, seed);
}
/// @notice Pays one slot to the holder whose committed ticket interval contains its index.
function claim(
uint64 roundId,
uint8 slot,
RaffleTypes.Leaf calldata leaf,
RaffleTypes.ProofElement[] calldata proof
) external nonReentrant returns (uint256 paid) {
_requireWinningClaim(roundId, slot, leaf, proof);
paid = _settleSlot(roundId, slot, leaf.holder, false);
_assertSolvent();
}
/// @notice Settles a stock slot in the funding asset instead of the selected stock.
/// @dev Every route component is immutable, so a route that stops quoting or stops executing
/// stops being claimable — permanently, and for a fixed share of every future round. Without
/// this the reserve would sit until `expireRound` returned it to the pool and the winner would
/// receive nothing. Two properties keep it from degrading the ordinary path: it opens only in
/// the final quarter of the claim window, so transient guard failures and genuine slippage are
/// retried for stock first; and only the winner may invoke it, so a keeper cannot downgrade a
/// payout the winner is still willing to wait for.
function claimFunding(
uint64 roundId,
uint8 slot,
RaffleTypes.Leaf calldata leaf,
RaffleTypes.ProofElement[] calldata proof
) external nonReentrant returns (uint256 paid) {
if (_stockRewards.length == 0) revert FallbackUnavailable();
if (msg.sender != leaf.holder) revert Unauthorized();
_requireWinningClaim(roundId, slot, leaf, proof);
// forge-lint: disable-next-line(block-timestamp)
if (block.timestamp < fundingFallbackAt(roundId)) revert FallbackUnavailable();
paid = _settleSlot(roundId, slot, leaf.holder, true);
_assertSolvent();
}
/// @dev Every check that can reject a claim, in one place and before any state changes.
function _requireWinningClaim(
uint64 roundId,
uint8 slot,
RaffleTypes.Leaf calldata leaf,
RaffleTypes.ProofElement[] calldata proof
) private view {
RaffleTypes.Round storage round = rounds[roundId];
if (round.state != RaffleTypes.RoundState.DRAWN) revert InvalidRound();
// forge-lint: disable-next-line(block-timestamp)
if (block.timestamp > uint256(round.drawnAt) + settings.claimWindow) {
revert ClaimWindowClosed();
}
if (slot >= settings.winnersPerRound) revert InvalidSlot();
if (round.slotsPaidMask & _slotBit(slot) != 0) revert SlotAlreadyPaid();
if (leaf.tickets == 0) revert InvalidProof();
if (isExcluded[leaf.holder]) revert ExcludedHolder();
if (proof.length > MAX_PROOF_LENGTH) revert InvalidProof();
(bool valid, uint256 offset) =
_verify(roundId, round.snapshotBlock, round.rootHash, round.totalTickets, leaf, proof);
if (!valid) revert InvalidProof();
uint256 index = winningIndex(roundId, slot);
if (index < offset || index >= offset + leaf.tickets) revert NotWinningLeaf();
}
/// @dev Consumes the slot's reserve, splits the tax, and attempts payment. `fundingFallback`
/// pays the funding asset on a stock raffle; it is gated by `claimFunding`, not here.
function _settleSlot(uint64 roundId, uint8 slot, address holder, bool fundingFallback)
private
returns (uint256 paid)
{
RaffleTypes.Round storage round = rounds[roundId];
uint8 winners = settings.winnersPerRound;
round.slotsPaidMask |= _slotBit(slot);
uint256 share = _slotPrize(round.prize, winners, slot);
round.paidTotal += share;
if (round.paidTotal > round.prize) revert InvariantViolation();
if (round.slotsPaidMask == _fullMask(winners)) {
round.state = RaffleTypes.RoundState.SETTLED;
}
totalReserved -= share;
// Each share is floored independently, so neither can round into the other and any
// rounding dust stays with the winner.
uint256 recipientTax = _applyBps(share, settings.recipientTaxBps);
uint256 recycleTax = _applyBps(share, settings.recycleTaxBps);
uint256 net = share - recipientTax - recycleTax;
if (recipientTax != 0) taxOwed += recipientTax;
if (recycleTax != 0) availablePool += recycleTax;
if (!fundingFallback && _stockRewards.length != 0) {
return _settleStockPrize(roundId, slot, holder, share, recipientTax, recycleTax, net);
}
if (net == 0) {
emit PrizePaid(roundId, slot, holder, share, recipientTax, recycleTax, 0);
return 0;
}
try this.payWinner(holder, net) {
paid = net;
emit PrizePaid(roundId, slot, holder, share, recipientTax, recycleTax, net);
} catch (bytes memory reason) {
owed[holder] += net;
totalOwed += net;
emit PaymentDeferred(
roundId, slot, holder, share, recipientTax, recycleTax, net, reason
);
}
}
function _settleStockPrize(
uint64 roundId,
uint8 slot,
address holder,
uint256 gross,
uint256 recipientTax,
uint256 recycleTax,
uint256 fundingAmount
) private returns (uint256 paid) {
RaffleTypes.StockReward storage reward = _stockRewards[_selectedStockIndex(roundId, slot)];
address payoutAsset = reward.asset;
uint256 payoutAmount;
if (fundingAmount != 0) {
payoutAmount = _swapStockReward(reward, fundingAmount);
}
if (payoutAmount == 0) {
emit StockPrizePaid(
roundId,
slot,
holder,
gross,
recipientTax,
recycleTax,
fundingAmount,
payoutAsset,
0
);
return 0;
}
try this.payStockWinner(holder, payoutAsset, payoutAmount) {
paid = payoutAmount;
emit StockPrizePaid(
roundId,
slot,
holder,
gross,
recipientTax,
recycleTax,
fundingAmount,
payoutAsset,
payoutAmount
);
} catch (bytes memory reason) {
stockOwed[holder][payoutAsset] += payoutAmount;
totalStockOwed[payoutAsset] += payoutAmount;
_assertStockSolvent(payoutAsset);
emit StockPaymentDeferred(
roundId,
slot,
holder,
gross,
recipientTax,
recycleTax,
fundingAmount,
payoutAsset,
payoutAmount,
reason
);
}
}
function _swapStockReward(RaffleTypes.StockReward storage reward, uint256 amountIn)
private
returns (uint256 amountOut)
{
address fundingAsset = settings.prizeAsset;
(uint256 minimum, uint48 validUntil) = ISinjohPriceGuard(reward.priceGuard)
.minimumOutput(
reward.asset,
fundingAsset,
reward.asset,
amountIn,
keccak256(reward.routeData),
reward.guardData
);
// forge-lint: disable-next-line(block-timestamp)
if (minimum == 0 || block.timestamp > validUntil) revert QuoteExpired();
uint256 inputBefore = fundingAsset.safeBalanceOf(address(this));
uint256 outputBefore = reward.asset.safeBalanceOf(address(this));
fundingAsset.safeApprove(reward.swapAdapter, amountIn);
ISinjohSwapAdapter(reward.swapAdapter)
.swap(fundingAsset, reward.asset, amountIn, minimum, reward.routeData);
fundingAsset.safeApprove(reward.swapAdapter, 0);
uint256 inputAfter = fundingAsset.safeBalanceOf(address(this));
uint256 spent = inputBefore >= inputAfter ? inputBefore - inputAfter : 0;
if (spent != amountIn) revert UnexpectedBalanceDelta(amountIn, spent);
uint256 outputAfter = reward.asset.safeBalanceOf(address(this));
amountOut = outputAfter >= outputBefore ? outputAfter - outputBefore : 0;
if (amountOut < minimum) revert InsufficientOutput(minimum, amountOut);
}
/// @dev Isolated so a reverting winner cannot roll back an already-settled slot.
function payWinner(address holder, uint256 amount) external {
if (msg.sender != address(this)) revert OnlySelf();
_sendExactAsset(settings.prizeAsset, holder, amount);
}
/// @dev Isolated so a rejecting stock token or winner cannot roll back settlement.
function payStockWinner(address holder, address asset, uint256 amount) external {
if (msg.sender != address(this)) revert OnlySelf();
_sendExactAsset(asset, holder, amount);
}
/// @notice Delivers value that a winner's transfer previously rejected. Retryable forever.
function deliverOwed(address holder) external nonReentrant returns (uint256 amount) {
amount = owed[holder];
if (amount == 0) revert NothingOwed();
owed[holder] = 0;
totalOwed -= amount;
_sendExactAsset(settings.prizeAsset, holder, amount);
_assertSolvent();
emit OwedDelivered(holder, amount, msg.sender);
}
/// @notice Delivers a stock prize that a previous transfer rejected. Retryable forever.
function deliverStockOwed(address holder, address asset)
external
nonReentrant
returns (uint256 amount)
{
amount = stockOwed[holder][asset];
if (amount == 0) revert NothingOwed();
stockOwed[holder][asset] = 0;
totalStockOwed[asset] -= amount;
_sendExactAsset(asset, holder, amount);
_assertStockSolvent(asset);
emit StockOwedDelivered(holder, asset, amount, msg.sender);
}
/// @notice Returns an unclaimed reserve to the pool once the claim window closes.
function expireRound(uint64 roundId) external nonReentrant returns (uint256 returned) {
RaffleTypes.Round storage round = rounds[roundId];
if (round.state != RaffleTypes.RoundState.DRAWN) revert InvalidRound();
// forge-lint: disable-next-line(block-timestamp)
if (block.timestamp <= uint256(round.drawnAt) + settings.claimWindow) {
revert ClaimWindowOpen();
}
returned = round.prize - round.paidTotal;
round.state = RaffleTypes.RoundState.EXPIRED;
if (returned != 0) {
totalReserved -= returned;
availablePool += returned;
}
emit RoundExpired(roundId, returned);
}
/// @notice Returns a reserve to the pool when randomness never arrived.
/// @dev The round is closed permanently: no snapshot can ever be re-rolled.
function abandonRound(uint64 roundId) external nonReentrant returns (uint256 returned) {
RaffleTypes.Round storage round = rounds[roundId];
if (round.state != RaffleTypes.RoundState.COMMITTED) revert InvalidRound();
// forge-lint: disable-next-line(block-timestamp)
if (block.timestamp <= uint256(round.committedAt) + settings.randomnessTimeout) {
revert RandomnessPending();
}
returned = round.prize;
round.state = RaffleTypes.RoundState.ABANDONED;
pendingRounds -= 1;
if (returned != 0) {
totalReserved -= returned;
availablePool += returned;
}
emit RoundAbandoned(roundId, returned);
}
// --------------------------------------------------------------------------------
// Views
// --------------------------------------------------------------------------------
function winningIndex(uint64 roundId, uint8 slot) public view returns (uint256) {
RaffleTypes.Round storage round = rounds[roundId];
uint256 seed = round.seed;
if (seed == 0) revert RandomnessPending();
return uint256(
keccak256(abi.encode(SLOT_DOMAIN, block.chainid, address(this), roundId, slot, seed))
) % round.totalTickets;
}
/// @notice The timestamp from which `claimFunding` opens for a drawn round.
/// @dev Undrawn rounds report a meaningless early time; `claimFunding` rejects them on state.
function fundingFallbackAt(uint64 roundId) public view returns (uint256) {
uint32 window = settings.claimWindow;
return
uint256(rounds[roundId].drawnAt) + window - window / STOCK_FALLBACK_DIVISOR;
}
/// @notice The immutable stock route selected by VRF for one winning slot.
function selectedStock(uint64 roundId, uint8 slot)
external
view
returns (uint256 index, address asset)
{
index = _selectedStockIndex(roundId, slot);
asset = _stockRewards[index].asset;
}
function stockRewardCount() external view returns (uint256) {
return _stockRewards.length;
}
function stockReward(uint256 index) external view returns (RaffleTypes.StockReward memory) {
return _stockRewards[index];
}
function leafHash(uint64 roundId, uint64 snapshotBlock, address holder, uint256 tickets)
public
view
returns (bytes32)
{
return keccak256(
abi.encode(
LEAF_DOMAIN, block.chainid, address(this), roundId, snapshotBlock, holder, tickets
)
);
}
function nodeHash(bytes32 leftHash, uint256 leftSum, bytes32 rightHash, uint256 rightSum)
public
pure
returns (bytes32)
{
return keccak256(abi.encode(NODE_DOMAIN, leftHash, leftSum, rightHash, rightSum));
}
function emptyLeafHash(uint64 roundId) public pure returns (bytes32) {
return keccak256(abi.encode(EMPTY_DOMAIN, roundId));
}
/// @notice Verifies a proof and returns the leaf's derived ticket-interval start.
function verify(
uint64 roundId,
RaffleTypes.Leaf calldata leaf,
RaffleTypes.ProofElement[] calldata proof
) external view returns (bool valid, uint256 offset) {
RaffleTypes.Round storage round = rounds[roundId];
return
_verify(roundId, round.snapshotBlock, round.rootHash, round.totalTickets, leaf, proof);
}
function slotPrize(uint64 roundId, uint8 slot) external view returns (uint256) {
return _slotPrize(rounds[roundId].prize, settings.winnersPerRound, slot);
}
/// @notice The frozen configuration, as one struct.
function configuration() external view returns (RaffleTypes.Settings memory) {
return settings;
}
/// @notice Total payout tax in basis points: the recipient share plus the recycled share.
function payoutTaxBps() external view returns (uint256) {
return uint256(settings.recipientTaxBps) + settings.recycleTaxBps;
}
function nextPrize() external view returns (uint256) {
return _prizeFor(availablePool);
}
function liabilities() external view returns (uint256) {
return _liabilities();
}
function ticketsFor(uint256 weight) external view returns (uint256 tickets) {
tickets = weight / settings.tokensPerTicket;
uint256 cap = settings.maxTicketsPerHolder;
if (cap != 0 && tickets > cap) tickets = cap;
}
// --------------------------------------------------------------------------------
// Internal
// --------------------------------------------------------------------------------
function _validate(RaffleTypes.Config calldata config) private view {
if (
config.creator == address(0) || config.attestor == address(0)
|| config.randomness == address(0) || config.protocolFeeRecipient == address(0)
) revert InvalidAddress();
if (config.randomness.code.length == 0) revert InvalidAddress();
if (config.prizeAsset != address(0) && config.prizeAsset.code.length == 0) {
revert InvalidAddress();
}
if (config.recipientTaxBps != 0 && config.taxRecipient == address(0)) {
revert InvalidAddress();
}
if (config.tokensPerTicket == 0) revert InvalidConfiguration();
if (config.prizeBps == 0 || config.prizeBps > BPS) revert InvalidConfiguration();
if (uint256(config.recipientTaxBps) + config.recycleTaxBps > MAX_PAYOUT_TAX_BPS) {
revert InvalidConfiguration();
}
if (config.minPrize == 0) revert InvalidConfiguration();
if (config.maxPrize != 0 && config.maxPrize < config.minPrize) {
revert InvalidConfiguration();
}
if (config.winnersPerRound == 0 || config.winnersPerRound > MAX_WINNERS_PER_ROUND) {
revert InvalidConfiguration();
}
if (
config.minRoundInterval < MIN_ROUND_INTERVAL
|| config.minRoundInterval > MAX_ROUND_INTERVAL
) revert InvalidConfiguration();
if (config.minConfirmations == 0 || config.minConfirmations > 255) {
revert InvalidConfiguration();
}
if (config.basis == RaffleTypes.TicketBasis.SNAPSHOT) {
if (config.weightWindowBlocks != 0) revert InvalidConfiguration();
} else if (
config.weightWindowBlocks == 0 || config.weightWindowBlocks > MAX_WEIGHT_WINDOW_BLOCKS
) {
revert InvalidConfiguration();
}
if (
config.randomnessTimeout < MIN_RANDOMNESS_TIMEOUT
|| config.randomnessTimeout > MAX_RANDOMNESS_TIMEOUT
) revert InvalidConfiguration();
if (config.claimWindow < MIN_CLAIM_WINDOW || config.claimWindow > MAX_CLAIM_WINDOW) {
revert InvalidConfiguration();
}
uint256 exclusionLength = config.exclusions.length;
if (exclusionLength > MAX_EXCLUSIONS) revert InvalidConfiguration();
address previous;
for (uint256 i; i < exclusionLength; ++i) {
address excluded = config.exclusions[i];
if (excluded == address(0) || excluded <= previous) revert InvalidConfiguration();
previous = excluded;
}
uint256 stockRewardLength = config.stockRewards.length;
if (stockRewardLength > MAX_STOCK_REWARDS) revert InvalidConfiguration();
if (stockRewardLength != 0 && config.prizeAsset == address(0)) {
revert InvalidConfiguration();
}
previous = address(0);
for (uint256 i; i < stockRewardLength; ++i) {
RaffleTypes.StockReward calldata reward = config.stockRewards[i];
if (
reward.asset == address(0) || reward.asset == config.prizeAsset
|| reward.asset <= previous || reward.asset.code.length == 0
|| reward.swapAdapter.code.length == 0 || reward.priceGuard.code.length == 0
) revert InvalidConfiguration();
if (
reward.routeData.length > MAX_ROUTE_DATA_LENGTH
|| reward.guardData.length > MAX_ROUTE_DATA_LENGTH
) revert InvalidConfiguration();
previous = reward.asset;
}
}
function _credit(uint256 gross) private returns (uint256 fee, uint256 net) {
uint16 remainder = _feeRemainder;
uint256 scaledRemainder = (gross % BPS) * PROTOCOL_FEE_BPS + remainder;
// Quotient/remainder decomposition avoids overflow without losing precision.
// forge-lint: disable-next-line(divide-before-multiply)
fee = (gross / BPS) * PROTOCOL_FEE_BPS + scaledRemainder / BPS;
// The modulo result is strictly below BPS and therefore fits uint16.
// forge-lint: disable-next-line(unsafe-typecast)
_feeRemainder = uint16(scaledRemainder % BPS);
net = gross - fee;
protocolOwed += fee;
availablePool += net;
totalIntake += gross;
}
function _prizeFor(uint256 pool) private view returns (uint256 prize) {
prize = _applyBps(pool, settings.prizeBps);
uint256 cap = settings.maxPrize;
if (cap != 0 && prize > cap) prize = cap;
}
/// @dev Computes floor(value * bps / BPS) without overflowing for any uint256 value.
function _applyBps(uint256 value, uint16 bps) private pure returns (uint256) {
// forge-lint: disable-next-line(divide-before-multiply)
return (value / BPS) * bps + ((value % BPS) * bps) / BPS;
}
function _slotPrize(uint256 prize, uint8 winners, uint8 slot) private pure returns (uint256) {
uint256 base = prize / winners;
return slot == 0 ? base + (prize % winners) : base;
}
function _slotBit(uint8 slot) private pure returns (uint16) {
// forge-lint: disable-next-line(unsafe-typecast)
return uint16(uint256(1) << slot);
}
function _fullMask(uint8 winners) private pure returns (uint16) {
// forge-lint: disable-next-line(unsafe-typecast)
return uint16((uint256(1) << winners) - 1);
}
function _selectedStockIndex(uint64 roundId, uint8 slot) private view returns (uint256) {
uint256 stockRewardLength = _stockRewards.length;
if (stockRewardLength == 0 || slot >= settings.winnersPerRound) revert InvalidSlot();
uint256 seed = rounds[roundId].seed;
if (seed == 0) revert RandomnessPending();
return uint256(
keccak256(abi.encode(STOCK_DOMAIN, block.chainid, address(this), roundId, slot, seed))
) % stockRewardLength;
}
function _verify(
uint64 roundId,
uint64 snapshotBlock,
bytes32 rootHash,
uint256 totalTickets,
RaffleTypes.Leaf calldata leaf,
RaffleTypes.ProofElement[] calldata proof
) private view returns (bool valid, uint256 offset) {
if (rootHash == bytes32(0)) return (false, 0);
bytes32 hash = leafHash(roundId, snapshotBlock, leaf.holder, leaf.tickets);
uint256 sum = leaf.tickets;
uint256 proofLength = proof.length;
for (uint256 i; i < proofLength; ++i) {
RaffleTypes.ProofElement calldata element = proof[i];
if (element.siblingIsLeft) {
hash = nodeHash(element.siblingHash, element.siblingSum, hash, sum);
offset += element.siblingSum;
} else {
hash = nodeHash(hash, sum, element.siblingHash, element.siblingSum);
}
sum += element.siblingSum;
}
valid = hash == rootHash && sum == totalTickets;
if (!valid) offset = 0;
}
function _balance() private view returns (uint256) {
address prizeAsset = settings.prizeAsset;
return
prizeAsset == address(0)
? address(this).balance
: prizeAsset.safeBalanceOf(address(this));
}
function _liabilities() private view returns (uint256) {
return availablePool + totalReserved + totalOwed + protocolOwed + taxOwed;
}
function _sendExactAsset(address asset, address recipient, uint256 amount) private {
uint256 beforeBalance =
asset == address(0) ? address(this).balance : asset.safeBalanceOf(address(this));
if (asset == address(0)) {
SafeTransferLib.safeTransferETH(recipient, amount);
} else {
uint256 recipientBefore = asset.safeBalanceOf(recipient);
asset.safeTransfer(recipient, amount);
uint256 recipientAfter = asset.safeBalanceOf(recipient);
uint256 received =
recipientAfter >= recipientBefore ? recipientAfter - recipientBefore : 0;
if (received != amount) revert UnexpectedBalanceDelta(amount, received);
}
uint256 afterBalance =
asset == address(0) ? address(this).balance : asset.safeBalanceOf(address(this));
uint256 spent = beforeBalance >= afterBalance ? beforeBalance - afterBalance : 0;
if (spent != amount) revert UnexpectedBalanceDelta(amount, spent);
}
function _assertSolvent() private view {
if (_balance() < _liabilities()) revert Insolvent();
}
function _assertStockSolvent(address asset) private view {
if (asset.safeBalanceOf(address(this)) < totalStockOwed[asset]) revert Insolvent();
}
}[
{
"type": "constructor",
"inputs": [],
"stateMutability": "nonpayable"
},
{
"name": "AlreadyInitialized",
"type": "error",
"inputs": []
},
{
"name": "ApprovalFailed",
"type": "error",
"inputs": []
},
{
"name": "BalanceQueryFailed",
"type": "error",
"inputs": []
},
{
"name": "ClaimWindowClosed",
"type": "error",
"inputs": []
},
{
"name": "ClaimWindowOpen",
"type": "error",
"inputs": []
},
{
"name": "ConfigurationMismatch",
"type": "error",
"inputs": []
},
{
"name": "ExcludedHolder",
"type": "error",
"inputs": []
},
{
"name": "FallbackUnavailable",
"type": "error",
"inputs": []
},
{
"name": "Insolvent",
"type": "error",
"inputs": []
},
{
"name": "InsufficientOutput",
"type": "error",
"inputs": [
{
"name": "minimum",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "actual",
"type": "uint256",
"internalType": "uint256"
}
]
},
{
"name": "InvalidAddress",
"type": "error",
"inputs": []
},
{
"name": "InvalidAmount",
"type": "error",
"inputs": []
},
{
"name": "InvalidConfiguration",
"type": "error",
"inputs": []
},
{
"name": "InvalidProof",
"type": "error",
"inputs": []
},
{
"name": "InvalidRequest",
"type": "error",
"inputs": []
},
{
"name": "InvalidRoot",
"type": "error",
"inputs": []
},
{
"name": "InvalidRound",
"type": "error",
"inputs": []
},
{
"name": "InvalidSeed",
"type": "error",
"inputs": []
},
{
"name": "InvalidSlot",
"type": "error",
"inputs": []
},
{
"name": "InvalidSnapshot",
"type": "error",
"inputs": []
},
{
"name": "InvalidValue",
"type": "error",
"inputs": []
},
{
"name": "InvariantViolation",
"type": "error",
"inputs": []
},
{
"name": "NativeTransferFailed",
"type": "error",
"inputs": []
},
{
"name": "NonCanonicalConfiguration",
"type": "error",
"inputs": []
},
{
"name": "NotInitialized",
"type": "error",
"inputs": []
},
{
"name": "NotWinningLeaf",
"type": "error",
"inputs": []
},
{
"name": "NothingOwed",
"type": "error",
"inputs": []
},
{
"name": "OnlySelf",
"type": "error",
"inputs": []
},
{
"name": "PrizeBelowFloor",
"type": "error",
"inputs": []
},
{
"name": "QuoteExpired",
"type": "error",
"inputs": []
},
{
"name": "RandomnessPending",
"type": "error",
"inputs": []
},
{
"name": "Reentrancy",
"type": "error",
"inputs": []
},
{
"name": "RoundTooSoon",
"type": "error",
"inputs": []
},
{
"name": "SlotAlreadyPaid",
"type": "error",
"inputs": []
},
{
"name": "SubjectAlreadyBound",
"type": "error",
"inputs": []
},
{
"name": "SubjectNotBound",
"type": "error",
"inputs": []
},
{
"name": "TooManyPendingRounds",
"type": "error",
"inputs": []
},
{
"name": "TransferFailed",
"type": "error",
"inputs": []
},
{
"name": "TransferFromFailed",
"type": "error",
"inputs": []
},
{
"name": "Unauthorized",
"type": "error",
"inputs": []
},
{
"name": "UnexpectedBalanceDelta",
"type": "error",
"inputs": [
{
"name": "expected",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "actual",
"type": "uint256",
"internalType": "uint256"
}
]
},
{
"name": "Deposited",
"type": "event",
"inputs": [
{
"name": "source",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "gross",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
},
{
"name": "fee",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
},
{
"name": "net",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
},
{
"name": "attributed",
"type": "bool",
"indexed": false,
"internalType": "bool"
}
],
"anonymous": false
},
{
"name": "OwedDelivered",
"type": "event",
"inputs": [
{
"name": "holder",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "amount",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
},
{
"name": "caller",
"type": "address",
"indexed": true,
"internalType": "address"
}
],
"anonymous": false
},
{
"name": "PaymentDeferred",
"type": "event",
"inputs": [
{
"name": "roundId",
"type": "uint64",
"indexed": true,
"internalType": "uint64"
},
{
"name": "slot",
"type": "uint8",
"indexed": true,
"internalType": "uint8"
},
{
"name": "holder",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "gross",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
},
{
"name": "recipientTax",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
},
{
"name": "recycleTax",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
},
{
"name": "net",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
},
{
"name": "reason",
"type": "bytes",
"indexed": false,
"internalType": "bytes"
}
],
"anonymous": false
},
{
"name": "PrizePaid",
"type": "event",
"inputs": [
{
"name": "roundId",
"type": "uint64",
"indexed": true,
"internalType": "uint64"
},
{
"name": "slot",
"type": "uint8",
"indexed": true,
"internalType": "uint8"
},
{
"name": "holder",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "gross",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
},
{
"name": "recipientTax",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
},
{
"name": "recycleTax",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
},
{
"name": "net",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
}
],
"anonymous": false
},
{
"name": "ProtocolFeeSent",
"type": "event",
"inputs": [
{
"name": "recipient",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "amount",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
},
{
"name": "caller",
"type": "address",
"indexed": true,
"internalType": "address"
}
],
"anonymous": false
},
{
"name": "RaffleInitialized",
"type": "event",
"inputs": [
{
"name": "configHash",
"type": "bytes32",
"indexed": true,
"internalType": "bytes32"
},
{
"name": "configuration",
"type": "tuple",
"indexed": false,
"components": [
{
"name": "creator",
"type": "address",
"internalType": "address"
},
{
"name": "attestor",
"type": "address",
"internalType": "address"
},
{
"name": "randomness",
"type": "address",
"internalType": "address"
},
{
"name": "prizeAsset",
"type": "address",
"internalType": "address"
},
{
"name": "protocolFeeRecipient",
"type": "address",
"internalType": "address"
},
{
"name": "taxRecipient",
"type": "address",
"internalType": "address"
},
{
"name": "tokensPerTicket",
"type": "uint128",
"internalType": "uint128"
},
{
"name": "maxTicketsPerHolder",
"type": "uint128",
"internalType": "uint128"
},
{
"name": "minPrize",
"type": "uint128",
"internalType": "uint128"
},
{
"name": "maxPrize",
"type": "uint128",
"internalType": "uint128"
},
{
"name": "prizeBps",
"type": "uint16",
"internalType": "uint16"
},
{
"name": "recipientTaxBps",
"type": "uint16",
"internalType": "uint16"
},
{
"name": "recycleTaxBps",
"type": "uint16",
"internalType": "uint16"
},
{
"name": "minConfirmations",
"type": "uint16",
"internalType": "uint16"
},
{
"name": "winnersPerRound",
"type": "uint8",
"internalType": "uint8"
},
{
"name": "minRoundInterval",
"type": "uint32",
"internalType": "uint32"
},
{
"name": "weightWindowBlocks",
"type": "uint32",
"internalType": "uint32"
},
{
"name": "randomnessTimeout",
"type": "uint32",
"internalType": "uint32"
},
{
"name": "claimWindow",
"type": "uint32",
"internalType": "uint32"
},
{
"name": "basis",
"type": "uint8",
"internalType": "enum RaffleTypes.TicketBasis"
}
],
"internalType": "struct RaffleTypes.Settings"
},
{
"name": "exclusions",
"type": "address[]",
"indexed": false,
"internalType": "address[]"
}
],
"anonymous": false
},
{
"name": "RandomnessReceived",
"type": "event",
"inputs": [
{
"name": "roundId",
"type": "uint64",
"indexed": true,
"internalType": "uint64"
},
{
"name": "requestId",
"type": "bytes32",
"indexed": false,
"internalType": "bytes32"
},
{
"name": "seed",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
}
],
"anonymous": false
},
{
"name": "RoundAbandoned",
"type": "event",
"inputs": [
{
"name": "roundId",
"type": "uint64",
"indexed": true,
"internalType": "uint64"
},
{
"name": "returned",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
}
],
"anonymous": false
},
{
"name": "RoundCommitted",
"type": "event",
"inputs": [
{
"name": "roundId",
"type": "uint64",
"indexed": true,
"internalType": "uint64"
},
{
"name": "snapshotBlock",
"type": "uint64",
"indexed": false,
"internalType": "uint64"
},
{
"name": "snapshotBlockHash",
"type": "bytes32",
"indexed": false,
"internalType": "bytes32"
},
{
"name": "rootHash",
"type": "bytes32",
"indexed": false,
"internalType": "bytes32"
},
{
"name": "totalTickets",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
},
{
"name": "prize",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
},
{
"name": "winnersPerRound",
"type": "uint8",
"indexed": false,
"internalType": "uint8"
},
{
"name": "requestId",
"type": "bytes32",
"indexed": false,
"internalType": "bytes32"
}
],
"anonymous": false
},
{
"name": "RoundExpired",
"type": "event",
"inputs": [
{
"name": "roundId",
"type": "uint64",
"indexed": true,
"internalType": "uint64"
},
{
"name": "returned",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
}
],
"anonymous": false
},
{
"name": "StockOwedDelivered",
"type": "event",
"inputs": [
{
"name": "holder",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "asset",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "amount",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
},
{
"name": "caller",
"type": "address",
"indexed": true,
"internalType": "address"
}
],
"anonymous": false
},
{
"name": "StockPaymentDeferred",
"type": "event",
"inputs": [
{
"name": "roundId",
"type": "uint64",
"indexed": true,
"internalType": "uint64"
},
{
"name": "slot",
"type": "uint8",
"indexed": true,
"internalType": "uint8"
},
{
"name": "holder",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "gross",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
},
{
"name": "recipientTax",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
},
{
"name": "recycleTax",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
},
{
"name": "fundingSpent",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
},
{
"name": "payoutAsset",
"type": "address",
"indexed": false,
"internalType": "address"
},
{
"name": "payoutAmount",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
},
{
"name": "reason",
"type": "bytes",
"indexed": false,
"internalType": "bytes"
}
],
"anonymous": false
},
{
"name": "StockPrizePaid",
"type": "event",
"inputs": [
{
"name": "roundId",
"type": "uint64",
"indexed": true,
"internalType": "uint64"
},
{
"name": "slot",
"type": "uint8",
"indexed": true,
"internalType": "uint8"
},
{
"name": "holder",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "gross",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
},
{
"name": "recipientTax",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
},
{
"name": "recycleTax",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
},
{
"name": "fundingSpent",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
},
{
"name": "payoutAsset",
"type": "address",
"indexed": false,
"internalType": "address"
},
{
"name": "payoutAmount",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
}
],
"anonymous": false
},
{
"name": "StockRewardConfigured",
"type": "event",
"inputs": [
{
"name": "index",
"type": "uint8",
"indexed": true,
"internalType": "uint8"
},
{
"name": "asset",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "swapAdapter",
"type": "address",
"indexed": false,
"internalType": "address"
},
{
"name": "priceGuard",
"type": "address",
"indexed": false,
"internalType": "address"
},
{
"name": "routeData",
"type": "bytes",
"indexed": false,
"internalType": "bytes"
},
{
"name": "guardData",
"type": "bytes",
"indexed": false,
"internalType": "bytes"
}
],
"anonymous": false
},
{
"name": "SubjectBound",
"type": "event",
"inputs": [
{
"name": "subject",
"type": "address",
"indexed": true,
"internalType": "address"
}
],
"anonymous": false
},
{
"name": "TaxSent",
"type": "event",
"inputs": [
{
"name": "recipient",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "amount",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
},
{
"name": "caller",
"type": "address",
"indexed": true,
"internalType": "address"
}
],
"anonymous": false
},
{
"name": "ARBSYS",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "address",
"internalType": "address"
}
],
"stateMutability": "view"
},
{
"name": "BPS",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint16",
"internalType": "uint16"
}
],
"stateMutability": "view"
},
{
"name": "BURN_ADDRESS",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "address",
"internalType": "address"
}
],
"stateMutability": "view"
},
{
"name": "EMPTY_DOMAIN",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "bytes32",
"internalType": "bytes32"
}
],
"stateMutability": "view"
},
{
"name": "LEAF_DOMAIN",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "bytes32",
"internalType": "bytes32"
}
],
"stateMutability": "view"
},
{
"name": "MAX_CLAIM_WINDOW",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint32",
"internalType": "uint32"
}
],
"stateMutability": "view"
},
{
"name": "MAX_EXCLUSIONS",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint8",
"internalType": "uint8"
}
],
"stateMutability": "view"
},
{
"name": "MAX_PAYOUT_TAX_BPS",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint16",
"internalType": "uint16"
}
],
"stateMutability": "view"
},
{
"name": "MAX_PENDING_ROUNDS",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint8",
"internalType": "uint8"
}
],
"stateMutability": "view"
},
{
"name": "MAX_PROOF_LENGTH",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint8",
"internalType": "uint8"
}
],
"stateMutability": "view"
},
{
"name": "MAX_RANDOMNESS_TIMEOUT",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint32",
"internalType": "uint32"
}
],
"stateMutability": "view"
},
{
"name": "MAX_ROUND_INTERVAL",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint32",
"internalType": "uint32"
}
],
"stateMutability": "view"
},
{
"name": "MAX_ROUTE_DATA_LENGTH",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint16",
"internalType": "uint16"
}
],
"stateMutability": "view"
},
{
"name": "MAX_STOCK_REWARDS",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint8",
"internalType": "uint8"
}
],
"stateMutability": "view"
},
{
"name": "MAX_WEIGHT_WINDOW_BLOCKS",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint32",
"internalType": "uint32"
}
],
"stateMutability": "view"
},
{
"name": "MAX_WINNERS_PER_ROUND",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint8",
"internalType": "uint8"
}
],
"stateMutability": "view"
},
{
"name": "MIN_CLAIM_WINDOW",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint32",
"internalType": "uint32"
}
],
"stateMutability": "view"
},
{
"name": "MIN_RANDOMNESS_TIMEOUT",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint32",
"internalType": "uint32"
}
],
"stateMutability": "view"
},
{
"name": "MIN_ROUND_INTERVAL",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint32",
"internalType": "uint32"
}
],
"stateMutability": "view"
},
{
"name": "NODE_DOMAIN",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "bytes32",
"internalType": "bytes32"
}
],
"stateMutability": "view"
},
{
"name": "PROTOCOL_FEE_BPS",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint16",
"internalType": "uint16"
}
],
"stateMutability": "view"
},
{
"name": "SLOT_DOMAIN",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "bytes32",
"internalType": "bytes32"
}
],
"stateMutability": "view"
},
{
"name": "STOCK_DOMAIN",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "bytes32",
"internalType": "bytes32"
}
],
"stateMutability": "view"
},
{
"name": "STOCK_FALLBACK_DIVISOR",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint32",
"internalType": "uint32"
}
],
"stateMutability": "view"
},
{
"name": "abandonRound",
"type": "function",
"inputs": [
{
"name": "roundId",
"type": "uint64",
"internalType": "uint64"
}
],
"outputs": [
{
"name": "returned",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "nonpayable"
},
{
"name": "availablePool",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "bind",
"type": "function",
"inputs": [
{
"name": "subject_",
"type": "address",
"internalType": "address"
}
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"name": "claim",
"type": "function",
"inputs": [
{
"name": "roundId",
"type": "uint64",
"internalType": "uint64"
},
{
"name": "slot",
"type": "uint8",
"internalType": "uint8"
},
{
"name": "leaf",
"type": "tuple",
"components": [
{
"name": "holder",
"type": "address",
"internalType": "address"
},
{
"name": "tickets",
"type": "uint256",
"internalType": "uint256"
}
],
"internalType": "struct RaffleTypes.Leaf"
},
{
"name": "proof",
"type": "tuple[]",
"components": [
{
"name": "siblingHash",
"type": "bytes32",
"internalType": "bytes32"
},
{
"name": "siblingSum",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "siblingIsLeft",
"type": "bool",
"internalType": "bool"
}
],
"internalType": "struct RaffleTypes.ProofElement[]"
}
],
"outputs": [
{
"name": "paid",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "nonpayable"
},
{
"name": "claimFunding",
"type": "function",
"inputs": [
{
"name": "roundId",
"type": "uint64",
"internalType": "uint64"
},
{
"name": "slot",
"type": "uint8",
"internalType": "uint8"
},
{
"name": "leaf",
"type": "tuple",
"components": [
{
"name": "holder",
"type": "address",
"internalType": "address"
},
{
"name": "tickets",
"type": "uint256",
"internalType": "uint256"
}
],
"internalType": "struct RaffleTypes.Leaf"
},
{
"name": "proof",
"type": "tuple[]",
"components": [
{
"name": "siblingHash",
"type": "bytes32",
"internalType": "bytes32"
},
{
"name": "siblingSum",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "siblingIsLeft",
"type": "bool",
"internalType": "bool"
}
],
"internalType": "struct RaffleTypes.ProofElement[]"
}
],
"outputs": [
{
"name": "paid",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "nonpayable"
},
{
"name": "commitRound",
"type": "function",
"inputs": [
{
"name": "roundId",
"type": "uint64",
"internalType": "uint64"
},
{
"name": "snapshotBlock",
"type": "uint64",
"internalType": "uint64"
},
{
"name": "snapshotBlockHash",
"type": "bytes32",
"internalType": "bytes32"
},
{
"name": "rootHash",
"type": "bytes32",
"internalType": "bytes32"
},
{
"name": "totalTickets",
"type": "uint256",
"internalType": "uint256"
}
],
"outputs": [
{
"name": "prize",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "nonpayable"
},
{
"name": "configHash",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "bytes32",
"internalType": "bytes32"
}
],
"stateMutability": "view"
},
{
"name": "configuration",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "tuple",
"components": [
{
"name": "creator",
"type": "address",
"internalType": "address"
},
{
"name": "attestor",
"type": "address",
"internalType": "address"
},
{
"name": "randomness",
"type": "address",
"internalType": "address"
},
{
"name": "prizeAsset",
"type": "address",
"internalType": "address"
},
{
"name": "protocolFeeRecipient",
"type": "address",
"internalType": "address"
},
{
"name": "taxRecipient",
"type": "address",
"internalType": "address"
},
{
"name": "tokensPerTicket",
"type": "uint128",
"internalType": "uint128"
},
{
"name": "maxTicketsPerHolder",
"type": "uint128",
"internalType": "uint128"
},
{
"name": "minPrize",
"type": "uint128",
"internalType": "uint128"
},
{
"name": "maxPrize",
"type": "uint128",
"internalType": "uint128"
},
{
"name": "prizeBps",
"type": "uint16",
"internalType": "uint16"
},
{
"name": "recipientTaxBps",
"type": "uint16",
"internalType": "uint16"
},
{
"name": "recycleTaxBps",
"type": "uint16",
"internalType": "uint16"
},
{
"name": "minConfirmations",
"type": "uint16",
"internalType": "uint16"
},
{
"name": "winnersPerRound",
"type": "uint8",
"internalType": "uint8"
},
{
"name": "minRoundInterval",
"type": "uint32",
"internalType": "uint32"
},
{
"name": "weightWindowBlocks",
"type": "uint32",
"internalType": "uint32"
},
{
"name": "randomnessTimeout",
"type": "uint32",
"internalType": "uint32"
},
{
"name": "claimWindow",
"type": "uint32",
"internalType": "uint32"
},
{
"name": "basis",
"type": "uint8",
"internalType": "enum RaffleTypes.TicketBasis"
}
],
"internalType": "struct RaffleTypes.Settings"
}
],
"stateMutability": "view"
},
{
"name": "deliverOwed",
"type": "function",
"inputs": [
{
"name": "holder",
"type": "address",
"internalType": "address"
}
],
"outputs": [
{
"name": "amount",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "nonpayable"
},
{
"name": "deliverStockOwed",
"type": "function",
"inputs": [
{
"name": "holder",
"type": "address",
"internalType": "address"
},
{
"name": "asset",
"type": "address",
"internalType": "address"
}
],
"outputs": [
{
"name": "amount",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "nonpayable"
},
{
"name": "emptyLeafHash",
"type": "function",
"inputs": [
{
"name": "roundId",
"type": "uint64",
"internalType": "uint64"
}
],
"outputs": [
{
"name": "",
"type": "bytes32",
"internalType": "bytes32"
}
],
"stateMutability": "pure"
},
{
"name": "expireRound",
"type": "function",
"inputs": [
{
"name": "roundId",
"type": "uint64",
"internalType": "uint64"
}
],
"outputs": [
{
"name": "returned",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "nonpayable"
},
{
"name": "fund",
"type": "function",
"inputs": [
{
"name": "subject_",
"type": "address",
"internalType": "address"
},
{
"name": "asset",
"type": "address",
"internalType": "address"
},
{
"name": "amount",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "configData",
"type": "bytes",
"internalType": "bytes"
}
],
"outputs": [
{
"name": "received",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "payable"
},
{
"name": "fundingFallbackAt",
"type": "function",
"inputs": [
{
"name": "roundId",
"type": "uint64",
"internalType": "uint64"
}
],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "initialize",
"type": "function",
"inputs": [
{
"name": "config",
"type": "tuple",
"components": [
{
"name": "creator",
"type": "address",
"internalType": "address"
},
{
"name": "attestor",
"type": "address",
"internalType": "address"
},
{
"name": "randomness",
"type": "address",
"internalType": "address"
},
{
"name": "prizeAsset",
"type": "address",
"internalType": "address"
},
{
"name": "protocolFeeRecipient",
"type": "address",
"internalType": "address"
},
{
"name": "taxRecipient",
"type": "address",
"internalType": "address"
},
{
"name": "tokensPerTicket",
"type": "uint128",
"internalType": "uint128"
},
{
"name": "maxTicketsPerHolder",
"type": "uint128",
"internalType": "uint128"
},
{
"name": "minPrize",
"type": "uint128",
"internalType": "uint128"
},
{
"name": "maxPrize",
"type": "uint128",
"internalType": "uint128"
},
{
"name": "prizeBps",
"type": "uint16",
"internalType": "uint16"
},
{
"name": "recipientTaxBps",
"type": "uint16",
"internalType": "uint16"
},
{
"name": "recycleTaxBps",
"type": "uint16",
"internalType": "uint16"
},
{
"name": "minConfirmations",
"type": "uint16",
"internalType": "uint16"
},
{
"name": "winnersPerRound",
"type": "uint8",
"internalType": "uint8"
},
{
"name": "minRoundInterval",
"type": "uint32",
"internalType": "uint32"
},
{
"name": "weightWindowBlocks",
"type": "uint32",
"internalType": "uint32"
},
{
"name": "randomnessTimeout",
"type": "uint32",
"internalType": "uint32"
},
{
"name": "claimWindow",
"type": "uint32",
"internalType": "uint32"
},
{
"name": "basis",
"type": "uint8",
"internalType": "enum RaffleTypes.TicketBasis"
},
{
"name": "exclusions",
"type": "address[]",
"internalType": "address[]"
},
{
"name": "stockRewards",
"type": "tuple[]",
"components": [
{
"name": "asset",
"type": "address",
"internalType": "address"
},
{
"name": "swapAdapter",
"type": "address",
"internalType": "address"
},
{
"name": "priceGuard",
"type": "address",
"internalType": "address"
},
{
"name": "routeData",
"type": "bytes",
"internalType": "bytes"
},
{
"name": "guardData",
"type": "bytes",
"internalType": "bytes"
}
],
"internalType": "struct RaffleTypes.StockReward[]"
}
],
"internalType": "struct RaffleTypes.Config"
}
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"name": "initialized",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "bool",
"internalType": "bool"
}
],
"stateMutability": "view"
},
{
"name": "isExcluded",
"type": "function",
"inputs": [
{
"name": "holder",
"type": "address",
"internalType": "address"
}
],
"outputs": [
{
"name": "excluded",
"type": "bool",
"internalType": "bool"
}
],
"stateMutability": "view"
},
{
"name": "lastCommitAt",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint64",
"internalType": "uint64"
}
],
"stateMutability": "view"
},
{
"name": "latestRoundId",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint64",
"internalType": "uint64"
}
],
"stateMutability": "view"
},
{
"name": "latestSnapshotBlock",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint64",
"internalType": "uint64"
}
],
"stateMutability": "view"
},
{
"name": "leafHash",
"type": "function",
"inputs": [
{
"name": "roundId",
"type": "uint64",
"internalType": "uint64"
},
{
"name": "snapshotBlock",
"type": "uint64",
"internalType": "uint64"
},
{
"name": "holder",
"type": "address",
"internalType": "address"
},
{
"name": "tickets",
"type": "uint256",
"internalType": "uint256"
}
],
"outputs": [
{
"name": "",
"type": "bytes32",
"internalType": "bytes32"
}
],
"stateMutability": "view"
},
{
"name": "liabilities",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "nextPrize",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "nodeHash",
"type": "function",
"inputs": [
{
"name": "leftHash",
"type": "bytes32",
"internalType": "bytes32"
},
{
"name": "leftSum",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "rightHash",
"type": "bytes32",
"internalType": "bytes32"
},
{
"name": "rightSum",
"type": "uint256",
"internalType": "uint256"
}
],
"outputs": [
{
"name": "",
"type": "bytes32",
"internalType": "bytes32"
}
],
"stateMutability": "pure"
},
{
"name": "owed",
"type": "function",
"inputs": [
{
"name": "holder",
"type": "address",
"internalType": "address"
}
],
"outputs": [
{
"name": "amount",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "payStockWinner",
"type": "function",
"inputs": [
{
"name": "holder",
"type": "address",
"internalType": "address"
},
{
"name": "asset",
"type": "address",
"internalType": "address"
},
{
"name": "amount",
"type": "uint256",
"internalType": "uint256"
}
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"name": "payWinner",
"type": "function",
"inputs": [
{
"name": "holder",
"type": "address",
"internalType": "address"
},
{
"name": "amount",
"type": "uint256",
"internalType": "uint256"
}
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"name": "payoutTaxBps",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "pendingRounds",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint8",
"internalType": "uint8"
}
],
"stateMutability": "view"
},
{
"name": "protocolOwed",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "receiveRandomness",
"type": "function",
"inputs": [
{
"name": "requestId",
"type": "bytes32",
"internalType": "bytes32"
},
{
"name": "seed",
"type": "uint256",
"internalType": "uint256"
}
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"name": "roundOfRequest",
"type": "function",
"inputs": [
{
"name": "requestId",
"type": "bytes32",
"internalType": "bytes32"
}
],
"outputs": [
{
"name": "roundId",
"type": "uint64",
"internalType": "uint64"
}
],
"stateMutability": "view"
},
{
"name": "rounds",
"type": "function",
"inputs": [
{
"name": "roundId",
"type": "uint64",
"internalType": "uint64"
}
],
"outputs": [
{
"name": "rootHash",
"type": "bytes32",
"internalType": "bytes32"
},
{
"name": "requestId",
"type": "bytes32",
"internalType": "bytes32"
},
{
"name": "totalTickets",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "prize",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "paidTotal",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "seed",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "snapshotBlock",
"type": "uint64",
"internalType": "uint64"
},
{
"name": "committedAt",
"type": "uint64",
"internalType": "uint64"
},
{
"name": "drawnAt",
"type": "uint64",
"internalType": "uint64"
},
{
"name": "slotsPaidMask",
"type": "uint16",
"internalType": "uint16"
},
{
"name": "state",
"type": "uint8",
"internalType": "enum RaffleTypes.RoundState"
}
],
"stateMutability": "view"
},
{
"name": "selectedStock",
"type": "function",
"inputs": [
{
"name": "roundId",
"type": "uint64",
"internalType": "uint64"
},
{
"name": "slot",
"type": "uint8",
"internalType": "uint8"
}
],
"outputs": [
{
"name": "index",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "asset",
"type": "address",
"internalType": "address"
}
],
"stateMutability": "view"
},
{
"name": "sendProtocolFee",
"type": "function",
"inputs": [
{
"name": "amount",
"type": "uint256",
"internalType": "uint256"
}
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"name": "sendTax",
"type": "function",
"inputs": [
{
"name": "amount",
"type": "uint256",
"internalType": "uint256"
}
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"name": "slotPrize",
"type": "function",
"inputs": [
{
"name": "roundId",
"type": "uint64",
"internalType": "uint64"
},
{
"name": "slot",
"type": "uint8",
"internalType": "uint8"
}
],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "stockOwed",
"type": "function",
"inputs": [
{
"name": "holder",
"type": "address",
"internalType": "address"
},
{
"name": "asset",
"type": "address",
"internalType": "address"
}
],
"outputs": [
{
"name": "amount",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "stockReward",
"type": "function",
"inputs": [
{
"name": "index",
"type": "uint256",
"internalType": "uint256"
}
],
"outputs": [
{
"name": "",
"type": "tuple",
"components": [
{
"name": "asset",
"type": "address",
"internalType": "address"
},
{
"name": "swapAdapter",
"type": "address",
"internalType": "address"
},
{
"name": "priceGuard",
"type": "address",
"internalType": "address"
},
{
"name": "routeData",
"type": "bytes",
"internalType": "bytes"
},
{
"name": "guardData",
"type": "bytes",
"internalType": "bytes"
}
],
"internalType": "struct RaffleTypes.StockReward"
}
],
"stateMutability": "view"
},
{
"name": "stockRewardCount",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "subject",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "address",
"internalType": "address"
}
],
"stateMutability": "view"
},
{
"name": "sync",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "credited",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "fee",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "nonpayable"
},
{
"name": "taxOwed",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "ticketsFor",
"type": "function",
"inputs": [
{
"name": "weight",
"type": "uint256",
"internalType": "uint256"
}
],
"outputs": [
{
"name": "tickets",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "totalIntake",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "totalOwed",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "totalReserved",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "totalStockOwed",
"type": "function",
"inputs": [
{
"name": "asset",
"type": "address",
"internalType": "address"
}
],
"outputs": [
{
"name": "amount",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "verify",
"type": "function",
"inputs": [
{
"name": "roundId",
"type": "uint64",
"internalType": "uint64"
},
{
"name": "leaf",
"type": "tuple",
"components": [
{
"name": "holder",
"type": "address",
"internalType": "address"
},
{
"name": "tickets",
"type": "uint256",
"internalType": "uint256"
}
],
"internalType": "struct RaffleTypes.Leaf"
},
{
"name": "proof",
"type": "tuple[]",
"components": [
{
"name": "siblingHash",
"type": "bytes32",
"internalType": "bytes32"
},
{
"name": "siblingSum",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "siblingIsLeft",
"type": "bool",
"internalType": "bool"
}
],
"internalType": "struct RaffleTypes.ProofElement[]"
}
],
"outputs": [
{
"name": "valid",
"type": "bool",
"internalType": "bool"
},
{
"name": "offset",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "winningIndex",
"type": "function",
"inputs": [
{
"name": "roundId",
"type": "uint64",
"internalType": "uint64"
},
{
"name": "slot",
"type": "uint8",
"internalType": "uint8"
}
],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"type": "receive",
"stateMutability": "payable"
}
]0x610140806040526004361015610055575b50361561001b575f80fd5b6001600160a01b036003541661002d57005b7faa7feadc000000000000000000000000000000000000000000000000000000005f5260045ffd5b5f3560e01c9081630572877114613f6557508063070d19c314613f265780630a59a98c14613f005780630c0fd2c0146138ac5780630f7e4b601461388f5780630f9cd729146135725780631139a85e1461354f57806311a8f41314613525578063158ef93e1461350057806316ba05fc146134dd5780631cfe7edf146134d85780631e9d0823146134d85780632473da1414613493578063249d39e91461347757806325e28c63146134435780632ac1e975146132595780632af674dd1461323c578063354861ef146132155780633608edee146131f857806347917561146131aa57806348bbbd9c1461318d5780634c3314a11461309b5780634e958d0514613062578063517aaad71461304557806357660f0d1461301e5780635dc0031514612ff25780635e17445c1461125b5780635e79eac314612fb857806362a9e04f1461168a5780636379113e146115dc578063663b5b8814611533578063697860c8146115165780636b346fef146114b75780636c70bee9146112bc5780637be24a1a146112925780637e64910714611276578063811be0101461125b57806381bac14f146110705780638a29d788146110365780639404dcd61461101a5780639621ec2414610f735780639e52dd7d14610f56578063a921153914610f3a578063a93778f714610e6b578063a972d20714610e0b578063b2fc1cc314610d9d578063b4add30714610d83578063b757369e14610d37578063b9df205114610d1c578063ba14f5f314610d00578063ba643dc814610b97578063bb57d81d14610a87578063bc3ac875146109b5578063be3782281461099a578063bf0a12cf1461099a578063c28c62b11461097d578063c3ce52b91461094b578063c5bf1fed14610911578063c70166ac146108f7578063c71b0e1c146108da578063c789f829146108a2578063cba0e99614610865578063cd7c99d814610848578063cfae30541461080e578063d060200d14610610578063d0f9ff9a146105d6578063df18e0471461059e578063e1f1176d14610581578063e641782c14610565578063e7fa9f7d14610548578063f69299d8146104f4578063fa3fee3714610411578063fccc2813146103f55763fff6cae91461038f575f610010565b346103f1575f6003193601126103f1576002601a54146103c9576002601a5560406103b8614949565b6001601a5582519182526020820152f35b7fab143c06000000000000000000000000000000000000000000000000000000005f5260045ffd5b5f80fd5b346103f1575f6003193601126103f157602060405161dead8152f35b346103f15760206003193601126103f15761042a61406e565b6002601a54146103c9576002601a556001600160a01b038116805f52601660205260405f20549081156104cc5761048b82602094835f52601686525f604081205561047782600e54614340565b600e556001600160a01b03600354166153b0565b61049361517b565b604051908282527f2b39585a34c1b0e26d70f3a0fb64ed3fe3fa86e876e764b68ab8675423e2660e843393a36001601a55604051908152f35b7f797dba54000000000000000000000000000000000000000000000000000000005f5260045ffd5b346103f15760406003193601126103f15761050d61406e565b6001600160a01b0361051d614084565b91165f5260176020526001600160a01b0360405f2091165f52602052602060405f2054604051908152f35b346103f1575f6003193601126103f1576020600e54604051908152f35b346103f1575f6003193601126103f15760206040516104008152f35b346103f1575f6003193601126103f1576020600954604051908152f35b346103f15760206003193601126103f1576001600160a01b036105bf61406e565b165f526016602052602060405f2054604051908152f35b346103f1575f6003193601126103f15760206040517f12e616e45a8a158f57403c35cb32cc321330702d775da334a74d3c77cfa6e0168152f35b346103f15760206003193601126103f157610629613f7f565b6002601a54146103c95767ffffffffffffffff906002601a5516805f52601360205260405f20906006820190815460ff8160d01c1660068110156107e1576001036107b9576106919067ffffffffffffffff63ffffffff60085460881c169160401c166142b9565b4211156107915760036020930154917a0500000000000000000000000000000000000000000000000000007fffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffff825416179055600b547fffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffff70ff0000000000000000000000000000000061072860ff8460801c16614455565b60801b16911617600b558161076e575b7fda5481848b883c20cef167617802651a1d02e8b501280d4c739a94e8db7fdab083604051848152a26001601a55604051908152f35b61077a82600d54614340565b600d5561078982600c546142b9565b600c55610738565b7f319b7143000000000000000000000000000000000000000000000000000000005f5260045ffd5b7fa2b52a54000000000000000000000000000000000000000000000000000000005f5260045ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b346103f1575f6003193601126103f15760206040517fda0d6b03f0a47b245a46f6b87ac8ccc1e8015c0f314e99192cd2092a7ccd75368152f35b346103f1575f6003193601126103f1576020600f54604051908152f35b346103f15760206003193601126103f1576001600160a01b0361088661406e565b165f526015602052602060ff60405f2054166040519015158152f35b346103f15760206003193601126103f1576001600160a01b036108c361406e565b165f526018602052602060405f2054604051908152f35b346103f1575f6003193601126103f1576020600d54604051908152f35b346103f1575f6003193601126103f1576020604051818152f35b346103f1575f6003193601126103f15760206040517fa2ccf457a3f753423c6de87b8ceb44d840ce1fc220d9248378d71de45cb70d648152f35b346103f1575f6003193601126103f157602061097560085461ffff8082851c169160101c166142b9565b604051908152f35b346103f1575f6003193601126103f157602060405162093a808152f35b346103f1575f6003193601126103f157602060405160648152f35b346103f15760206003193601126103f15767ffffffffffffffff6109d7613f7f565b165f52601360205260405f20805461ffff6001830154926002810154906003810154600482015490600660058401549301549360ff8560d01c1697604051978852602088015260408701526060860152608085015260a084015267ffffffffffffffff811660c084015267ffffffffffffffff8160401c1660e084015267ffffffffffffffff8160801c1661010084015260c01c1661012082015260068210156107e15761016091610140820152f35b346103f15760206003193601126103f15760606080604051610aa8816142e3565b5f81525f60208201525f6040820152828082015201526001600160a01b03610ad16004356147c5565b50610b9360405191610ae2836142e3565b838154168352610b6284600183015416916020850192835285806002830154166040870190815281610b296004610b1b6003870161488d565b9560608b019687520161488d565b9560808901968752604051998a9960208b52511660208a015251166040880152511660608601525160a0608086015260c0850190614262565b90517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08483030160a0850152614262565b0390f35b346103f15760206003193601126103f157610bb0613f7f565b6002601a54146103c95767ffffffffffffffff906002601a5516805f52601360205260405f20906006820190815460ff8160d01c1660068110156107e1576002036107b957610c189067ffffffffffffffff63ffffffff60085460a81c169160801c166142b9565b421115610cd857610c358360046003602096015491015490614340565b917a0400000000000000000000000000000000000000000000000000007fffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffff82541617905581610cb5575b7f50f1aa98078216a310c50fc8442d12d5628b96591d1037e48fdae4a897c97bba83604051848152a26001601a55604051908152f35b610cc182600d54614340565b600d55610cd082600c546142b9565b600c55610c7f565b7f29dfa3ce000000000000000000000000000000000000000000000000000000005f5260045ffd5b346103f1575f6003193601126103f15760206040516102588152f35b346103f1575f6003193601126103f157602060405160408152f35b346103f15760406003193601126103f1576040610d63610d55613f7f565b610d5d613fad565b906157ac565b6001600160a01b03610d74826147c5565b50541682519182526020820152f35b346103f1575f6003193601126103f1576020610975615779565b346103f15760206003193601126103f1576020610db8613f7f565b60405167ffffffffffffffff838201927fda0d6b03f0a47b245a46f6b87ac8ccc1e8015c0f314e99192cd2092a7ccd7536845216604082015260408152610e006060826142ff565b519020604051908152f35b346103f15760206003193601126103f1576020600654610e3f6fffffffffffffffffffffffffffffffff8216600435614883565b9060801c80151580610e62575b610e5a575b50604051908152f35b905082610e51565b50808211610e4c565b346103f15760206003193601126103f1576004356002601a54146103c9576002601a5580158015610f2f575b610f0757610ea781600f54614340565b600f556001600160a01b0360045416610ecc82826001600160a01b03600354166153b0565b610ed461517b565b6040519182527f0fe745ac6801862b12d38ec49086a425ce32d2b9739733963cd587e30976a1c460203393a36001601a55005b7f2c5211c6000000000000000000000000000000000000000000000000000000005f5260045ffd5b50600f548111610e97565b346103f1575f6003193601126103f1576020604051610e108152f35b346103f1575f6003193601126103f1576020610975600c546151ba565b346103f15760206003193601126103f1576004356002601a54146103c9576002601a558015801561100f575b610f0757610faf81601054614340565b6010556001600160a01b0360055416610fd482826001600160a01b03600354166153b0565b610fdc61517b565b6040519182527fe76cbe14d13f133c4eefe3dc6ef66ffd55e3380f898f252ab3e13cca9af6b5e460203393a36001601a55005b506010548111610f9f565b346103f1575f6003193601126103f15760206040516113888152f35b346103f1575f6003193601126103f15760206040517fa28987eac77d820323ec80839b371c0fc243690a2615da31ee8784c29b537cbb8152f35b346103f15760206003193601126103f15761108961406e565b600a549060ff8260a01c1615611233576001600160a01b035f5416330361120b576001600160a01b0382166111e3576001600160a01b0381169081159081156111d9575b81156111c4575b81156111ba575b50611192576019545f5b8181106111705782807fffffffffffffffffffffffff0000000000000000000000000000000000000000861617600a55805f52601560205260405f2060017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008254161790557f5e674be4be11406bfae6fefefad257830cdc59d04399d7fc3cfb65aa67c8ad715f80a2005b6001600160a01b03611181826147c5565b5054168314611192576001016110e5565b7fe6c4247b000000000000000000000000000000000000000000000000000000005f5260045ffd5b90503b15836110db565b6003546001600160a01b0316831491506110d4565b30831491506110cd565b7fb1e7512d000000000000000000000000000000000000000000000000000000005f5260045ffd5b7f82b42900000000000000000000000000000000000000000000000000000000005f5260045ffd5b7f87138d5c000000000000000000000000000000000000000000000000000000005f5260045ffd5b346103f1575f6003193601126103f157602060405160048152f35b346103f1575f6003193601126103f15760206040516103848152f35b346103f1575f6003193601126103f157602067ffffffffffffffff600b5460401c16604051908152f35b346103f1575f6003193601126103f1575f6102606040516112dc816142c6565b8281528260208201528260408201528260608201528260808201528260a08201528260c08201528260e08201528261010082015282610120820152826101408201528261016082015282610180820152826101a0820152826101c0820152826101e08201528261020082015282610220820152826102408201520152610280604051611367816142c6565b6001600160a01b035f541681526001600160a01b036001541660208201526001600160a01b036002541660408201526001600160a01b036003541660608201526001600160a01b036004541660808201526001600160a01b036005541660a08201526006546fffffffffffffffffffffffffffffffff811660c083015260801c60e08201526007546fffffffffffffffffffffffffffffffff811661010083015260801c6101208201526114a860ff60085461ffff811661014085015261ffff8160101c1661016085015261ffff8160201c1661018085015261ffff8160301c166101a0850152818160401c166101c085015263ffffffff8160481c166101e085015263ffffffff8160681c1661020085015263ffffffff8160881c1661022085015263ffffffff8160a81c1661024085015260c81c1661026083016146e8565b6114b560405180926140d6565bf35b346103f15760606003193601126103f1576114d061406e565b6114d8614084565b3033036114ee576114ec91604435916153b0565b005b7f14d4a4e8000000000000000000000000000000000000000000000000000000005f5260045ffd5b346103f1575f6003193601126103f1576020604051620f42408152f35b346103f15760806003193601126103f15761154c613f7f565b60407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc3601126103f15760643567ffffffffffffffff81116103f15760409161159c6115ce923690600401613fbd565b9167ffffffffffffffff81165f526013602052845f2067ffffffffffffffff60068201541660028254920154926155e4565b825191151582526020820152f35b346103f1576115ea36613fee565b6002601a9593949554146103c9576002601a5560195415611662576001600160a01b03611616856142a5565b16330361120b57611629918486856149d7565b61163281614387565b42106116625760209261164761164d936142a5565b91614f95565b61165561517b565b6001601a55604051908152f35b7f347eb59e000000000000000000000000000000000000000000000000000000005f5260045ffd5b346103f15760206003193601126103f15767ffffffffffffffff600435116103f1576102c0600319600435360301126103f157600a5460ff8160a01c16612f90576001600160a01b036116e16004356004016142a5565b16158015612f72575b8015612f54575b8015612f36575b6111925761170a6044600435016142a5565b3b15611192576001600160a01b036117266064600435016142a5565b16151580612f20575b6111925761ffff611745610164600435016146ba565b16151580612f02575b611192576fffffffffffffffffffffffffffffffff61177160c46004350161469d565b1615612c715761ffff611789610144600435016146ba565b16158015612ee5575b612c71576113886117c861ffff6117ae610164600435016146ba565b1661ffff6117c1610184600435016146ba565b16906142b9565b11612c71576fffffffffffffffffffffffffffffffff6117ed6101046004350161469d565b1615612c71576fffffffffffffffffffffffffffffffff6118136101246004350161469d565b16151580612eab575b612c715760ff6118316101c4600435016146c9565b16158015612e90575b612c715761025863ffffffff6118556101e4600435016146d7565b16108015612e70575b612c715761ffff6118746101a4600435016146ba565b16158015612e54575b612c71576002610264600435013510156103f1576004356102640135612deb5763ffffffff6118b1610204600435016146d7565b16612c71575b61038463ffffffff6118ce610224600435016146d7565b16108015612dcb575b612c7157610e1063ffffffff6118f2610244600435016146d7565b16108015612dab575b612c7157611914610284600435016004356004016146f4565b905060208111612c71575f90815b818310612d55578361193f6102a4600435016004356004016146f4565b905060108111612c715780151580612d37575b612c71575f90815b818310612bea57740100000000000000000000000000000000000000007fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff851617600a556040516020808201526001600160a01b036119bd60043560040161409a565b1660408201526001600160a01b036119d960246004350161409a565b1660608201526001600160a01b036119f560446004350161409a565b1660808201526001600160a01b03611a1160646004350161409a565b1660a08201526001600160a01b03611a2d60846004350161409a565b1660c08201526001600160a01b03611a4960a46004350161409a565b1660e08201526fffffffffffffffffffffffffffffffff611a6e60c46004350161457f565b166101008201526fffffffffffffffffffffffffffffffff611a9460e46004350161457f565b166101208201526fffffffffffffffffffffffffffffffff611abb6101046004350161457f565b166101408201526fffffffffffffffffffffffffffffffff611ae26101246004350161457f565b1661016082015261ffff611afb6101446004350161459c565b1661018082015261ffff611b146101646004350161459c565b166101a082015261ffff611b2d6101846004350161459c565b166101c082015261ffff611b466101a46004350161459c565b166101e08201526101c4600435013560ff811681036103f15760ff1661020082015263ffffffff611b7c6101e4600435016145ab565b1661022082015263ffffffff611b97610204600435016145ab565b1661024082015263ffffffff611bb2610224600435016145ab565b1661026082015263ffffffff611bcd610244600435016145ab565b16610280820152611be96102a0820161026460043501356140c9565b611bfe610284600435016004356004016145bc565b6102c080849394015280610300830152610320820192905f5b818110612bc257505050611c366102a4600435016004356004016145bc565b92907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0838303016102e0840152838252602082019360208160051b84010192825f915b838310612ac757868087037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081018252611cb390826142ff565b80519060200120600955600435600401611ccc906142a5565b611cda6024600435016142a5565b61010052611cec6044600435016142a5565b61012052611cfe6064600435016142a5565b611d0c6084600435016142a5565b611d1a60a4600435016142a5565b611d2860c46004350161469d565b611d3660e46004350161469d565b611d456101046004350161469d565b611d546101246004350161469d565b90611d64610144600435016146ba565b92611d74610164600435016146ba565b94611d84610184600435016146ba565b96611d946101a4600435016146ba565b98611da46101c4600435016146c9565b9a611db46101e4600435016146d7565b9c611dc4610204600435016146d7565b608052611dd6610224600435016146d7565b60c052611de8610244600435016146d7565b60e05260405160a05260a051611dfd906142c6565b6001600160a01b031660a05152610100516001600160a01b031660a05160200152610120516001600160a01b031660a051604001526001600160a01b031660a051606001526001600160a01b031660a051608001526001600160a01b031660a05160a001526fffffffffffffffffffffffffffffffff1660a05160c001526fffffffffffffffffffffffffffffffff1660a05160e001526fffffffffffffffffffffffffffffffff1660a05161010001526fffffffffffffffffffffffffffffffff1660a051610120015261ffff1660a051610140015261ffff1660a051610160015261ffff1660a051610180015261ffff1660a0516101a0015260ff1660a0516101c0015263ffffffff1660a0516101e0015260805163ffffffff1660a051610200015260c05163ffffffff1660a051610220015260e05163ffffffff1660a0516102400152600435610264013560a0516102600190611f5d916146e8565b60a051516001600160a01b03165f547fffffffffffffffffffffffff000000000000000000000000000000000000000016175f5560a051602001516001600160a01b03166001547fffffffffffffffffffffffff0000000000000000000000000000000000000000161760015560a051604001516001600160a01b03166002547fffffffffffffffffffffffff0000000000000000000000000000000000000000161760025560a051606001516001600160a01b03166003547fffffffffffffffffffffffff0000000000000000000000000000000000000000161760035560a051608001516001600160a01b03166004547fffffffffffffffffffffffff0000000000000000000000000000000000000000161760045560a05160a001516001600160a01b03166005547fffffffffffffffffffffffff0000000000000000000000000000000000000000161760055560a05160c001516fffffffffffffffffffffffffffffffff166006547fffffffffffffffffffffffffffffffff00000000000000000000000000000000161760065560a05160e001516006549060801b7fffffffffffffffffffffffffffffffff00000000000000000000000000000000167fffffffffffffffffffffffffffffffff0000000000000000000000000000000016906fffffffffffffffffffffffffffffffff161760065560a05161010001516fffffffffffffffffffffffffffffffff166007547fffffffffffffffffffffffffffffffff00000000000000000000000000000000161760075560a05161012001516007549060801b7fffffffffffffffffffffffffffffffff00000000000000000000000000000000167fffffffffffffffffffffffffffffffff0000000000000000000000000000000016906fffffffffffffffffffffffffffffffff161760075560a051610140015161ffff166008547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000161760085560a051610160015160085460a051610180015160201b65ffff000000001660a0516101a0015160301b67ffff0000000000001660a0516101c0015160401b68ff00000000000000001660a0516101e0015160481b6cffffffff000000000000000000169060a051610200015160681b70ffffffff00000000000000000000000000169260a051610220015160881b74ffffffff0000000000000000000000000000000000169460a051610240015160a81b78ffffffff000000000000000000000000000000000000000000169660a051610260015160028110156107e15760c81b79ff00000000000000000000000000000000000000000000000000169860101b63ffff000016907fffffffffffffffffffffffffffffffffffffffffffffffff000000000000ffff16177fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff16177fffffffffffffffffffffffffffffffffffffff00000000ffffffffffffffffff16177fffffffffffffffffffffffffffffff00000000ffffffffffffffffffffffffff16177fffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffffff16177fffffffffffffff00000000ffffffffffffffffffffffffffffffffffffffffff16177fffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffff161717176008556004356102840160043560040190612454916146f4565b90505f5b818110612a5b576124746102a4600435016004356004016146f4565b90505f5b8181106125a75760156020527fa31547ce6245cdb9ecea19cf8c7eb9f5974025bb4075011409251ae855b30aed80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0090811660019081179092557f7ed1dca03d96f947ab02d66053f47073699eb6287021936c92f54972932767e58054821683179055305f908152604090208054909116909117905560095461252560048035610284810191016146f4565b9060405191806102a0840161253c8560a0516140d6565b6102a0610280860152526102c0830191905f5b81811061257f57857fe0b4708807be9c9916a8c8474f77b6359445f93db50922eecb21ed647073885f86860387a2005b9091926020806001926001600160a01b036125998861409a565b16815201940192910161254f565b6125c6816125c06102a4600435016004356004016146f4565b90614785565b6019546801000000000000000081101561292c578060016125ea92016019556147c5565b919091612a2f576001600160a01b03612602826142a5565b167fffffffffffffffffffffffff000000000000000000000000000000000000000083541617825560208101612637816142a5565b6001600160a01b036001850191167fffffffffffffffffffffffff0000000000000000000000000000000000000000825416179055604082019161267a836142a5565b6001600160a01b036002860191167fffffffffffffffffffffffff0000000000000000000000000000000000000000825416179055600384019360608201946126c386846147e1565b9067ffffffffffffffff821161292c576126dd8354614832565b601f81116129ea575b505f90601f8311600114612964576004949392915f9183612959575b50505f198260011b9260031b1c19161790555b01608082019061272582846147e1565b9067ffffffffffffffff821161292c5761273f8354614832565b601f81116128e7575b505f90601f831160011461282b576128027f56f82f6ee7d8fe77ddc5cc15e62c578dcb4eda4776fe4db50945269c379672bc966001600160a01b039995968a97866128179760019f9e9c978b975f92612820575b50508f825f19911b9260031b1c19161790555b6127df6127d76127d06127ca6127c4866142a5565b986142a5565b996142a5565b9b846147e1565b9290936147e1565b9b909a604051998a9916895216602088015260806040880152608087019161465f565b918483036060860152169660ff89169661465f565b0390a301612478565b013590505f8061279c565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0831691845f5260205f20925f5b8181106128cf5750966001600160a01b039995968a97600187819f9e9c978b97612802976128179b7f56f82f6ee7d8fe77ddc5cc15e62c578dcb4eda4776fe4db50945269c379672bc9f106128b6575b505050811b0190556127af565b5f1960f88560031b161c199101351690555f80806128a9565b91936020600181928787013581550195019201612859565b835f5260205f20601f840160051c81019160208510612922575b601f0160051c01905b8181106129175750612748565b5f815560010161290a565b9091508190612901565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b013590508b80612702565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0831691845f5260205f20925f5b8181106129d25750916001939185600498979694106129b9575b505050811b019055612715565b5f1960f88560031b161c199101351690558b80806129ac565b91936020600181928787013581550195019201612992565b835f5260205f20601f840160051c81019160208510612a25575b601f0160051c01905b818110612a1a57506126e6565b5f8155600101612a0d565b9091508190612a04565b7f4e487b71000000000000000000000000000000000000000000000000000000005f525f60045260245ffd5b806001600160a01b03612a8d612a88600194612a82610284600435016004356004016146f4565b90614748565b6142a5565b165f52601560205260405f20827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0082541617905501612458565b90919293947fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe082820301885285357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff61843603018112156103f1576020612bb160019386839401906001600160a01b03612b3f8361409a565b1681526001600160a01b03612b5585840161409a565b16848201526001600160a01b03612b6e6040840161409a565b166040820152612ba3612b98612b87606085018561460f565b60a0606086015260a085019161465f565b92608081019061460f565b91608081850391015261465f565b970198019301919096939296611c79565b9091936020806001926001600160a01b03612bdc8961409a565b168152019501929101611c17565b612c03836125c06102a4600435016004356004016146f4565b906001600160a01b03612c15836142a5565b1615908115612d0b575b8115612ceb575b508015612cda575b8015612cc6575b8015612cb2575b612c7157610400612c5060608301836147e1565b9050118015612c99575b612c7157612c696001916142a5565b92019161195a565b7fc52a9bd3000000000000000000000000000000000000000000000000000000005f5260045ffd5b50610400612caa60808301836147e1565b905011612c5a565b50612cbf604082016142a5565b3b15612c3c565b50612cd3602082016142a5565b3b15612c35565b50612ce4816142a5565b3b15612c2e565b90506001600160a01b0380612cff846142a5565b92169116111585612c26565b9050612d16826142a5565b6001600160a01b0380612d2d6064600435016142a5565b1691161490612c1f565b506001600160a01b03612d4e6064600435016142a5565b1615611952565b612d71612a8884612a82610284600435016004356004016146f4565b906001600160a01b0382168015918215612d97575b5050612c7157600190920191611922565b6001600160a01b0316101590508580612d86565b5062278d0063ffffffff612dc4610244600435016146d7565b16116118fb565b506201518063ffffffff612de4610224600435016146d7565b16116118d7565b6102046004350163ffffffff612e00826146d7565b1615908115612e38575b50156118b7577fc52a9bd3000000000000000000000000000000000000000000000000000000005f5260045ffd5b620f42409150612e4c63ffffffff916146d7565b161182612e0a565b5060ff61ffff612e696101a4600435016146ba565b161161187d565b5062093a8063ffffffff612e896101e4600435016146d7565b161161185e565b50601060ff612ea46101c4600435016146c9565b161161183a565b50612ebb6101246004350161469d565b6fffffffffffffffffffffffffffffffff80612edc6101046004350161469d565b1691161061181c565b5061271061ffff612efb610144600435016146ba565b1611611792565b506001600160a01b03612f1960a4600435016142a5565b161561174e565b50612f2f6064600435016142a5565b3b1561172f565b506001600160a01b03612f4d6084600435016142a5565b16156116f8565b506001600160a01b03612f6b6044600435016142a5565b16156116f1565b506001600160a01b03612f896024600435016142a5565b16156116ea565b7f0dc149f0000000000000000000000000000000000000000000000000000000005f5260045ffd5b346103f1575f6003193601126103f15760206040517fef10588cb6aa10e3ebbab1e074c9571ff0aa1dac562c2dfa08b2630e2e8848b38152f35b346103f15760406003193601126103f1576020610975613010613f7f565b613018613fad565b906144f0565b346103f15760806003193601126103f1576020610975606435604435602435600435614467565b346103f1575f6003193601126103f157602060405162278d008152f35b346103f15760406003193601126103f15761307b61406e565b3033036114ee576114ec90602435906001600160a01b03600354166153b0565b346103f15760406003193601126103f1576130b461406e565b6130bc614084565b906002601a54146103c9576002601a556001600160a01b038116805f52601760205260405f206001600160a01b0384165f5260205260405f20549182156104cc57613154602094835f526017865260405f206001600160a01b0382165f5286525f604081205561314f856001600160a01b03831694855f526018895260405f20613147838254614340565b9055836153b0565b6155bd565b604051918383527fad3d3ee5e2339f145d2ef38f8cb3a2efc78c7a150178b84a50ac7075e3ad4888853394a46001601a55604051908152f35b346103f1575f6003193601126103f1576020601154604051908152f35b346103f15760406003193601126103f15760206109756131c8613f7f565b67ffffffffffffffff6131d9613fad565b91165f5260138352600360405f20015460ff60085460401c1690615380565b346103f1575f6003193601126103f1576020604051620151808152f35b346103f1575f6003193601126103f157602067ffffffffffffffff600b5416604051908152f35b346103f1575f6003193601126103f1576020600c54604051908152f35b346103f15760406003193601126103f1576004356024356002601a54146103c9576002601a556001600160a01b0360025416330361120b57801561341b57815f52601460205267ffffffffffffffff60405f2054169182156133f357825f52601360205260405f2090600682019283549360ff8560d01c1660068110156107e1576001036107b9577f26cb6fa2fe64b5be80ee004f48827b223251b132f66488a2d42a11e280b0f1fc9482600560409601557fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff77ffffffffffffffff000000000000000000000000000000004260801b1691161781557a0200000000000000000000000000000000000000000000000000007fffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffff825416179055600b547fffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffff70ff000000000000000000000000000000006133d760ff8460801c16614455565b60801b16911617600b5582519182526020820152a26001601a55005b7f41abc801000000000000000000000000000000000000000000000000000000005f5260045ffd5b7f863a7486000000000000000000000000000000000000000000000000000000005f5260045ffd5b346103f15760206003193601126103f1576004355f526014602052602067ffffffffffffffff60405f205416604051908152f35b346103f1575f6003193601126103f15760206040516127108152f35b346103f15760806003193601126103f1576134ac613f7f565b6134b4613f96565b604435916001600160a01b03831683036103f15760209261097592606435926143da565b6140ae565b346103f15760206003193601126103f15760206109756134fb613f7f565b614387565b346103f1575f6003193601126103f157602060ff600a5460a01c166040519015158152f35b346103f1575f6003193601126103f157602067ffffffffffffffff600a5460a81c16604051908152f35b346103f1575f6003193601126103f157602060ff600b5460801c16604051908152f35b60806003193601126103f15761358661406e565b61358e614084565b6044359160643567ffffffffffffffff81116103f157366023820112156103f15780600401359167ffffffffffffffff83116103f15736602484840101116103f1576002601a54146103c9576002601a556001600160a01b03600a5416908115613867576001600160a01b031603611192576001600160a01b039283600354169384911603611192578315610f0757811515918261382a575b50506138025780613699575080340361002d576020905b613647816152e1565b61364f61517b565b60405191838352848301526040820152600160608201527f7b271871083f855c8477257e2b60675da696d3329dcf38ed9c6ef20de95ed73260803392a26001601a55604051908152f35b3461002d576136a830826151ef565b6040517f23b872dd0000000000000000000000000000000000000000000000000000000060208201908152336024830152306044830152606482018590529192915f9182919061372381608481015b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081018352826142ff565b519082855af1613731614bd9565b90159081156137d2575b506137aa5761374b9030906151ef565b908082106137a15761375c91614340565b905b819080830361377157506020915061363e565b90507f55e5b61d000000000000000000000000000000000000000000000000000000005f5260045260245260445ffd5b50505f9061375e565b7f7939f424000000000000000000000000000000000000000000000000000000005f5260045ffd5b80518015159250826137e7575b50508461373b565b6137fa92506020809183010191016152a0565b1584806137df565b7f95fca54a000000000000000000000000000000000000000000000000000000005f5260045ffd5b9091505f60206138398361434d565b9261384760405194856142ff565b808452806024838601960186378301015251902060095414158380613627565b7fe6944a15000000000000000000000000000000000000000000000000000000005f5260045ffd5b346103f1575f6003193601126103f1576020601954604051908152f35b346103f15760a06003193601126103f1576138c5613f7f565b6138cd613f96565b9060443591606435608435936001600160a01b0360015416330361120b576002601a54146103c9576002601a55600a546001600160a01b0381161561386757600167ffffffffffffffff8260a81c16019367ffffffffffffffff8511613d7a5767ffffffffffffffff808716951685036107b95767ffffffffffffffff600b5491169167ffffffffffffffff8216831115613dcf5784158015613ef8575b613ed057600460ff8360801c161015613ea85767ffffffffffffffff8260401c1680613e5e575b506040517fa3b1b31d00000000000000000000000000000000000000000000000000000000815260208160048160645afa908115613d6f575f91613e2c575b506139e561ffff60085460301c16856142b9565b8110613dcf5760ff840190818511613d7a5711613dcf576040517f2b407a8200000000000000000000000000000000000000000000000000000000815283600482015260208160248160645afa8015613d6f5785915f91613df7575b5003613dcf57600c5496613a54886151ba565b976fffffffffffffffffffffffffffffffff600754168910613da7577fffffff0000000000000000ffffffffffffffffffffffffffffffffffffffffff91613aba8a7cffffffffffffffff00000000000000000000000000000000000000000093614340565b600c55613ac98a600d546142b9565b600d5560a81b16911617600a556fffffffffffffffff00000000000000004260401b1692600160ff85857fffffffffffffffffffffffffffffffff000000000000000000000000000000008616171760801c16019160ff8311613d7a57837fffffffffffffffffffffffffffffff000000000000000000000000000000000070ff000000000000000000000000000000005f9560801b16921617851717600b5560206001600160a01b03600254166024604051809581937fcc0ec08e0000000000000000000000000000000000000000000000000000000083528b60048401525af1918215613d6f575f92613d3b575b5081158015613d1c575b6133f3576020977f7b2eab248e0aec4ce9dcc4be33fa3c34a22558ddc82c6d23ef7faa7e375768879560e095845f5260148b5260405f20897fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000825416179055885f5260138b52600660405f208381558660018201558460028201558b60038201550190867fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000008354161782557fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff8254161781557a0100000000000000000000000000000000000000000000000000007fffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffff825416179055613ce061517b565b60ff60085460401c16926040519586528a8601526040850152606084015286608084015260a083015260c0820152a26001601a55604051908152f35b50815f52601460205267ffffffffffffffff60405f2054161515613bc3565b9091506020813d602011613d67575b81613d57602093836142ff565b810103126103f157519088613bb9565b3d9150613d4a565b6040513d5f823e3d90fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b7f0afc4709000000000000000000000000000000000000000000000000000000005f5260045ffd5b7f40f08cfe000000000000000000000000000000000000000000000000000000005f5260045ffd5b9150506020813d602011613e24575b81613e13602093836142ff565b810103126103f1578490518a613a41565b3d9150613e06565b90506020813d602011613e56575b81613e47602093836142ff565b810103126103f15751896139d1565b3d9150613e3a565b613e749063ffffffff60085460481c16906142b9565b4210613e805788613992565b7f150976fd000000000000000000000000000000000000000000000000000000005f5260045ffd5b7f0232c5d6000000000000000000000000000000000000000000000000000000005f5260045ffd5b7f504570e3000000000000000000000000000000000000000000000000000000005f5260045ffd5b50871561396b565b346103f1575f6003193601126103f15760206001600160a01b03600a5416604051908152f35b346103f157613f3436613fee565b6002601a95939594929454146103c957602094612a88613f5f9261164d966002601a558386886149d7565b91614c08565b346103f1575f6003193601126103f1576020906010548152f35b6004359067ffffffffffffffff821682036103f157565b6024359067ffffffffffffffff821682036103f157565b6024359060ff821682036103f157565b9181601f840112156103f15782359167ffffffffffffffff83116103f157602080850194606085020101116103f157565b9060a06003198301126103f15760043567ffffffffffffffff811681036103f1579160243560ff811681036103f1579160407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbc8301126103f1576044916084359067ffffffffffffffff82116103f15761406a91600401613fbd565b9091565b600435906001600160a01b03821682036103f157565b602435906001600160a01b03821682036103f157565b35906001600160a01b03821682036103f157565b346103f1575f6003193601126103f157602060405160108152f35b9060028210156107e15752565b9061026080614260936001600160a01b0381511684526001600160a01b0360208201511660208501526001600160a01b0360408201511660408501526001600160a01b0360608201511660608501526001600160a01b0360808201511660808501526001600160a01b0360a08201511660a08501526fffffffffffffffffffffffffffffffff60c08201511660c08501526fffffffffffffffffffffffffffffffff60e08201511660e08501526fffffffffffffffffffffffffffffffff610100820151166101008501526fffffffffffffffffffffffffffffffff6101208201511661012085015261ffff6101408201511661014085015261ffff6101608201511661016085015261ffff6101808201511661018085015261ffff6101a0820151166101a085015260ff6101c0820151166101c085015263ffffffff6101e0820151166101e085015263ffffffff6102008201511661020085015263ffffffff6102208201511661022085015263ffffffff6102408201511661024085015201519101906140c9565b565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f602080948051918291828752018686015e5f8582860101520116010190565b356001600160a01b03811681036103f15790565b91908201809211613d7a57565b610280810190811067ffffffffffffffff82111761292c57604052565b60a0810190811067ffffffffffffffff82111761292c57604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761292c57604052565b91908203918211613d7a57565b67ffffffffffffffff811161292c57601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b6143d79067ffffffffffffffff60085491165f526013602052633fffffff6143cc63ffffffff8360a81c1667ffffffffffffffff600660405f20015460801c166142b9565b9160aa1c1690614340565b90565b9290916001600160a01b039067ffffffffffffffff604051948160208701977f12e616e45a8a158f57403c35cb32cc321330702d775da334a74d3c77cfa6e01689524660408901523060608901521660808701521660a08501521660c083015260e082015260e0815261444f610100826142ff565b51902090565b60ff5f199116019060ff8211613d7a57565b9290916040519260208401947fa2ccf457a3f753423c6de87b8ceb44d840ce1fc220d9248378d71de45cb70d64865260408501526060840152608083015260a082015260a0815261444f60c0826142ff565b81156144c3570690565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b67ffffffffffffffff16805f52601360205260405f20906005820154908115610791576143d79360029260ff6040519260208401947fa28987eac77d820323ec80839b371c0fc243690a2615da31ee8784c29b537cbb865246604086015230606086015260808501521660a083015260c082015260c0815261457360e0826142ff565b519020910154906144b9565b35906fffffffffffffffffffffffffffffffff821682036103f157565b359061ffff821682036103f157565b359063ffffffff821682036103f157565b90357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1823603018112156103f157016020813591019167ffffffffffffffff82116103f1578160051b360383136103f157565b90357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1823603018112156103f157016020813591019167ffffffffffffffff82116103f15781360383136103f157565b601f82602094937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe093818652868601375f8582860101520116010190565b356fffffffffffffffffffffffffffffffff811681036103f15790565b3561ffff811681036103f15790565b3560ff811681036103f15790565b3563ffffffff811681036103f15790565b60028210156107e15752565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1813603018212156103f1570180359067ffffffffffffffff82116103f157602001918160051b360383136103f157565b91908110156147585760051b0190565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b91908110156147585760051b810135907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff61813603018212156103f1570190565b6019548110156147585760195f52600560205f20910201905f90565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1813603018212156103f1570180359067ffffffffffffffff82116103f1576020019181360383136103f157565b90600182811c92168015614879575b602083101461484c57565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b91607f1691614841565b81156144c3570490565b9060405191825f8254926148a084614832565b808452936001811690811561490957506001146148c5575b50614260925003836142ff565b90505f9291925260205f20905f915b8183106148ed575050906020614260928201015f6148b8565b60209193508060019154838589010152019101909184926148d4565b602093506142609592507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0091501682840152151560051b8201015f6148b8565b60ff600a5460a01c16156112335761495f615779565b614967615858565b90808211156149cf5761497991614340565b90614983826152e1565b90919083908361499161517b565b604051928352602083015260408201525f60608201527f7b271871083f855c8477257e2b60675da696d3329dcf38ed9c6ef20de95ed73260803392a2565b50505f905f90565b9192909367ffffffffffffffff83165f52601360205260405f209160068301549460ff8660d01c1660068110156107e1576002036107b957600854614a3263ffffffff8260a81c1667ffffffffffffffff8960801c166142b9565b4211614bb15760ff8089169160401c16811015614b8957600161ffff911b8760c01c1616614b61576020810135958615614b11576001600160a01b03614a77836142a5565b165f52601560205260ff60405f205416614b395760408411614b11578467ffffffffffffffff6002614aaf97549201549216876156d1565b939015614b1157614abf916144f0565b90828210928315614afc575b505050614ad457565b7fd2eb70b6000000000000000000000000000000000000000000000000000000005f5260045ffd5b614b079293506142b9565b11155f8080614acb565b7f09bde339000000000000000000000000000000000000000000000000000000005f5260045ffd5b7f6e67fae6000000000000000000000000000000000000000000000000000000005f5260045ffd5b7ff54358f5000000000000000000000000000000000000000000000000000000005f5260045ffd5b7f1258e443000000000000000000000000000000000000000000000000000000005f5260045ffd5b7ff0f25a33000000000000000000000000000000000000000000000000000000005f5260045ffd5b3d15614c03573d90614bea8261434d565b91614bf860405193846142ff565b82523d5f602084013e565b606090565b929190925f915f9467ffffffffffffffff831691825f52601360205260405f209060ff60085460401c169460ff841695600684019081547fffffffffffff0000ffffffffffffffffffffffffffffffffffffffffffffffff79ffff00000000000000000000000000000000000000000000000061ffff60018c1b1661ffff8460c01c161760c01b169116179081835560038601546004614ca9898484615380565b9701614cb68882546142b9565b80915511614f6d576001901b5f198101908111613d7a5761ffff8091169160c01c1614614f24575b50614ceb83600d54614340565b600d5560085493614d1261ffff614d07818860101c1687615879565b9660201c1685615879565b90614d2682614d218888614340565b614340565b9286614f10575b82614efc575b601954614ee75750508115614e9457303b156103f1576040517f4e958d050000000000000000000000000000000000000000000000000000000081526001600160a01b0384166004820152602481018390525f8180604481015b038183305af19081614e7f575b50614e2f5791614e2a917f890c089e137303a12b74d62e44361ca7b826dc9e53e4988805b2ae161c3b2a3a95949360406001600160a01b03614dda614bd9565b94169a8b8152601660205220614df18382546142b9565b9055614dff82600e546142b9565b600e55604051958695865260208601526040850152606084015260a0608084015260a0830190614262565b0390a4565b7f40051245c9f8d5c57cdb71e5d318cfea743ce529a98e28c9bb39dd3c6cf976e99499506080939750906001600160a01b039291819a604051998a5260208a0152604089015260608801521694a4565b614e8c9199505f906142ff565b5f975f614d9a565b90506001600160a01b03929798507f40051245c9f8d5c57cdb71e5d318cfea743ce529a98e28c9bb39dd3c6cf976e994959650608093604051988952602089015260408801525f60608801521694a45f90565b929850929394955095506143d79798506158a4565b614f0883600c546142b9565b600c55614d33565b614f1c876010546142b9565b601055614d2d565b7a0300000000000000000000000000000000000000000000000000007fffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffff8254161790555f614cde565b7f302e29cb000000000000000000000000000000000000000000000000000000005f5260045ffd5b92919067ffffffffffffffff5f9416805f52601360205260405f2060ff60085460401c1660ff841693600683019182547fffffffffffff0000ffffffffffffffffffffffffffffffffffffffffffffffff79ffff00000000000000000000000000000000000000000000000061ffff60018a1b1661ffff8460c01c161760c01b1691161791828455600461502f6003870154928484615380565b950161503c8682546142b9565b80915511614f6d576001901b5f198101908111613d7a5761ffff8091169160c01c1614615132575b5061507181600d54614340565b600d556008549061509861ffff61508d818560101c1684615879565b9360201c1682615879565b946150a786614d218585614340565b8361511e575b8661510a575b5f968115614e9457303b156103f1576040517f4e958d050000000000000000000000000000000000000000000000000000000081526001600160a01b0384166004820152602481018390525f818060448101614d8d565b61511687600c546142b9565b600c556150b3565b61512a846010546142b9565b6010556150ad565b7a0300000000000000000000000000000000000000000000000000007fffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffff8254161790555f615064565b615183615858565b61518b615779565b1161519257565b7ffc220038000000000000000000000000000000000000000000000000000000005f5260045ffd5b6151cb9061ffff6008541690615879565b9060075460801c801515806151e6575b6151e25750565b9150565b508083116151db565b5f919082916040516001600160a01b0360208201927f70a082310000000000000000000000000000000000000000000000000000000084521660248201526024815261523c6044826142ff565b51915afa615248614bd9565b90158015615295575b61526d57602081519181808201938492010103126103f1575190565b7f971e17d6000000000000000000000000000000000000000000000000000000005f5260045ffd5b506020815110615251565b908160209103126103f1575180151581036103f15790565b90606482029180830460641490151715613d7a57565b81810292918115918404141715613d7a57565b601254916152ff61ffff84166152fa61271085066152b8565b6142b9565b927fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000061ffff61271061533e6153358288046152b8565b828904906142b9565b96061691161760125561537b6153548484614340565b9261536185600f546142b9565b600f5561537084600c546142b9565b600c556011546142b9565b601155565b9060ff169060ff6153918383614883565b93166153ab576143d792916153a5916144b9565b906142b9565b505090565b6001600160a01b0381161580156155ac578347935b8215615476575f80809381935af16153db614bd9565b501561544e575b1561543e5750475b808210615435576153fa91614340565b905b808203615407575050565b7f55e5b61d000000000000000000000000000000000000000000000000000000005f5260045260245260445ffd5b50505f906153fc565b6154499030906151ef565b6153ea565b7ff4b3b1bc000000000000000000000000000000000000000000000000000000005f5260045ffd5b905061548281846151ef565b905f8060405160208101907fa9059cbb0000000000000000000000000000000000000000000000000000000082526154d8816136f78c8860248401602090939291936001600160a01b0360408201951681520152565b519082885af16154e6614bd9565b901590811561557c575b50615554576154ff90846151ef565b9080821061554c5761551091614340565b84810361551d57506153e2565b847f55e5b61d000000000000000000000000000000000000000000000000000000005f5260045260245260445ffd5b50505f615510565b7f90b8ec18000000000000000000000000000000000000000000000000000000005f5260045ffd5b8051801515925082615591575b50505f6154f0565b6155a492506020809183010191016152a0565b155f80615589565b836155b730846151ef565b936153c5565b6001600160a01b036155cf30836151ef565b91165f52601860205260405f20541161519257565b95909391925f9684156156c357602435906001600160a01b03821682036103f1576044359896615618928a929091906143da565b96935f945b87861015615699576060860285019860408a013580151581036103f15715615677578160206156628c61565c60019661566c9685840135809435614467565b9b6142b9565b9b5b0135906142b9565b95019497959761561d565b600191602061569361566c93828e9c9e013590848d3591614467565b99615664565b9792959650925092501493846156b9575b505082156156b457565b5f9150565b1492505f806156aa565b50509450505050505f905f90565b96919396949290945f97851561576a57908160206156f46156ff949b999b6142a5565b910135998a926143da565b96935f945b87861015615699576060860285019860408a013580151581036103f1571561574e578160206156628c61565c6001966157439685840135809435614467565b950194979597615704565b600191602061569361574393828e9c9e013590848d3591614467565b5050509450505050505f905f90565b6143d76157a361579a615791600c54600d54906142b9565b600e54906142b9565b600f54906142b9565b601054906142b9565b6019549081158015615843575b614b895767ffffffffffffffff16805f526013602052600560405f200154928315610791576143d79360ff6040519260208401947fef10588cb6aa10e3ebbab1e074c9571ff0aa1dac562c2dfa08b2630e2e8848b3865246604086015230606086015260808501521660a083015260c082015260c0815261583b60e0826142ff565b5190206144b9565b5060ff60085460401c1660ff841610156157b9565b6003546001600160a01b03168061586e57504790565b6143d79030906151ef565b61271061589d6143d7938261589661ffff828704931680936152ce565b94066152ce565b04906142b9565b5f979688969195939492916158c16158bc84896157ac565b6147c5565b50916001600160a01b03835416915f9382615b00575b508315615a9357303b15615a8f576040517f6b346fef0000000000000000000000000000000000000000000000000000000081526001600160a01b03898116600483015284166024820152604481018590528a808260648183305af19182615a76575b5050615a0a5793614e2a9367ffffffffffffffff9360ff937f7f34c0073cb5985959dedf30577305918f36a8aada6c969a8bda8323760538ed99989760406001600160a01b03615988614bd9565b9d169e8f815260176020528181206001600160a01b0386165f52602052815f206159b38782546142b9565b90558481526018602052206159c98582546142b9565b90556159d4836155bd565b604051998a998a5260208a015260408901526060880152608087015260a086015260e060c08601521696169460e0830190614262565b7fae6b2961edbbcc239931a9b3da49a5037ec89e39f890e170effcaece9e7382b4969b5067ffffffffffffffff949950926001600160a01b039260c096989260ff95839e6040519b8c5260208c015260408b015260608a0152608089015260a0880152169616941692a4565b81615a80916142ff565b615a8b578a5f61593a565b8a80fd5b8980fd5b67ffffffffffffffff94999a9b5060ff93509160c09597916001600160a01b03937fae6b2961edbbcc239931a9b3da49a5037ec89e39f890e170effcaece9e7382b4986040519a8b5260208b015260408a0152606089015260808801528960a0880152169616941692a490565b9093506001600160a01b03600354166001600160a01b036002830154169160038101916040615b2e8461488d565b6020815191012081519586917f734cb408000000000000000000000000000000000000000000000000000000008352896004840152846024840152896044840152886064840152608483015260c060a48301528180615b9360c4820160048901615f56565b03915afa8015613d6f575f945f91615f0c575b508415908115615efa575b50615ed257615bc030826151ef565b90615bcb30886151ef565b6001840180546040517f095ea7b300000000000000000000000000000000000000000000000000000000602082019081526001600160a01b039092166024820152604481018a9052929691925f918291615c2881606481016136f7565b519082875af1615c36614bd9565b9015908115615ea2575b50615e7a576001600160a01b038254166001600160a01b03865416813b156103f1575f918a838b93615cbe604051978896879586947f2506c0180000000000000000000000000000000000000000000000000000000086528d600487015260248601526044850152606484015260a0608484015260a4830190615f56565b03925af18015613d6f57615e5e575b508e6001600160a01b038192541660405160208101917f095ea7b3000000000000000000000000000000000000000000000000000000008352602482015282604482015260448152615d206064826142ff565b519082855af1615d2e614bd9565b9015908115615e2e575b50615e0657615d489030906151ef565b808210615dfe57615d5891614340565b848103615dce5750615d75906001600160a01b03309154166151ef565b90808210615dc557615d8691614340565b905b808210615d975750925f6158d7565b7f2c19b8b8000000000000000000000000000000000000000000000000000000008b52600452602452604489fd5b50508990615d88565b8c604491867f55e5b61d000000000000000000000000000000000000000000000000000000008352600452602452fd5b50508b615d58565b60048e7f8164f842000000000000000000000000000000000000000000000000000000008152fd5b8051801515925082615e43575b50505f615d38565b615e5692506020809183010191016152a0565b155f80615e3b565b615e6b919f505f906142ff565b5f9d6001600160a01b03615ccd565b7f8164f842000000000000000000000000000000000000000000000000000000005f5260045ffd5b8051801515925082615eb7575b50505f615c40565b615eca92506020809183010191016152a0565b155f80615eaf565b7f8727a7f9000000000000000000000000000000000000000000000000000000005f5260045ffd5b65ffffffffffff91501642115f615bb1565b9450506040843d604011615f4e575b81615f28604093836142ff565b810103126103f157602084519401519365ffffffffffff851685036103f157935f615ba6565b3d9150615f1b565b5f9291815491615f6583614832565b8083529260018116908115615fba5750600114615f8157505050565b5f9081526020812093945091925b838310615fa0575060209250010190565b600181602092949394548385870101520191019190615f8f565b905060209495507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0091509291921683830152151560051b01019056
| Token | Symbol | Balance | Price | Value |
|---|---|---|---|---|
| no token holdings | ||||
| Type | Age | Block | Details |
|---|---|---|---|
| no cross-chain L1↔L2 transactions for this address | |||
| Transaction Hash | Method ? | Block | Age | From | To | Amount | Txn Fee ? | ||
|---|---|---|---|---|---|---|---|---|---|
| No direct transactions — this address is only ever reached via internal calls (common for a contract only invoked through a router or proxy). View Internal Transactions → | |||||||||
| Transaction Hash | Method | Block | Age | From | To | Type | Item | ||
|---|---|---|---|---|---|---|---|---|---|
| no NFT transfers for this address yet | |||||||||
| Txn Hash | Age | Event | Topics / Data |
|---|---|---|---|
| no event logs emitted by this address | |||
| Transaction Hash | Method | Block | Age | From | To | Amount | Token | ||
|---|---|---|---|---|---|---|---|---|---|
| no token transfers for this address yet | |||||||||
| Block | Age | Parent Transaction Hash | Type | Method | From | To | Value | |
|---|---|---|---|---|---|---|---|---|
| 28,821,627 | 11 days agoWed, 05 Aug 2026 21:48:22 UTC | 0x515680…c4f9e1 | CREATE | 0x60c03461 | 0xd030…7112 | IN | 0x982f…b47d | 0 ETH |