Repository navigation
Expand file tree
/
Copy pathdata.js
More file actions
1 lines (1 loc) · 412 KB
/
Copy pathdata.js
File metadata and controls
1 lines (1 loc) · 412 KB
1
window.__GRAPH_PROTOCOL__ = {"meta":{"branch":"deployment/testnet/2026-06-09/gip-0088","network":"Arbitrum Sepolia (chain 421614)","generated":"from compiled ABIs in packages/interfaces + packages/contracts","note":"Read = view/pure functions. Write = state-changing functions. Function and event signatures are extracted verbatim from compiled ABIs; per-function and per-event descriptions are the contracts’ own NatSpec (@notice/@dev/@param/@return) harvested from compiled metadata; roles and access control are parsed from the .sol modifiers; contract descriptions and edges are curated from NatSpec and on-chain wiring (Controller registry, GraphDirectory, Directory, constructor references).","layers":{"token":{"label":"GRT Token","color":"#F5A623"},"staking":{"label":"Horizon Staking","color":"#7C6CF0"},"payments":{"label":"Horizon Payments","color":"#12B886"},"service":{"label":"Subgraph Service","color":"#3B9DF8"},"disputes":{"label":"Disputes","color":"#E8534B"},"issuance":{"label":"Issuance & Rewards","color":"#E84393"},"curation":{"label":"Curation & Discovery","color":"#16C7C0"},"governance":{"label":"Governance","color":"#9AA6B2"},"bridge":{"label":"L1 ↔ L2 Bridge","color":"#E8843C"},"legacy":{"label":"Legacy & Periphery","color":"#7A8694"}}},"nodes":[{"id":"L2GraphToken","name":"L2GraphToken (GRT)","layer":"token","chain":"L2","core":true,"legacy":false,"address":"0xf8c05dCF59E8B28BFD5eed176C562bEbcfc7Ac04","desc":"The L2 version of the GRT ERC-20 token. It is the unit of value across the whole protocol: indexers stake it, curators signal with it, payers spend it, and the protocol mints it as indexing rewards. On L2 it can only be minted or burned by the token gateway (when bridging) and by the rewards/issuance system.","contractDoc":{"title":"L2 Graph Token Contract","notice":"Provides the L2 version of the GRT token, meant to be minted/burned through the L2GraphTokenGateway."},"implements":["IL2GraphToken","IGraphToken","ERC20","ERC20Burnable"],"deps":[],"roles":[],"reads":[{"name":"allowance","sig":"allowance(address,address)","inputs":[{"name":"owner","type":"address"},{"name":"spender","type":"address"}],"outputs":[{"name":"","type":"uint256"}],"mut":"view","doc":{"details":"See {IERC20-allowance}."}},{"name":"balanceOf","sig":"balanceOf(address)","inputs":[{"name":"account","type":"address"}],"outputs":[{"name":"","type":"uint256"}],"mut":"view","doc":{"details":"See {IERC20-balanceOf}."}},{"name":"gateway","sig":"gateway()","inputs":[],"outputs":[{"name":"","type":"address"}],"mut":"view","doc":{"notice":"Address of the gateway (on L2) that is allowed to mint tokens","returns":{"_0":"The address of the gateway contract"}}},{"name":"isMinter","sig":"isMinter(address)","inputs":[{"name":"account","type":"address"}],"outputs":[{"name":"","type":"bool"}],"mut":"view","doc":{"notice":"Return if the `_account` is a minter or not.","params":{"_account":"Address to check"},"returns":{"_0":"True if the `_account` is minter"}}},{"name":"l1Address","sig":"l1Address()","inputs":[],"outputs":[{"name":"","type":"address"}],"mut":"view","doc":{"notice":"Address of the corresponding Graph Token contract on L1","returns":{"_0":"The address of the L1 contract"}}},{"name":"totalSupply","sig":"totalSupply()","inputs":[],"outputs":[{"name":"","type":"uint256"}],"mut":"view","doc":{"details":"See {IERC20-totalSupply}."}}],"writes":[{"name":"addMinter","sig":"addMinter(address)","inputs":[{"name":"account","type":"address"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Add a new minter.","details":"Only callable by accounts with appropriate permissions","params":{"_account":"Address of the minter"}}},{"name":"approve","sig":"approve(address,uint256)","inputs":[{"name":"spender","type":"address"},{"name":"amount","type":"uint256"}],"outputs":[{"name":"","type":"bool"}],"mut":"nonpayable","doc":{"details":"See {IERC20-approve}. Requirements: - `spender` cannot be the zero address."}},{"name":"bridgeBurn","sig":"bridgeBurn(address,uint256)","inputs":[{"name":"account","type":"address"},{"name":"amount","type":"uint256"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"should decrease token supply by amount, and should (probably) only be callable by the L1 bridge.","details":"Only callable by the L2GraphTokenGateway when tokens are transferred back to L1","params":{"account":"Account to burn tokens from","amount":"Amount of tokens to burn"}},"access":{"roles":[],"mods":["onlyGateway"]},"emits":["BridgeBurned"]},{"name":"bridgeMint","sig":"bridgeMint(address,uint256)","inputs":[{"name":"account","type":"address"},{"name":"amount","type":"uint256"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"should increase token supply by amount, and should (probably) only be callable by the L1 bridge.","details":"Only callable by the L2GraphTokenGateway when tokens are transferred to L2","params":{"account":"Account to mint tokens to","amount":"Amount of tokens to mint"}},"access":{"roles":[],"mods":["onlyGateway"]},"emits":["BridgeMinted"]},{"name":"burn","sig":"burn(uint256)","inputs":[{"name":"amount","type":"uint256"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Burns tokens from the caller's account","details":"Destroys `amount` tokens from the caller. See {ERC20-_burn}.","params":{"amount":"The amount of tokens to burn"}}},{"name":"burnFrom","sig":"burnFrom(address,uint256)","inputs":[{"name":"from","type":"address"},{"name":"amount","type":"uint256"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Burns tokens from a specified account (requires allowance)","details":"Destroys `amount` tokens from `account`, deducting from the caller's allowance. See {ERC20-_burn} and {ERC20-allowance}. Requirements: - the caller must have allowance for ``accounts``'s tokens of at least `amount`.","params":{"amount":"The amount of tokens to burn","from":"The account to burn tokens from"}}},{"name":"decreaseAllowance","sig":"decreaseAllowance(address,uint256)","inputs":[{"name":"spender","type":"address"},{"name":"subtractedValue","type":"uint256"}],"outputs":[{"name":"","type":"bool"}],"mut":"nonpayable","doc":{"notice":"Decreases the allowance granted to a spender","details":"Atomically decreases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address. - `spender` must have allowance for the caller of at least `subtractedValue`.","params":{"spender":"The account whose allowance will be decreased","subtractedValue":"The amount to decrease the allowance by"},"returns":{"_0":"True if the operation succeeded"}}},{"name":"increaseAllowance","sig":"increaseAllowance(address,uint256)","inputs":[{"name":"spender","type":"address"},{"name":"addedValue","type":"uint256"}],"outputs":[{"name":"","type":"bool"}],"mut":"nonpayable","doc":{"notice":"Increases the allowance granted to a spender","details":"Atomically increases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address.","params":{"addedValue":"The amount to increase the allowance by","spender":"The account whose allowance will be increased"},"returns":{"_0":"True if the operation succeeded"}}},{"name":"initialize","sig":"initialize(address)","inputs":[{"name":"owner","type":"address"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"L2 Graph Token Contract initializer.","details":"Note some parameters have to be set separately as they are generally not expected to be available at initialization time: - gateway using setGateway - l1Address using setL1Address","params":{"_owner":"Governance address that owns this contract"}}},{"name":"mint","sig":"mint(address,uint256)","inputs":[{"name":"to","type":"address"},{"name":"amount","type":"uint256"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Mint new tokens.","details":"Only callable by accounts with minter role","params":{"_amount":"Amount of tokens to mint","_to":"Address to send the newly minted tokens"}}},{"name":"permit","sig":"permit(address,address,uint256,uint256,uint8,bytes32,bytes32)","inputs":[{"name":"owner","type":"address"},{"name":"spender","type":"address"},{"name":"value","type":"uint256"},{"name":"deadline","type":"uint256"},{"name":"v","type":"uint8"},{"name":"r","type":"bytes32"},{"name":"s","type":"bytes32"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Approve token allowance by validating a message signed by the holder.","params":{"_deadline":"Expiration time of the signed permit (if zero, the permit will never expire, so use with caution)","_owner":"Address of the token holder","_r":"Signature r value","_s":"Signature s value","_spender":"Address of the approved spender","_v":"Signature recovery id","_value":"Amount of tokens to approve the spender"}}},{"name":"removeMinter","sig":"removeMinter(address)","inputs":[{"name":"account","type":"address"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Remove a minter.","details":"Only callable by accounts with appropriate permissions","params":{"_account":"Address of the minter"}}},{"name":"renounceMinter","sig":"renounceMinter()","inputs":[],"outputs":[],"mut":"nonpayable","doc":{"notice":"Renounce being a minter.","details":"Allows a minter to voluntarily give up their minting privileges"}},{"name":"setGateway","sig":"setGateway(address)","inputs":[{"name":"gw","type":"address"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Sets the address of the L2 gateway allowed to mint tokens","params":{"_gw":"Address for the L2GraphTokenGateway that will be allowed to mint tokens"}},"access":{"roles":[],"mods":["onlyGovernor"]},"emits":["GatewaySet"]},{"name":"setL1Address","sig":"setL1Address(address)","inputs":[{"name":"addr","type":"address"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Sets the address of the counterpart token on L1","params":{"_addr":"Address for the GraphToken contract on L1"}},"access":{"roles":[],"mods":["onlyGovernor"]},"emits":["L1AddressSet"]},{"name":"transfer","sig":"transfer(address,uint256)","inputs":[{"name":"recipient","type":"address"},{"name":"amount","type":"uint256"}],"outputs":[{"name":"","type":"bool"}],"mut":"nonpayable","doc":{"details":"See {IERC20-transfer}. Requirements: - `recipient` cannot be the zero address. - the caller must have a balance of at least `amount`."}},{"name":"transferFrom","sig":"transferFrom(address,address,uint256)","inputs":[{"name":"sender","type":"address"},{"name":"recipient","type":"address"},{"name":"amount","type":"uint256"}],"outputs":[{"name":"","type":"bool"}],"mut":"nonpayable","doc":{"details":"See {IERC20-transferFrom}. Emits an {Approval} event indicating the updated allowance. This is not required by the EIP. See the note at the beginning of {ERC20}. Requirements: - `sender` and `recipient` cannot be the zero address. - `sender` must have a balance of at least `amount`. - the caller must have allowance for ``sender``'s tokens of at least `amount`."}}],"events":[{"name":"Approval","sig":"Approval(address,address,uint256)","inputs":[{"name":"owner","type":"address","indexed":true},{"name":"spender","type":"address","indexed":true},{"name":"value","type":"uint256","indexed":false}],"doc":{"details":"Emitted when the allowance of a `spender` for an `owner` is set by a call to {approve}. `value` is the new allowance."}},{"name":"BridgeBurned","sig":"BridgeBurned(address,uint256)","inputs":[{"name":"account","type":"address","indexed":true},{"name":"amount","type":"uint256","indexed":false}],"doc":{"notice":"Emitted when the bridge / gateway has burned tokens, i.e. tokens were transferred back to L1","params":{"account":"Address from which tokens were burned","amount":"Amount of tokens burned"}}},{"name":"BridgeMinted","sig":"BridgeMinted(address,uint256)","inputs":[{"name":"account","type":"address","indexed":true},{"name":"amount","type":"uint256","indexed":false}],"doc":{"notice":"Emitted when the bridge / gateway has minted new tokens, i.e. tokens were transferred to L2","params":{"account":"Address that received the minted tokens","amount":"Amount of tokens minted"}}},{"name":"GatewaySet","sig":"GatewaySet(address)","inputs":[{"name":"gateway","type":"address","indexed":false}],"doc":{"notice":"Emitted when the address of the gateway has been updated","params":{"gateway":"Address of the new gateway"}}},{"name":"L1AddressSet","sig":"L1AddressSet(address)","inputs":[{"name":"l1Address","type":"address","indexed":false}],"doc":{"notice":"Emitted when the address of the Graph Token contract on L1 has been updated","params":{"l1Address":"Address of the L1 Graph Token contract"}}},{"name":"Transfer","sig":"Transfer(address,address,uint256)","inputs":[{"name":"from","type":"address","indexed":true},{"name":"to","type":"address","indexed":true},{"name":"value","type":"uint256","indexed":false}],"doc":{"details":"Emitted when `value` tokens are moved from one account (`from`) to another (`to`). Note that `value` may be zero."}}],"counts":{"reads":6,"writes":17,"events":6}},{"id":"HorizonStaking","name":"HorizonStaking","layer":"staking","chain":"L2","core":true,"legacy":false,"address":"0x865365C425f3A593Ffe698D9c4E6707D14d51e08","desc":"The heart of Graph Horizon. Service providers stake GRT and carve it into \"provisions\" locked to a specific verifier (data service) such as the Subgraph Service. Delegators add stake on top. It tracks provisions, thawing/withdrawal, delegation pools, and lets verifiers slash misbehaving providers. It replaced the older monolithic Staking contract at the same proxy.","contractDoc":null,"implements":["IHorizonStaking","IHorizonStakingMain","IHorizonStakingBase"],"deps":[{"to":"L2GraphToken","label":"locks / moves staked GRT"},{"to":"Controller","label":"reads protocol registry","kind":"registry"}],"roles":[],"reads":[{"name":"getDelegatedTokensAvailable","sig":"getDelegatedTokensAvailable(address,address)","inputs":[{"name":"serviceProvider","type":"address"},{"name":"verifier","type":"address"}],"outputs":[{"name":"","type":"uint256"}],"mut":"view","doc":{"notice":"Gets the delegator's tokens available in a provision.","details":"Calculated as the tokens available minus the tokens thawing.","params":{"serviceProvider":"The address of the service provider.","verifier":"The address of the verifier."},"returns":{"_0":"The amount of tokens available."}}},{"name":"getDelegation","sig":"getDelegation(address,address,address)","inputs":[{"name":"serviceProvider","type":"address"},{"name":"verifier","type":"address"},{"name":"delegator","type":"address"}],"outputs":[{"name":"","type":"(uint256)"}],"mut":"view","doc":{"notice":"Gets the details of a delegation.","details":"Removes deprecated fields from the return value.","params":{"delegator":"The address of the delegator.","serviceProvider":"The address of the service provider.","verifier":"The address of the verifier."},"returns":{"_0":"The delegation details."}}},{"name":"getDelegationFeeCut","sig":"getDelegationFeeCut(address,address,uint8)","inputs":[{"name":"serviceProvider","type":"address"},{"name":"verifier","type":"address"},{"name":"paymentType","type":"uint8"}],"outputs":[{"name":"","type":"uint256"}],"mut":"view","doc":{"notice":"Gets the delegation fee cut for a payment type.","params":{"paymentType":"The payment type as defined by {IGraphPayments.PaymentTypes}.","serviceProvider":"The address of the service provider.","verifier":"The address of the verifier."},"returns":{"_0":"The delegation fee cut in PPM."}}},{"name":"getDelegationPool","sig":"getDelegationPool(address,address)","inputs":[{"name":"serviceProvider","type":"address"},{"name":"verifier","type":"address"}],"outputs":[{"name":"","type":"(uint256,uint256,uint256,uint256,uint256)"}],"mut":"view","doc":{"notice":"Gets the details of delegation pool.","details":"Removes deprecated fields from the return value.","params":{"serviceProvider":"The address of the service provider.","verifier":"The address of the verifier."},"returns":{"_0":"The delegation pool details."}}},{"name":"getIdleStake","sig":"getIdleStake(address)","inputs":[{"name":"serviceProvider","type":"address"}],"outputs":[{"name":"","type":"uint256"}],"mut":"view","doc":{"notice":"Gets the service provider's idle stake which is the stake that is not being used for any provision. Note that this only includes service provider's self stake.","params":{"serviceProvider":"The address of the service provider."},"returns":{"_0":"The amount of tokens that are idle."}}},{"name":"getMaxThawingPeriod","sig":"getMaxThawingPeriod()","inputs":[],"outputs":[{"name":"","type":"uint64"}],"mut":"view","doc":{"notice":"Gets the maximum allowed thawing period for a provision.","returns":{"_0":"The maximum allowed thawing period in seconds."}}},{"name":"getProviderTokensAvailable","sig":"getProviderTokensAvailable(address,address)","inputs":[{"name":"serviceProvider","type":"address"},{"name":"verifier","type":"address"}],"outputs":[{"name":"","type":"uint256"}],"mut":"view","doc":{"notice":"Gets the service provider's tokens available in a provision.","details":"Calculated as the tokens available minus the tokens thawing.","params":{"serviceProvider":"The address of the service provider.","verifier":"The address of the verifier."},"returns":{"_0":"The amount of tokens available."}}},{"name":"getProvision","sig":"getProvision(address,address)","inputs":[{"name":"serviceProvider","type":"address"},{"name":"verifier","type":"address"}],"outputs":[{"name":"","type":"(uint256,uint256,uint256,uint32,uint64,uint64,uint32,uint64,uint256,uint256)"}],"mut":"view","doc":{"notice":"Gets the details of a provision.","params":{"serviceProvider":"The address of the service provider.","verifier":"The address of the verifier."},"returns":{"_0":"The provision details."}}},{"name":"getServiceProvider","sig":"getServiceProvider(address)","inputs":[{"name":"serviceProvider","type":"address"}],"outputs":[{"name":"","type":"(uint256,uint256)"}],"mut":"view","doc":{"notice":"Gets the details of a service provider.","details":"Removes deprecated fields from the return value.","params":{"serviceProvider":"The address of the service provider."},"returns":{"_0":"The service provider details."}}},{"name":"getStake","sig":"getStake(address)","inputs":[{"name":"serviceProvider","type":"address"}],"outputs":[{"name":"","type":"uint256"}],"mut":"view","doc":{"notice":"Gets the stake of a service provider.","params":{"serviceProvider":"The address of the service provider."},"returns":{"_0":"The amount of tokens staked."}}},{"name":"getSubgraphService","sig":"getSubgraphService()","inputs":[],"outputs":[{"name":"","type":"address"}],"mut":"view","doc":{"notice":"Gets the address of the subgraph data service.","returns":{"_0":"The address of the subgraph data service."}}},{"name":"getThawedTokens","sig":"getThawedTokens(uint8,address,address,address)","inputs":[{"name":"thawRequestType","type":"uint8"},{"name":"serviceProvider","type":"address"},{"name":"verifier","type":"address"},{"name":"owner","type":"address"}],"outputs":[{"name":"","type":"uint256"}],"mut":"view","doc":{"notice":"Gets the amount of thawed tokens that can be releasedfor a given provision.","details":"Note that the value returned by this function does not return the total amount of thawed tokens but only those that can be released. If thaw requests are created with different thawing periods it's possible that an unexpired thaw request temporarily blocks the release of other ones that have already expired. This function will stop counting when it encounters the first thaw request that is not yet expired.","params":{"owner":"The owner of the thaw requests. Use either the service provider or delegator address.","serviceProvider":"The address of the service provider.","thawRequestType":"The type of thaw request.","verifier":"The address of the verifier."},"returns":{"_0":"The amount of thawed tokens."}}},{"name":"getThawRequest","sig":"getThawRequest(uint8,bytes32)","inputs":[{"name":"thawRequestType","type":"uint8"},{"name":"thawRequestId","type":"bytes32"}],"outputs":[{"name":"","type":"(uint256,uint64,bytes32,uint256)"}],"mut":"view","doc":{"notice":"Gets a thaw request.","params":{"thawRequestId":"The id of the thaw request.","thawRequestType":"The type of thaw request."},"returns":{"_0":"The thaw request details."}}},{"name":"getThawRequestList","sig":"getThawRequestList(uint8,address,address,address)","inputs":[{"name":"thawRequestType","type":"uint8"},{"name":"serviceProvider","type":"address"},{"name":"verifier","type":"address"},{"name":"owner","type":"address"}],"outputs":[{"name":"","type":"(bytes32,bytes32,uint256,uint256)"}],"mut":"view","doc":{"notice":"Gets the metadata of a thaw request list. Service provider and delegators each have their own thaw request list per provision. Metadata includes the head and tail of the list, plus the total number of thaw requests.","params":{"owner":"The owner of the thaw requests. Use either the service provider or delegator address.","serviceProvider":"The address of the service provider.","thawRequestType":"The type of thaw request.","verifier":"The address of the verifier."},"returns":{"_0":"The thaw requests list metadata."}}},{"name":"getTokensAvailable","sig":"getTokensAvailable(address,address,uint32)","inputs":[{"name":"serviceProvider","type":"address"},{"name":"verifier","type":"address"},{"name":"delegationRatio","type":"uint32"}],"outputs":[{"name":"","type":"uint256"}],"mut":"view","doc":{"notice":"Gets the tokens available in a provision. Tokens available are the tokens in a provision that are not thawing. Includes service provider's and delegator's stake. Allows specifying a `delegationRatio` which caps the amount of delegated tokens that are considered available.","params":{"delegationRatio":"The delegation ratio.","serviceProvider":"The address of the service provider.","verifier":"The address of the verifier."},"returns":{"_0":"The amount of tokens available."}}},{"name":"isAllocation","sig":"isAllocation(address)","inputs":[{"name":"allocationID","type":"address"}],"outputs":[{"name":"","type":"bool"}],"mut":"view","doc":{"notice":"Return if allocationID is used.","details":"This function is used to check for allocation id collisions with legacy allocations that were created before the Horizon upgrade.","params":{"allocationID":"Address used as signer by the indexer for an allocation"},"returns":{"_0":"True if allocationID already used"}}},{"name":"isAllowedLockedVerifier","sig":"isAllowedLockedVerifier(address)","inputs":[{"name":"verifier","type":"address"}],"outputs":[{"name":"","type":"bool"}],"mut":"view","doc":{"notice":"Return true if the verifier is an allowed locked verifier.","params":{"verifier":"Address of the verifier"},"returns":{"_0":"True if verifier is allowed locked verifier, false otherwise"}}},{"name":"isAuthorized","sig":"isAuthorized(address,address,address)","inputs":[{"name":"serviceProvider","type":"address"},{"name":"verifier","type":"address"},{"name":"operator","type":"address"}],"outputs":[{"name":"","type":"bool"}],"mut":"view","doc":{"notice":"Check if an operator is authorized for the caller on a specific verifier / data service.","params":{"operator":"The address to check for auth","serviceProvider":"The service provider on behalf of whom they're claiming to act","verifier":"The verifier / data service on which they're claiming to act"},"returns":{"_0":"Whether the operator is authorized or not"}}},{"name":"isDelegationSlashingEnabled","sig":"isDelegationSlashingEnabled()","inputs":[],"outputs":[{"name":"","type":"bool"}],"mut":"view","doc":{"notice":"Return true if delegation slashing is enabled, false otherwise.","returns":{"_0":"True if delegation slashing is enabled, false otherwise"}}}],"writes":[{"name":"acceptProvisionParameters","sig":"acceptProvisionParameters(address)","inputs":[{"name":"serviceProvider","type":"address"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Accepts a staged provision parameter update.","details":"Only the provision's verifier can call this function. Emits a {ProvisionParametersSet} event.","params":{"serviceProvider":"The service provider address"}},"emits":["ProvisionParametersSet"]},{"name":"addToDelegationPool","sig":"addToDelegationPool(address,address,uint256)","inputs":[{"name":"serviceProvider","type":"address"},{"name":"verifier","type":"address"},{"name":"tokens","type":"uint256"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Add tokens to a delegation pool without issuing shares. Used by data services to pay delegation fees/rewards. Delegators SHOULD NOT call this function.","details":"Requirements: - `tokens` cannot be zero. - Caller must have previously approved this contract to pull tokens from their balance. Emits a {TokensToDelegationPoolAdded} event.","params":{"serviceProvider":"The service provider address","tokens":"The amount of tokens to add to the delegation pool","verifier":"The verifier address for which the tokens are provisioned"}},"emits":["TokensToDelegationPoolAdded"]},{"name":"addToProvision","sig":"addToProvision(address,address,uint256)","inputs":[{"name":"serviceProvider","type":"address"},{"name":"verifier","type":"address"},{"name":"tokens","type":"uint256"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Adds tokens from the service provider's idle stake to a provision","details":"Requirements: - The `serviceProvider` must have previously provisioned stake to `verifier`. - `tokens` cannot be zero. - The `serviceProvider` must have enough idle stake to cover the tokens to add. Emits a {ProvisionIncreased} event.","params":{"serviceProvider":"The service provider address","tokens":"The amount of tokens to add to the provision","verifier":"The verifier address"}},"emits":["ProvisionIncreased"]},{"name":"delegate","sig":"delegate(address,uint256)","inputs":[{"name":"serviceProvider","type":"address"},{"name":"tokens","type":"uint256"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Delegate tokens to the subgraph data service provision. This function is for backwards compatibility with the legacy staking contract. It only allows delegating to the subgraph data service and DOES NOT have slippage protection.","details":"See {delegate}.","params":{"serviceProvider":"The service provider address","tokens":"The amount of tokens to delegate"}},"emits":["TokensDelegated"]},{"name":"delegate","sig":"delegate(address,address,uint256,uint256)","inputs":[{"name":"serviceProvider","type":"address"},{"name":"verifier","type":"address"},{"name":"tokens","type":"uint256"},{"name":"minSharesOut","type":"uint256"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Delegate tokens to a provision.","details":"Requirements: - `tokens` cannot be zero. - Caller must have previously approved this contract to pull tokens from their balance. - The provision must exist. Emits a {TokensDelegated} event.","params":{"minSharesOut":"The minimum amount of shares to accept, slippage protection.","serviceProvider":"The service provider address","tokens":"The amount of tokens to delegate","verifier":"The verifier address"}},"emits":["TokensDelegated"]},{"name":"deprovision","sig":"deprovision(address,address,uint256)","inputs":[{"name":"serviceProvider","type":"address"},{"name":"verifier","type":"address"},{"name":"nThawRequests","type":"uint256"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Remove tokens from a provision and move them back to the service provider's idle stake.","details":"The parameter `nThawRequests` can be set to a non zero value to fulfill a specific number of thaw requests in the event that fulfilling all of them results in a gas limit error. Otherwise, the function will attempt to fulfill all thaw requests until the first one that is not yet expired is found. Requirements: - Must have previously initiated a thaw request using {thaw}. Emits {ThawRequestFulfilled}, {ThawRequestsFulfilled} and {TokensDeprovisioned} events.","params":{"nThawRequests":"The number of thaw requests to fulfill. Set to 0 to fulfill all thaw requests.","serviceProvider":"The service provider address","verifier":"The verifier address"}},"emits":["TokensDeprovisioned","ThawRequestsFulfilled"]},{"name":"forceWithdraw","sig":"forceWithdraw(address)","inputs":[{"name":"serviceProvider","type":"address"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Withdraw service provider legacy locked tokens. This is a permissionless function that allows anyone to withdraw on behalf of a service provider. It only allows withdrawing tokens that were unstaked before the Horizon upgrade.","details":"Tokens are always sent to the service provider, not the caller. Emits a {HorizonStakeWithdrawn} event.","params":{"serviceProvider":"Address of service provider to withdraw funds from"}},"emits":["HorizonStakeWithdrawn"]},{"name":"forceWithdrawDelegated","sig":"forceWithdrawDelegated(address,address)","inputs":[{"name":"serviceProvider","type":"address"},{"name":"delegator","type":"address"}],"outputs":[{"name":"","type":"uint256"}],"mut":"nonpayable","doc":{"notice":"Withdraw delegator legacy undelegated tokens. This is a permissionless function that allows anyone to withdraw on behalf of a delegator. It only allows withdrawing tokens that were undelegated before the Horizon upgrade.","details":"Tokens are always sent to the delegator, not the caller. Emits a {StakeDelegatedWithdrawn} event.","params":{"delegator":"The delegator address to withdraw funds for","serviceProvider":"The service provider address"},"returns":{"_0":"The amount of tokens withdrawn"}},"emits":["StakeDelegatedWithdrawn"]},{"name":"provision","sig":"provision(address,address,uint256,uint32,uint64)","inputs":[{"name":"serviceProvider","type":"address"},{"name":"verifier","type":"address"},{"name":"tokens","type":"uint256"},{"name":"maxVerifierCut","type":"uint32"},{"name":"thawingPeriod","type":"uint64"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Provision stake to a verifier. The tokens will be locked with a thawing period and will be slashable by the verifier. This is the main mechanism to provision stake to a data service, where the data service is the verifier. This function can be called by the service provider or by an operator authorized by the provider for this specific verifier.","details":"Requirements: - `tokens` cannot be zero. - The `serviceProvider` must have enough idle stake to cover the tokens to provision. - `maxVerifierCut` must be a valid PPM. - `thawingPeriod` must be less than or equal to `_maxThawingPeriod`. Emits a {ProvisionCreated} event.","params":{"maxVerifierCut":"The maximum cut, expressed in PPM, that a verifier can transfer instead of burning when slashing","serviceProvider":"The service provider address","thawingPeriod":"The period in seconds that the tokens will be thawing before they can be removed from the provision","tokens":"The amount of tokens that will be locked and slashable","verifier":"The verifier address for which the tokens are provisioned (who will be able to slash the tokens)"}},"emits":["ProvisionCreated"]},{"name":"provisionLocked","sig":"provisionLocked(address,address,uint256,uint32,uint64)","inputs":[{"name":"serviceProvider","type":"address"},{"name":"verifier","type":"address"},{"name":"tokens","type":"uint256"},{"name":"maxVerifierCut","type":"uint32"},{"name":"thawingPeriod","type":"uint64"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Provision stake to a verifier using locked tokens (i.e. from GraphTokenLockWallets).","details":"See {provision}. Additional requirements: - The `verifier` must be allowed to be used for locked provisions.","params":{"maxVerifierCut":"The maximum cut, expressed in PPM, that a verifier can transfer instead of burning when slashing","serviceProvider":"The service provider address","thawingPeriod":"The period in seconds that the tokens will be thawing before they can be removed from the provision","tokens":"The amount of tokens that will be locked and slashable","verifier":"The verifier address for which the tokens are provisioned (who will be able to slash the tokens)"}},"emits":["ProvisionCreated"]},{"name":"redelegate","sig":"redelegate(address,address,address,address,uint256,uint256)","inputs":[{"name":"oldServiceProvider","type":"address"},{"name":"oldVerifier","type":"address"},{"name":"newServiceProvider","type":"address"},{"name":"newVerifier","type":"address"},{"name":"minSharesForNewProvider","type":"uint256"},{"name":"nThawRequests","type":"uint256"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Re-delegate undelegated tokens from a provision after thawing to a `newServiceProvider` and `newVerifier`.","details":"The parameter `nThawRequests` can be set to a non zero value to fulfill a specific number of thaw requests in the event that fulfilling all of them results in a gas limit error. Requirements: - Must have previously initiated a thaw request using {undelegate}. - `newServiceProvider` and `newVerifier` must not be the zero address. - `newServiceProvider` must have previously provisioned stake to `newVerifier`. Emits {ThawRequestFulfilled} and {ThawRequestsFulfilled} events.","params":{"minSharesForNewProvider":"The minimum amount of shares to accept for the new service provider","nThawRequests":"The number of thaw requests to fulfill. Set to 0 to fulfill all thaw requests.","newServiceProvider":"The address of a new service provider","newVerifier":"The address of a new verifier","oldServiceProvider":"The old service provider address","oldVerifier":"The old verifier address"}},"emits":["DelegatedTokensWithdrawn","TokensDelegated","ThawRequestsFulfilled"]},{"name":"reprovision","sig":"reprovision(address,address,address,uint256)","inputs":[{"name":"serviceProvider","type":"address"},{"name":"oldVerifier","type":"address"},{"name":"newVerifier","type":"address"},{"name":"nThawRequests","type":"uint256"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Move already thawed stake from one provision into another provision This function can be called by the service provider or by an operator authorized by the provider for the two corresponding verifiers.","details":"Requirements: - Must have previously initiated a thaw request using {thaw}. - `tokens` cannot be zero. - The `serviceProvider` must have previously provisioned stake to `newVerifier`. - The `serviceProvider` must have enough idle stake to cover the tokens to add. Emits {ThawRequestFulfilled}, {ThawRequestsFulfilled}, {TokensDeprovisioned} and {ProvisionIncreased} events.","params":{"nThawRequests":"The number of thaw requests to fulfill. Set to 0 to fulfill all thaw requests.","newVerifier":"The verifier address for which the tokens will be provisioned","oldVerifier":"The verifier address for which the tokens are currently provisioned","serviceProvider":"The service provider address"}},"emits":["ProvisionIncreased","TokensDeprovisioned","ThawRequestsFulfilled"]},{"name":"setAllowedLockedVerifier","sig":"setAllowedLockedVerifier(address,bool)","inputs":[{"name":"verifier","type":"address"},{"name":"allowed","type":"bool"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Sets a verifier as a globally allowed verifier for locked provisions.","details":"This function can only be called by the contract governor, it's used to maintain a whitelist of verifiers that do not allow the stake from a locked wallet to escape the lock.Emits a {AllowedLockedVerifierSet} event.","params":{"allowed":"Whether the verifier is allowed or not","verifier":"The verifier address"}},"access":{"roles":[],"mods":["onlyGovernor"]},"emits":["AllowedLockedVerifierSet"]},{"name":"setDelegationFeeCut","sig":"setDelegationFeeCut(address,address,uint8,uint256)","inputs":[{"name":"serviceProvider","type":"address"},{"name":"verifier","type":"address"},{"name":"paymentType","type":"uint8"},{"name":"feeCut","type":"uint256"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Set the fee cut for a verifier on a specific payment type.","details":"Emits a {DelegationFeeCutSet} event.","params":{"feeCut":"The fee cut to set, in PPM","paymentType":"The payment type for which the fee cut is set, as defined in {IGraphPayments}","serviceProvider":"The service provider address","verifier":"The verifier address"}},"emits":["DelegationFeeCutSet"]},{"name":"setDelegationSlashingEnabled","sig":"setDelegationSlashingEnabled()","inputs":[],"outputs":[],"mut":"nonpayable","doc":{"notice":"Set the global delegation slashing flag to true.","details":"This function can only be called by the contract governor."},"access":{"roles":[],"mods":["onlyGovernor"]},"emits":["DelegationSlashingEnabled"]},{"name":"setMaxThawingPeriod","sig":"setMaxThawingPeriod(uint64)","inputs":[{"name":"maxThawingPeriod","type":"uint64"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Sets the global maximum thawing period allowed for provisions.","params":{"maxThawingPeriod":"The new maximum thawing period, in seconds"}},"access":{"roles":[],"mods":["onlyGovernor"]},"emits":["MaxThawingPeriodSet"]},{"name":"setOperator","sig":"setOperator(address,address,bool)","inputs":[{"name":"verifier","type":"address"},{"name":"operator","type":"address"},{"name":"allowed","type":"bool"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Authorize or unauthorize an address to be an operator for the caller on a data service.","details":"Emits a {OperatorSet} event.","params":{"allowed":"Whether the operator is authorized or not","operator":"Address to authorize or unauthorize","verifier":"The verifier / data service on which they'll be allowed to operate"}},"emits":["OperatorSet"]},{"name":"setOperatorLocked","sig":"setOperatorLocked(address,address,bool)","inputs":[{"name":"verifier","type":"address"},{"name":"operator","type":"address"},{"name":"allowed","type":"bool"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Authorize or unauthorize an address to be an operator for the caller on a verifier.","details":"See {setOperator}. Additional requirements: - The `verifier` must be allowed to be used for locked provisions.","params":{"allowed":"Whether the operator is authorized or not","operator":"Address to authorize or unauthorize","verifier":"The verifier / data service on which they'll be allowed to operate"}},"emits":["OperatorSet"]},{"name":"setProvisionParameters","sig":"setProvisionParameters(address,address,uint32,uint64)","inputs":[{"name":"serviceProvider","type":"address"},{"name":"verifier","type":"address"},{"name":"maxVerifierCut","type":"uint32"},{"name":"thawingPeriod","type":"uint64"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Stages a provision parameter update. Note that the change is not effective until the verifier calls {acceptProvisionParameters}. Calling this function is a no-op if the new parameters are the same as the current ones.","details":"This two step update process prevents the service provider from changing the parameters without the verifier's consent. Requirements: - `thawingPeriod` must be less than or equal to `_maxThawingPeriod`. Note that if `_maxThawingPeriod` changes the function will not revert if called with the same thawing period as the current one. Emits a {ProvisionParametersStaged} event if at least one of the parameters changed.","params":{"maxVerifierCut":"The proposed maximum cut, expressed in PPM of the slashed amount, that a verifier can take for themselves when slashing","serviceProvider":"The service provider address","thawingPeriod":"The proposed period in seconds that the tokens will be thawing before they can be removed from the provision","verifier":"The verifier address"}},"emits":["ProvisionParametersStaged"]},{"name":"slash","sig":"slash(address,uint256,uint256,address)","inputs":[{"name":"serviceProvider","type":"address"},{"name":"tokens","type":"uint256"},{"name":"tokensVerifier","type":"uint256"},{"name":"verifierDestination","type":"address"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Slash a service provider. This can only be called by a verifier to which the provider has provisioned stake, and up to the amount of tokens they have provisioned. If the service provider's stake is not enough, the associated delegation pool might be slashed depending on the value of the global delegation slashing flag. Part of the slashed tokens are sent to the `verifierDestination` as a reward.","details":"Requirements: - `tokens` must be less than or equal to the amount of tokens provisioned by the service provider. - `tokensVerifier` must be less than the provision's tokens times the provision's maximum verifier cut. Emits a {ProvisionSlashed} and {VerifierTokensSent} events. Emits a {DelegationSlashed} or {DelegationSlashingSkipped} event depending on the global delegation slashing flag.","params":{"serviceProvider":"The service provider to slash","tokens":"The amount of tokens to slash","tokensVerifier":"The amount of tokens to transfer instead of burning","verifierDestination":"The address to transfer the verifier cut to"}},"emits":["VerifierTokensSent","ProvisionSlashed","DelegationSlashed","DelegationSlashingSkipped"]},{"name":"stake","sig":"stake(uint256)","inputs":[{"name":"tokens","type":"uint256"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Deposit tokens on the staking contract.","details":"Pulls tokens from the caller. Requirements: - `_tokens` cannot be zero. - Caller must have previously approved this contract to pull tokens from their balance. Emits a {HorizonStakeDeposited} event.","params":{"tokens":"Amount of tokens to stake"}},"emits":["HorizonStakeDeposited"]},{"name":"stakeTo","sig":"stakeTo(address,uint256)","inputs":[{"name":"serviceProvider","type":"address"},{"name":"tokens","type":"uint256"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Deposit tokens on the service provider stake, on behalf of the service provider.","details":"Pulls tokens from the caller. Requirements: - `_tokens` cannot be zero. - Caller must have previously approved this contract to pull tokens from their balance. Emits a {HorizonStakeDeposited} event.","params":{"serviceProvider":"Address of the service provider","tokens":"Amount of tokens to stake"}},"emits":["HorizonStakeDeposited"]},{"name":"stakeToProvision","sig":"stakeToProvision(address,address,uint256)","inputs":[{"name":"serviceProvider","type":"address"},{"name":"verifier","type":"address"},{"name":"tokens","type":"uint256"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Deposit tokens on the service provider stake, on behalf of the service provider, provisioned to a specific verifier.","details":"This function can be called by the service provider, by an authorized operator or by the verifier itself.Requirements: - The `serviceProvider` must have previously provisioned stake to `verifier`. - `_tokens` cannot be zero. - Caller must have previously approved this contract to pull tokens from their balance. Emits {HorizonStakeDeposited} and {ProvisionIncreased} events.","params":{"serviceProvider":"Address of the service provider","tokens":"Amount of tokens to stake","verifier":"Address of the verifier"}},"emits":["ProvisionIncreased","HorizonStakeDeposited"]},{"name":"thaw","sig":"thaw(address,address,uint256)","inputs":[{"name":"serviceProvider","type":"address"},{"name":"verifier","type":"address"},{"name":"tokens","type":"uint256"}],"outputs":[{"name":"","type":"bytes32"}],"mut":"nonpayable","doc":{"notice":"Start thawing tokens to remove them from a provision. This function can be called by the service provider or by an operator authorized by the provider for this specific verifier. Note that removing tokens from a provision is a two step process: - First the tokens are thawed using this function. - Then after the thawing period, the tokens are removed from the provision using {deprovision} or {reprovision}.","details":"Requirements: - The provision must have enough tokens available to thaw. - `tokens` cannot be zero. Emits {ProvisionThawed} and {ThawRequestCreated} events.","params":{"serviceProvider":"The service provider address","tokens":"The amount of tokens to thaw","verifier":"The verifier address for which the tokens are provisioned"},"returns":{"_0":"The ID of the thaw request"}},"emits":["ProvisionThawed","ThawRequestCreated"]},{"name":"undelegate","sig":"undelegate(address,uint256)","inputs":[{"name":"serviceProvider","type":"address"},{"name":"shares","type":"uint256"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Undelegate tokens from the subgraph data service provision and start thawing them. This function is for backwards compatibility with the legacy staking contract. It only allows undelegating from the subgraph data service.","details":"See {undelegate}.","params":{"serviceProvider":"The service provider address","shares":"The amount of shares to undelegate"}},"emits":["TokensUndelegated","ThawRequestCreated"]},{"name":"undelegate","sig":"undelegate(address,address,uint256)","inputs":[{"name":"serviceProvider","type":"address"},{"name":"verifier","type":"address"},{"name":"shares","type":"uint256"}],"outputs":[{"name":"","type":"bytes32"}],"mut":"nonpayable","doc":{"notice":"Undelegate tokens from a provision and start thawing them. Note that undelegating tokens from a provision is a two step process: - First the tokens are thawed using this function. - Then after the thawing period, the tokens are removed from the provision using {withdrawDelegated}. Requirements: - `shares` cannot be zero. Emits a {TokensUndelegated} and {ThawRequestCreated} event.","params":{"serviceProvider":"The service provider address","shares":"The amount of shares to undelegate","verifier":"The verifier address"},"returns":{"_0":"The ID of the thaw request"}},"emits":["TokensUndelegated","ThawRequestCreated"]},{"name":"unstake","sig":"unstake(uint256)","inputs":[{"name":"tokens","type":"uint256"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Move idle stake back to the owner's account. Stake is immediately removed from the protocol.","details":"Requirements: - `_tokens` cannot be zero. - `_serviceProvider` must have enough idle stake to cover the staking amount. Emits a {HorizonStakeWithdrawn} event.","params":{"tokens":"Amount of tokens to unstake"}},"emits":["HorizonStakeWithdrawn"]},{"name":"withdraw","sig":"withdraw()","inputs":[],"outputs":[],"mut":"nonpayable","doc":{"notice":"Withdraw service provider tokens once the thawing period (initiated by {unstake}) has passed. All thawed tokens are withdrawn. This function is for backwards compatibility with the legacy staking contract. It only allows withdrawing tokens unstaked before horizon upgrade.","details":"This function can't be removed in case there are still pre-horizon unstakes. Emits a {HorizonStakeWithdrawn} event."},"emits":["HorizonStakeWithdrawn"]},{"name":"withdrawDelegated","sig":"withdrawDelegated(address,address,uint256)","inputs":[{"name":"serviceProvider","type":"address"},{"name":"verifier","type":"address"},{"name":"nThawRequests","type":"uint256"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Withdraw undelegated tokens from a provision after thawing.","details":"The parameter `nThawRequests` can be set to a non zero value to fulfill a specific number of thaw requests in the event that fulfilling all of them results in a gas limit error. Otherwise, the function will attempt to fulfill all thaw requests until the first one that is not yet expired is found.If the delegation pool was completely slashed before withdrawing, calling this function will fulfill the thaw requests with an amount equal to zero. Requirements: - Must have previously initiated a thaw request using {undelegate}. Emits {ThawRequestFulfilled}, {ThawRequestsFulfilled} and {DelegatedTokensWithdrawn} events.","params":{"nThawRequests":"The number of thaw requests to fulfill. Set to 0 to fulfill all thaw requests.","serviceProvider":"The service provider address","verifier":"The verifier address"}},"emits":["StakeDelegatedWithdrawn","DelegatedTokensWithdrawn","TokensDelegated","ThawRequestsFulfilled"]},{"name":"withdrawDelegated","sig":"withdrawDelegated(address,address)","inputs":[{"name":"serviceProvider","type":"address"},{"name":"deprecated","type":"address"}],"outputs":[{"name":"","type":"uint256"}],"mut":"nonpayable","doc":{"notice":"Withdraw undelegated tokens from the subgraph data service provision after thawing. This function is for backwards compatibility with the legacy staking contract. It only allows withdrawing tokens undelegated before horizon upgrade.","details":"This function can't be removed in case there are still pre-horizon undelegations.See {delegate}.","params":{"deprecated":"Deprecated parameter kept for backwards compatibility","serviceProvider":"The service provider address"},"returns":{"_0":"The amount of tokens withdrawn"}},"emits":["StakeDelegatedWithdrawn","DelegatedTokensWithdrawn","TokensDelegated","ThawRequestsFulfilled"]}],"events":[{"name":"AllowedLockedVerifierSet","sig":"AllowedLockedVerifierSet(address,bool)","inputs":[{"name":"verifier","type":"address","indexed":true},{"name":"allowed","type":"bool","indexed":false}],"doc":{"notice":"Emitted when a verifier is allowed or disallowed to be used for locked provisions.","params":{"allowed":"Whether the verifier is allowed or disallowed","verifier":"The address of the verifier"}}},{"name":"DelegatedTokensWithdrawn","sig":"DelegatedTokensWithdrawn(address,address,address,uint256)","inputs":[{"name":"serviceProvider","type":"address","indexed":true},{"name":"verifier","type":"address","indexed":true},{"name":"delegator","type":"address","indexed":true},{"name":"tokens","type":"uint256","indexed":false}],"doc":{"notice":"Emitted when a delegator withdraws tokens from a provision after thawing.","params":{"delegator":"The address of the delegator","serviceProvider":"The address of the service provider","tokens":"The amount of tokens withdrawn","verifier":"The address of the verifier"}}},{"name":"DelegationFeeCutSet","sig":"DelegationFeeCutSet(address,address,uint8,uint256)","inputs":[{"name":"serviceProvider","type":"address","indexed":true},{"name":"verifier","type":"address","indexed":true},{"name":"paymentType","type":"uint8","indexed":true},{"name":"feeCut","type":"uint256","indexed":false}],"doc":{"notice":"Emitted when a service provider sets delegation fee cuts for a verifier.","params":{"feeCut":"The fee cut set, in PPM","paymentType":"The payment type for which the fee cut is set, as defined in {IGraphPayments}","serviceProvider":"The address of the service provider","verifier":"The address of the verifier"}}},{"name":"DelegationSlashed","sig":"DelegationSlashed(address,address,uint256)","inputs":[{"name":"serviceProvider","type":"address","indexed":true},{"name":"verifier","type":"address","indexed":true},{"name":"tokens","type":"uint256","indexed":false}],"doc":{"notice":"Emitted when a delegation pool is slashed by a verifier.","params":{"serviceProvider":"The address of the service provider","tokens":"The amount of tokens slashed (note this only represents delegation pool's slashed stake)","verifier":"The address of the verifier"}}},{"name":"DelegationSlashingEnabled","sig":"DelegationSlashingEnabled()","inputs":[],"doc":{"notice":"Emitted when the delegation slashing global flag is set."}},{"name":"DelegationSlashingSkipped","sig":"DelegationSlashingSkipped(address,address,uint256)","inputs":[{"name":"serviceProvider","type":"address","indexed":true},{"name":"verifier","type":"address","indexed":true},{"name":"tokens","type":"uint256","indexed":false}],"doc":{"notice":"Emitted when a delegation pool would have been slashed by a verifier, but the slashing was skipped because delegation slashing global parameter is not enabled.","params":{"serviceProvider":"The address of the service provider","tokens":"The amount of tokens that would have been slashed (note this only represents delegation pool's slashed stake)","verifier":"The address of the verifier"}}},{"name":"HorizonStakeDeposited","sig":"HorizonStakeDeposited(address,uint256)","inputs":[{"name":"serviceProvider","type":"address","indexed":true},{"name":"tokens","type":"uint256","indexed":false}],"doc":{"notice":"Emitted when a service provider stakes tokens.","params":{"serviceProvider":"The address of the service provider.","tokens":"The amount of tokens staked."}}},{"name":"HorizonStakeWithdrawn","sig":"HorizonStakeWithdrawn(address,uint256)","inputs":[{"name":"serviceProvider","type":"address","indexed":true},{"name":"tokens","type":"uint256","indexed":false}],"doc":{"notice":"Emitted when a service provider unstakes tokens.","params":{"serviceProvider":"The address of the service provider","tokens":"The amount of tokens withdrawn"}}},{"name":"MaxThawingPeriodSet","sig":"MaxThawingPeriodSet(uint64)","inputs":[{"name":"maxThawingPeriod","type":"uint64","indexed":false}],"doc":{"notice":"Emitted when the global maximum thawing period allowed for provisions is set.","params":{"maxThawingPeriod":"The new maximum thawing period"}}},{"name":"OperatorSet","sig":"OperatorSet(address,address,address,bool)","inputs":[{"name":"serviceProvider","type":"address","indexed":true},{"name":"verifier","type":"address","indexed":true},{"name":"operator","type":"address","indexed":true},{"name":"allowed","type":"bool","indexed":false}],"doc":{"notice":"Emitted when an operator is allowed or denied by a service provider for a particular verifier","params":{"allowed":"Whether the operator is allowed or denied","operator":"The address of the operator","serviceProvider":"The address of the service provider","verifier":"The address of the verifier"}}},{"name":"ProvisionCreated","sig":"ProvisionCreated(address,address,uint256,uint32,uint64)","inputs":[{"name":"serviceProvider","type":"address","indexed":true},{"name":"verifier","type":"address","indexed":true},{"name":"tokens","type":"uint256","indexed":false},{"name":"maxVerifierCut","type":"uint32","indexed":false},{"name":"thawingPeriod","type":"uint64","indexed":false}],"doc":{"notice":"Emitted when a service provider provisions staked tokens to a verifier.","params":{"maxVerifierCut":"The maximum cut, expressed in PPM of the slashed amount, that a verifier can take for themselves when slashing","serviceProvider":"The address of the service provider","thawingPeriod":"The period in seconds that the tokens will be thawing before they can be removed from the provision","tokens":"The amount of tokens provisioned","verifier":"The address of the verifier"}}},{"name":"ProvisionIncreased","sig":"ProvisionIncreased(address,address,uint256)","inputs":[{"name":"serviceProvider","type":"address","indexed":true},{"name":"verifier","type":"address","indexed":true},{"name":"tokens","type":"uint256","indexed":false}],"doc":{"notice":"Emitted whenever staked tokens are added to an existing provision","params":{"serviceProvider":"The address of the service provider","tokens":"The amount of tokens added to the provision","verifier":"The address of the verifier"}}},{"name":"ProvisionParametersSet","sig":"ProvisionParametersSet(address,address,uint32,uint64)","inputs":[{"name":"serviceProvider","type":"address","indexed":true},{"name":"verifier","type":"address","indexed":true},{"name":"maxVerifierCut","type":"uint32","indexed":false},{"name":"thawingPeriod","type":"uint64","indexed":false}],"doc":{"notice":"Emitted when a service provider accepts a staged provision parameter update.","params":{"maxVerifierCut":"The new maximum cut, expressed in PPM of the slashed amount, that a verifier can take for themselves when slashing","serviceProvider":"The address of the service provider","thawingPeriod":"The new period in seconds that the tokens will be thawing before they can be removed from the provision","verifier":"The address of the verifier"}}},{"name":"ProvisionParametersStaged","sig":"ProvisionParametersStaged(address,address,uint32,uint64)","inputs":[{"name":"serviceProvider","type":"address","indexed":true},{"name":"verifier","type":"address","indexed":true},{"name":"maxVerifierCut","type":"uint32","indexed":false},{"name":"thawingPeriod","type":"uint64","indexed":false}],"doc":{"notice":"Emitted when a service provider stages a provision parameter update.","params":{"maxVerifierCut":"The proposed maximum cut, expressed in PPM of the slashed amount, that a verifier can take for themselves when slashing","serviceProvider":"The address of the service provider","thawingPeriod":"The proposed period in seconds that the tokens will be thawing before they can be removed from the provision","verifier":"The address of the verifier"}}},{"name":"ProvisionSlashed","sig":"ProvisionSlashed(address,address,uint256)","inputs":[{"name":"serviceProvider","type":"address","indexed":true},{"name":"verifier","type":"address","indexed":true},{"name":"tokens","type":"uint256","indexed":false}],"doc":{"notice":"Emitted when a provision is slashed by a verifier.","params":{"serviceProvider":"The address of the service provider","tokens":"The amount of tokens slashed (note this only represents service provider's slashed stake)","verifier":"The address of the verifier"}}},{"name":"ProvisionThawed","sig":"ProvisionThawed(address,address,uint256)","inputs":[{"name":"serviceProvider","type":"address","indexed":true},{"name":"verifier","type":"address","indexed":true},{"name":"tokens","type":"uint256","indexed":false}],"doc":{"notice":"Emitted when a service provider thaws tokens from a provision.","params":{"serviceProvider":"The address of the service provider","tokens":"The amount of tokens thawed","verifier":"The address of the verifier"}}},{"name":"StakeDelegatedWithdrawn","sig":"StakeDelegatedWithdrawn(address,address,uint256)","inputs":[{"name":"indexer","type":"address","indexed":true},{"name":"delegator","type":"address","indexed":true},{"name":"tokens","type":"uint256","indexed":false}],"doc":{"notice":"Emitted when `delegator` withdrew delegated `tokens` from `indexer` using `withdrawDelegated`.","details":"This event is for the legacy `withdrawDelegated` function, only emitted for pre-horizon undelegations.","params":{"delegator":"The address of the delegator","indexer":"The address of the indexer","tokens":"The amount of tokens withdrawn"}}},{"name":"ThawRequestCreated","sig":"ThawRequestCreated(uint8,address,address,address,uint256,uint64,bytes32,uint256)","inputs":[{"name":"requestType","type":"uint8","indexed":true},{"name":"serviceProvider","type":"address","indexed":true},{"name":"verifier","type":"address","indexed":true},{"name":"owner","type":"address","indexed":false},{"name":"shares","type":"uint256","indexed":false},{"name":"thawingUntil","type":"uint64","indexed":false},{"name":"thawRequestId","type":"bytes32","indexed":false},{"name":"nonce","type":"uint256","indexed":false}],"doc":{"notice":"Emitted when a thaw request is created.","details":"Can be emitted by the service provider when thawing stake or by the delegator when undelegating.","params":{"nonce":"The nonce of the thaw request","owner":"The address of the owner of the thaw request.","requestType":"The type of thaw request","serviceProvider":"The address of the service provider","shares":"The amount of shares being thawed","thawRequestId":"The ID of the thaw request","thawingUntil":"The timestamp until the stake is thawed","verifier":"The address of the verifier"}}},{"name":"ThawRequestFulfilled","sig":"ThawRequestFulfilled(uint8,bytes32,uint256,uint256,uint64,bool)","inputs":[{"name":"requestType","type":"uint8","indexed":true},{"name":"thawRequestId","type":"bytes32","indexed":true},{"name":"tokens","type":"uint256","indexed":false},{"name":"shares","type":"uint256","indexed":false},{"name":"thawingUntil","type":"uint64","indexed":false},{"name":"valid","type":"bool","indexed":false}],"doc":{"notice":"Emitted when a thaw request is fulfilled, meaning the stake is released.","params":{"requestType":"The type of thaw request","shares":"The amount of shares being released","thawRequestId":"The ID of the thaw request","thawingUntil":"The timestamp until the stake has thawed","tokens":"The amount of tokens being released","valid":"Whether the thaw request was valid at the time of fulfillment"}}},{"name":"ThawRequestsFulfilled","sig":"ThawRequestsFulfilled(uint8,address,address,address,uint256,uint256)","inputs":[{"name":"requestType","type":"uint8","indexed":true},{"name":"serviceProvider","type":"address","indexed":true},{"name":"verifier","type":"address","indexed":true},{"name":"owner","type":"address","indexed":false},{"name":"thawRequestsFulfilled","type":"uint256","indexed":false},{"name":"tokens","type":"uint256","indexed":false}],"doc":{"notice":"Emitted when a series of thaw requests are fulfilled.","params":{"owner":"The address of the owner of the thaw requests","requestType":"The type of thaw request","serviceProvider":"The address of the service provider","thawRequestsFulfilled":"The number of thaw requests fulfilled","tokens":"The total amount of tokens being released","verifier":"The address of the verifier"}}},{"name":"TokensDelegated","sig":"TokensDelegated(address,address,address,uint256,uint256)","inputs":[{"name":"serviceProvider","type":"address","indexed":true},{"name":"verifier","type":"address","indexed":true},{"name":"delegator","type":"address","indexed":true},{"name":"tokens","type":"uint256","indexed":false},{"name":"shares","type":"uint256","indexed":false}],"doc":{"notice":"Emitted when tokens are delegated to a provision.","params":{"delegator":"The address of the delegator","serviceProvider":"The address of the service provider","shares":"The amount of shares delegated","tokens":"The amount of tokens delegated","verifier":"The address of the verifier"}}},{"name":"TokensDeprovisioned","sig":"TokensDeprovisioned(address,address,uint256)","inputs":[{"name":"serviceProvider","type":"address","indexed":true},{"name":"verifier","type":"address","indexed":true},{"name":"tokens","type":"uint256","indexed":false}],"doc":{"notice":"Emitted when a service provider removes tokens from a provision.","params":{"serviceProvider":"The address of the service provider","tokens":"The amount of tokens removed","verifier":"The address of the verifier"}}},{"name":"TokensToDelegationPoolAdded","sig":"TokensToDelegationPoolAdded(address,address,uint256)","inputs":[{"name":"serviceProvider","type":"address","indexed":true},{"name":"verifier","type":"address","indexed":true},{"name":"tokens","type":"uint256","indexed":false}],"doc":{"notice":"Emitted when tokens are added to a delegation pool's reserve.","params":{"serviceProvider":"The address of the service provider","tokens":"The amount of tokens withdrawn","verifier":"The address of the verifier"}}},{"name":"TokensUndelegated","sig":"TokensUndelegated(address,address,address,uint256,uint256)","inputs":[{"name":"serviceProvider","type":"address","indexed":true},{"name":"verifier","type":"address","indexed":true},{"name":"delegator","type":"address","indexed":true},{"name":"tokens","type":"uint256","indexed":false},{"name":"shares","type":"uint256","indexed":false}],"doc":{"notice":"Emitted when a delegator undelegates tokens from a provision and starts thawing them.","params":{"delegator":"The address of the delegator","serviceProvider":"The address of the service provider","shares":"The amount of shares undelegated","tokens":"The amount of tokens undelegated","verifier":"The address of the verifier"}}},{"name":"VerifierTokensSent","sig":"VerifierTokensSent(address,address,address,uint256)","inputs":[{"name":"serviceProvider","type":"address","indexed":true},{"name":"verifier","type":"address","indexed":true},{"name":"destination","type":"address","indexed":true},{"name":"tokens","type":"uint256","indexed":false}],"doc":{"notice":"Emitted when the verifier cut is sent to the verifier after slashing a provision.","params":{"destination":"The address where the verifier cut is sent","serviceProvider":"The address of the service provider","tokens":"The amount of tokens sent to the verifier","verifier":"The address of the verifier"}}}],"counts":{"reads":19,"writes":30,"events":25}},{"id":"GraphPayments","name":"GraphPayments","layer":"payments","chain":"L2","core":true,"legacy":false,"address":"0x57E70eC8905E26341d40aF60Dca56cDBA8C166E5","desc":"The settlement router for Horizon payments. When a collector releases funds, GraphPayments splits the amount between the service provider, its delegators, a data-service cut, and a protocol burn, then routes each slice to the right place. It is the single place that knows how a payment is divided.","contractDoc":null,"implements":["IGraphPayments"],"deps":[{"to":"HorizonStaking","label":"pays providers & delegators"},{"to":"L2GraphToken","label":"burns protocol cut"}],"roles":[],"reads":[{"name":"PROTOCOL_PAYMENT_CUT","sig":"PROTOCOL_PAYMENT_CUT()","inputs":[],"outputs":[{"name":"","type":"uint256"}],"mut":"view","doc":{"notice":"Protocol payment cut in PPM","returns":{"_0":"The protocol payment cut in PPM"}}}],"writes":[{"name":"collect","sig":"collect(uint8,address,uint256,address,uint256,address)","inputs":[{"name":"paymentType","type":"uint8"},{"name":"receiver","type":"address"},{"name":"tokens","type":"uint256"},{"name":"dataService","type":"address"},{"name":"dataServiceCut","type":"uint256"},{"name":"receiverDestination","type":"address"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Collects funds from a payer. It will pay cuts to all relevant parties and forward the rest to the receiver destination address. If the destination address is zero the funds are automatically staked to the receiver. Note that the receiver destination address can be set to the receiver address to collect funds on the receiver without re-staking. Note that the collected amount can be zero.","params":{"dataService":"The address of the data service","dataServiceCut":"The data service cut in PPM","paymentType":"The type of payment as defined in {IGraphPayments}","receiver":"The address of the receiver","receiverDestination":"The address where the receiver's payment cut is sent.","tokens":"The amount of tokens being collected."}},"emits":["GraphPaymentCollected"]},{"name":"initialize","sig":"initialize()","inputs":[],"outputs":[],"mut":"nonpayable","doc":{"notice":"Initialize the contract"}}],"events":[{"name":"GraphPaymentCollected","sig":"GraphPaymentCollected(uint8,address,address,address,uint256,uint256,uint256,uint256,uint256,address)","inputs":[{"name":"paymentType","type":"uint8","indexed":true},{"name":"payer","type":"address","indexed":true},{"name":"receiver","type":"address","indexed":false},{"name":"dataService","type":"address","indexed":true},{"name":"tokens","type":"uint256","indexed":false},{"name":"tokensProtocol","type":"uint256","indexed":false},{"name":"tokensDataService","type":"uint256","indexed":false},{"name":"tokensDelegationPool","type":"uint256","indexed":false},{"name":"tokensReceiver","type":"uint256","indexed":false},{"name":"receiverDestination","type":"address","indexed":false}],"doc":{"notice":"Emitted when a payment is collected","params":{"dataService":"The address of the data service","payer":"The address of the payer","paymentType":"The type of payment as defined in {IGraphPayments}","receiver":"The address of the receiver","receiverDestination":"The address where the receiver's payment cut is sent.","tokens":"The total amount of tokens being collected","tokensDataService":"Amount of tokens for the data service","tokensDelegationPool":"Amount of tokens for delegators","tokensProtocol":"Amount of tokens charged as protocol tax","tokensReceiver":"Amount of tokens for the receiver"}}}],"counts":{"reads":1,"writes":2,"events":1}},{"id":"PaymentsEscrow","name":"PaymentsEscrow","layer":"payments","chain":"L2","core":true,"legacy":false,"address":"0x4b5D3Da463F7E076bb7CDF5030960bf123245681","desc":"Holds GRT that payers lock up in advance for a specific (payer, collector, receiver) relationship. Collectors draw down from these escrow accounts as work is delivered. Payers must signal a thawing period before they can withdraw unspent funds, which protects receivers from sudden rug-pulls.","contractDoc":null,"implements":["IPaymentsEscrow"],"deps":[{"to":"GraphPayments","label":"forwards collected funds"},{"to":"L2GraphToken","label":"custodies GRT"}],"roles":[],"reads":[{"name":"escrowAccounts","sig":"escrowAccounts(address,address,address)","inputs":[{"name":"payer","type":"address"},{"name":"collector","type":"address"},{"name":"receiver","type":"address"}],"outputs":[{"name":"balance","type":"uint256"},{"name":"tokensThawing","type":"uint256"},{"name":"thawEndTimestamp","type":"uint256"}],"mut":"view","doc":{"notice":"Escrow account details for payer-collector-receiver tuples","params":{"collector":"The address of the collector","payer":"The address of the payer","receiver":"The address of the receiver"},"returns":{"balance":"The total token balance","thawEndTimestamp":"The timestamp at which thawing period ends (zero if not thawing)","tokensThawing":"The amount of tokens currently being thawed"}}},{"name":"getBalance","sig":"getBalance(address,address,address)","inputs":[{"name":"payer","type":"address"},{"name":"collector","type":"address"},{"name":"receiver","type":"address"}],"outputs":[{"name":"","type":"uint256"}],"mut":"view","doc":{"notice":"Get the balance of a payer-collector-receiver tuple This function will return 0 if the current balance is less than the amount of funds being thawed.","params":{"collector":"The address of the collector","payer":"The address of the payer","receiver":"The address of the receiver"},"returns":{"_0":"The balance of the payer-collector-receiver tuple"}}},{"name":"MAX_WAIT_PERIOD","sig":"MAX_WAIT_PERIOD()","inputs":[],"outputs":[{"name":"","type":"uint256"}],"mut":"view","doc":{"notice":"The maximum thawing period (in seconds) for both escrow withdrawal and collector revocation","returns":{"_0":"The maximum thawing period in seconds"}}},{"name":"WITHDRAW_ESCROW_THAWING_PERIOD","sig":"WITHDRAW_ESCROW_THAWING_PERIOD()","inputs":[],"outputs":[{"name":"","type":"uint256"}],"mut":"view","doc":{"notice":"Thawing period in seconds for escrow funds withdrawal","returns":{"_0":"The thawing period in seconds"}}}],"writes":[{"name":"adjustThaw","sig":"adjustThaw(address,address,uint256,bool)","inputs":[{"name":"collector","type":"address"},{"name":"receiver","type":"address"},{"name":"tokensToThaw","type":"uint256"},{"name":"evenIfTimerReset","type":"bool"}],"outputs":[{"name":"tokensThawing","type":"uint256"}],"mut":"nonpayable","doc":{"notice":"Adjusts the thawing amount with a guard against timer reset. Caps the requested amount to the current balance. When decreasing, the timer is preserved. When increasing, the timer resets; if `evenIfTimerReset` is false and the timer would change, the call is a no-op and returns the current tokensThawing. Setting tokens to 0 cancels the thaw entirely.","params":{"collector":"The address of the collector","evenIfTimerReset":"If true, always proceed. If false, skip increases that would reset the timer.","receiver":"The address of the receiver","tokensToThaw":"The desired amount of tokens to thaw"},"returns":{"tokensThawing":"The resulting amount of tokens thawing after the operation"}},"emits":["CancelThaw","Thaw"]},{"name":"cancelThaw","sig":"cancelThaw(address,address)","inputs":[{"name":"collector","type":"address"},{"name":"receiver","type":"address"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Cancels the thawing of escrow from a payer-collector-receiver's escrow account.","details":"Requirements: - The payer must be thawing funds Emits a {CancelThaw} event.","params":{"collector":"The address of the collector","receiver":"The address of the receiver"}},"emits":["CancelThaw"]},{"name":"collect","sig":"collect(uint8,address,address,uint256,address,uint256,address)","inputs":[{"name":"paymentType","type":"uint8"},{"name":"payer","type":"address"},{"name":"receiver","type":"address"},{"name":"tokens","type":"uint256"},{"name":"dataService","type":"address"},{"name":"dataServiceCut","type":"uint256"},{"name":"receiverDestination","type":"address"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Collects funds from the payer-collector-receiver's escrow and sends them to {GraphPayments} for distribution using the Graph Horizon Payments protocol. The function will revert if there are not enough funds in the escrow. Emits an {EscrowCollected} event","params":{"dataService":"The address of the data service","dataServiceCut":"The data service cut in PPM that {GraphPayments} should send","payer":"The address of the payer","paymentType":"The type of payment being collected as defined in the {IGraphPayments} interface","receiver":"The address of the receiver","receiverDestination":"The address where the receiver's payment should be sent.","tokens":"The amount of tokens to collect"}},"emits":["EscrowCollected"]},{"name":"deposit","sig":"deposit(address,address,uint256)","inputs":[{"name":"collector","type":"address"},{"name":"receiver","type":"address"},{"name":"tokens","type":"uint256"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Deposits funds into the escrow for a payer-collector-receiver tuple, where the payer is the transaction caller.","details":"Emits a {Deposit} event","params":{"collector":"The address of the collector","receiver":"The address of the receiver","tokens":"The amount of tokens to deposit"}},"emits":["Deposit"]},{"name":"depositTo","sig":"depositTo(address,address,address,uint256)","inputs":[{"name":"payer","type":"address"},{"name":"collector","type":"address"},{"name":"receiver","type":"address"},{"name":"tokens","type":"uint256"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Deposits funds into the escrow for a payer-collector-receiver tuple, where the payer can be specified.","details":"Emits a {Deposit} event","params":{"collector":"The address of the collector","payer":"The address of the payer","receiver":"The address of the receiver","tokens":"The amount of tokens to deposit"}},"emits":["Deposit"]},{"name":"initialize","sig":"initialize()","inputs":[],"outputs":[],"mut":"nonpayable","doc":{"notice":"Initialize the contract"}},{"name":"thaw","sig":"thaw(address,address,uint256)","inputs":[{"name":"collector","type":"address"},{"name":"receiver","type":"address"},{"name":"tokens","type":"uint256"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Thaw a specific amount of escrow from a payer-collector-receiver's escrow account. The payer is the transaction caller. Note that repeated calls to this function will overwrite the previous thawing amount and reset the thawing period.","details":"Requirements: - `tokens` must be less than or equal to the available balance Emits a {Thaw} event.","params":{"collector":"The address of the collector","receiver":"The address of the receiver","tokens":"The amount of tokens to thaw"}},"emits":["Thaw"]},{"name":"withdraw","sig":"withdraw(address,address)","inputs":[{"name":"collector","type":"address"},{"name":"receiver","type":"address"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Withdraws all thawed escrow from a payer-collector-receiver's escrow account. The payer is the transaction caller. Note that the withdrawn funds might be less than the thawed amount if there were payment collections in the meantime.","details":"Requirements: - Funds must be thawed Emits a {Withdraw} event","params":{"collector":"The address of the collector","receiver":"The address of the receiver"}},"emits":["Withdraw"]}],"events":[{"name":"CancelThaw","sig":"CancelThaw(address,address,address,uint256,uint256)","inputs":[{"name":"payer","type":"address","indexed":true},{"name":"collector","type":"address","indexed":true},{"name":"receiver","type":"address","indexed":true},{"name":"tokensThawing","type":"uint256","indexed":false},{"name":"thawEndTimestamp","type":"uint256","indexed":false}],"doc":{"notice":"Emitted when a payer cancels an escrow thawing","params":{"collector":"The address of the collector","payer":"The address of the payer","receiver":"The address of the receiver","thawEndTimestamp":"The timestamp at which the thawing period was ending","tokensThawing":"The amount of tokens that were being thawed"}}},{"name":"Deposit","sig":"Deposit(address,address,address,uint256)","inputs":[{"name":"payer","type":"address","indexed":true},{"name":"collector","type":"address","indexed":true},{"name":"receiver","type":"address","indexed":true},{"name":"tokens","type":"uint256","indexed":false}],"doc":{"notice":"Emitted when a payer deposits funds into the escrow for a payer-collector-receiver tuple","params":{"collector":"The address of the collector","payer":"The address of the payer","receiver":"The address of the receiver","tokens":"The amount of tokens deposited"}}},{"name":"EscrowCollected","sig":"EscrowCollected(uint8,address,address,address,uint256,address)","inputs":[{"name":"paymentType","type":"uint8","indexed":true},{"name":"payer","type":"address","indexed":true},{"name":"collector","type":"address","indexed":true},{"name":"receiver","type":"address","indexed":false},{"name":"tokens","type":"uint256","indexed":false},{"name":"receiverDestination","type":"address","indexed":false}],"doc":{"notice":"Emitted when a collector collects funds from the escrow for a payer-collector-receiver tuple","params":{"collector":"The address of the collector","payer":"The address of the payer","paymentType":"The type of payment being collected as defined in the {IGraphPayments} interface","receiver":"The address of the receiver","receiverDestination":"The address where the receiver's payment should be sent.","tokens":"The amount of tokens collected"}}},{"name":"Thaw","sig":"Thaw(address,address,address,uint256,uint256)","inputs":[{"name":"payer","type":"address","indexed":true},{"name":"collector","type":"address","indexed":true},{"name":"receiver","type":"address","indexed":true},{"name":"tokens","type":"uint256","indexed":false},{"name":"thawEndTimestamp","type":"uint256","indexed":false}],"doc":{"notice":"Emitted when a payer thaws funds from the escrow for a payer-collector-receiver tuple","params":{"collector":"The address of the collector","payer":"The address of the payer","receiver":"The address of the receiver","thawEndTimestamp":"The timestamp at which the thawing period ends","tokens":"The amount of tokens being thawed"}}},{"name":"Withdraw","sig":"Withdraw(address,address,address,uint256)","inputs":[{"name":"payer","type":"address","indexed":true},{"name":"collector","type":"address","indexed":true},{"name":"receiver","type":"address","indexed":true},{"name":"tokens","type":"uint256","indexed":false}],"doc":{"notice":"Emitted when a payer withdraws funds from the escrow for a payer-collector-receiver tuple","params":{"collector":"The address of the collector","payer":"The address of the payer","receiver":"The address of the receiver","tokens":"The amount of tokens withdrawn"}}}],"counts":{"reads":4,"writes":8,"events":5}},{"id":"GraphTallyCollector","name":"GraphTallyCollector","layer":"payments","chain":"L2","core":true,"legacy":false,"address":"0x382863e7B662027117449bd2c49285582bbBd21B","desc":"Collects query-fee payments from a signed \"Receipt Aggregate Voucher\" (RAV). A gateway signs a RAV whose total only ever grows; the collector verifies the signature, works out the newly-owed amount since the last RAV, and pulls exactly that from escrow. This is how off-chain query fees settle on-chain.","contractDoc":null,"implements":["IGraphTallyCollector","IPaymentsCollector","IAuthorizable"],"deps":[{"to":"PaymentsEscrow","label":"draws owed query fees"},{"to":"GraphPayments","label":"triggers settlement"}],"roles":[],"reads":[{"name":"encodeRAV","sig":"encodeRAV((bytes32,address,address,address,uint64,uint128,bytes))","inputs":[{"name":"rav","type":"(bytes32,address,address,address,uint64,uint128,bytes)"}],"outputs":[{"name":"","type":"bytes32"}],"mut":"view","doc":{"notice":"Computes the hash of a ReceiptAggregateVoucher (RAV).","params":{"rav":"The RAV for which to compute the hash."},"returns":{"_0":"The hash of the RAV."}}},{"name":"getThawEnd","sig":"getThawEnd(address)","inputs":[{"name":"signer","type":"address"}],"outputs":[{"name":"","type":"uint256"}],"mut":"view","doc":{"notice":"Returns the timestamp at which the thawing period ends for a signer. Returns 0 if the signer is not thawing.","params":{"signer":"The address of the signer"},"returns":{"_0":"The timestamp at which the thawing period ends"}}},{"name":"isAuthorized","sig":"isAuthorized(address,address)","inputs":[{"name":"authorizer","type":"address"},{"name":"signer","type":"address"}],"outputs":[{"name":"","type":"bool"}],"mut":"view","doc":{"notice":"Returns true if the signer is authorized by the authorizer","params":{"authorizer":"The address of the authorizer","signer":"The address of the signer"},"returns":{"_0":"true if the signer is authorized by the authorizer, false otherwise"}}},{"name":"recoverRAVSigner","sig":"recoverRAVSigner(((bytes32,address,address,address,uint64,uint128,bytes),bytes))","inputs":[{"name":"signedRAV","type":"((bytes32,address,address,address,uint64,uint128,bytes),bytes)"}],"outputs":[{"name":"","type":"address"}],"mut":"view","doc":{"notice":"Recovers the signer address of a signed ReceiptAggregateVoucher (RAV).","params":{"signedRAV":"The SignedRAV containing the RAV and its signature."},"returns":{"_0":"The address of the signer."}}},{"name":"REVOKE_AUTHORIZATION_THAWING_PERIOD","sig":"REVOKE_AUTHORIZATION_THAWING_PERIOD()","inputs":[],"outputs":[{"name":"","type":"uint256"}],"mut":"view","doc":{"notice":"The duration (in seconds) for which an authorization is thawing before it can be revoked","returns":{"_0":"The period in seconds"}}}],"writes":[{"name":"authorizeSigner","sig":"authorizeSigner(address,uint256,bytes)","inputs":[{"name":"signer","type":"address"},{"name":"proofDeadline","type":"uint256"},{"name":"proof","type":"bytes"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Authorize a signer to sign on behalf of the authorizer","details":"Requirements: - `signer` must not be already authorized - `proofDeadline` must be greater than the current timestamp - `proof` must be a valid signature from the signer being authorized Emits a {SignerAuthorized} event","params":{"proof":"The proof provided by the signer to be authorized by the authorizer consists of (chain id, verifying contract address, domain, proof deadline, authorizer address)","proofDeadline":"The deadline for the proof provided by the signer","signer":"The address of the signer"}}},{"name":"cancelThawSigner","sig":"cancelThawSigner(address)","inputs":[{"name":"signer","type":"address"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Stops thawing a signer.","details":"Requirements: - `signer` must be thawing and authorized by the function caller Emits a {SignerThawCanceled} event","params":{"signer":"The address of the signer to cancel thawing"}}},{"name":"collect","sig":"collect(uint8,bytes,uint256)","inputs":[{"name":"paymentType","type":"uint8"},{"name":"data","type":"bytes"},{"name":"tokensToCollect","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}],"mut":"nonpayable","doc":{"notice":"See {IPaymentsCollector.collect} This variant adds the ability to partially collect a RAV by specifying the amount of tokens to collect. Requirements: - The amount of tokens to collect must be less than or equal to the total amount of tokens in the RAV minus the tokens already collected.","params":{"data":"Additional data required for the payment collection. Encoded as follows: - SignedRAV `signedRAV`: The signed RAV - uint256 `dataServiceCut`: The data service cut in PPM - address `receiverDestination`: The address where the receiver's payment should be sent.","paymentType":"The payment type to collect","tokensToCollect":"The amount of tokens to collect"},"returns":{"_0":"The amount of tokens collected"}},"emits":["PaymentCollected","RAVCollected"]},{"name":"collect","sig":"collect(uint8,bytes)","inputs":[{"name":"paymentType","type":"uint8"},{"name":"data","type":"bytes"}],"outputs":[{"name":"","type":"uint256"}],"mut":"nonpayable","doc":{"notice":"Initiate a payment collection through the payments protocol","details":"This function should require the caller to present some form of evidence of the payer's debt to the receiver. The collector should validate this evidence and, if valid, collect the payment. Emits a {PaymentCollected} event","params":{"data":"Additional data required for the payment collection. Will vary depending on the collector implementation.","paymentType":"The payment type to collect, as defined by {IGraphPayments}"},"returns":{"_0":"The amount of tokens collected"}},"emits":["PaymentCollected","RAVCollected"]},{"name":"revokeAuthorizedSigner","sig":"revokeAuthorizedSigner(address)","inputs":[{"name":"signer","type":"address"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Revokes a signer if thawed.","details":"Requirements: - `signer` must be thawed and authorized by the function caller Emits a {SignerRevoked} event","params":{"signer":"The address of the signer"}}},{"name":"thawSigner","sig":"thawSigner(address)","inputs":[{"name":"signer","type":"address"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Starts thawing a signer to be de-authorized","details":"Thawing a signer signals that signatures from that signer will soon be deemed invalid. Once a signer is thawed, they should be viewed as revoked regardless of their revocation status. If a signer is already thawing and this function is called, the thawing period is reset. Requirements: - `signer` must be authorized by the authorizer calling this function Emits a {SignerThawing} event","params":{"signer":"The address of the signer to thaw"}}}],"events":[{"name":"PaymentCollected","sig":"PaymentCollected(uint8,bytes32,address,address,address,uint256)","inputs":[{"name":"paymentType","type":"uint8","indexed":false},{"name":"collectionId","type":"bytes32","indexed":true},{"name":"payer","type":"address","indexed":true},{"name":"receiver","type":"address","indexed":false},{"name":"dataService","type":"address","indexed":true},{"name":"tokens","type":"uint256","indexed":false}],"doc":{"notice":"Emitted when a payment is collected","params":{"collectionId":"The id for the collection. Can be used at the discretion of the collector to group multiple payments.","dataService":"The address of the data service","payer":"The address of the payer","paymentType":"The payment type collected as defined by {IGraphPayments}","receiver":"The address of the receiver","tokens":"The amount of tokens being collected"}}},{"name":"RAVCollected","sig":"RAVCollected(bytes32,address,address,address,uint64,uint128,bytes,bytes)","inputs":[{"name":"collectionId","type":"bytes32","indexed":true},{"name":"payer","type":"address","indexed":true},{"name":"serviceProvider","type":"address","indexed":false},{"name":"dataService","type":"address","indexed":true},{"name":"timestampNs","type":"uint64","indexed":false},{"name":"valueAggregate","type":"uint128","indexed":false},{"name":"metadata","type":"bytes","indexed":false},{"name":"signature","type":"bytes","indexed":false}],"doc":{"notice":"Emitted when a RAV is collected","params":{"collectionId":"The ID of the collection \"bucket\" the RAV belongs to.","dataService":"The address of the data service","metadata":"Arbitrary metadata","payer":"The address of the payer","serviceProvider":"The address of the service provider","signature":"The signature of the RAV","timestampNs":"The timestamp of the RAV","valueAggregate":"The total amount owed to the service provider"}}},{"name":"SignerAuthorized","sig":"SignerAuthorized(address,address)","inputs":[{"name":"authorizer","type":"address","indexed":true},{"name":"signer","type":"address","indexed":true}],"doc":{"notice":"Emitted when a signer is authorized to sign for a authorizer","params":{"authorizer":"The address of the authorizer","signer":"The address of the signer"}}},{"name":"SignerRevoked","sig":"SignerRevoked(address,address)","inputs":[{"name":"authorizer","type":"address","indexed":true},{"name":"signer","type":"address","indexed":true}],"doc":{"notice":"Emitted when a signer has been revoked after thawing","params":{"authorizer":"The address of the authorizer revoking the signer","signer":"The address of the signer"}}},{"name":"SignerThawCanceled","sig":"SignerThawCanceled(address,address,uint256)","inputs":[{"name":"authorizer","type":"address","indexed":true},{"name":"signer","type":"address","indexed":true},{"name":"thawEndTimestamp","type":"uint256","indexed":false}],"doc":{"notice":"Emitted when the thawing of a signer is cancelled","params":{"authorizer":"The address of the authorizer cancelling the thawing","signer":"The address of the signer","thawEndTimestamp":"The timestamp at which the thawing period was scheduled to end"}}},{"name":"SignerThawing","sig":"SignerThawing(address,address,uint256)","inputs":[{"name":"authorizer","type":"address","indexed":true},{"name":"signer","type":"address","indexed":true},{"name":"thawEndTimestamp","type":"uint256","indexed":false}],"doc":{"notice":"Emitted when a signer is thawed to be de-authorized","params":{"authorizer":"The address of the authorizer thawing the signer","signer":"The address of the signer to thaw","thawEndTimestamp":"The timestamp at which the thawing period ends"}}}],"counts":{"reads":5,"writes":6,"events":6}},{"id":"RecurringCollector","name":"RecurringCollector","layer":"payments","chain":"L2","core":true,"legacy":false,"address":"0x0b18befc60455121ad66ae6e4a647955fcde3900","desc":"Collects payments on a schedule from a signed \"Recurring Collection Agreement\" (RCA) rather than a one-off voucher. It enforces a minimum gap between collections and can require eligibility checks and payer callbacks. This is the engine behind indexing-fee agreements that pay out repeatedly over time.","contractDoc":null,"implements":["IRecurringCollector","IAgreementCollector","IPaymentsCollector","IAuthorizable"],"deps":[{"to":"PaymentsEscrow","label":"draws scheduled payments"},{"to":"GraphPayments","label":"triggers settlement"}],"roles":[],"reads":[{"name":"generateAgreementId","sig":"generateAgreementId(address,address,address,uint64,uint256)","inputs":[{"name":"payer","type":"address"},{"name":"dataService","type":"address"},{"name":"serviceProvider","type":"address"},{"name":"deadline","type":"uint64"},{"name":"nonce","type":"uint256"}],"outputs":[{"name":"agreementId","type":"bytes16"}],"mut":"pure","doc":{"notice":"Generate a deterministic agreement ID from agreement parameters","params":{"dataService":"The address of the data service","deadline":"The deadline for accepting the agreement","nonce":"A unique nonce for preventing collisions","payer":"The address of the payer","serviceProvider":"The address of the service provider"},"returns":{"_0":"The deterministically generated agreement ID"}}},{"name":"getAgreement","sig":"getAgreement(bytes16)","inputs":[{"name":"agreementId","type":"bytes16"}],"outputs":[{"name":"","type":"(address,uint64,uint32,address,uint64,uint32,address,uint64,uint32,uint256,uint256,bytes32,uint64,uint16,uint8)"}],"mut":"view","doc":{"notice":"Gets an agreement.","params":{"agreementId":"The ID of the agreement to retrieve."},"returns":{"_0":"The AgreementData struct containing the agreement's data."}}},{"name":"getAgreementDetails","sig":"getAgreementDetails(bytes16,uint256)","inputs":[{"name":"agreementId","type":"bytes16"},{"name":"index","type":"uint256"}],"outputs":[{"name":"","type":"(bytes16,address,address,address,bytes32,uint16)"}],"mut":"view","doc":{"notice":"Get agreement details at a given version index.","details":"Versions are enumerated from 0. VERSION_CURRENT is the active version (or pre-acceptance offer); VERSION_NEXT is the queued pending update, if any. Empty details are returned when no version exists at the requested index — callers can iterate versions until reaching an empty result.","params":{"agreementId":"The ID of the agreement","index":"Version index (VERSION_CURRENT, VERSION_NEXT, or higher if the implementation supports more)"},"returns":{"_0":"Agreement details including participants, version hash, and state flags"}}},{"name":"getAgreementOfferAt","sig":"getAgreementOfferAt(bytes16,uint256)","inputs":[{"name":"agreementId","type":"bytes16"},{"name":"index","type":"uint256"}],"outputs":[{"name":"offerType","type":"uint8"},{"name":"offerData","type":"bytes"}],"mut":"view","doc":{"notice":"Original offer data for a given version index, enabling independent access and hash verification.","details":"Returns the offer type and the ABI-encoded original struct so callers can decode and rehash to verify the version hash returned by getAgreementDetails. Version semantics mirror getAgreementDetails, but empty data is returned when the version's offer was not stored (e.g. signed acceptance without a prior offer(), or overwritten by a later update).","params":{"agreementId":"The ID of the agreement","index":"Version index (VERSION_CURRENT, VERSION_NEXT, or higher if supported)"},"returns":{"offerData":"ABI-encoded original offer struct, or empty when offerType is OFFER_TYPE_NONE","offerType":"OFFER_TYPE_NEW, OFFER_TYPE_UPDATE, or OFFER_TYPE_NONE when no offer is stored"}}},{"name":"getCollectionInfo","sig":"getCollectionInfo(bytes16)","inputs":[{"name":"agreementId","type":"bytes16"}],"outputs":[{"name":"isCollectable","type":"bool"},{"name":"collectionSeconds","type":"uint256"},{"name":"reason","type":"uint8"}],"mut":"view","doc":{"notice":"Get collection info for an agreement","params":{"agreementId":"The agreement id"},"returns":{"collectionSeconds":"The valid collection duration in seconds (0 if not collectable)","isCollectable":"Whether the agreement is in a valid state that allows collection attempts, not that there are necessarily funds available to collect.","reason":"The reason why the agreement is not collectable (None if collectable)"}}},{"name":"getMaxNextClaim","sig":"getMaxNextClaim(bytes16,uint8)","inputs":[{"name":"agreementId","type":"bytes16"},{"name":"scope","type":"uint8"}],"outputs":[{"name":"","type":"uint256"}],"mut":"view","doc":{"notice":"Get the maximum tokens collectable for an agreement, scoped by active and/or pending terms.","params":{"agreementId":"The ID of the agreement","scope":"Bitmask: 1 = active terms, 2 = pending terms, 3 = max of both"},"returns":{"_0":"The maximum tokens that could be collected under the requested scope"}}},{"name":"getMaxNextClaim","sig":"getMaxNextClaim(bytes16)","inputs":[{"name":"agreementId","type":"bytes16"}],"outputs":[{"name":"","type":"uint256"}],"mut":"view","doc":{"notice":"Convenience overload: returns max of both active and pending terms.","details":"Computes the worst-case (maximum possible) claim amount based on current on-chain agreement state. For active agreements, uses `endsAt` as the upper bound (not block.timestamp). Returns 0 for NotAccepted, CanceledByServiceProvider, or fully expired agreements.","params":{"agreementId":"The ID of the agreement"},"returns":{"_0":"The maximum tokens that could be collected"}}},{"name":"getThawEnd","sig":"getThawEnd(address)","inputs":[{"name":"signer","type":"address"}],"outputs":[{"name":"","type":"uint256"}],"mut":"view","doc":{"notice":"Returns the timestamp at which the thawing period ends for a signer. Returns 0 if the signer is not thawing.","params":{"signer":"The address of the signer"},"returns":{"_0":"The timestamp at which the thawing period ends"}}},{"name":"hashRCA","sig":"hashRCA((uint64,uint64,address,address,address,uint256,uint256,uint32,uint32,uint16,uint256,bytes))","inputs":[{"name":"rca","type":"(uint64,uint64,address,address,address,uint256,uint256,uint32,uint32,uint16,uint256,bytes)"}],"outputs":[{"name":"","type":"bytes32"}],"mut":"view","doc":{"notice":"Computes the hash of a RecurringCollectionAgreement (RCA).","params":{"rca":"The RCA for which to compute the hash."},"returns":{"_0":"The hash of the RCA."}}},{"name":"hashRCAU","sig":"hashRCAU((bytes16,uint64,uint64,uint256,uint256,uint32,uint32,uint16,uint32,bytes))","inputs":[{"name":"rcau","type":"(bytes16,uint64,uint64,uint256,uint256,uint32,uint32,uint16,uint32,bytes)"}],"outputs":[{"name":"","type":"bytes32"}],"mut":"view","doc":{"notice":"Computes the hash of a RecurringCollectionAgreementUpdate (RCAU).","params":{"rcau":"The RCAU for which to compute the hash."},"returns":{"_0":"The hash of the RCAU."}}},{"name":"isAuthorized","sig":"isAuthorized(address,address)","inputs":[{"name":"authorizer","type":"address"},{"name":"signer","type":"address"}],"outputs":[{"name":"","type":"bool"}],"mut":"view","doc":{"notice":"Returns true if the signer is authorized by the authorizer","params":{"authorizer":"The address of the authorizer","signer":"The address of the signer"},"returns":{"_0":"true if the signer is authorized by the authorizer, false otherwise"}}},{"name":"pauseGuardians","sig":"pauseGuardians(address)","inputs":[{"name":"pauseGuardian","type":"address"}],"outputs":[{"name":"","type":"bool"}],"mut":"view","doc":{"notice":"Returns the status of a pause guardian.","params":{"pauseGuardian":"The address to check"},"returns":{"_0":"Whether the address is a pause guardian"}}},{"name":"recoverRCASigner","sig":"recoverRCASigner((uint64,uint64,address,address,address,uint256,uint256,uint32,uint32,uint16,uint256,bytes),bytes)","inputs":[{"name":"rca","type":"(uint64,uint64,address,address,address,uint256,uint256,uint32,uint32,uint16,uint256,bytes)"},{"name":"signature","type":"bytes"}],"outputs":[{"name":"","type":"address"}],"mut":"view","doc":{"notice":"Recovers the signer address of a signed RecurringCollectionAgreement (RCA).","params":{"rca":"The RCA whose hash was signed.","signature":"The ECDSA signature bytes."},"returns":{"_0":"The address of the signer."}}},{"name":"recoverRCAUSigner","sig":"recoverRCAUSigner((bytes16,uint64,uint64,uint256,uint256,uint32,uint32,uint16,uint32,bytes),bytes)","inputs":[{"name":"rcau","type":"(bytes16,uint64,uint64,uint256,uint256,uint32,uint32,uint16,uint32,bytes)"},{"name":"signature","type":"bytes"}],"outputs":[{"name":"","type":"address"}],"mut":"view","doc":{"notice":"Recovers the signer address of a signed RecurringCollectionAgreementUpdate (RCAU).","params":{"rcau":"The RCAU whose hash was signed.","signature":"The ECDSA signature bytes."},"returns":{"_0":"The address of the signer."}}},{"name":"REVOKE_AUTHORIZATION_THAWING_PERIOD","sig":"REVOKE_AUTHORIZATION_THAWING_PERIOD()","inputs":[],"outputs":[{"name":"","type":"uint256"}],"mut":"view","doc":{"notice":"The duration (in seconds) for which an authorization is thawing before it can be revoked","returns":{"_0":"The period in seconds"}}}],"writes":[{"name":"accept","sig":"accept((uint64,uint64,address,address,address,uint256,uint256,uint32,uint32,uint16,uint256,bytes),bytes)","inputs":[{"name":"rca","type":"(uint64,uint64,address,address,address,uint256,uint256,uint32,uint32,uint16,uint256,bytes)"},{"name":"signature","type":"bytes"}],"outputs":[{"name":"agreementId","type":"bytes16"}],"mut":"nonpayable","doc":{"notice":"Accept a Recurring Collection Agreement.","details":"Caller must be the data service the RCA was issued to. Idempotent: re-accepting an already-accepted agreement with the same RCA hash is a no-op (skips deadline and auth checks). Otherwise enforces `block.timestamp <= rca.deadline` and authorizes via one of: - `signature` non-empty: ECDSA signature recovery against the payer (or its authorized signer); - `signature` empty: the payer must have previously stored an offer for the same RCA hash via {IAgreementCollector.offer}; the stored hash is checked instead of a signature.","params":{"rca":"The Recurring Collection Agreement to accept","signature":"ECDSA signature bytes, or empty for contract-approved agreements"},"returns":{"agreementId":"The deterministically generated agreement ID"}},"access":{"roles":[],"mods":["whenNotPaused"]},"emits":["OfferStored","AgreementAccepted"]},{"name":"authorizeSigner","sig":"authorizeSigner(address,uint256,bytes)","inputs":[{"name":"signer","type":"address"},{"name":"proofDeadline","type":"uint256"},{"name":"proof","type":"bytes"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Authorize a signer to sign on behalf of the authorizer","details":"Requirements: - `signer` must not be already authorized - `proofDeadline` must be greater than the current timestamp - `proof` must be a valid signature from the signer being authorized Emits a {SignerAuthorized} event","params":{"proof":"The proof provided by the signer to be authorized by the authorizer consists of (chain id, verifying contract address, domain, proof deadline, authorizer address)","proofDeadline":"The deadline for the proof provided by the signer","signer":"The address of the signer"}}},{"name":"cancel","sig":"cancel(bytes16,uint8)","inputs":[{"name":"agreementId","type":"bytes16"},{"name":"by","type":"uint8"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Cancel a Recurring Collection Agreement.","details":"Caller must be the data service for the agreement; the agreement must be in the Accepted state. Records `canceledAt = block.timestamp` and transitions to CanceledByPayer or CanceledByServiceProvider per `by`. Any pending RCAU offer whose hash differs from the active terms is dropped.","params":{"agreementId":"The agreement's ID.","by":"The party that is canceling the agreement."}},"access":{"roles":[],"mods":["whenNotPaused"]},"emits":["AgreementCanceled","OfferCancelled"]},{"name":"cancel","sig":"cancel(bytes16,bytes32,uint16)","inputs":[{"name":"agreementId","type":"bytes16"},{"name":"termsHash","type":"bytes32"},{"name":"options","type":"uint16"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Cancel an agreement, revoke a pending offer, or invalidate a signed offer.","details":"Targets the payer side only; extending cancel to data-service or service-provider callers is left for a future revision.","params":{"agreementId":"The agreement's ID. For SCOPE_SIGNED, only blocks accept/update when the agreementId matches; passing bytes16(0) undoes a previous cancellation.","options":"Bitmask — SCOPE_ACTIVE (1) active terms, SCOPE_PENDING (2) pending offers, SCOPE_SIGNED (4) signed offers.","termsHash":"EIP-712 hash identifying which terms to cancel."}},"access":{"roles":[],"mods":["whenNotPaused"]},"emits":["AgreementCanceled","OfferCancelled"]},{"name":"cancelThawSigner","sig":"cancelThawSigner(address)","inputs":[{"name":"signer","type":"address"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Stops thawing a signer.","details":"Requirements: - `signer` must be thawing and authorized by the function caller Emits a {SignerThawCanceled} event","params":{"signer":"The address of the signer to cancel thawing"}}},{"name":"collect","sig":"collect(uint8,bytes)","inputs":[{"name":"paymentType","type":"uint8"},{"name":"data","type":"bytes"}],"outputs":[{"name":"","type":"uint256"}],"mut":"nonpayable","doc":{"notice":"Initiate a payment collection through the payments protocol","details":"Caller must be the data service the RCA was issued to.","params":{"data":"Additional data required for the payment collection. Will vary depending on the collector implementation.","paymentType":"The payment type to collect, as defined by {IGraphPayments}"},"returns":{"_0":"The amount of tokens collected"}},"access":{"roles":[],"mods":["whenNotPaused"]},"emits":["PaymentCollected","RCACollected","PayerCallbackFailed"]},{"name":"offer","sig":"offer(uint8,bytes,uint16)","inputs":[{"name":"offerType","type":"uint8"},{"name":"data","type":"bytes"},{"name":"options","type":"uint16"}],"outputs":[{"name":"","type":"(bytes16,address,address,address,bytes32,uint16)"}],"mut":"nonpayable","doc":{"notice":"Offer a new agreement or update an existing one.","details":"Returns {AgreementDetails} for the just-stored offer. The `state` field describes that version in context of its agreement (see {AgreementDetails}): version-specific flags (REGISTERED, ACCEPTED, UPDATE, SETTLED) are set when they apply to the offered version; agreement-wide flags (NOTICE_GIVEN, BY_*) reflect current agreement state.","params":{"data":"ABI-encoded offer data","offerType":"The type of offer (OFFER_TYPE_NEW or OFFER_TYPE_UPDATE)","options":"Bitmask reserved for implementation-specific options; pass 0 when none apply. No flags are defined at the interface level."},"returns":{"details":"Agreement details including participants and version hash"}},"access":{"roles":[],"mods":["whenNotPaused"]},"emits":["OfferStored"]},{"name":"pause","sig":"pause()","inputs":[],"outputs":[],"mut":"nonpayable","doc":{"notice":"Pauses the collector, blocking accept, update, collect, and cancel.","details":"Only callable by a pause guardian. Uses OpenZeppelin Pausable."}},{"name":"revokeAuthorizedSigner","sig":"revokeAuthorizedSigner(address)","inputs":[{"name":"signer","type":"address"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Revokes a signer if thawed.","details":"Requirements: - `signer` must be thawed and authorized by the function caller Emits a {SignerRevoked} event","params":{"signer":"The address of the signer"}}},{"name":"thawSigner","sig":"thawSigner(address)","inputs":[{"name":"signer","type":"address"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Starts thawing a signer to be de-authorized","details":"Thawing a signer signals that signatures from that signer will soon be deemed invalid. Once a signer is thawed, they should be viewed as revoked regardless of their revocation status. If a signer is already thawing and this function is called, the thawing period is reset. Requirements: - `signer` must be authorized by the authorizer calling this function Emits a {SignerThawing} event","params":{"signer":"The address of the signer to thaw"}}},{"name":"unpause","sig":"unpause()","inputs":[],"outputs":[],"mut":"nonpayable","doc":{"notice":"Unpauses the collector.","details":"Only callable by a pause guardian."}},{"name":"update","sig":"update((bytes16,uint64,uint64,uint256,uint256,uint32,uint32,uint16,uint32,bytes),bytes)","inputs":[{"name":"rcau","type":"(bytes16,uint64,uint64,uint256,uint256,uint32,uint32,uint16,uint32,bytes)"},{"name":"signature","type":"bytes"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Update a Recurring Collection Agreement.","details":"Updated pricing terms apply immediately and affect the next collection for the entire period since lastCollectionAt.","params":{"rcau":"The Recurring Collection Agreement Update to apply","signature":"ECDSA signature bytes, or empty for contract-approved updates"}},"access":{"roles":[],"mods":["whenNotPaused"]},"emits":["OfferStored","AgreementUpdated"]}],"events":[{"name":"AgreementAccepted","sig":"AgreementAccepted(address,address,address,bytes16,uint64,uint256,uint256,uint32,uint32)","inputs":[{"name":"dataService","type":"address","indexed":true},{"name":"payer","type":"address","indexed":true},{"name":"serviceProvider","type":"address","indexed":true},{"name":"agreementId","type":"bytes16","indexed":false},{"name":"endsAt","type":"uint64","indexed":false},{"name":"maxInitialTokens","type":"uint256","indexed":false},{"name":"maxOngoingTokensPerSecond","type":"uint256","indexed":false},{"name":"minSecondsPerCollection","type":"uint32","indexed":false},{"name":"maxSecondsPerCollection","type":"uint32","indexed":false}],"doc":{"notice":"Emitted when an agreement is accepted","params":{"agreementId":"The agreement ID","dataService":"The address of the data service","endsAt":"The timestamp when the agreement ends","maxInitialTokens":"The maximum amount of tokens that can be collected in the first collection","maxOngoingTokensPerSecond":"The maximum amount of tokens that can be collected per second","maxSecondsPerCollection":"The maximum seconds of service that can be collected in a single collection","minSecondsPerCollection":"The minimum amount of seconds that must pass between collections","payer":"The address of the payer","serviceProvider":"The address of the service provider"}}},{"name":"AgreementCanceled","sig":"AgreementCanceled(address,address,address,bytes16,uint8)","inputs":[{"name":"dataService","type":"address","indexed":true},{"name":"payer","type":"address","indexed":true},{"name":"serviceProvider","type":"address","indexed":true},{"name":"agreementId","type":"bytes16","indexed":false},{"name":"canceledBy","type":"uint8","indexed":false}],"doc":{"notice":"Emitted when an agreement is canceled","params":{"agreementId":"The agreement ID","canceledBy":"The party that canceled the agreement","dataService":"The address of the data service","payer":"The address of the payer","serviceProvider":"The address of the service provider"}}},{"name":"AgreementUpdated","sig":"AgreementUpdated(address,address,address,bytes16,uint64,uint256,uint256,uint32,uint32)","inputs":[{"name":"dataService","type":"address","indexed":true},{"name":"payer","type":"address","indexed":true},{"name":"serviceProvider","type":"address","indexed":true},{"name":"agreementId","type":"bytes16","indexed":false},{"name":"endsAt","type":"uint64","indexed":false},{"name":"maxInitialTokens","type":"uint256","indexed":false},{"name":"maxOngoingTokensPerSecond","type":"uint256","indexed":false},{"name":"minSecondsPerCollection","type":"uint32","indexed":false},{"name":"maxSecondsPerCollection","type":"uint32","indexed":false}],"doc":{"notice":"Emitted when an agreement is updated","params":{"agreementId":"The agreement ID","dataService":"The address of the data service","endsAt":"The timestamp when the agreement ends","maxInitialTokens":"The maximum amount of tokens that can be collected in the first collection","maxOngoingTokensPerSecond":"The maximum amount of tokens that can be collected per second","maxSecondsPerCollection":"The maximum seconds of service that can be collected in a single collection","minSecondsPerCollection":"The minimum amount of seconds that must pass between collections","payer":"The address of the payer","serviceProvider":"The address of the service provider"}}},{"name":"OfferCancelled","sig":"OfferCancelled(address,bytes16,bytes32)","inputs":[{"name":"caller","type":"address","indexed":true},{"name":"agreementId","type":"bytes16","indexed":true},{"name":"hash","type":"bytes32","indexed":true}],"doc":{"notice":"Emitted when a stored offer is cancelled via {IAgreementCollector.cancel}.","details":"Fired for SCOPE_PENDING cancellations that delete a stored RCA or RCAU offer entry.","params":{"agreementId":"The agreement ID","caller":"The msg.sender of the cancel call (the payer for SCOPE_PENDING)","hash":"The EIP-712 hash of the cancelled offer"}}},{"name":"OfferStored","sig":"OfferStored(bytes16,address,uint8,bytes32)","inputs":[{"name":"agreementId","type":"bytes16","indexed":true},{"name":"payer","type":"address","indexed":true},{"name":"offerType","type":"uint8","indexed":true},{"name":"offerHash","type":"bytes32","indexed":false}],"doc":{"notice":"Emitted when an offer (RCA or RCAU) is stored via {IAgreementCollector.offer}","params":{"agreementId":"The agreement ID","offerHash":"The EIP-712 hash of the stored offer","offerType":"OFFER_TYPE_NEW or OFFER_TYPE_UPDATE","payer":"The payer that stored the offer"}}},{"name":"PauseGuardianSet","sig":"PauseGuardianSet(address,bool)","inputs":[{"name":"account","type":"address","indexed":true},{"name":"allowed","type":"bool","indexed":false}],"doc":{"notice":"Emitted when a pause guardian is set","params":{"account":"The address of the pause guardian","allowed":"The allowed status"}}},{"name":"PayerCallbackFailed","sig":"PayerCallbackFailed(bytes16,address,uint8)","inputs":[{"name":"agreementId","type":"bytes16","indexed":true},{"name":"payer","type":"address","indexed":true},{"name":"stage","type":"uint8","indexed":false}],"doc":{"notice":"Emitted when a payer callback (beforeCollection / afterCollection) reverts.","details":"The try/catch ensures provider liveness but this event enables off-chain monitoring to detect repeated failures and trigger reconciliation.","params":{"agreementId":"The agreement ID","payer":"The payer contract whose callback reverted","stage":"Whether the failure occurred before or after collection"}}},{"name":"PaymentCollected","sig":"PaymentCollected(uint8,bytes32,address,address,address,uint256)","inputs":[{"name":"paymentType","type":"uint8","indexed":false},{"name":"collectionId","type":"bytes32","indexed":true},{"name":"payer","type":"address","indexed":true},{"name":"receiver","type":"address","indexed":false},{"name":"dataService","type":"address","indexed":true},{"name":"tokens","type":"uint256","indexed":false}],"doc":{"notice":"Emitted when a payment is collected","params":{"collectionId":"The id for the collection. Can be used at the discretion of the collector to group multiple payments.","dataService":"The address of the data service","payer":"The address of the payer","paymentType":"The payment type collected as defined by {IGraphPayments}","receiver":"The address of the receiver","tokens":"The amount of tokens being collected"}}},{"name":"RCACollected","sig":"RCACollected(address,address,address,bytes16,bytes32,uint256,uint256)","inputs":[{"name":"dataService","type":"address","indexed":true},{"name":"payer","type":"address","indexed":true},{"name":"serviceProvider","type":"address","indexed":true},{"name":"agreementId","type":"bytes16","indexed":false},{"name":"collectionId","type":"bytes32","indexed":false},{"name":"tokens","type":"uint256","indexed":false},{"name":"dataServiceCut","type":"uint256","indexed":false}],"doc":{"notice":"Emitted when an RCA is collected","params":{"agreementId":"The agreement ID","collectionId":"The collection ID","dataService":"The address of the data service","dataServiceCut":"The tokens cut for the data service","payer":"The address of the payer","serviceProvider":"The address of the service provider","tokens":"The amount of tokens collected"}}},{"name":"SignerAuthorized","sig":"SignerAuthorized(address,address)","inputs":[{"name":"authorizer","type":"address","indexed":true},{"name":"signer","type":"address","indexed":true}],"doc":{"notice":"Emitted when a signer is authorized to sign for a authorizer","params":{"authorizer":"The address of the authorizer","signer":"The address of the signer"}}},{"name":"SignerRevoked","sig":"SignerRevoked(address,address)","inputs":[{"name":"authorizer","type":"address","indexed":true},{"name":"signer","type":"address","indexed":true}],"doc":{"notice":"Emitted when a signer has been revoked after thawing","params":{"authorizer":"The address of the authorizer revoking the signer","signer":"The address of the signer"}}},{"name":"SignerThawCanceled","sig":"SignerThawCanceled(address,address,uint256)","inputs":[{"name":"authorizer","type":"address","indexed":true},{"name":"signer","type":"address","indexed":true},{"name":"thawEndTimestamp","type":"uint256","indexed":false}],"doc":{"notice":"Emitted when the thawing of a signer is cancelled","params":{"authorizer":"The address of the authorizer cancelling the thawing","signer":"The address of the signer","thawEndTimestamp":"The timestamp at which the thawing period was scheduled to end"}}},{"name":"SignerThawing","sig":"SignerThawing(address,address,uint256)","inputs":[{"name":"authorizer","type":"address","indexed":true},{"name":"signer","type":"address","indexed":true},{"name":"thawEndTimestamp","type":"uint256","indexed":false}],"doc":{"notice":"Emitted when a signer is thawed to be de-authorized","params":{"authorizer":"The address of the authorizer thawing the signer","signer":"The address of the signer to thaw","thawEndTimestamp":"The timestamp at which the thawing period ends"}}}],"counts":{"reads":15,"writes":12,"events":13}},{"id":"SubgraphService","name":"SubgraphService","layer":"service","chain":"L2","core":true,"legacy":false,"address":"0xc24A3dAC5d06d771f657A48B20cE1a671B78f26b","desc":"The data service indexers register with to serve subgraphs under Horizon. Indexers provision stake here, open allocations against subgraph deployments, present proofs of indexing (POIs) to claim indexing rewards, and collect query fees. It ties together staking, payments, curation and rewards for the indexing business.","contractDoc":null,"implements":["ISubgraphService","IDataService","IDataServiceFees","IDataServicePausable","IRewardsIssuer"],"deps":[{"to":"HorizonStaking","label":"reads provisions, slashes"},{"to":"GraphTallyCollector","label":"collects query fees"},{"to":"RecurringCollector","label":"collects indexing fees"},{"to":"Curation","label":"pays curation cut"},{"to":"RewardsManager","label":"claims indexing rewards"},{"to":"GraphPayments","label":"defines payment types","kind":"registry"}],"roles":[],"reads":[{"name":"curationFeesCut","sig":"curationFeesCut()","inputs":[],"outputs":[{"name":"","type":"uint256"}],"mut":"view","doc":{"notice":"The cut curators take from query fee payments. In PPM.","returns":{"_0":"The curation fees cut"}}},{"name":"encodeAllocationProof","sig":"encodeAllocationProof(address,address)","inputs":[{"name":"indexer","type":"address"},{"name":"allocationId","type":"address"}],"outputs":[{"name":"","type":"bytes32"}],"mut":"view","doc":{"notice":"Encodes the allocation proof for EIP712 signing","params":{"allocationId":"The id of the allocation","indexer":"The address of the indexer"},"returns":{"_0":"The encoded allocation proof"}}},{"name":"getAllocation","sig":"getAllocation(address)","inputs":[{"name":"allocationId","type":"address"}],"outputs":[{"name":"","type":"(address,bytes32,uint256,uint256,uint256,uint256,uint256,uint256,uint256)"}],"mut":"view","doc":{"notice":"Gets the details of an allocation For legacy allocations use {getLegacyAllocation}","params":{"allocationId":"The id of the allocation"},"returns":{"_0":"The allocation details"}}},{"name":"getBlockClosingAllocationWithActiveAgreement","sig":"getBlockClosingAllocationWithActiveAgreement()","inputs":[],"outputs":[{"name":"enabled","type":"bool"}],"mut":"view","doc":{"notice":"Whether closing an allocation with an active agreement is blocked","returns":{"enabled":"True if blocking is enabled"}}},{"name":"getCuration","sig":"getCuration()","inputs":[],"outputs":[{"name":"","type":"address"}],"mut":"view","doc":{"notice":"Gets the address of the curation contract","returns":{"_0":"The address of the curation contract"}}},{"name":"getDelegationRatio","sig":"getDelegationRatio()","inputs":[],"outputs":[{"name":"","type":"uint32"}],"mut":"view","doc":{"notice":"External getter for the delegation ratio","returns":{"_0":"The delegation ratio"}}},{"name":"getDisputeManager","sig":"getDisputeManager()","inputs":[],"outputs":[{"name":"","type":"address"}],"mut":"view","doc":{"notice":"Gets the address of the dispute manager","returns":{"_0":"The address of the dispute manager"}}},{"name":"getGraphTallyCollector","sig":"getGraphTallyCollector()","inputs":[],"outputs":[{"name":"","type":"address"}],"mut":"view","doc":{"notice":"Gets the address of the graph tally collector","returns":{"_0":"The address of the graph tally collector"}}},{"name":"getIndexingAgreement","sig":"getIndexingAgreement(bytes16)","inputs":[{"name":"agreementId","type":"bytes16"}],"outputs":[{"name":"","type":"((address,uint8),(address,uint64,uint32,address,uint64,uint32,address,uint64,uint32,uint256,uint256,bytes32,uint64,uint16,uint8))"}],"mut":"view","doc":{"notice":"Get the indexing agreement for a given agreement ID.","params":{"agreementId":"The id of the indexing agreement"},"returns":{"_0":"The indexing agreement details"}}},{"name":"getLegacyAllocation","sig":"getLegacyAllocation(address)","inputs":[{"name":"allocationId","type":"address"}],"outputs":[{"name":"","type":"(address,bytes32)"}],"mut":"view","doc":{"notice":"Gets the details of a legacy allocation For non-legacy allocations use {getAllocation}","params":{"allocationId":"The id of the allocation"},"returns":{"_0":"The legacy allocation details"}}},{"name":"getProvisionTokensRange","sig":"getProvisionTokensRange()","inputs":[],"outputs":[{"name":"","type":"uint256"},{"name":"","type":"uint256"}],"mut":"view","doc":{"notice":"External getter for the provision tokens range","returns":{"_0":"Minimum provision tokens allowed","_1":"Maximum provision tokens allowed"}}},{"name":"getThawingPeriodRange","sig":"getThawingPeriodRange()","inputs":[],"outputs":[{"name":"","type":"uint64"},{"name":"","type":"uint64"}],"mut":"view","doc":{"notice":"External getter for the thawing period range","returns":{"_0":"Minimum thawing period allowed","_1":"Maximum thawing period allowed"}}},{"name":"getVerifierCutRange","sig":"getVerifierCutRange()","inputs":[],"outputs":[{"name":"","type":"uint32"},{"name":"","type":"uint32"}],"mut":"view","doc":{"notice":"External getter for the verifier cut range","returns":{"_0":"Minimum verifier cut allowed","_1":"Maximum verifier cut allowed"}}},{"name":"indexers","sig":"indexers(address)","inputs":[{"name":"indexer","type":"address"}],"outputs":[{"name":"url","type":"string"},{"name":"geoHash","type":"string"}],"mut":"view","doc":{"notice":"Service providers registered in the data service","details":"Note that this storage getter actually returns a {Indexer} struct, but ethers v6 is not good at dealing with dynamic types on return values.","params":{"indexer":"The address of the indexer"},"returns":{"geoHash":"The indexer's geo location, expressed as a geo hash","url":"The URL where the indexer can be reached at for queries"}}},{"name":"isOverAllocated","sig":"isOverAllocated(address)","inputs":[{"name":"allocationId","type":"address"}],"outputs":[{"name":"","type":"bool"}],"mut":"view","doc":{"notice":"Checks if an indexer is over-allocated","params":{"allocationId":"The id of the allocation"},"returns":{"_0":"True if the indexer is over-allocated, false otherwise"}}},{"name":"paymentsDestination","sig":"paymentsDestination(address)","inputs":[{"name":"indexer","type":"address"}],"outputs":[{"name":"","type":"address"}],"mut":"view","doc":{"notice":"Destination of indexer payments","params":{"indexer":"The address of the indexer"},"returns":{"_0":"The payments destination"}}},{"name":"stakeToFeesRatio","sig":"stakeToFeesRatio()","inputs":[],"outputs":[{"name":"","type":"uint256"}],"mut":"view","doc":{"notice":"Multiplier for how many tokens back collected query fees","returns":{"_0":"The stake to fees ratio"}}}],"writes":[{"name":"acceptIndexingAgreement","sig":"acceptIndexingAgreement(address,(uint64,uint64,address,address,address,uint256,uint256,uint32,uint32,uint16,uint256,bytes),bytes)","inputs":[{"name":"allocationId","type":"address"},{"name":"rca","type":"(uint64,uint64,address,address,address,uint256,uint256,uint32,uint32,uint16,uint256,bytes)"},{"name":"signature","type":"bytes"}],"outputs":[{"name":"","type":"bytes16"}],"mut":"nonpayable","doc":{"notice":"Accept an indexing agreement. See {ISubgraphService.acceptIndexingAgreement}. Requirements: - The agreement's indexer must be registered - The caller must be authorized by the agreement's indexer - The provision must be valid according to the subgraph service rules - Allocation must belong to the indexer and be open - Agreement must be for this data service - Agreement's subgraph deployment must match the allocation's subgraph deployment - Agreement must not have been accepted before - Allocation must not have an agreement already","details":"rca.metadata is an encoding of {IndexingAgreement.AcceptIndexingAgreementMetadata} Emits {IndexingAgreement.IndexingAgreementAccepted} event","params":{"allocationId":"The id of the allocation","rca":"The Recurring Collection Agreement","signature":"ECDSA signature bytes, or empty for contract-approved agreements"},"returns":{"_0":"agreementId The ID of the accepted indexing agreement"}}},{"name":"acceptProvisionPendingParameters","sig":"acceptProvisionPendingParameters(address,bytes)","inputs":[{"name":"serviceProvider","type":"address"},{"name":"data","type":"bytes"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Accepts pending parameters in the provision of a service provider in the {Graph Horizon staking contract}.","details":"Provides a way for the data service to validate and accept provision parameter changes. Call {_acceptProvision}. Emits a {ProvisionPendingParametersAccepted} event.","params":{"data":"Custom data, usage defined by the data service.","serviceProvider":"The address of the service provider."}},"emits":["ProvisionPendingParametersAccepted"]},{"name":"cancelIndexingAgreement","sig":"cancelIndexingAgreement(address,bytes16)","inputs":[{"name":"indexer","type":"address"},{"name":"agreementId","type":"bytes16"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Cancel an indexing agreement by indexer / operator. See {IndexingAgreement.cancel}.","details":"Can only be canceled on behalf of a valid indexer. Requirements: - The contract must not be paused - The indexer must be valid","params":{"agreementId":"The id of the agreement","indexer":"The indexer address"}}},{"name":"cancelIndexingAgreementByPayer","sig":"cancelIndexingAgreementByPayer(bytes16)","inputs":[{"name":"agreementId","type":"bytes16"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Cancel an indexing agreement by payer / signer. See {IDataServiceAgreements.cancelIndexingAgreementByPayer}. Requirements: - The caller must be authorized by the payer - The agreement must be active Emits {IndexingAgreementCanceled} event","params":{"agreementId":"The id of the agreement"}},"access":{"roles":[],"mods":["whenNotPaused"]}},{"name":"closeStaleAllocation","sig":"closeStaleAllocation(address)","inputs":[{"name":"allocationId","type":"address"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Resize a stale allocation to zero tokens","details":"This function can be permissionlessly called when the allocation is stale. This ensures that rewards for other allocations are not diluted by an inactive allocation. The allocation stays open as a stakeless allocation (0 tokens) rather than being closed. Allocations are long-lived and track agreement bindings, so force-closing would inadvertently cancel the associated agreement. Any bound indexing agreement remains active. Requirements: - Allocation must exist and be open - Allocation must be stale - Allocation cannot already be stakeless Emits a {AllocationResized} event.","params":{"allocationId":"The id of the allocation"}},"access":{"roles":[],"mods":["whenNotPaused"]}},{"name":"collect","sig":"collect(address,uint8,bytes)","inputs":[{"name":"serviceProvider","type":"address"},{"name":"feeType","type":"uint8"},{"name":"data","type":"bytes"}],"outputs":[{"name":"","type":"uint256"}],"mut":"nonpayable","doc":{"notice":"Collects payment earnt by the service provider.","details":"The implementation of this function is expected to interact with {GraphPayments} to collect payment from the service payer, which is done via {IGraphPayments-collect}. Emits a {ServicePaymentCollected} event. NOTE: Data services that are vetted by the Graph Council might qualify for a portion of protocol issuance to cover for these payments. In this case, the funds are taken by interacting with the rewards manager contract instead of the {GraphPayments} contract.","params":{"data":"Custom data, usage defined by the data service.","feeType":"The type of fee to collect as defined in {GraphPayments}.","serviceProvider":"The address of the service provider."},"returns":{"_0":"The amount of tokens collected."}},"emits":["ServicePaymentCollected","QueryFeesCollected"]},{"name":"initialize","sig":"initialize(address,uint256,uint32,uint256)","inputs":[{"name":"owner","type":"address"},{"name":"minimumProvisionTokens","type":"uint256"},{"name":"maximumDelegationRatio","type":"uint32"},{"name":"stakeToFeesRatio","type":"uint256"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Initialize the contract","details":"The thawingPeriod and verifierCut ranges are not set here because they are variables on the DisputeManager. We use the {ProvisionManager} overrideable getters to get the ranges.","params":{"maximumDelegationRatio":"The maximum delegation ratio allowed for an allocation","minimumProvisionTokens":"The minimum amount of provisioned tokens required to create an allocation","owner":"The owner of the contract","stakeToFeesRatio":"The ratio of stake to fees to lock when collecting query fees"}},"emits":["StakeToFeesRatioSet"]},{"name":"register","sig":"register(address,bytes)","inputs":[{"name":"serviceProvider","type":"address"},{"name":"data","type":"bytes"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Registers a service provider with the data service. The service provider can now start providing the service.","details":"Before registering, the service provider must have created a provision in the Graph Horizon staking contract with parameters that are compatible with the data service. Verifies provision parameters and rejects registration in the event they are not valid. Emits a {ServiceProviderRegistered} event. NOTE: Failing to accept the provision will result in the service provider operating on an unverified provision. Depending on of the data service this can be a security risk as the protocol won't be able to guarantee economic security for the consumer.","params":{"data":"Custom data, usage defined by the data service.","serviceProvider":"The address of the service provider."}},"emits":["ServiceProviderRegistered","PaymentsDestinationSet"]},{"name":"releaseStake","sig":"releaseStake(uint256)","inputs":[{"name":"numClaimsToRelease","type":"uint256"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Releases expired stake claims for the caller.","details":"This function is only meant to be called if the service provider has enough stake claims that releasing them all at once would exceed the block gas limit.This function can be overriden and/or disabled.Emits a {StakeClaimsReleased} event, and a {StakeClaimReleased} event for each claim released.","params":{"numClaimsToRelease":"Amount of stake claims to process. If 0, all stake claims are processed."}}},{"name":"resizeAllocation","sig":"resizeAllocation(address,address,uint256)","inputs":[{"name":"indexer","type":"address"},{"name":"allocationId","type":"address"},{"name":"tokens","type":"uint256"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Change the amount of tokens in an allocation","details":"Requirements: - The indexer must be registered - The provision must be valid according to the subgraph service rules - `tokens` must be different from the current allocation size - The indexer must have enough available tokens to allocate if they are upsizing the allocation Emits a {AllocationResized} event. See {AllocationManager-_resizeAllocation} for more details.","params":{"allocationId":"The id of the allocation","indexer":"The address of the indexer","tokens":"The new amount of tokens in the allocation"}}},{"name":"setBlockClosingAllocationWithActiveAgreement","sig":"setBlockClosingAllocationWithActiveAgreement(bool)","inputs":[{"name":"enabled","type":"bool"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Enables or disables blocking allocation closure when an active agreement exists. When enabled, closing an allocation that has an active indexing agreement will revert.","params":{"enabled":"True to enable, false to disable"}},"emits":["BlockClosingAllocationWithActiveAgreementSet"]},{"name":"setCurationCut","sig":"setCurationCut(uint256)","inputs":[{"name":"curationCut","type":"uint256"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Sets the curators payment cut for query fees","details":"Emits a {CuratorCutSet} event","params":{"curationCut":"The curation cut for the payment type"}},"emits":["CurationCutSet"]},{"name":"setDelegationRatio","sig":"setDelegationRatio(uint32)","inputs":[{"name":"delegationRatio","type":"uint32"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Sets the delegation ratio","params":{"delegationRatio":"The delegation ratio"}}},{"name":"setIndexingFeesCut","sig":"setIndexingFeesCut(uint256)","inputs":[{"name":"indexingFeesCut","type":"uint256"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Sets the data service payment cut for indexing fees","details":"Emits a {IndexingFeesCutSet} event","params":{"indexingFeesCut":"The indexing fees cut for the payment type"}},"emits":["IndexingFeesCutSet"]},{"name":"setMaxPOIStaleness","sig":"setMaxPOIStaleness(uint256)","inputs":[{"name":"newMaxPoiStaleness","type":"uint256"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Sets the max POI staleness See {AllocationManagerV1Storage-maxPOIStaleness} for more details.","params":{"newMaxPoiStaleness":"The max POI staleness in seconds"}}},{"name":"setMinimumProvisionTokens","sig":"setMinimumProvisionTokens(uint256)","inputs":[{"name":"minimumProvisionTokens","type":"uint256"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Sets the minimum amount of provisioned tokens required to create an allocation","params":{"minimumProvisionTokens":"The minimum amount of provisioned tokens required to create an allocation"}}},{"name":"setPauseGuardian","sig":"setPauseGuardian(address,bool)","inputs":[{"name":"pauseGuardian","type":"address"},{"name":"allowed","type":"bool"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Sets a pause guardian","params":{"allowed":"True if the pause guardian is allowed to pause the contract, false otherwise","pauseGuardian":"The address of the pause guardian"}}},{"name":"setPaymentsDestination","sig":"setPaymentsDestination(address)","inputs":[{"name":"newPaymentsDestination","type":"address"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Sets the payments destination for an indexer to receive payments","details":"Emits a {PaymentsDestinationSet} event","params":{"newPaymentsDestination":"The address where payments should be sent"}},"emits":["PaymentsDestinationSet"]},{"name":"setStakeToFeesRatio","sig":"setStakeToFeesRatio(uint256)","inputs":[{"name":"newStakeToFeesRatio","type":"uint256"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Sets the stake to fees ratio","params":{"newStakeToFeesRatio":"The stake to fees ratio"}},"emits":["StakeToFeesRatioSet"]},{"name":"slash","sig":"slash(address,bytes)","inputs":[{"name":"serviceProvider","type":"address"},{"name":"data","type":"bytes"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Slash a service provider for misbehaviour.","details":"To slash the service provider's provision the function should call {Staking-slash}. Emits a {ServiceProviderSlashed} event.","params":{"data":"Custom data, usage defined by the data service.","serviceProvider":"The address of the service provider."}},"emits":["ServiceProviderSlashed"]},{"name":"startService","sig":"startService(address,bytes)","inputs":[{"name":"serviceProvider","type":"address"},{"name":"data","type":"bytes"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Service provider starts providing the service.","details":"Emits a {ServiceStarted} event.","params":{"data":"Custom data, usage defined by the data service.","serviceProvider":"The address of the service provider."}},"emits":["ServiceStarted"]},{"name":"stopService","sig":"stopService(address,bytes)","inputs":[{"name":"serviceProvider","type":"address"},{"name":"data","type":"bytes"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Service provider stops providing the service.","details":"Emits a {ServiceStopped} event.","params":{"data":"Custom data, usage defined by the data service.","serviceProvider":"The address of the service provider."}},"emits":["ServiceStopped"]},{"name":"updateIndexingAgreement","sig":"updateIndexingAgreement(address,(bytes16,uint64,uint64,uint256,uint256,uint32,uint32,uint16,uint32,bytes),bytes)","inputs":[{"name":"indexer","type":"address"},{"name":"rcau","type":"(bytes16,uint64,uint64,uint256,uint256,uint32,uint32,uint16,uint32,bytes)"},{"name":"signature","type":"bytes"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Update an indexing agreement. See {IndexingAgreement.update}. Requirements: - The contract must not be paused - The indexer must be valid","details":"If `signature` is non-empty it is treated as an ECDSA signature; if empty the payer must be a contract implementing {IAgreementOwner}.","params":{"indexer":"The indexer address","rcau":"The Recurring Collection Agreement Update","signature":"ECDSA signature bytes, or empty for contract-approved updates"}}}],"events":[{"name":"BlockClosingAllocationWithActiveAgreementSet","sig":"BlockClosingAllocationWithActiveAgreementSet(bool)","inputs":[{"name":"enabled","type":"bool","indexed":false}],"doc":{"notice":"Emitted when the block closing allocation with active agreement setting is toggled","params":{"enabled":"Whether the setting is enabled"}}},{"name":"CurationCutSet","sig":"CurationCutSet(uint256)","inputs":[{"name":"curationCut","type":"uint256","indexed":false}],"doc":{"notice":"Emitted when curator cuts are set","params":{"curationCut":"The curation cut"}}},{"name":"IndexingFeesCutSet","sig":"IndexingFeesCutSet(uint256)","inputs":[{"name":"indexingFeesCut","type":"uint256","indexed":false}],"doc":{"notice":"Emitted when indexing fees cut is set","params":{"indexingFeesCut":"The indexing fees cut"}}},{"name":"PaymentsDestinationSet","sig":"PaymentsDestinationSet(address,address)","inputs":[{"name":"indexer","type":"address","indexed":true},{"name":"paymentsDestination","type":"address","indexed":true}],"doc":{"notice":"Emitted when an indexer sets a new payments destination","params":{"indexer":"The address of the indexer","paymentsDestination":"The address where payments should be sent"}}},{"name":"ProvisionPendingParametersAccepted","sig":"ProvisionPendingParametersAccepted(address)","inputs":[{"name":"serviceProvider","type":"address","indexed":true}],"doc":{"notice":"Emitted when a service provider accepts a provision in {Graph Horizon staking contract}.","params":{"serviceProvider":"The address of the service provider."}}},{"name":"QueryFeesCollected","sig":"QueryFeesCollected(address,address,address,bytes32,uint256,uint256)","inputs":[{"name":"serviceProvider","type":"address","indexed":true},{"name":"payer","type":"address","indexed":true},{"name":"allocationId","type":"address","indexed":true},{"name":"subgraphDeploymentId","type":"bytes32","indexed":false},{"name":"tokensCollected","type":"uint256","indexed":false},{"name":"tokensCurators","type":"uint256","indexed":false}],"doc":{"notice":"Emitted when a subgraph service collects query fees from Graph Payments","params":{"allocationId":"The id of the allocation","payer":"The address paying for the query fees","serviceProvider":"The address of the service provider","subgraphDeploymentId":"The id of the subgraph deployment","tokensCollected":"The amount of tokens collected","tokensCurators":"The amount of tokens curators receive"}}},{"name":"ServicePaymentCollected","sig":"ServicePaymentCollected(address,uint8,uint256)","inputs":[{"name":"serviceProvider","type":"address","indexed":true},{"name":"feeType","type":"uint8","indexed":true},{"name":"tokens","type":"uint256","indexed":false}],"doc":{"notice":"Emitted when a service provider collects payment.","params":{"feeType":"The type of fee to collect as defined in {GraphPayments}.","serviceProvider":"The address of the service provider.","tokens":"The amount of tokens collected."}}},{"name":"ServiceProviderRegistered","sig":"ServiceProviderRegistered(address,bytes)","inputs":[{"name":"serviceProvider","type":"address","indexed":true},{"name":"data","type":"bytes","indexed":false}],"doc":{"notice":"Emitted when a service provider is registered with the data service.","params":{"data":"Custom data, usage defined by the data service.","serviceProvider":"The address of the service provider."}}},{"name":"ServiceProviderSlashed","sig":"ServiceProviderSlashed(address,uint256)","inputs":[{"name":"serviceProvider","type":"address","indexed":true},{"name":"tokens","type":"uint256","indexed":false}],"doc":{"notice":"Emitted when a service provider is slashed.","params":{"serviceProvider":"The address of the service provider.","tokens":"The amount of tokens slashed."}}},{"name":"ServiceStarted","sig":"ServiceStarted(address,bytes)","inputs":[{"name":"serviceProvider","type":"address","indexed":true},{"name":"data","type":"bytes","indexed":false}],"doc":{"notice":"Emitted when a service provider starts providing the service.","params":{"data":"Custom data, usage defined by the data service.","serviceProvider":"The address of the service provider."}}},{"name":"ServiceStopped","sig":"ServiceStopped(address,bytes)","inputs":[{"name":"serviceProvider","type":"address","indexed":true},{"name":"data","type":"bytes","indexed":false}],"doc":{"notice":"Emitted when a service provider stops providing the service.","params":{"data":"Custom data, usage defined by the data service.","serviceProvider":"The address of the service provider."}}},{"name":"StakeToFeesRatioSet","sig":"StakeToFeesRatioSet(uint256)","inputs":[{"name":"ratio","type":"uint256","indexed":false}],"doc":{"notice":"Emitted when the stake to fees ratio is set.","params":{"ratio":"The stake to fees ratio"}}}],"counts":{"reads":17,"writes":23,"events":12}},{"id":"DisputeManager","name":"DisputeManager","layer":"disputes","chain":"L2","core":true,"legacy":false,"address":"0x7C9B82717f9433932507dF6EdA93A9678b258698","desc":"The court of the Subgraph Service. Anyone (a \"fisherman\") can post a deposit to dispute an indexer's query response or indexing claim. An arbitrator then accepts, rejects, or draws the dispute; accepted disputes slash the indexer's provisioned stake and reward the fisherman.","contractDoc":{"title":"DisputeManager","notice":"Provides a way to align the incentives of participants by having slashing as deterrent for incorrect behaviour. There are two types of disputes that can be created: Query disputes and Indexing disputes. Query Disputes: Graph nodes receive queries and return responses with signed receipts called attestations. An attestation can be disputed if the consumer thinks the query response was invalid. Indexers use the derived private key for an allocation to sign attestations. Indexing Disputes: Indexers present a Proof of Indexing (POI) when they close allocations to prove they were indexing a subgraph. The Staking contract emits that proof with the format keccak256(indexer.address, POI). Any challenger can dispute the validity of a POI by submitting a dispute to this contract along with a deposit. Arbitration: Disputes can only be accepted, rejected or drawn by the arbitrator role that can be delegated to a EOA or DAO."},"implements":["IDisputeManager"],"deps":[{"to":"SubgraphService","label":"slashes via the service"},{"to":"HorizonStaking","label":"reads provisioned stake"}],"roles":[],"reads":[{"name":"arbitrator","sig":"arbitrator()","inputs":[],"outputs":[{"name":"","type":"address"}],"mut":"view","doc":{"notice":"The arbitrator is solely in control of arbitrating disputes","returns":{"_0":"Arbitrator address"}}},{"name":"areConflictingAttestations","sig":"areConflictingAttestations((bytes32,bytes32,bytes32,bytes32,bytes32,uint8),(bytes32,bytes32,bytes32,bytes32,bytes32,uint8))","inputs":[{"name":"attestation1","type":"(bytes32,bytes32,bytes32,bytes32,bytes32,uint8)"},{"name":"attestation2","type":"(bytes32,bytes32,bytes32,bytes32,bytes32,uint8)"}],"outputs":[{"name":"","type":"bool"}],"mut":"pure","doc":{"notice":"Checks if two attestations are conflicting","details":"Everything must match except for the responseID.","params":{"attestation1":"The first attestation","attestation2":"The second attestation"},"returns":{"_0":"Whether the attestations are conflicting"}}},{"name":"disputeDeposit","sig":"disputeDeposit()","inputs":[],"outputs":[{"name":"","type":"uint256"}],"mut":"view","doc":{"notice":"Deposit required to create a Dispute","returns":{"_0":"Dispute deposit"}}},{"name":"disputePeriod","sig":"disputePeriod()","inputs":[],"outputs":[{"name":"","type":"uint64"}],"mut":"view","doc":{"notice":"dispute period in seconds","returns":{"_0":"Dispute period in seconds"}}},{"name":"disputes","sig":"disputes(bytes32)","inputs":[{"name":"disputeId","type":"bytes32"}],"outputs":[{"name":"indexer","type":"address"},{"name":"fisherman","type":"address"},{"name":"deposit","type":"uint256"},{"name":"relatedDisputeId","type":"bytes32"},{"name":"disputeType","type":"uint8"},{"name":"status","type":"uint8"},{"name":"createdAt","type":"uint256"},{"name":"cancellableAt","type":"uint256"},{"name":"stakeSnapshot","type":"uint256"}],"mut":"view","doc":{"notice":"List of disputes created","params":{"disputeId":"The dispute ID"},"returns":{"cancellableAt":"The timestamp when the dispute can be cancelled","createdAt":"The timestamp when the dispute was created","deposit":"The amount of tokens deposited by the fisherman","disputeType":"The type of dispute","fisherman":"The fisherman that created the dispute","indexer":"The indexer that is being disputed","relatedDisputeId":"The link to a related dispute","stakeSnapshot":"The stake snapshot of the indexer at the time of the dispute","status":"The status of the dispute"}}},{"name":"encodeReceipt","sig":"encodeReceipt((bytes32,bytes32,bytes32))","inputs":[{"name":"receipt","type":"(bytes32,bytes32,bytes32)"}],"outputs":[{"name":"","type":"bytes32"}],"mut":"view","doc":{"notice":"Get the message hash that a indexer used to sign the receipt. Encodes a receipt using a domain separator, as described on https://github.com/ethereum/EIPs/blob/master/EIPS/eip-712.md#specification.","details":"Return the message hash used to sign the receipt","params":{"receipt":"Receipt returned by indexer and submitted by fisherman"},"returns":{"_0":"Message hash used to sign the receipt"}}},{"name":"fishermanRewardCut","sig":"fishermanRewardCut()","inputs":[],"outputs":[{"name":"","type":"uint32"}],"mut":"view","doc":{"notice":"Percentage of indexer slashed funds to assign as a reward to fisherman in successful dispute. In PPM.","returns":{"_0":"Fisherman reward cut in percentage (ppm)"}}},{"name":"getAttestationIndexer","sig":"getAttestationIndexer((bytes32,bytes32,bytes32,bytes32,bytes32,uint8))","inputs":[{"name":"attestation","type":"(bytes32,bytes32,bytes32,bytes32,bytes32,uint8)"}],"outputs":[{"name":"","type":"address"}],"mut":"view","doc":{"notice":"Returns the indexer that signed an attestation.","params":{"attestation":"Attestation"},"returns":{"_0":"indexer address"}}},{"name":"getDisputePeriod","sig":"getDisputePeriod()","inputs":[],"outputs":[{"name":"","type":"uint64"}],"mut":"view","doc":{"notice":"Get the dispute period.","returns":{"_0":"Dispute period in seconds"}}},{"name":"getFishermanRewardCut","sig":"getFishermanRewardCut()","inputs":[],"outputs":[{"name":"","type":"uint32"}],"mut":"view","doc":{"notice":"Get the fisherman reward cut.","returns":{"_0":"Fisherman reward cut in percentage (ppm)"}}},{"name":"getStakeSnapshot","sig":"getStakeSnapshot(address)","inputs":[{"name":"indexer","type":"address"}],"outputs":[{"name":"","type":"uint256"}],"mut":"view","doc":{"notice":"Get the stake snapshot for an indexer.","params":{"indexer":"The indexer address"},"returns":{"_0":"The stake snapshot"}}},{"name":"isDisputeCreated","sig":"isDisputeCreated(bytes32)","inputs":[{"name":"disputeId","type":"bytes32"}],"outputs":[{"name":"","type":"bool"}],"mut":"view","doc":{"notice":"Return whether a dispute exists or not.","details":"Return if dispute with Id `disputeId` exists","params":{"disputeId":"True if dispute already exists"},"returns":{"_0":"True if dispute already exists"}}},{"name":"maxSlashingCut","sig":"maxSlashingCut()","inputs":[],"outputs":[{"name":"","type":"uint32"}],"mut":"view","doc":{"notice":"Maximum percentage of indexer stake that can be slashed on a dispute. In PPM.","returns":{"_0":"Max percentage slashing for disputes"}}},{"name":"subgraphService","sig":"subgraphService()","inputs":[],"outputs":[{"name":"","type":"address"}],"mut":"view","doc":{"notice":"The Subgraph Service contract address","returns":{"_0":"Subgraph service address"}}}],"writes":[{"name":"acceptDispute","sig":"acceptDispute(bytes32,uint256)","inputs":[{"name":"disputeId","type":"bytes32"},{"name":"tokensSlash","type":"uint256"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"The arbitrator accepts a dispute as being valid. This function will revert if the indexer is not slashable, whether because it does not have any stake available or the slashing percentage is configured to be zero. In those cases a dispute must be resolved using drawDispute or rejectDispute. This function will also revert if the dispute is in conflict, to accept a conflicting dispute use acceptDisputeConflict.","details":"Accept a dispute with Id `disputeId`","params":{"disputeId":"Id of the dispute to be accepted","tokensSlash":"Amount of tokens to slash from the indexer"}},"emits":["DisputeAccepted","DisputeRejected"]},{"name":"acceptDisputeConflict","sig":"acceptDisputeConflict(bytes32,uint256,bool,uint256)","inputs":[{"name":"disputeId","type":"bytes32"},{"name":"tokensSlash","type":"uint256"},{"name":"acceptDisputeInConflict","type":"bool"},{"name":"tokensSlashRelated","type":"uint256"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"The arbitrator accepts a conflicting dispute as being valid. This function will revert if the indexer is not slashable, whether because it does not have any stake available or the slashing percentage is configured to be zero. In those cases a dispute must be resolved using drawDispute.","params":{"acceptDisputeInConflict":"Accept the conflicting dispute. Otherwise it will be drawn automatically","disputeId":"Id of the dispute to be accepted","tokensSlash":"Amount of tokens to slash from the indexer for the first dispute","tokensSlashRelated":"Amount of tokens to slash from the indexer for the related dispute in case acceptDisputeInConflict is true, otherwise it will be ignored"}}},{"name":"cancelDispute","sig":"cancelDispute(bytes32)","inputs":[{"name":"disputeId","type":"bytes32"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Once the dispute period ends, if the dispute status remains Pending, the fisherman can cancel the dispute and get back their initial deposit. Note that cancelling a conflicting query dispute will also cancel the related dispute.","details":"Cancel a dispute with Id `disputeId`","params":{"disputeId":"Id of the dispute to be cancelled"}}},{"name":"createIndexingDispute","sig":"createIndexingDispute(address,bytes32,uint256)","inputs":[{"name":"allocationId","type":"address"},{"name":"poi","type":"bytes32"},{"name":"blockNumber","type":"uint256"}],"outputs":[{"name":"","type":"bytes32"}],"mut":"nonpayable","doc":{"notice":"Create an indexing dispute for the arbitrator to resolve. The disputes are created in reference to an allocationId and specifically a POI for that allocation. This function is called by a fisherman and it will pull `disputeDeposit` GRT tokens. Requirements: - fisherman must have previously approved this contract to pull `disputeDeposit` amount of tokens from their balance.","params":{"allocationId":"The allocation to dispute","blockNumber":"The block number for which the POI was calculated","poi":"The Proof of Indexing (POI) being disputed"},"returns":{"_0":"The dispute id"}},"emits":["IndexingDisputeCreated"]},{"name":"createIndexingFeeDisputeV1","sig":"createIndexingFeeDisputeV1(bytes16,bytes32,uint256,uint256)","inputs":[{"name":"agreementId","type":"bytes16"},{"name":"poi","type":"bytes32"},{"name":"entities","type":"uint256"},{"name":"blockNumber","type":"uint256"}],"outputs":[{"name":"","type":"bytes32"}],"mut":"nonpayable","doc":{"notice":"Create an indexing fee (version 1) dispute for the arbitrator to resolve. The disputes are created in reference to a version 1 indexing agreement and specifically a POI and entities provided when collecting that agreement. This function is called by a fisherman and it will pull `disputeDeposit` GRT tokens. Requirements: - fisherman must have previously approved this contract to pull `disputeDeposit` amount of tokens from their balance.","params":{"agreementId":"The indexing agreement to dispute","blockNumber":"The block number at which the indexing fee was collected","entities":"The number of entities disputed","poi":"The Proof of Indexing (POI) being disputed"},"returns":{"_0":"The dispute id"}}},{"name":"createQueryDispute","sig":"createQueryDispute(bytes)","inputs":[{"name":"attestationData","type":"bytes"}],"outputs":[{"name":"","type":"bytes32"}],"mut":"nonpayable","doc":{"notice":"Create a query dispute for the arbitrator to resolve. This function is called by a fisherman and it will pull `disputeDeposit` GRT tokens. * Requirements: - fisherman must have previously approved this contract to pull `disputeDeposit` amount of tokens from their balance.","params":{"attestationData":"Attestation bytes submitted by the fisherman"},"returns":{"_0":"The dispute id"}},"emits":["QueryDisputeCreated"]},{"name":"createQueryDisputeConflict","sig":"createQueryDisputeConflict(bytes,bytes)","inputs":[{"name":"attestationData1","type":"bytes"},{"name":"attestationData2","type":"bytes"}],"outputs":[{"name":"","type":"bytes32"},{"name":"","type":"bytes32"}],"mut":"nonpayable","doc":{"notice":"Create query disputes for two conflicting attestations. A conflicting attestation is a proof presented by two different indexers where for the same request on a subgraph the response is different. Two linked disputes will be created and if the arbitrator resolve one, the other one will be automatically resolved. Note that: - it's not possible to reject a conflicting query dispute as by definition at least one of the attestations is incorrect. - if both attestations are proven to be incorrect, the arbitrator can slash the indexer twice. Requirements: - fisherman must have previously approved this contract to pull `disputeDeposit` amount of tokens from their balance.","params":{"attestationData1":"First attestation data submitted","attestationData2":"Second attestation data submitted"},"returns":{"_0":"The first dispute id","_1":"The second dispute id"}},"emits":["DisputeLinked","QueryDisputeCreated"]},{"name":"drawDispute","sig":"drawDispute(bytes32)","inputs":[{"name":"disputeId","type":"bytes32"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"The arbitrator draws dispute. Note that drawing a conflicting query dispute should not be possible however it is allowed to give arbitrators greater flexibility when resolving disputes.","details":"Ignore a dispute with Id `disputeId`","params":{"disputeId":"Id of the dispute to be disregarded"}},"emits":["DisputeDrawn"]},{"name":"initialize","sig":"initialize(address,address,uint64,uint256,uint32,uint32)","inputs":[{"name":"owner","type":"address"},{"name":"arbitrator_","type":"address"},{"name":"disputePeriod_","type":"uint64"},{"name":"disputeDeposit_","type":"uint256"},{"name":"fishermanRewardCut_","type":"uint32"},{"name":"maxSlashingCut_","type":"uint32"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Initialize this contract.","params":{"arbitrator_":"Arbitrator role","disputeDeposit_":"Deposit required to create a Dispute","disputePeriod_":"Dispute period in seconds","fishermanRewardCut_":"Percent of slashed funds for fisherman (ppm)","maxSlashingCut_":"Maximum percentage of indexer stake that can be slashed (ppm)","owner":"The owner of the contract"}}},{"name":"rejectDispute","sig":"rejectDispute(bytes32)","inputs":[{"name":"disputeId","type":"bytes32"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"The arbitrator rejects a dispute as being invalid. Note that conflicting query disputes cannot be rejected.","details":"Reject a dispute with Id `disputeId`","params":{"disputeId":"Id of the dispute to be rejected"}},"emits":["DisputeRejected"]},{"name":"setArbitrator","sig":"setArbitrator(address)","inputs":[{"name":"newArbitrator","type":"address"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Set the arbitrator address.","details":"Update the arbitrator to `_arbitrator`","params":{"newArbitrator":"The address of the arbitration contract or party"}},"access":{"roles":[],"mods":["onlyGovernor"]}},{"name":"setDisputeDeposit","sig":"setDisputeDeposit(uint256)","inputs":[{"name":"newDisputeDeposit","type":"uint256"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Set the dispute deposit required to create a dispute.","details":"Update the dispute deposit to `_disputeDeposit` Graph Tokens","params":{"newDisputeDeposit":"The dispute deposit in Graph Tokens"}}},{"name":"setDisputePeriod","sig":"setDisputePeriod(uint64)","inputs":[{"name":"newDisputePeriod","type":"uint64"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Set the dispute period.","details":"Update the dispute period to `_disputePeriod` in seconds","params":{"newDisputePeriod":"Dispute period in seconds"}}},{"name":"setFishermanRewardCut","sig":"setFishermanRewardCut(uint32)","inputs":[{"name":"fishermanRewardCut_","type":"uint32"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Set the percent reward that the fisherman gets when slashing occurs.","details":"Update the reward percentage to `_percentage`","params":{"fishermanRewardCut_":"Reward as a percentage of indexer stake"}}},{"name":"setMaxSlashingCut","sig":"setMaxSlashingCut(uint32)","inputs":[{"name":"maxSlashingCut_","type":"uint32"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Set the maximum percentage that can be used for slashing indexers.","params":{"maxSlashingCut_":"Max percentage slashing for disputes"}}},{"name":"setSubgraphService","sig":"setSubgraphService(address)","inputs":[{"name":"newSubgraphService","type":"address"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Set the subgraph service address.","details":"Update the subgraph service to `_subgraphService`","params":{"newSubgraphService":"The address of the subgraph service contract"}}}],"events":[{"name":"ArbitratorSet","sig":"ArbitratorSet(address)","inputs":[{"name":"arbitrator","type":"address","indexed":true}],"doc":{"notice":"Emitted when arbitrator is set.","params":{"arbitrator":"The address of the arbitrator."}}},{"name":"DisputeAccepted","sig":"DisputeAccepted(bytes32,address,address,uint256)","inputs":[{"name":"disputeId","type":"bytes32","indexed":true},{"name":"indexer","type":"address","indexed":true},{"name":"fisherman","type":"address","indexed":true},{"name":"tokens","type":"uint256","indexed":false}],"doc":{"notice":"Emitted when arbitrator accepts a `disputeID` to `indexer` created by `fisherman`. The event emits the amount `tokens` transferred to the fisherman, the deposit plus reward.","params":{"disputeID":"ID of the dispute","fisherman":"Address of the fisherman who created the dispute","indexer":"Address of the indexer being disputed","tokens":"Amount of tokens transferred to the fisherman (deposit plus reward)"}}},{"name":"DisputeCancelled","sig":"DisputeCancelled(bytes32,address,address,uint256)","inputs":[{"name":"disputeId","type":"bytes32","indexed":true},{"name":"indexer","type":"address","indexed":true},{"name":"fisherman","type":"address","indexed":true},{"name":"tokens","type":"uint256","indexed":false}],"doc":{"notice":"Emitted when a dispute is cancelled by the fisherman. The event emits the amount `tokens` returned to the fisherman.","params":{"disputeId":"The dispute id","fisherman":"The fisherman address","indexer":"The indexer address","tokens":"The amount of tokens returned to the fisherman - the deposit"}}},{"name":"DisputeDepositSet","sig":"DisputeDepositSet(uint256)","inputs":[{"name":"disputeDeposit","type":"uint256","indexed":false}],"doc":{"notice":"Emitted when dispute deposit is set.","params":{"disputeDeposit":"The dispute deposit required to create a dispute."}}},{"name":"DisputeDrawn","sig":"DisputeDrawn(bytes32,address,address,uint256)","inputs":[{"name":"disputeId","type":"bytes32","indexed":true},{"name":"indexer","type":"address","indexed":true},{"name":"fisherman","type":"address","indexed":true},{"name":"tokens","type":"uint256","indexed":false}],"doc":{"notice":"Emitted when arbitrator draw a `disputeID` for `indexer` created by `fisherman`. The event emits the amount `tokens` used as deposit and returned to the fisherman.","params":{"disputeID":"ID of the dispute","fisherman":"Address of the fisherman who created the dispute","indexer":"Address of the indexer being disputed","tokens":"Amount of tokens used as deposit and returned to the fisherman"}}},{"name":"DisputeLinked","sig":"DisputeLinked(bytes32,bytes32)","inputs":[{"name":"disputeId1","type":"bytes32","indexed":true},{"name":"disputeId2","type":"bytes32","indexed":true}],"doc":{"notice":"Emitted when two disputes are in conflict to link them. This event will be emitted after each DisputeCreated event is emitted for each of the individual disputes.","params":{"disputeID1":"ID of the first dispute","disputeID2":"ID of the second dispute"}}},{"name":"DisputePeriodSet","sig":"DisputePeriodSet(uint64)","inputs":[{"name":"disputePeriod","type":"uint64","indexed":false}],"doc":{"notice":"Emitted when dispute period is set.","params":{"disputePeriod":"The dispute period in seconds."}}},{"name":"DisputeRejected","sig":"DisputeRejected(bytes32,address,address,uint256)","inputs":[{"name":"disputeId","type":"bytes32","indexed":true},{"name":"indexer","type":"address","indexed":true},{"name":"fisherman","type":"address","indexed":true},{"name":"tokens","type":"uint256","indexed":false}],"doc":{"notice":"Emitted when arbitrator rejects a `disputeID` for `indexer` created by `fisherman`. The event emits the amount `tokens` burned from the fisherman deposit.","params":{"disputeID":"ID of the dispute","fisherman":"Address of the fisherman who created the dispute","indexer":"Address of the indexer being disputed","tokens":"Amount of tokens burned from the fisherman deposit"}}},{"name":"FishermanRewardCutSet","sig":"FishermanRewardCutSet(uint32)","inputs":[{"name":"fishermanRewardCut","type":"uint32","indexed":false}],"doc":{"notice":"Emitted when fisherman reward cut is set.","params":{"fishermanRewardCut":"The fisherman reward cut."}}},{"name":"IndexingDisputeCreated","sig":"IndexingDisputeCreated(bytes32,address,address,uint256,address,bytes32,uint256,uint256,uint256)","inputs":[{"name":"disputeId","type":"bytes32","indexed":true},{"name":"indexer","type":"address","indexed":true},{"name":"fisherman","type":"address","indexed":true},{"name":"tokens","type":"uint256","indexed":false},{"name":"allocationId","type":"address","indexed":false},{"name":"poi","type":"bytes32","indexed":false},{"name":"blockNumber","type":"uint256","indexed":false},{"name":"stakeSnapshot","type":"uint256","indexed":false},{"name":"cancellableAt","type":"uint256","indexed":false}],"doc":{"notice":"Emitted when an indexing dispute is created for `allocationId` and `indexer` by `fisherman`. The event emits the amount of `tokens` deposited by the fisherman.","params":{"allocationId":"The allocation id","blockNumber":"The block number for which the POI was calculated","cancellableAt":"The timestamp when the dispute can be cancelled","disputeId":"The dispute id","fisherman":"The fisherman address","indexer":"The indexer address","poi":"The POI","stakeSnapshot":"The stake snapshot of the indexer at the time of the dispute","tokens":"The amount of tokens deposited by the fisherman"}}},{"name":"IndexingFeeDisputeCreated","sig":"IndexingFeeDisputeCreated(bytes32,address,address,uint256,address,bytes16,bytes32,uint256,uint256)","inputs":[{"name":"disputeId","type":"bytes32","indexed":true},{"name":"indexer","type":"address","indexed":true},{"name":"fisherman","type":"address","indexed":true},{"name":"tokens","type":"uint256","indexed":false},{"name":"payer","type":"address","indexed":false},{"name":"agreementId","type":"bytes16","indexed":false},{"name":"poi","type":"bytes32","indexed":false},{"name":"entities","type":"uint256","indexed":false},{"name":"stakeSnapshot","type":"uint256","indexed":false}],"doc":{"notice":"Emitted when an indexing fee dispute is created for `agreementId` and `indexer` by `fisherman`.","details":"The event emits the amount of `tokens` deposited by the fisherman.","params":{"agreementId":"The agreement id","disputeId":"The dispute id","entities":"The entities disputed","fisherman":"The fisherman address","indexer":"The indexer address","payer":"The address of the payer of the indexing fee","poi":"The POI disputed","stakeSnapshot":"The stake snapshot of the indexer at the time of the dispute","tokens":"The amount of tokens deposited by the fisherman"}}},{"name":"MaxSlashingCutSet","sig":"MaxSlashingCutSet(uint32)","inputs":[{"name":"maxSlashingCut","type":"uint32","indexed":false}],"doc":{"notice":"Emitted when max slashing cut is set.","params":{"maxSlashingCut":"The maximum slashing cut that can be set."}}},{"name":"QueryDisputeCreated","sig":"QueryDisputeCreated(bytes32,address,address,uint256,bytes32,bytes,uint256,uint256)","inputs":[{"name":"disputeId","type":"bytes32","indexed":true},{"name":"indexer","type":"address","indexed":true},{"name":"fisherman","type":"address","indexed":true},{"name":"tokens","type":"uint256","indexed":false},{"name":"subgraphDeploymentId","type":"bytes32","indexed":false},{"name":"attestation","type":"bytes","indexed":false},{"name":"stakeSnapshot","type":"uint256","indexed":false},{"name":"cancellableAt","type":"uint256","indexed":false}],"doc":{"notice":"Emitted when a query dispute is created for `subgraphDeploymentId` and `indexer` by `fisherman`. The event emits the amount of `tokens` deposited by the fisherman and `attestation` submitted.","params":{"attestation":"The attestation","cancellableAt":"The timestamp when the dispute can be cancelled","disputeId":"The dispute id","fisherman":"The fisherman address","indexer":"The indexer address","stakeSnapshot":"The stake snapshot of the indexer at the time of the dispute","subgraphDeploymentId":"The subgraph deployment id","tokens":"The amount of tokens deposited by the fisherman"}}},{"name":"SubgraphServiceSet","sig":"SubgraphServiceSet(address)","inputs":[{"name":"subgraphService","type":"address","indexed":true}],"doc":{"notice":"Emitted when subgraph service is set.","params":{"subgraphService":"The address of the subgraph service."}}}],"counts":{"reads":14,"writes":16,"events":14}},{"id":"RewardsManager","name":"RewardsManager","layer":"issuance","chain":"L2","core":true,"legacy":false,"address":"0x1F49caE7669086c8ba53CC35d1E9f80176d67E79","desc":"Accrues and hands out GRT indexing rewards in proportion to how much curation signal each subgraph has. On this branch it draws its issuance budget from the IssuanceAllocator, checks each indexer against the Rewards Eligibility Oracle before paying, and honours the Subgraph Availability Manager's allow/deny decisions per subgraph.","contractDoc":{"title":"Rewards Manager Contract","notice":"Manages rewards distribution for indexers and delegators in the Graph Protocol"},"implements":["IRewardsManager","IRewardsIssuer","IIssuanceTarget","IProviderEligibilityManagement"],"deps":[{"to":"L2GraphToken","label":"mints rewards"},{"to":"Curation","label":"reads signal per subgraph"},{"to":"SubgraphService","label":"reads allocations","kind":"registry"},{"to":"RewardsEligibilityOracle","label":"checks indexer eligibility"},{"to":"IssuanceAllocator","label":"pulls issuance budget"}],"roles":[],"reads":[{"name":"calcRewards","sig":"calcRewards(uint256,uint256)","inputs":[{"name":"tokens","type":"uint256"},{"name":"accRewardsPerAllocatedToken","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}],"mut":"pure","doc":{"notice":"Calculate rewards for a given accumulated rewards per allocated token","params":{"_accRewardsPerAllocatedToken":"Allocation accumulated rewards per token","_tokens":"Tokens allocated"},"returns":{"_0":"Rewards amount"}}},{"name":"getAccRewardsForSubgraph","sig":"getAccRewardsForSubgraph(bytes32)","inputs":[{"name":"subgraphDeploymentID","type":"bytes32"}],"outputs":[{"name":"","type":"uint256"}],"mut":"view","doc":{"notice":"Get the accumulated rewards for a specific subgraph","details":"Returns accumulated rewards for external callers. New rewards are only included if the subgraph is claimable (neither denied nor below minimum signal). Reclaim for non-claimable subgraphs is handled in `onSubgraphSignalUpdate()` and `onSubgraphAllocationUpdate()`.","params":{"subgraphDeploymentID":"The subgraph deployment ID"},"returns":{"_0":"The accumulated rewards for the subgraph"}}},{"name":"getAccRewardsPerAllocatedToken","sig":"getAccRewardsPerAllocatedToken(bytes32)","inputs":[{"name":"subgraphDeploymentID","type":"bytes32"}],"outputs":[{"name":"","type":"uint256"},{"name":"","type":"uint256"}],"mut":"view","doc":{"notice":"Gets the accumulated rewards per allocated token for the subgraph","details":"New rewards are only included via `getAccRewardsForSubgraph` when subgraph is claimable. Pre-existing stored rewards are always shown as distributable (preserved for when conditions clear). Does not check indexer eligibility - that can change and doesn't affect reward accrual.","params":{"subgraphDeploymentID":"Subgraph deployment"},"returns":{"_0":"Accumulated rewards per allocated token for the subgraph","_1":"Accumulated rewards for subgraph"}}},{"name":"getAccRewardsPerSignal","sig":"getAccRewardsPerSignal()","inputs":[],"outputs":[{"name":"","type":"uint256"}],"mut":"view","doc":{"notice":"Gets the currently accumulated rewards per signal","returns":{"_0":"Currently accumulated rewards per signal"}}},{"name":"getAllocatedIssuancePerBlock","sig":"getAllocatedIssuancePerBlock()","inputs":[],"outputs":[{"name":"","type":"uint256"}],"mut":"view","doc":{"notice":"Gets the effective issuance per block, accounting for the issuance allocator","details":"When an issuance allocator is set, returns the allocated rate for this contract. Otherwise falls back to the raw storage value.","returns":{"_0":"The effective issuance per block"}}},{"name":"getDefaultReclaimAddress","sig":"getDefaultReclaimAddress()","inputs":[],"outputs":[{"name":"","type":"address"}],"mut":"view","doc":{"notice":"Get the default reclaim address","returns":{"_0":"The fallback address for reclaims when no reason-specific address is configured"}}},{"name":"getNewRewardsPerSignal","sig":"getNewRewardsPerSignal()","inputs":[],"outputs":[{"name":"","type":"uint256"}],"mut":"view","doc":{"notice":"Gets the issuance of rewards per signal since last updated","returns":{"claimablePerSignal":"newly accrued rewards per signal since last update"}}},{"name":"getRawIssuancePerBlock","sig":"getRawIssuancePerBlock()","inputs":[],"outputs":[{"name":"","type":"uint256"}],"mut":"view","doc":{"notice":"Gets the raw issuance per block value from contract storage","details":"This returns the storage value directly, ignoring the issuance allocator. Prefer {getAllocatedIssuancePerBlock} for the effective protocol rate.","returns":{"_0":"The raw issuance per block from storage"}}},{"name":"getReclaimAddress","sig":"getReclaimAddress(bytes32)","inputs":[{"name":"reason","type":"bytes32"}],"outputs":[{"name":"","type":"address"}],"mut":"view","doc":{"notice":"Get the reclaim address for a specific reason","params":{"reason":"The reclaim reason identifier"},"returns":{"_0":"The address that receives reclaimed tokens for this reason (zero address if not set)"}}},{"name":"getRevertOnIneligible","sig":"getRevertOnIneligible()","inputs":[],"outputs":[{"name":"revertOnIneligible","type":"bool"}],"mut":"view","doc":{"notice":"Get whether ineligible indexers cause takeRewards to revert","returns":{"revertOnIneligible":"True if takeRewards reverts for ineligible indexers"}}},{"name":"getRewards","sig":"getRewards(address,address)","inputs":[{"name":"rewardsIssuer","type":"address"},{"name":"allocationID","type":"address"}],"outputs":[{"name":"","type":"uint256"}],"mut":"view","doc":{"notice":"Calculate current rewards for a given allocation on demand","details":"Reflects the gap between the subgraph accumulator and the allocation's snapshot, plus stored pending rewards. During exclusion (denied, below minimum signal, no allocations), the accumulator is frozen: new rewards are excluded but the existing gap remains claimable when conditions clear. Does not check indexer eligibility - that is verified at claim time via takeRewards().","params":{"allocationID":"Allocation","rewardsIssuer":"The rewards issuer contract"},"returns":{"_0":"Rewards amount for an allocation"}}},{"name":"isDenied","sig":"isDenied(bytes32)","inputs":[{"name":"subgraphDeploymentID","type":"bytes32"}],"outputs":[{"name":"","type":"bool"}],"mut":"view","doc":{"notice":"Check if a subgraph deployment is denied","params":{"subgraphDeploymentID":"The subgraph deployment ID to check"},"returns":{"_0":"True if the subgraph is denied, false otherwise"}}},{"name":"subgraphService","sig":"subgraphService()","inputs":[],"outputs":[{"name":"","type":"address"}],"mut":"view","doc":{"notice":"Address of the subgraph service","returns":{"_0":"The subgraph service contract"}}}],"writes":[{"name":"onSubgraphAllocationUpdate","sig":"onSubgraphAllocationUpdate(bytes32)","inputs":[{"name":"subgraphDeploymentID","type":"bytes32"}],"outputs":[{"name":"","type":"uint256"}],"mut":"nonpayable","doc":{"notice":"Triggers an update of rewards for a subgraph","details":"Hook called from the IRewardsIssuer contract on allocate() and close() ## Claimability Behavior When a subgraph is not claimable (denied, below minimum signal, or no allocations): - Rewards are reclaimed immediately with the appropriate reason - `accRewardsForSubgraph` is NOT updated (rewards go to reclaim, not accumulator) - `accRewardsPerAllocatedToken` does NOT increase When claimable (not denied, above minimum signal, has allocations): - Rewards are added to `accRewardsForSubgraph` - `accRewardsPerAllocatedToken` increases (rewards distributable to allocations)","params":{"subgraphDeploymentID":"Subgraph deployment"},"returns":{"accRewardsPerAllocatedToken":"Current `accRewardsPerAllocatedToken`"}},"emits":["RewardsReclaimed"]},{"name":"onSubgraphSignalUpdate","sig":"onSubgraphSignalUpdate(bytes32)","inputs":[{"name":"subgraphDeploymentID","type":"bytes32"}],"outputs":[{"name":"","type":"uint256"}],"mut":"nonpayable","doc":{"notice":"Triggers an update of rewards for a subgraph","details":"Must be called before `signalled GRT` on a subgraph changes. Hook called from the Curation contract on mint() and burn() ## Claimability Behavior When a subgraph is not claimable (denied, below minimum signal, or no allocations): - Rewards are reclaimed immediately with the appropriate reason - `accRewardsForSubgraph` is NOT updated (rewards go to reclaim, not accumulator) When claimable (not denied, above minimum signal, has allocations): - Rewards are added to `accRewardsForSubgraph` for later distribution via `onSubgraphAllocationUpdate`","params":{"subgraphDeploymentID":"Subgraph deployment"},"returns":{"accRewardsForSubgraph":"Accumulated rewards for subgraph"}},"emits":["RewardsReclaimed"]},{"name":"reclaimRewards","sig":"reclaimRewards(bytes32,address)","inputs":[{"name":"reason","type":"bytes32"},{"name":"allocationID","type":"address"}],"outputs":[{"name":"","type":"uint256"}],"mut":"nonpayable","doc":{"notice":"Reclaim rewards for an allocation","details":"bytes32(0) (NONE) cannot be used as a reclaim reason and will return 0. Use specific RewardsCondition constants for reclaim reasons.","params":{"allocationID":"Allocation","reason":"The reclaim reason identifier (see RewardsCondition library for canonical reasons)"},"returns":{"_0":"The amount of rewards that were reclaimed (0 if no reclaim address set)"}},"emits":["RewardsReclaimed"],"calls":["SubgraphService"]},{"name":"setDefaultReclaimAddress","sig":"setDefaultReclaimAddress(address)","inputs":[{"name":"newDefaultReclaimAddress","type":"address"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Set the default reclaim address used when no reason-specific address is configured","details":"This is the fallback address used after trying all applicable reason-specific addresses. Set to zero to disable (rewards will be dropped if no specific address matches).","params":{"newDefaultReclaimAddress":"The fallback address for reclaims"}},"access":{"roles":[],"mods":["onlyGovernor"]},"emits":["DefaultReclaimAddressSet"]},{"name":"setDenied","sig":"setDenied(bytes32,bool)","inputs":[{"name":"subgraphDeploymentID","type":"bytes32"},{"name":"deny","type":"bool"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Set the denied status for a subgraph deployment","details":"Can only be called by the subgraph availability oracle","params":{"deny":"True to deny, false to allow","subgraphDeploymentID":"The subgraph deployment ID"}},"emits":["RewardsDenylistUpdated","RewardsReclaimed"]},{"name":"setMinimumSubgraphSignal","sig":"setMinimumSubgraphSignal(uint256)","inputs":[{"name":"minimumSubgraphSignal","type":"uint256"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Sets the minimum signaled tokens on a subgraph to start accruing rewards","details":"Can be set to zero which means that this feature is not being used","params":{"_minimumSubgraphSignal":"Minimum signaled tokens IMPORTANT: This function does not update existing subgraphs. When subgraphs are later updated, the current threshold is applied to ALL pending rewards since their last update, regardless of historical threshold values. ## Rewards Accounting Issue - Threshold increase: Pending rewards on previously eligible subgraphs are reclaimed - Threshold decrease: Previously ineligible subgraphs retroactively accumulate pending rewards ## Mitigation 1. Communicate the planned threshold change with a specific future date 2. Wait - notice period allows participants to adjust signal if desired 3. Identify affected subgraphs off-chain (those crossing the threshold) 4. Call onSubgraphSignalUpdate() for all affected subgraphs to accumulate pending rewards under current eligibility rules 5. Execute threshold change via this function (promptly after step 4, ideally same block)"}}},{"name":"setReclaimAddress","sig":"setReclaimAddress(bytes32,address)","inputs":[{"name":"reason","type":"bytes32"},{"name":"newReclaimAddress","type":"address"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Set the reclaim address for a specific reason","details":"bytes32(0) is reserved as an invalid reason to prevent accidental misconfiguration and catch uninitialized reason identifiers. IMPORTANT: Changes take effect immediately and retroactively. All unclaimed rewards from previous periods will be sent to the new reclaim address when they are eventually reclaimed, regardless of which address was configured when the rewards were originally accrued.","params":{"newReclaimAddress":"The address to receive tokens","reason":"The reclaim reason identifier (see RewardsCondition library for canonical reasons)"}},"access":{"roles":[],"mods":["onlyGovernor"]},"emits":["ReclaimAddressSet"]},{"name":"setRevertOnIneligible","sig":"setRevertOnIneligible(bool)","inputs":[{"name":"revertOnIneligible","type":"bool"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Set whether ineligible indexers cause takeRewards to revert","details":"When true, takeRewards reverts for ineligible indexers, keeping rewards claimable if the indexer becomes eligible and collects before the allocation goes stale. When false (default), takeRewards succeeds but rewards are reclaimed.","params":{"revertOnIneligible":"True to revert on ineligible, false to reclaim"}},"access":{"roles":[],"mods":["onlyGovernor"]}},{"name":"setSubgraphAvailabilityOracle","sig":"setSubgraphAvailabilityOracle(address)","inputs":[{"name":"subgraphAvailabilityOracle","type":"address"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Set the subgraph availability oracle address","params":{"subgraphAvailabilityOracle":"The address of the subgraph availability oracle"}},"access":{"roles":[],"mods":["onlyGovernor"]}},{"name":"setSubgraphService","sig":"setSubgraphService(address)","inputs":[{"name":"newSubgraphService","type":"address"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Set the subgraph service address","params":{"newSubgraphService":"Address of the subgraph service contract"}},"access":{"roles":[],"mods":["onlyGovernor"]},"emits":["SubgraphServiceSet"]},{"name":"takeRewards","sig":"takeRewards(address)","inputs":[{"name":"allocationID","type":"address"}],"outputs":[{"name":"","type":"uint256"}],"mut":"nonpayable","doc":{"notice":"Pull rewards from the contract for a particular allocation","details":"This function can only be called by an authorized rewards issuer which are - the subgraph service (for allocations). Mints 0 tokens if the allocation is not active.First successful reclaim wins - short-circuits on reclaim: - If subgraph denied with reclaim address → reclaim to SUBGRAPH_DENIED address (eligibility NOT checked) - If subgraph not denied OR denied without address, then check eligibility → reclaim to INDEXER_INELIGIBLE if configured - Subsequent denial emitted only when earlier denial has no reclaim address - Any denial without reclaim address drops rewards (no minting)","params":{"allocationID":"Allocation"},"returns":{"_0":"Assigned rewards amount"}},"emits":["HorizonRewardsAssigned","RewardsReclaimed"],"calls":["SubgraphService"]},{"name":"updateAccRewardsPerSignal","sig":"updateAccRewardsPerSignal()","inputs":[],"outputs":[{"name":"","type":"uint256"}],"mut":"nonpayable","doc":{"notice":"Updates the accumulated rewards per signal and save checkpoint block number","details":"Must be called before `issuancePerBlock` or `total signalled GRT` changes. Called from the Curation contract on mint() and burn() ## Zero Signal Handling When total signalled tokens is zero, issuance for the period is reclaimed (if NO_SIGNAL reclaim address is configured) rather than being lost.","returns":{"_0":"Accumulated rewards per signal"}},"emits":["RewardsReclaimed"]}],"events":[{"name":"DefaultReclaimAddressSet","sig":"DefaultReclaimAddressSet(address,address)","inputs":[{"name":"oldAddress","type":"address","indexed":true},{"name":"newAddress","type":"address","indexed":true}],"doc":{"notice":"Default reclaim address changed","params":{"newAddress":"New default reclaim address","oldAddress":"Previous default reclaim address"}}},{"name":"HorizonRewardsAssigned","sig":"HorizonRewardsAssigned(address,address,uint256)","inputs":[{"name":"indexer","type":"address","indexed":true},{"name":"allocationID","type":"address","indexed":true},{"name":"amount","type":"uint256","indexed":false}],"doc":{"notice":"Emitted when rewards are assigned to an indexer (Horizon version)","details":"We use the Horizon prefix to change the event signature which makes network subgraph development much easier","params":{"allocationID":"Address of the allocation receiving rewards","amount":"Amount of rewards assigned","indexer":"Address of the indexer receiving rewards"}}},{"name":"ReclaimAddressSet","sig":"ReclaimAddressSet(bytes32,address,address)","inputs":[{"name":"reason","type":"bytes32","indexed":true},{"name":"oldAddress","type":"address","indexed":true},{"name":"newAddress","type":"address","indexed":true}],"doc":{"notice":"New reclaim address set","params":{"newAddress":"New address for this reason","oldAddress":"Previous address for this reason","reason":"The reclaim reason (or condition) identifier (see RewardsCondition library for canonical reasons)"}}},{"name":"RewardsDenied","sig":"RewardsDenied(address,address)","inputs":[{"name":"indexer","type":"address","indexed":true},{"name":"allocationID","type":"address","indexed":true}],"doc":{"notice":"Emitted when rewards are denied to an indexer","params":{"allocationID":"Address of the allocation being denied rewards","indexer":"Address of the indexer being denied rewards"}}},{"name":"RewardsDeniedDueToEligibility","sig":"RewardsDeniedDueToEligibility(address,address,uint256)","inputs":[{"name":"indexer","type":"address","indexed":true},{"name":"allocationID","type":"address","indexed":true},{"name":"amount","type":"uint256","indexed":false}],"doc":{"notice":"Emitted when rewards are denied to an indexer due to eligibility","params":{"allocationID":"Address of the allocation being denied rewards","amount":"Amount of rewards denied","indexer":"Address of the indexer being denied rewards"}}},{"name":"RewardsDenylistUpdated","sig":"RewardsDenylistUpdated(bytes32,uint256)","inputs":[{"name":"subgraphDeploymentID","type":"bytes32","indexed":true},{"name":"sinceBlock","type":"uint256","indexed":false}],"doc":{"notice":"Emitted when a subgraph is denied for claiming rewards","params":{"sinceBlock":"Block number since when the subgraph is denied","subgraphDeploymentID":"Subgraph deployment ID being denied"}}},{"name":"RewardsReclaimed","sig":"RewardsReclaimed(bytes32,uint256,address,address,bytes32)","inputs":[{"name":"reason","type":"bytes32","indexed":true},{"name":"amount","type":"uint256","indexed":false},{"name":"indexer","type":"address","indexed":true},{"name":"allocationID","type":"address","indexed":true},{"name":"subgraphDeploymentID","type":"bytes32","indexed":false}],"doc":{"notice":"Rewards reclaimed to a configured address","params":{"allocationID":"Address of the allocation","amount":"Amount of rewards reclaimed","indexer":"Address of the indexer","reason":"The reclaim reason identifier","subgraphDeploymentID":"Subgraph deployment ID for the allocation"}}},{"name":"SubgraphServiceSet","sig":"SubgraphServiceSet(address,address)","inputs":[{"name":"oldSubgraphService","type":"address","indexed":true},{"name":"newSubgraphService","type":"address","indexed":true}],"doc":{"notice":"Emitted when the subgraph service is set","params":{"newSubgraphService":"New subgraph service address","oldSubgraphService":"Previous subgraph service address"}}}],"counts":{"reads":13,"writes":12,"events":8}},{"id":"IssuanceAllocator","name":"IssuanceAllocator","layer":"issuance","chain":"L2","core":true,"legacy":false,"address":"0x76a0d75651d4db83f74ac502b86a0ae4e19ac38b","desc":"Splits the protocol's GRT issuance across several \"targets\" while holding a 100% allocation invariant via a default target. Each target gets either freshly-minted tokens or a notification to mint its own. This is the new programmable issuance budget that sits upstream of the RewardsManager and recurring agreements.","contractDoc":{"title":"IssuanceAllocator","notice":"This contract is responsible for allocating token issuance to different components of the protocol. It calculates issuance for all targets based on their configured rates (tokens per block) and handles minting for allocator-minting targets."},"implements":["IIssuanceAllocationDistribution","IIssuanceAllocationAdministration","IIssuanceAllocationStatus"],"deps":[{"to":"L2GraphToken","label":"mints issuance"},{"to":"RewardsManager","label":"allocates issuance to"},{"to":"DirectAllocation","label":"allocates issuance to"},{"to":"RecurringAgreementManager","label":"allocates issuance to"}],"roles":[{"name":"GOVERNOR_ROLE","notice":"Role identifier for governor accounts","dev":"Governors have the highest level of access and can: - Grant and revoke roles within the established hierarchy - Perform administrative functions and system configuration - Set critical parameters and upgrade contracts Admin of: GOVERNOR_ROLE, PAUSE_ROLE, OPERATOR_ROLE","admin":"GOVERNOR_ROLE","gates":["distributePendingIssuance","forceTargetNoChangeNotificationBlock","notifyTarget","setDefaultTarget","setIssuancePerBlock","setSelfMintingEventMode","setTargetAllocation"]},{"name":"PAUSE_ROLE","notice":"Role identifier for pause accounts","dev":"Pause role holders can: - Pause and unpause contract operations for emergency situations Typically granted to automated monitoring systems or emergency responders. Pausing is intended for quick response to potential threats, and giving time for investigation and resolution (potentially with governance intervention). Admin: GOVERNOR_ROLE","admin":"GOVERNOR_ROLE","gates":["pause","unpause"]},{"name":"OPERATOR_ROLE","notice":"Role identifier for operator accounts","dev":"Operators can: - Perform operational tasks as defined by inheriting contracts - Manage roles that are designated as operator-administered Admin: GOVERNOR_ROLE","admin":"GOVERNOR_ROLE","gates":[]}],"reads":[{"name":"getDistributionState","sig":"getDistributionState()","inputs":[],"outputs":[{"name":"distributionState","type":"(uint256,uint256,uint256)"}],"mut":"view","doc":{"notice":"Get pending issuance distribution state","returns":{"_0":"DistributionState struct containing block tracking and accumulation info"}}},{"name":"getIssuancePerBlock","sig":"getIssuancePerBlock()","inputs":[],"outputs":[{"name":"issuancePerBlock","type":"uint256"}],"mut":"view","doc":{"notice":"Get the current issuance per block","returns":{"_0":"The current issuance per block"}}},{"name":"getSelfMintingEventMode","sig":"getSelfMintingEventMode()","inputs":[],"outputs":[{"name":"mode","type":"uint8"}],"mut":"view","doc":{"notice":"Get the current self-minting event emission mode","returns":{"_0":"The current emission mode"}}},{"name":"getTargetAllocation","sig":"getTargetAllocation(address)","inputs":[{"name":"target","type":"address"}],"outputs":[{"name":"allocation","type":"(uint256,uint256,uint256)"}],"mut":"view","doc":{"notice":"Get the current allocation for a target","details":"Returns assigned allocation regardless of whether target is address(0) or the default.For address(0), no minting occurs but the allocation represents the unallocated portion.For effective allocations excluding unmintable portion, use getTotalAllocation().","params":{"target":"Address of the target"},"returns":{"_0":"Allocation struct containing total, allocator-minting, and self-minting allocations"}}},{"name":"getTargetAt","sig":"getTargetAt(uint256)","inputs":[{"name":"index","type":"uint256"}],"outputs":[{"name":"target","type":"address"}],"mut":"view","doc":{"notice":"Get a specific allocated target address by index","params":{"index":"The index of the target address to retrieve"},"returns":{"_0":"The target address at the specified index"}}},{"name":"getTargetCount","sig":"getTargetCount()","inputs":[],"outputs":[{"name":"count","type":"uint256"}],"mut":"view","doc":{"notice":"Get the number of allocated targets","returns":{"_0":"The total number of allocated targets"}}},{"name":"getTargetData","sig":"getTargetData(address)","inputs":[{"name":"target","type":"address"}],"outputs":[{"name":"","type":"(uint256,uint256,uint256)"}],"mut":"view","doc":{"notice":"Get target data for a specific target","params":{"target":"Address of the target"},"returns":{"_0":"AllocationTarget struct containing target information including lastChangeNotifiedBlock"}}},{"name":"getTargetIssuancePerBlock","sig":"getTargetIssuancePerBlock(address)","inputs":[{"name":"target","type":"address"}],"outputs":[{"name":"targetIssuance","type":"(uint256,uint256,uint256,uint256)"}],"mut":"view","doc":{"notice":"Target issuance per block information","details":"Returns assigned issuance rates regardless of whether target is address(0) or the default.For address(0), no minting occurs but rates reflect what would be issued if mintable.selfIssuanceBlockAppliedTo reflects the last block for which self-minting allowances have been calculated and emitted (lastSelfMintingBlock). This advances continuously, unaffected by pause state.","params":{"target":"Address of the target"},"returns":{"_0":"TargetIssuancePerBlock struct containing allocatorIssuanceBlockAppliedTo, selfIssuanceBlockAppliedTo, allocatorIssuanceRate, and selfIssuanceRate"}}},{"name":"getTargets","sig":"getTargets()","inputs":[],"outputs":[{"name":"targets","type":"address[]"}],"mut":"view","doc":{"notice":"Get all allocated target addresses","returns":{"_0":"Array of target addresses"}}},{"name":"getTotalAllocation","sig":"getTotalAllocation()","inputs":[],"outputs":[{"name":"allocation","type":"(uint256,uint256,uint256)"}],"mut":"view","doc":{"notice":"Get the current global allocation totals","details":"For reporting purposes, if the default target is address(0), its allocationis treated as \"unallocated\" since address(0) cannot receive minting.When default is address(0): returns actual allocated amounts (may be less than issuancePerBlock)When default is a real address: returns issuancePerBlockNote: Internally, the contract always maintains 100% allocation invariant, even when default is address(0)","returns":{"allocation":"Allocation struct containing total, allocator-minting, and self-minting allocations across all targets"}}}],"writes":[{"name":"distributeIssuance","sig":"distributeIssuance()","inputs":[],"outputs":[{"name":"","type":"uint256"}],"mut":"nonpayable","doc":{"notice":"Distribute issuance to allocated non-self-minting targets.","details":"Implementation details: - For allocator-minting targets, tokens are minted and transferred directly to targets based on their allocation rate - For self-minting targets (like the legacy RewardsManager), it does not mint tokens directly. Instead, these contracts are expected to handle minting themselves - The self-minting allocation is intended only for backwards compatibility with existing contracts and should not be used for new targets. New targets should use allocator-minting allocation to ensure robust control of token issuance by the IssuanceAllocatorPause behavior: - When paused: Self-minting allowances tracked via events/accumulation, but no allocator-minting tokens distributed. Returns lastDistributionBlock (frozen at pause point). lastSelfMintingBlock advances to current block. - When unpaused: Normal distribution if no accumulated self-minting, otherwise retroactive distribution using current rates for entire undistributed period, with accumulated self-minting reducing allocator budget. - Unless paused, always advances lastDistributionBlock to block.number, even if no issuance to distribute.Reentrancy: This function intentionally does NOT have a reentrancy guard to allow targets to legitimately call it during notifications (e.g., to claim pending issuance before their allocation changes). This is safe because the function has built-in block-tracking protection that prevents double-distribution within the same block, makes no external calls that could expose inconsistent state, and does not modify allocations.","returns":{"_0":"Block number that issuance has been distributed to. That will normally be the current block number, unless the contract is paused."}},"calls":["L2GraphToken"]},{"name":"distributePendingIssuance","sig":"distributePendingIssuance()","inputs":[],"outputs":[{"name":"distributedBlock","type":"uint256"}],"mut":"nonpayable","doc":{"notice":"Distribute pending accumulated allocator-minting issuance","details":"Distributes accumulated allocator-minting issuance using current rates (retroactively applied to the period from lastDistributionBlock to current block). Prioritizes non-default targets getting full rates; default gets remainder.Finalizes self-minting accumulation for the period being distributed.","returns":{"_0":"Block number that issuance was distributed up to"}},"access":{"roles":["GOVERNOR_ROLE"],"mods":["nonReentrant"]},"calls":["L2GraphToken"]},{"name":"distributePendingIssuance","sig":"distributePendingIssuance(uint256)","inputs":[{"name":"toBlockNumber","type":"uint256"}],"outputs":[{"name":"distributedBlock","type":"uint256"}],"mut":"nonpayable","doc":{"notice":"Distribute pending accumulated allocator-minting issuance up to specified block","details":"Distributes accumulated allocator-minting issuance using current rates (retroactively applied to the period from lastDistributionBlock to toBlockNumber). Prioritizes non-default targets getting full rates; default gets remainder.Finalizes self-minting accumulation for the period being distributed.","params":{"toBlockNumber":"Block number to distribute up to (must be <= block.number and >= lastDistributionBlock)"},"returns":{"_0":"Block number that issuance was distributed up to"}},"access":{"roles":["GOVERNOR_ROLE"],"mods":["nonReentrant"]},"calls":["L2GraphToken"]},{"name":"forceTargetNoChangeNotificationBlock","sig":"forceTargetNoChangeNotificationBlock(address,uint256)","inputs":[{"name":"target","type":"address"},{"name":"blockNumber","type":"uint256"}],"outputs":[{"name":"notificationBlock","type":"uint256"}],"mut":"nonpayable","doc":{"notice":"Force set the lastChangeNotifiedBlock for a target to a specific block number","details":"Implementation details: - This can be used to enable notification to be sent again (by setting to a past block) or to prevent notification until a future block (by setting to current or future block) - Returns the block number that was set, always equal to blockNumber in current implementation","params":{"blockNumber":"Block number to set as the lastChangeNotifiedBlock","target":"Address of the target to update"},"returns":{"_0":"The block number that was set"}},"access":{"roles":["GOVERNOR_ROLE"],"mods":[]}},{"name":"notifyTarget","sig":"notifyTarget(address)","inputs":[{"name":"target","type":"address"}],"outputs":[{"name":"notified","type":"bool"}],"mut":"nonpayable","doc":{"notice":"Notify a specific target about an upcoming allocation change","details":"Implementation details: - The target will be notified at most once per block to prevent reentrancy looping - Will revert if target notification reverts","params":{"target":"Address of the target to notify"},"returns":{"_0":"True if notification was sent or already sent this block, false otherwise"}},"access":{"roles":["GOVERNOR_ROLE"],"mods":["nonReentrant"]},"calls":["RewardsManager","DirectAllocation","RecurringAgreementManager"]},{"name":"setDefaultTarget","sig":"setDefaultTarget(address)","inputs":[{"name":"newAddress","type":"address"}],"outputs":[{"name":"applied","type":"bool"}],"mut":"nonpayable","doc":{"notice":"Set the address that receives the default portion of issuance not allocated to other targets","params":{"newAddress":"The new default target address (can be address(0))"},"returns":{"_0":"True if applied"}},"access":{"roles":["GOVERNOR_ROLE"],"mods":["nonReentrant"]},"calls":["RewardsManager","DirectAllocation","RecurringAgreementManager"]},{"name":"setDefaultTarget","sig":"setDefaultTarget(address,uint256)","inputs":[{"name":"newAddress","type":"address"},{"name":"minDistributedBlock","type":"uint256"}],"outputs":[{"name":"applied","type":"bool"}],"mut":"nonpayable","doc":{"notice":"Set the address that receives the default portion of issuance not allocated to other targets","details":"Governance should explicitly call distributePendingIssuance(blockNumber) first if paused and distribution is not up to minDistributedBlock block. then call this function with the same or lower blockNumber.","params":{"minDistributedBlock":"Minimum block number that distribution must have reached","newAddress":"The new default target address (can be address(0))"},"returns":{"_0":"True if applied, false if distribution has not reached minDistributedBlock and therefore the change was not applied"}},"access":{"roles":["GOVERNOR_ROLE"],"mods":["nonReentrant"]},"calls":["RewardsManager","DirectAllocation","RecurringAgreementManager"]},{"name":"setIssuancePerBlock","sig":"setIssuancePerBlock(uint256)","inputs":[{"name":"newIssuancePerBlock","type":"uint256"}],"outputs":[{"name":"applied","type":"bool"}],"mut":"nonpayable","doc":{"notice":"Set the issuance per block.","details":"Requires distribution to have reached block.number","params":{"newIssuancePerBlock":"New issuance per block"},"returns":{"_0":"True if the value is applied (including if already the case)"}},"access":{"roles":["GOVERNOR_ROLE"],"mods":["nonReentrant"]},"calls":["RewardsManager","DirectAllocation","RecurringAgreementManager"]},{"name":"setIssuancePerBlock","sig":"setIssuancePerBlock(uint256,uint256)","inputs":[{"name":"newIssuancePerBlock","type":"uint256"},{"name":"minDistributedBlock","type":"uint256"}],"outputs":[{"name":"applied","type":"bool"}],"mut":"nonpayable","doc":{"notice":"Set the issuance per block, requiring distribution has reached at least the specified block","details":"Implementation details: - Requires distribution to have reached at least minDistributedBlock - This allows configuration changes after calling distributePendingIssuance(blockNumber) while paused - Only the default target is notified (target rates don't change, only default target changes) - Target rates stay fixed; default target absorbs the change - Whenever the rate is changed, the updateL2MintAllowance function _must_ be called on the L1GraphTokenGateway in L1, to ensure the bridge can mint the right amount of tokensRate changes while paused: The new rate applies retroactively to the entire undistributed period when distribution resumes. Governance must exercise caution to ensure rates are applied to the correct block range. Use distributePendingIssuance(blockNumber) to control precisely which block the new rate applies from.","params":{"minDistributedBlock":"Minimum block number that distribution must have reached","newIssuancePerBlock":"New issuance per block"},"returns":{"_0":"True if the value is applied (including if already the case), false if distribution hasn't reached minDistributedBlock"}},"access":{"roles":["GOVERNOR_ROLE"],"mods":["nonReentrant"]},"calls":["RewardsManager","DirectAllocation","RecurringAgreementManager"]},{"name":"setSelfMintingEventMode","sig":"setSelfMintingEventMode(uint8)","inputs":[{"name":"newMode","type":"uint8"}],"outputs":[{"name":"applied","type":"bool"}],"mut":"nonpayable","doc":{"notice":"Set the self-minting event emission mode","details":"None: Skip event emission entirely (lowest gas)Aggregate: Emit single aggregated event for all self-minting (medium gas)PerTarget: Emit events for each target with self-minting (highest gas)Self-minting targets should call getTargetIssuancePerBlock() rather than relying on events","params":{"newMode":"The new emission mode (None, Aggregate, or PerTarget)"},"returns":{"_0":"True if the mode was set (including if already set to that mode)"}},"access":{"roles":["GOVERNOR_ROLE"],"mods":[]}},{"name":"setTargetAllocation","sig":"setTargetAllocation(address,uint256)","inputs":[{"name":"target","type":"address"},{"name":"allocatorMintingRate","type":"uint256"}],"outputs":[{"name":"applied","type":"bool"}],"mut":"nonpayable","doc":{"notice":"Set the allocation for a target with only allocator minting","details":"This variant sets selfMintingRate to 0 and evenIfDistributionPending to false","params":{"allocatorMintingRate":"Allocator-minting rate for the target (tokens per block)","target":"The target contract to update"},"returns":{"_0":"True if the value is applied (including if already the case), false if not applied"}},"access":{"roles":["GOVERNOR_ROLE"],"mods":["nonReentrant"]},"calls":["RewardsManager","DirectAllocation","RecurringAgreementManager"]},{"name":"setTargetAllocation","sig":"setTargetAllocation(address,uint256,uint256)","inputs":[{"name":"target","type":"address"},{"name":"allocatorMintingRate","type":"uint256"},{"name":"selfMintingRate","type":"uint256"}],"outputs":[{"name":"applied","type":"bool"}],"mut":"nonpayable","doc":{"notice":"Set the allocation for a target with both allocator and self minting","details":"This variant sets evenIfDistributionPending to false","params":{"allocatorMintingRate":"Allocator-minting rate for the target (tokens per block)","selfMintingRate":"Self-minting rate for the target (tokens per block)","target":"The target contract to update"},"returns":{"_0":"True if the value is applied (including if already the case), false if not applied"}},"access":{"roles":["GOVERNOR_ROLE"],"mods":["nonReentrant"]},"calls":["RewardsManager","DirectAllocation","RecurringAgreementManager"]},{"name":"setTargetAllocation","sig":"setTargetAllocation(address,uint256,uint256,uint256)","inputs":[{"name":"target","type":"address"},{"name":"allocatorMintingRate","type":"uint256"},{"name":"selfMintingRate","type":"uint256"},{"name":"minDistributedBlock","type":"uint256"}],"outputs":[{"name":"applied","type":"bool"}],"mut":"nonpayable","doc":{"notice":"Set the allocation for a target, provided distribution has reached at least the specified block","details":"Implementation details: - Requires distribution has reached at least minDistributedBlock issuance to change allocation - This allows configuration changes while paused by being deliberate about which block to distribute to - If the new allocations are the same as the current allocations, this function is a no-op - If both allocations are 0 and the target doesn't exist, this function is a no-op - If both allocations are 0 and the target exists, the target will be removed - If any allocation is non-zero and the target doesn't exist, the target will be added - Will revert if the total allocation would exceed available capacity (default target + current target allocation) - Will revert if attempting to add a target that doesn't support IIssuanceTargetSelf-minting targets must call getTargetIssuancePerBlock to determine their issuance and mint accordingly. See contract header for details on self-minting vs allocator-minting allocation.","params":{"allocatorMintingRate":"Allocator-minting rate for the target (tokens per block)","minDistributedBlock":"Minimum block number that distribution must have reached","selfMintingRate":"Self-minting rate for the target (tokens per block)","target":"The target contract to update"},"returns":{"_0":"True if the value is applied (including if already the case), false if distribution hasn't reached minDistributedBlock and therefore the change was not applied"}},"access":{"roles":["GOVERNOR_ROLE"],"mods":["nonReentrant"]},"calls":["RewardsManager","DirectAllocation","RecurringAgreementManager"]}],"events":[],"counts":{"reads":10,"writes":13,"events":0}},{"id":"DirectAllocation","name":"DirectAllocation","layer":"issuance","chain":"L2","core":true,"legacy":false,"address":"0xa0eab4367d753314840c09313a5c6d27174bd541","desc":"A minimal issuance target that simply receives minted GRT from the IssuanceAllocator and lets an authorized account forward it onward. It is the simplest possible recipient in the issuance system, used for budgets that are managed off-chain or by governance.","contractDoc":{"title":"DirectAllocation","notice":"A simple contract that receives tokens from the IssuanceAllocator and allows an authorized operator to withdraw them."},"implements":["IIssuanceTarget","ISendTokens"],"deps":[{"to":"L2GraphToken","label":"receives / sends GRT"}],"roles":[{"name":"GOVERNOR_ROLE","notice":"Role identifier for governor accounts","dev":"Governors have the highest level of access and can: - Grant and revoke roles within the established hierarchy - Perform administrative functions and system configuration - Set critical parameters and upgrade contracts Admin of: GOVERNOR_ROLE, PAUSE_ROLE, OPERATOR_ROLE","admin":"GOVERNOR_ROLE","gates":["setIssuanceAllocator"]},{"name":"PAUSE_ROLE","notice":"Role identifier for pause accounts","dev":"Pause role holders can: - Pause and unpause contract operations for emergency situations Typically granted to automated monitoring systems or emergency responders. Pausing is intended for quick response to potential threats, and giving time for investigation and resolution (potentially with governance intervention). Admin: GOVERNOR_ROLE","admin":"GOVERNOR_ROLE","gates":["pause","unpause"]},{"name":"OPERATOR_ROLE","notice":"Role identifier for operator accounts","dev":"Operators can: - Perform operational tasks as defined by inheriting contracts - Manage roles that are designated as operator-administered Admin: GOVERNOR_ROLE","admin":"GOVERNOR_ROLE","gates":["sendTokens"]}],"reads":[{"name":"getIssuanceAllocator","sig":"getIssuanceAllocator()","inputs":[],"outputs":[{"name":"","type":"address"}],"mut":"view","doc":{"notice":"Returns the current issuance allocator","returns":{"_0":"The issuance allocator contract (zero address if not set)"}}}],"writes":[{"name":"beforeIssuanceAllocationChange","sig":"beforeIssuanceAllocationChange()","inputs":[],"outputs":[],"mut":"nonpayable","doc":{"notice":"Called by the issuance allocator before the target's issuance allocation changes","details":"For DirectAllocation, this is a no-op since we don't need to perform any calculations before an allocation change. We simply receive tokens from the IssuanceAllocator."}},{"name":"sendTokens","sig":"sendTokens(address,uint256)","inputs":[{"name":"to","type":"address"},{"name":"amount","type":"uint256"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Send tokens to a specified address","params":{"amount":"The amount of tokens to send","to":"The address to send tokens to"}},"access":{"roles":["OPERATOR_ROLE"],"mods":["whenNotPaused"]},"calls":["L2GraphToken"]},{"name":"setIssuanceAllocator","sig":"setIssuanceAllocator(address)","inputs":[{"name":"newIssuanceAllocator","type":"address"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Sets the issuance allocator for this target","details":"This function facilitates upgrades by providing a standard way for targets to change their allocator. Implementations can define their own access control.","params":{"newIssuanceAllocator":"Address of the issuance allocator"}},"access":{"roles":["GOVERNOR_ROLE"],"mods":[]},"emits":["IssuanceAllocatorSet"]}],"events":[{"name":"BeforeIssuanceAllocationChange","sig":"BeforeIssuanceAllocationChange()","inputs":[],"doc":{"notice":"Emitted before the issuance allocation changes"}},{"name":"IssuanceAllocatorSet","sig":"IssuanceAllocatorSet(address,address)","inputs":[{"name":"oldIssuanceAllocator","type":"address","indexed":true},{"name":"newIssuanceAllocator","type":"address","indexed":true}],"doc":{"notice":"New issuance allocator set","params":{"newIssuanceAllocator":"New issuance allocator address","oldIssuanceAllocator":"Old issuance allocator address"}}}],"counts":{"reads":1,"writes":3,"events":2}},{"id":"RecurringAgreementManager","name":"RecurringAgreementManager","layer":"issuance","chain":"L2","core":true,"legacy":false,"address":"0x590dbbbdb1b6261e39bcc1fe88bffc21c847a68e","desc":"Funds recurring collection agreements out of issuance instead of payer deposits. As an issuance target it receives GRT from the IssuanceAllocator, parks it in the Payments Escrow, and owns the agreements that the RecurringCollector draws against, gating collection on provider eligibility. This is how the protocol can pay indexers for indexing on an ongoing, issuance-funded basis.","contractDoc":null,"implements":["IRecurringAgreements","IRecurringAgreementManagement","IRecurringEscrowManagement","IProviderEligibility","IAgreementOwner","IIssuanceTarget"],"deps":[{"to":"IssuanceAllocator","label":"receives issuance from"},{"to":"RecurringCollector","label":"owns agreements on"},{"to":"PaymentsEscrow","label":"funds escrow"},{"to":"L2GraphToken","label":"holds GRT"}],"roles":[{"name":"DATA_SERVICE_ROLE","notice":"Role identifier for approved data service contracts","dev":"Addresses with this role can be used as data services in offered agreements. Admin: GOVERNOR_ROLE","admin":"GOVERNOR_ROLE","gates":[]},{"name":"COLLECTOR_ROLE","notice":"Role identifier for approved collector contracts","dev":"Addresses with this role can be used as collectors in offered agreements. Admin: GOVERNOR_ROLE","admin":"GOVERNOR_ROLE","gates":[]},{"name":"AGREEMENT_MANAGER_ROLE","notice":"Role identifier for agreement lifecycle operations","dev":"Addresses with this role can offer, update, revoke, and cancel agreements. Admin: OPERATOR_ROLE","admin":"OPERATOR_ROLE","gates":["cancelAgreement","offerAgreement"]},{"name":"GOVERNOR_ROLE","notice":"Role identifier for governor accounts","dev":"Governors have the highest level of access and can: - Grant and revoke roles within the established hierarchy - Perform administrative functions and system configuration - Set critical parameters and upgrade contracts Admin of: GOVERNOR_ROLE, PAUSE_ROLE, OPERATOR_ROLE","admin":"GOVERNOR_ROLE","gates":["setIssuanceAllocator","setProviderEligibilityOracle"]},{"name":"PAUSE_ROLE","notice":"Role identifier for pause accounts","dev":"Pause role holders can: - Pause and unpause contract operations for emergency situations Typically granted to automated monitoring systems or emergency responders. Pausing is intended for quick response to potential threats, and giving time for investigation and resolution (potentially with governance intervention). Admin: GOVERNOR_ROLE","admin":"GOVERNOR_ROLE","gates":["emergencyClearEligibilityOracle","emergencyRevokeRole","pause","unpause"]},{"name":"OPERATOR_ROLE","notice":"Role identifier for operator accounts","dev":"Operators can: - Perform operational tasks as defined by inheriting contracts - Manage roles that are designated as operator-administered Admin: GOVERNOR_ROLE","admin":"GOVERNOR_ROLE","gates":["forceRemoveAgreement","setEscrowBasis","setMinFullBasisMargin","setMinOnDemandBasisThreshold","setMinResidualEscrowFactor","setMinThawFraction"]}],"reads":[{"name":"getAgreementAt","sig":"getAgreementAt(address,address,uint256)","inputs":[{"name":"collector","type":"address"},{"name":"provider","type":"address"},{"name":"index","type":"uint256"}],"outputs":[{"name":"agreementId","type":"bytes16"}],"mut":"view","doc":{"notice":"Get a managed agreement ID by index for a (collector, provider) pair","params":{"collector":"The collector contract","index":"The index in the agreement set","provider":"The provider address"},"returns":{"_0":"The agreement ID"}}},{"name":"getAgreementCount","sig":"getAgreementCount(address,address)","inputs":[{"name":"collector","type":"address"},{"name":"provider","type":"address"}],"outputs":[{"name":"count","type":"uint256"}],"mut":"view","doc":{"notice":"Get the number of managed agreements for a (collector, provider) pair","params":{"collector":"The collector contract","provider":"The provider address"},"returns":{"_0":"The pair agreement count"}}},{"name":"getAgreementInfo","sig":"getAgreementInfo(address,bytes16)","inputs":[{"name":"collector","type":"address"},{"name":"agreementId","type":"bytes16"}],"outputs":[{"name":"info","type":"(address,uint256)"}],"mut":"view","doc":{"notice":"Get the full tracked state for a specific agreement","params":{"agreementId":"The agreement ID","collector":"The collector contract"},"returns":{"_0":"The agreement info struct (all fields zero if not tracked)"}}},{"name":"getAgreementMaxNextClaim","sig":"getAgreementMaxNextClaim(address,bytes16)","inputs":[{"name":"collector","type":"address"},{"name":"agreementId","type":"bytes16"}],"outputs":[{"name":"tokens","type":"uint256"}],"mut":"view","doc":{"notice":"Get the max next claim for a specific agreement","params":{"agreementId":"The agreement ID","collector":"The collector contract address"},"returns":{"_0":"The current max next claim stored for this agreement"}}},{"name":"getCollectorAt","sig":"getCollectorAt(uint256)","inputs":[{"name":"index","type":"uint256"}],"outputs":[{"name":"collector","type":"address"}],"mut":"view","doc":{"notice":"Get a collector address by index","params":{"index":"The index in the collector set"},"returns":{"_0":"The collector address"}}},{"name":"getCollectorCount","sig":"getCollectorCount()","inputs":[],"outputs":[{"name":"count","type":"uint256"}],"mut":"view","doc":{"notice":"Get the number of collectors with active agreements","returns":{"_0":"The number of tracked collectors"}}},{"name":"getEscrowAccount","sig":"getEscrowAccount(address,address)","inputs":[{"name":"collector","type":"address"},{"name":"provider","type":"address"}],"outputs":[{"name":"account","type":"(uint256,uint256,uint256)"}],"mut":"view","doc":{"notice":"Get the escrow account for a (collector, provider) pair","params":{"collector":"The collector contract","provider":"The provider address"},"returns":{"account":"The escrow account data"}}},{"name":"getEscrowBasis","sig":"getEscrowBasis()","inputs":[],"outputs":[{"name":"basis","type":"uint8"}],"mut":"view","doc":{"notice":"Get the current escrow basis setting","returns":{"_0":"The configured escrow basis"}}},{"name":"getEscrowSnap","sig":"getEscrowSnap(address,address)","inputs":[{"name":"collector","type":"address"},{"name":"provider","type":"address"}],"outputs":[{"name":"escrowSnap","type":"uint256"}],"mut":"view","doc":{"notice":"Get the cached escrow balance for a (collector, provider) pair","details":"Compare with {getEscrowAccount} to detect stale escrow state requiring reconciliation.","params":{"collector":"The collector contract","provider":"The provider address"},"returns":{"_0":"The last-known escrow balance"}}},{"name":"getIssuanceAllocator","sig":"getIssuanceAllocator()","inputs":[],"outputs":[{"name":"","type":"address"}],"mut":"view","doc":{"notice":"Returns the current issuance allocator","returns":{"_0":"The issuance allocator contract (zero address if not set)"}}},{"name":"getMinFullBasisMargin","sig":"getMinFullBasisMargin()","inputs":[],"outputs":[{"name":"margin","type":"uint8"}],"mut":"view","doc":{"notice":"Get the minimum spare balance margin for Full basis.","details":"Effective basis limited to OnDemand when spare < sumMaxNextClaimAll * (256 + margin) / 256.","returns":{"_0":"The margin added to 256"}}},{"name":"getMinOnDemandBasisThreshold","sig":"getMinOnDemandBasisThreshold()","inputs":[],"outputs":[{"name":"threshold","type":"uint8"}],"mut":"view","doc":{"notice":"Get the minimum spare balance threshold for OnDemand basis.","details":"Effective basis limited to JustInTime when spare < sumMaxNextClaimAll * threshold / 256.","returns":{"_0":"The numerator over 256"}}},{"name":"getMinResidualEscrowFactor","sig":"getMinResidualEscrowFactor()","inputs":[],"outputs":[{"name":"value","type":"uint8"}],"mut":"view","doc":{"notice":"Minimum residual escrow factor for cleanup.","details":"Pairs with no agreements and escrow below 2^value are dropped from tracking.","returns":{"_0":"The exponent (threshold = 2^value)"}}},{"name":"getMinThawFraction","sig":"getMinThawFraction()","inputs":[],"outputs":[{"name":"fraction","type":"uint8"}],"mut":"view","doc":{"notice":"Minimum fraction of sumMaxNextClaim required to initiate an escrow thaw.","details":"Escrow thaw is not initiated if excess is below sumMaxNextClaim * minThawFraction / 256 for a (collector, provider) pair.","returns":{"_0":"The numerator over 256"}}},{"name":"getProviderAt","sig":"getProviderAt(address,uint256)","inputs":[{"name":"collector","type":"address"},{"name":"index","type":"uint256"}],"outputs":[{"name":"provider","type":"address"}],"mut":"view","doc":{"notice":"Get a provider address by index for a given collector","params":{"collector":"The collector contract","index":"The index in the provider set"},"returns":{"_0":"The provider address"}}},{"name":"getProviderCount","sig":"getProviderCount(address)","inputs":[{"name":"collector","type":"address"}],"outputs":[{"name":"count","type":"uint256"}],"mut":"view","doc":{"notice":"Get the number of providers with active agreements for a collector","params":{"collector":"The collector contract"},"returns":{"_0":"The number of tracked providers"}}},{"name":"getProviderEligibilityOracle","sig":"getProviderEligibilityOracle()","inputs":[],"outputs":[{"name":"oracle","type":"address"}],"mut":"view","doc":{"notice":"Get the current provider eligibility oracle","returns":{"_0":"The eligibility oracle (IProviderEligibility(address(0)) means disabled)"}}},{"name":"getSumMaxNextClaim","sig":"getSumMaxNextClaim(address,address)","inputs":[{"name":"collector","type":"address"},{"name":"provider","type":"address"}],"outputs":[{"name":"tokens","type":"uint256"}],"mut":"view","doc":{"notice":"Get the sum of maxNextClaim for all managed agreements for a (collector, provider) pair","params":{"collector":"The collector contract","provider":"The provider address"},"returns":{"_0":"The sum of max next claims"}}},{"name":"getSumMaxNextClaim","sig":"getSumMaxNextClaim()","inputs":[],"outputs":[{"name":"tokens","type":"uint256"}],"mut":"view","doc":{"notice":"Get the sum of maxNextClaim across all (collector, provider) pairs","details":"Populated lazily through normal operations.","returns":{"_0":"The global sum of max next claims"}}},{"name":"getTotalEscrowDeficit","sig":"getTotalEscrowDeficit()","inputs":[],"outputs":[{"name":"tokens","type":"uint256"}],"mut":"view","doc":{"notice":"Get the total undeposited escrow across all (collector, provider) pairs","details":"Maintained incrementally: sum of max(0, sumMaxNextClaim[c][p] - escrowSnap[c][p]) across all pairs. Per-pair clamping prevents over-deposited pairs from masking under-deposited ones.","returns":{"_0":"The total unfunded amount"}}},{"name":"isEligible","sig":"isEligible(address)","inputs":[{"name":"provider","type":"address"}],"outputs":[{"name":"eligible","type":"bool"}],"mut":"view","doc":{"notice":"Check if a service provider is eligible to receive rewards or other payments.","details":"When no oracle is configured (address(0)), all providers are eligible. When an oracle is set, delegates to the oracle's isEligible check.","params":{"provider":"Address of the service provider"},"returns":{"eligible":"True if the provider is eligible, false otherwise"}}}],"writes":[{"name":"afterCollection","sig":"afterCollection(bytes16,uint256)","inputs":[{"name":"agreementId","type":"bytes16"},{"name":"tokensCollected","type":"uint256"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Called by RecurringCollector after a successful collection","details":"Allows contract payers to reconcile escrow state in the same transaction as the collection. Wrapped in try/catch — reverts do not block collection.","params":{"agreementId":"The collected agreement","tokensCollected":"Amount of tokens collected"}},"access":{"roles":[],"mods":["whenNotPaused","nonReentrant"]},"emits":["AgreementReconciled","EscrowWithdrawn","EscrowFunded","AgreementRemoved","ProviderRemoved","CollectorRemoved","AgreementRejected","AgreementAdded"],"calls":["RecurringCollector","PaymentsEscrow","L2GraphToken","IssuanceAllocator"]},{"name":"beforeCollection","sig":"beforeCollection(bytes16,uint256)","inputs":[{"name":"agreementId","type":"bytes16"},{"name":"tokensToCollect","type":"uint256"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Called by RecurringCollector before PaymentsEscrow.collect()","details":"Allows contract payers to top up escrow if the balance is insufficient for the upcoming collection. Wrapped in try/catch — reverts do not block collection.","params":{"agreementId":"The agreement being collected","tokensToCollect":"Amount of tokens about to be collected"}},"access":{"roles":[],"mods":["whenNotPaused","nonReentrant"]},"emits":["AgreementRejected","AgreementAdded"],"calls":["L2GraphToken","PaymentsEscrow","IssuanceAllocator","RecurringCollector"]},{"name":"beforeIssuanceAllocationChange","sig":"beforeIssuanceAllocationChange()","inputs":[],"outputs":[],"mut":"nonpayable","doc":{"notice":"Called by the issuance allocator before the target's issuance allocation changes","details":"The target should ensure that all issuance related calculations are up-to-date with the current block so that an allocation change can be applied correctly. Note that the allocation could change multiple times in the same block after this function has been called, only the final allocation is relevant."}},{"name":"cancelAgreement","sig":"cancelAgreement(address,bytes16,bytes32,uint16)","inputs":[{"name":"collector","type":"address"},{"name":"agreementId","type":"bytes16"},{"name":"versionHash","type":"bytes32"},{"name":"options","type":"uint16"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Cancel an agreement or pending update by routing through the collector.","details":"Requires AGREEMENT_MANAGER_ROLE. Forwards the terms hash to the collector's cancel function, then reconciles locally after the call returns. The collector does not callback to `msg.sender` — see RecurringCollector callback model.","params":{"agreementId":"The agreement ID to cancel","collector":"The collector contract address for this agreement","options":"Bitmask — SCOPE_ACTIVE (1) targets active terms, SCOPE_PENDING (2) targets pending offers.","versionHash":"The terms hash to cancel (activeTerms.hash or pendingTerms.hash)"}},"access":{"roles":["AGREEMENT_MANAGER_ROLE"],"mods":["nonReentrant"]},"emits":["AgreementReconciled","EscrowWithdrawn","EscrowFunded","AgreementRemoved","ProviderRemoved","CollectorRemoved","AgreementRejected","AgreementAdded"],"calls":["RecurringCollector","PaymentsEscrow","L2GraphToken","IssuanceAllocator"]},{"name":"emergencyClearEligibilityOracle","sig":"emergencyClearEligibilityOracle()","inputs":[],"outputs":[],"mut":"nonpayable","doc":{"notice":"Emergency: clear the eligibility oracle so all providers become eligible.","details":"Emergency fail-open: if the oracle is broken or compromised and is wrongly blocking collections, the pause guardian can clear it so all providers become eligible. The governor can later set a replacement oracle."},"access":{"roles":["PAUSE_ROLE"],"mods":[]},"emits":["ProviderEligibilityOracleSet"]},{"name":"forceRemoveAgreement","sig":"forceRemoveAgreement(address,bytes16)","inputs":[{"name":"collector","type":"address"},{"name":"agreementId","type":"bytes16"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Force-remove a tracked agreement whose collector is unresponsive.","details":"Operator escape hatch for when a collector contract reverts on all calls (broken upgrade, self-destruct, permanent pause), making normal reconciliation impossible. Zeroes the agreement's maxNextClaim, removes it from pair tracking, and triggers pair reconciliation to thaw/withdraw the freed escrow. Requires OPERATOR_ROLE. Only use when the collector cannot be fixed.","params":{"agreementId":"The agreement ID to force-remove","collector":"The collector contract address"}},"access":{"roles":["OPERATOR_ROLE"],"mods":["nonReentrant"]},"emits":["AgreementRemoved","ProviderRemoved","CollectorRemoved","EscrowWithdrawn","EscrowFunded"],"calls":["PaymentsEscrow","L2GraphToken","IssuanceAllocator"]},{"name":"offerAgreement","sig":"offerAgreement(address,uint8,bytes)","inputs":[{"name":"collector","type":"address"},{"name":"offerType","type":"uint8"},{"name":"offerData","type":"bytes"}],"outputs":[{"name":"agreementId","type":"bytes16"}],"mut":"nonpayable","doc":{"notice":"Offer an RCA for escrow management.","details":"Forwards opaque offer data to the collector, which decodes and validates it, then reconciles agreement tracking and escrow locally after the call returns. The collector does not callback to `msg.sender` — see RecurringCollector callback model. Requires AGREEMENT_MANAGER_ROLE.","params":{"collector":"The RecurringCollector contract to use for this agreement","offerData":"Opaque ABI-encoded agreement data forwarded to the collector","offerType":"The offer type (OFFER_TYPE_NEW or OFFER_TYPE_UPDATE)"},"returns":{"agreementId":"The deterministic agreement ID"}},"access":{"roles":["AGREEMENT_MANAGER_ROLE"],"mods":["nonReentrant"]},"emits":["AgreementReconciled","EscrowWithdrawn","EscrowFunded","AgreementRemoved","ProviderRemoved","CollectorRemoved","AgreementRejected","AgreementAdded"],"calls":["RecurringCollector","PaymentsEscrow","L2GraphToken","IssuanceAllocator"]},{"name":"reconcileAgreement","sig":"reconcileAgreement(address,bytes16)","inputs":[{"name":"collector","type":"address"},{"name":"agreementId","type":"bytes16"}],"outputs":[{"name":"tracked","type":"bool"}],"mut":"nonpayable","doc":{"notice":"Reconcile a single agreement: re-read on-chain state, recalculate max next claim, update escrow, and delete the agreement if fully settled.","details":"Permissionless. Handles all agreement states: - NotAccepted before deadline: keeps pre-offer estimate (tracked = true) - NotAccepted past deadline: zeroes and deletes (tracked = false) - Accepted/Canceled: reconciles maxNextClaim, deletes if zero Should be called after collections, cancellations, or agreement updates.","params":{"agreementId":"The agreement ID to reconcile","collector":"The collector contract address for this agreement"},"returns":{"tracked":"True if the agreement is still tracked after this call"}},"access":{"roles":[],"mods":["whenNotPaused","nonReentrant"]},"emits":["AgreementReconciled","EscrowWithdrawn","EscrowFunded","AgreementRemoved","ProviderRemoved","CollectorRemoved","AgreementRejected","AgreementAdded"],"calls":["RecurringCollector","PaymentsEscrow","L2GraphToken","IssuanceAllocator"]},{"name":"reconcileProvider","sig":"reconcileProvider(address,address)","inputs":[{"name":"collector","type":"address"},{"name":"provider","type":"address"}],"outputs":[{"name":"tracked","type":"bool"}],"mut":"nonpayable","doc":{"notice":"Reconcile a (collector, provider) pair: rebalance escrow, withdraw completed thaws, and remove tracking if fully drained.","details":"Permissionless. First updates escrow state (deposit deficit, thaw excess, withdraw completed thaws), then removes pair tracking when both agreementCount and escrow balance are zero. Also serves as the permissionless \"poke\" to rebalance escrow after {IRecurringEscrowManagement-setEscrowBasis} or threshold/margin changes. Returns true if the pair still has agreements or escrow is still thawing.","params":{"collector":"The collector address","provider":"The provider address"},"returns":{"tracked":"True if the pair is still tracked after this call"}},"access":{"roles":[],"mods":["whenNotPaused","nonReentrant"]},"emits":["ProviderRemoved","CollectorRemoved","EscrowWithdrawn","EscrowFunded"],"calls":["PaymentsEscrow","L2GraphToken","IssuanceAllocator"]},{"name":"setEscrowBasis","sig":"setEscrowBasis(uint8)","inputs":[{"name":"basis","type":"uint8"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Set the escrow basis (maximum aspiration level).","details":"Requires OPERATOR_ROLE. The system automatically degrades below the configured level when balance is insufficient. Changing the basis does not immediately rebalance escrow — call {IRecurringAgreementManagement-reconcileProvider} per pair to apply.","params":{"basis":"The new escrow basis"}},"access":{"roles":["OPERATOR_ROLE"],"mods":[]},"emits":["EscrowBasisSet"]},{"name":"setIssuanceAllocator","sig":"setIssuanceAllocator(address)","inputs":[{"name":"newIssuanceAllocator","type":"address"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Sets the issuance allocator for this target","details":"The allocator is expected to call distributeIssuance() (bringing distribution up to the current block) before any configuration change. As a result, the same-block dedup in {_ensureIncomingDistributionToCurrentBlock} is harmless: if a prior call already set the block marker, the allocator has already distributed. Governance should set the allocator in a standalone transaction to avoid interleaving with collection in the same block. Even if interleaved, the only effect is a one-block lag before the new allocator's distribution is picked up — corrected automatically on the next block.","params":{"newIssuanceAllocator":"Address of the issuance allocator"}},"access":{"roles":["GOVERNOR_ROLE"],"mods":[]},"emits":["IssuanceAllocatorSet"]},{"name":"setMinFullBasisMargin","sig":"setMinFullBasisMargin(uint8)","inputs":[{"name":"margin","type":"uint8"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Set the minimum spare balance margin for Full basis.","details":"Requires OPERATOR_ROLE. The effective basis is limited to OnDemand when spare balance is not strictly greater than sumMaxNextClaimAll * (256 + minFullBasisMargin) / 256.","params":{"margin":"The margin added to 256 for the spare threshold numerator"}},"access":{"roles":["OPERATOR_ROLE"],"mods":[]},"emits":["MinFullBasisMarginSet"]},{"name":"setMinOnDemandBasisThreshold","sig":"setMinOnDemandBasisThreshold(uint8)","inputs":[{"name":"threshold","type":"uint8"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Set the minimum spare balance threshold for OnDemand basis.","details":"Requires OPERATOR_ROLE. The effective basis is limited to JustInTime when spare balance (balance - totalEscrowDeficit) is not strictly greater than sumMaxNextClaimAll * minOnDemandBasisThreshold / 256.","params":{"threshold":"The numerator over 256 for the spare threshold"}},"access":{"roles":["OPERATOR_ROLE"],"mods":[]},"emits":["MinOnDemandBasisThresholdSet"]},{"name":"setMinResidualEscrowFactor","sig":"setMinResidualEscrowFactor(uint8)","inputs":[{"name":"value","type":"uint8"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Set the minimum residual escrow factor for pair tracking cleanup.","details":"Requires OPERATOR_ROLE. When a (collector, provider) pair has no remaining agreements and the escrow balance is below 2^value, tracking is dropped because the residual is not worth the gas cost of further thaw/withdraw cycles. Funds remain in PaymentsEscrow but are no longer actively managed by RAM. Higher values drop tracking more aggressively. - 0: 2^0 = 1 wei (drop only at zero balance — effectively never drop) - 50: 2^50 ≈ 10^15 (0.001 GRT, default) - 60: 2^60 ≈ 10^18 (1 GRT) - 255: 2^255 (always drop when no agreements remain — effectively disables residual tracking)","params":{"value":"The exponent (threshold = 2^value)"}},"access":{"roles":["OPERATOR_ROLE"],"mods":[]},"emits":["MinResidualEscrowFactorSet"]},{"name":"setMinThawFraction","sig":"setMinThawFraction(uint8)","inputs":[{"name":"fraction","type":"uint8"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Set the minimum fraction to initiate thawing excess escrow.","details":"Requires OPERATOR_ROLE. When excess above max for a (collector, provider) pair is less than sumMaxNextClaim[collector][provider] * minThawFraction / 256, the thaw is skipped. This avoids wasting the thaw timer on negligible amounts and prevents micro-deposit griefing where an attacker deposits dust via depositTo() and triggers reconciliation to start a tiny thaw that blocks legitimate thaw increases. WARNING: Setting fraction to 0 disables the dust threshold entirely, allowing any excess (including dust amounts) to trigger a thaw. This re-enables the micro-deposit griefing vector described above. Setting fraction to very high values (e.g. 255) means thaws are almost never triggered (excess must exceed ~99.6% of sumMaxNextClaim), which can cause escrow to remain over-funded indefinitely. The default of 16 (~6.25%) provides a reasonable balance. Operators should keep this value between 8 and 64.","params":{"fraction":"The numerator over 256 for the dust threshold"}},"access":{"roles":["OPERATOR_ROLE"],"mods":[]},"emits":["MinThawFractionSet"]},{"name":"setProviderEligibilityOracle","sig":"setProviderEligibilityOracle(address)","inputs":[{"name":"oracle","type":"address"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Set the provider eligibility oracle.","details":"When set, {isEligible} delegates to this oracle. When set to IProviderEligibility(address(0)), all providers are considered eligible (passthrough).","params":{"oracle":"The eligibility oracle (or IProviderEligibility(address(0)) to disable)"}},"access":{"roles":["GOVERNOR_ROLE"],"mods":[]},"emits":["ProviderEligibilityOracleSet"]}],"events":[{"name":"AgreementAdded","sig":"AgreementAdded(bytes16,address,address,address)","inputs":[{"name":"agreementId","type":"bytes16","indexed":true},{"name":"collector","type":"address","indexed":true},{"name":"dataService","type":"address","indexed":false},{"name":"provider","type":"address","indexed":true}],"doc":{"notice":"Emitted when an agreement is discovered and registered for escrow management.","params":{"agreementId":"The deterministic agreement ID","collector":"The collector contract address","dataService":"The data service address","provider":"The service provider for this agreement"}}},{"name":"AgreementReconciled","sig":"AgreementReconciled(bytes16,uint256,uint256)","inputs":[{"name":"agreementId","type":"bytes16","indexed":true},{"name":"oldMaxNextClaim","type":"uint256","indexed":false},{"name":"newMaxNextClaim","type":"uint256","indexed":false}],"doc":{"notice":"Emitted when an agreement's max next claim is recalculated","params":{"agreementId":"The agreement ID","newMaxNextClaim":"The updated max next claim","oldMaxNextClaim":"The previous max next claim"}}},{"name":"AgreementRejected","sig":"AgreementRejected(bytes16,address,uint8)","inputs":[{"name":"agreementId","type":"bytes16","indexed":true},{"name":"collector","type":"address","indexed":true},{"name":"reason","type":"uint8","indexed":false}],"doc":{"notice":"Emitted when an agreement callback is ignored because it does not belong to this manager.","details":"Useful for debugging missed agreements.","params":{"agreementId":"The agreement ID","collector":"The collector that sent the callback","reason":"The rejection reason"}}},{"name":"AgreementRemoved","sig":"AgreementRemoved(bytes16)","inputs":[{"name":"agreementId","type":"bytes16","indexed":true}],"doc":{"notice":"Emitted when an agreement is removed from escrow management","params":{"agreementId":"The agreement ID being removed"}}},{"name":"BeforeIssuanceAllocationChange","sig":"BeforeIssuanceAllocationChange()","inputs":[],"doc":{"notice":"Emitted before the issuance allocation changes"}},{"name":"CollectorRemoved","sig":"CollectorRemoved(address)","inputs":[{"name":"collector","type":"address","indexed":true}],"doc":{"notice":"Emitted when a collector is removed from the global tracking set","details":"Emitted when the collector's last provider is removed, cascading from pair removal.","params":{"collector":"The collector address"}}},{"name":"EscrowBasisSet","sig":"EscrowBasisSet(uint8,uint8)","inputs":[{"name":"oldBasis","type":"uint8","indexed":true},{"name":"newBasis","type":"uint8","indexed":true}],"doc":{"notice":"Emitted when the escrow basis is changed","params":{"newBasis":"The new escrow basis","oldBasis":"The previous escrow basis"}}},{"name":"EscrowFunded","sig":"EscrowFunded(address,address,uint256)","inputs":[{"name":"provider","type":"address","indexed":true},{"name":"collector","type":"address","indexed":true},{"name":"deposited","type":"uint256","indexed":false}],"doc":{"notice":"Emitted when escrow is deposited for a provider","params":{"collector":"The collector address for the escrow account","deposited":"The amount deposited","provider":"The provider whose escrow was deposited into"}}},{"name":"EscrowWithdrawn","sig":"EscrowWithdrawn(address,address,uint256)","inputs":[{"name":"provider","type":"address","indexed":true},{"name":"collector","type":"address","indexed":true},{"name":"tokens","type":"uint256","indexed":false}],"doc":{"notice":"Emitted when thawed escrow tokens are withdrawn","params":{"collector":"The collector address for the escrow account","provider":"The provider whose escrow was withdrawn","tokens":"The amount of tokens withdrawn"}}},{"name":"IssuanceAllocatorSet","sig":"IssuanceAllocatorSet(address,address)","inputs":[{"name":"oldIssuanceAllocator","type":"address","indexed":true},{"name":"newIssuanceAllocator","type":"address","indexed":true}],"doc":{"notice":"New issuance allocator set","params":{"newIssuanceAllocator":"New issuance allocator address","oldIssuanceAllocator":"Old issuance allocator address"}}},{"name":"MinFullBasisMarginSet","sig":"MinFullBasisMarginSet(uint8,uint8)","inputs":[{"name":"oldMargin","type":"uint8","indexed":false},{"name":"newMargin","type":"uint8","indexed":false}],"doc":{"notice":"Emitted when the Full basis margin is changed","params":{"newMargin":"The new margin","oldMargin":"The previous margin"}}},{"name":"MinOnDemandBasisThresholdSet","sig":"MinOnDemandBasisThresholdSet(uint8,uint8)","inputs":[{"name":"oldThreshold","type":"uint8","indexed":false},{"name":"newThreshold","type":"uint8","indexed":false}],"doc":{"notice":"Emitted when the OnDemand basis threshold is changed","params":{"newThreshold":"The new threshold","oldThreshold":"The previous threshold"}}},{"name":"MinResidualEscrowFactorSet","sig":"MinResidualEscrowFactorSet(uint8,uint8)","inputs":[{"name":"oldValue","type":"uint8","indexed":false},{"name":"newValue","type":"uint8","indexed":false}],"doc":{"notice":"Emitted when the minimum residual escrow is changed","params":{"newValue":"The new value","oldValue":"The previous value"}}},{"name":"MinThawFractionSet","sig":"MinThawFractionSet(uint8,uint8)","inputs":[{"name":"oldFraction","type":"uint8","indexed":false},{"name":"newFraction","type":"uint8","indexed":false}],"doc":{"notice":"Emitted when the minimum thaw fraction is changed","params":{"newFraction":"The new fraction","oldFraction":"The previous fraction"}}},{"name":"ProviderEligibilityOracleSet","sig":"ProviderEligibilityOracleSet(address,address)","inputs":[{"name":"oldOracle","type":"address","indexed":true},{"name":"newOracle","type":"address","indexed":true}],"doc":{"notice":"Emitted when the provider eligibility oracle is changed","params":{"newOracle":"The new oracle (IProviderEligibility(address(0)) means disabled)","oldOracle":"The previous oracle (IProviderEligibility(address(0)) means none)"}}},{"name":"ProviderRemoved","sig":"ProviderRemoved(address,address)","inputs":[{"name":"collector","type":"address","indexed":true},{"name":"provider","type":"address","indexed":true}],"doc":{"notice":"Emitted when a (collector, provider) pair is removed from tracking","details":"Emitted when the pair has no agreements AND escrow balance is below the residual threshold (2^minResidualEscrowFactor). May cascade inline from agreement deletion or be triggered by {reconcileProvider}.","params":{"collector":"The collector address","provider":"The provider address"}}}],"counts":{"reads":21,"writes":16,"events":16}},{"id":"RecurringAgreementHelper","name":"RecurringAgreementHelper","layer":"issuance","chain":"L2","core":false,"legacy":false,"address":null,"desc":"A stateless, permissionless convenience wrapper around the RecurringAgreementManager that bundles common multi-step calls into one. It holds no funds and no privileged role; it exists purely to make integrating with agreements easier.","contractDoc":null,"implements":["IRecurringAgreementHelper"],"deps":[{"to":"RecurringAgreementManager","label":"convenience calls into"}],"roles":[],"reads":[{"name":"auditGlobal","sig":"auditGlobal()","inputs":[],"outputs":[{"name":"audit","type":"(uint256,uint256,uint256,uint8,uint8,uint8,uint256)"}],"mut":"view","doc":{"notice":"Global financial snapshot of the manager","returns":{"audit":"The global audit struct"}}},{"name":"auditProvider","sig":"auditProvider(address,address)","inputs":[{"name":"collector","type":"address"},{"name":"provider","type":"address"}],"outputs":[{"name":"providerAudit","type":"(address,address,uint256,uint256,uint256,(uint256,uint256,uint256))"}],"mut":"view","doc":{"notice":"Single provider summary","params":{"collector":"The collector address","provider":"The provider address"},"returns":{"pair":"The provider audit struct"}}},{"name":"auditProviders","sig":"auditProviders(address,uint256,uint256)","inputs":[{"name":"collector","type":"address"},{"name":"offset","type":"uint256"},{"name":"count","type":"uint256"}],"outputs":[{"name":"providers","type":"(address,address,uint256,uint256,uint256,(uint256,uint256,uint256))[]"}],"mut":"view","doc":{"notice":"Paginated provider summaries for a collector","params":{"collector":"The collector address","count":"Maximum number to return","offset":"Index to start from"},"returns":{"pairs":"Array of provider audit structs"}}},{"name":"auditProviders","sig":"auditProviders(address)","inputs":[{"name":"collector","type":"address"}],"outputs":[{"name":"providers","type":"(address,address,uint256,uint256,uint256,(uint256,uint256,uint256))[]"}],"mut":"view","doc":{"notice":"All provider summaries for a specific collector","params":{"collector":"The collector address"},"returns":{"pairs":"Array of provider audit structs"}}},{"name":"checkStaleness","sig":"checkStaleness(address,address)","inputs":[{"name":"collector","type":"address"},{"name":"provider","type":"address"}],"outputs":[{"name":"staleAgreements","type":"(bytes16,uint256,uint256,bool)[]"},{"name":"escrowStale","type":"bool"}],"mut":"view","doc":{"notice":"Check which agreements in a (collector, provider) pair need reconciliation","details":"Compares cached maxNextClaim against live collector values.","params":{"collector":"The collector address","provider":"The provider address"},"returns":{"escrowStale":"True if escrowSnap differs from actual escrow balance","staleAgreements":"Array of staleness info per agreement"}}},{"name":"getAgreements","sig":"getAgreements(address,address,uint256,uint256)","inputs":[{"name":"collector","type":"address"},{"name":"provider","type":"address"},{"name":"offset","type":"uint256"},{"name":"count","type":"uint256"}],"outputs":[{"name":"agreementIds","type":"bytes16[]"}],"mut":"view","doc":{"notice":"Get a paginated slice of managed agreement IDs for a (collector, provider) pair","params":{"collector":"The collector address","count":"Maximum number to return (clamped to available)","offset":"The index to start from","provider":"The provider address"},"returns":{"result":"The array of agreement IDs"}}},{"name":"getAgreements","sig":"getAgreements(address,address)","inputs":[{"name":"collector","type":"address"},{"name":"provider","type":"address"}],"outputs":[{"name":"agreementIds","type":"bytes16[]"}],"mut":"view","doc":{"notice":"Get all managed agreement IDs for a (collector, provider) pair","params":{"collector":"The collector address","provider":"The provider address"},"returns":{"_0":"The array of agreement IDs"}}},{"name":"getCollectors","sig":"getCollectors()","inputs":[],"outputs":[{"name":"result","type":"address[]"}],"mut":"view","doc":{"notice":"Get all collector addresses with active agreements","returns":{"_0":"Array of collector addresses"}}},{"name":"getCollectors","sig":"getCollectors(uint256,uint256)","inputs":[{"name":"offset","type":"uint256"},{"name":"count","type":"uint256"}],"outputs":[{"name":"result","type":"address[]"}],"mut":"view","doc":{"notice":"Get a paginated slice of collector addresses","params":{"count":"Maximum number to return (clamped to available)","offset":"The index to start from"},"returns":{"result":"Array of collector addresses"}}},{"name":"getProviders","sig":"getProviders(address,uint256,uint256)","inputs":[{"name":"collector","type":"address"},{"name":"offset","type":"uint256"},{"name":"count","type":"uint256"}],"outputs":[{"name":"result","type":"address[]"}],"mut":"view","doc":{"notice":"Get a paginated slice of provider addresses for a collector","params":{"collector":"The collector address","count":"Maximum number to return (clamped to available)","offset":"The index to start from"},"returns":{"result":"Array of provider addresses"}}},{"name":"getProviders","sig":"getProviders(address)","inputs":[{"name":"collector","type":"address"}],"outputs":[{"name":"result","type":"address[]"}],"mut":"view","doc":{"notice":"Get all provider addresses with active agreements for a collector","params":{"collector":"The collector address"},"returns":{"_0":"Array of provider addresses"}}}],"writes":[{"name":"reconcile","sig":"reconcile(address,address)","inputs":[{"name":"collector","type":"address"},{"name":"provider","type":"address"}],"outputs":[{"name":"removed","type":"uint256"},{"name":"providerExists","type":"bool"}],"mut":"nonpayable","doc":{"notice":"Reconcile all agreements for a (collector, provider) pair, then attempt to remove pair tracking if fully drained.","details":"Permissionless. May require multiple calls if escrow is still thawing.","params":{"collector":"The collector address","provider":"The provider address"},"returns":{"providerExists":"True if the provider is still tracked","removed":"Number of agreements removed"}},"calls":["RecurringAgreementManager"]},{"name":"reconcileAll","sig":"reconcileAll()","inputs":[],"outputs":[{"name":"removed","type":"uint256"}],"mut":"nonpayable","doc":{"notice":"Reconcile all agreements across all collectors and providers.","details":"Permissionless. May hit gas limits with many agreements.","returns":{"removed":"Total agreements removed"}},"calls":["RecurringAgreementManager"]},{"name":"reconcileCollector","sig":"reconcileCollector(address)","inputs":[{"name":"collector","type":"address"}],"outputs":[{"name":"removed","type":"uint256"},{"name":"collectorExists","type":"bool"}],"mut":"nonpayable","doc":{"notice":"Reconcile all pairs for a collector, then attempt collector removal.","details":"Permissionless. O(providers * agreements) gas.","params":{"collector":"The collector address"},"returns":{"collectorExists":"True if the collector is still tracked","removed":"Total agreements removed"}},"calls":["RecurringAgreementManager"]}],"events":[],"counts":{"reads":11,"writes":3,"events":0}},{"id":"RewardsEligibilityOracle","name":"RewardsEligibilityOracle","layer":"issuance","chain":"L2","core":true,"legacy":false,"address":"0x6ba849fbd33257162552578b2a432d30784f2f80","desc":"Lets authorized off-chain oracles mark indexers as eligible (or not) to receive rewards, with an expiry window. The RewardsManager queries it before paying out, so the protocol can withhold rewards from indexers failing service-quality checks. Several instances are deployed on testnet (A, B and a mock).","contractDoc":{"title":"RewardsEligibilityOracle","notice":"This contract allows authorized oracles to mark indexers as eligible to receive rewards with an expiration mechanism. Under normal configuration with reasonable eligibility periods, indexers are denied by default until they are explicitly marked as eligible, and their eligibility expires after a configurable eligibility period. The contract also includes a global eligibility check toggle and an oracle update timeout mechanism."},"implements":["IProviderEligibility","IRewardsEligibilityAdministration","IRewardsEligibilityReporting","IRewardsEligibilityStatus"],"deps":[],"roles":[{"name":"ORACLE_ROLE","notice":"Oracle role identifier","dev":"Oracle role holders can: - Mark indexers as eligible to receive rewards (based on off-chain quality assessment) This role is typically granted to automated quality assessment systems Admin: OPERATOR_ROLE (operators can manage oracle roles)","admin":"OPERATOR_ROLE","gates":["renewIndexerEligibility"]},{"name":"GOVERNOR_ROLE","notice":"Role identifier for governor accounts","dev":"Governors have the highest level of access and can: - Grant and revoke roles within the established hierarchy - Perform administrative functions and system configuration - Set critical parameters and upgrade contracts Admin of: GOVERNOR_ROLE, PAUSE_ROLE, OPERATOR_ROLE","admin":"GOVERNOR_ROLE","gates":[]},{"name":"PAUSE_ROLE","notice":"Role identifier for pause accounts","dev":"Pause role holders can: - Pause and unpause contract operations for emergency situations Typically granted to automated monitoring systems or emergency responders. Pausing is intended for quick response to potential threats, and giving time for investigation and resolution (potentially with governance intervention). Admin: GOVERNOR_ROLE","admin":"GOVERNOR_ROLE","gates":["pause","unpause"]},{"name":"OPERATOR_ROLE","notice":"Role identifier for operator accounts","dev":"Operators can: - Perform operational tasks as defined by inheriting contracts - Manage roles that are designated as operator-administered Admin: GOVERNOR_ROLE","admin":"GOVERNOR_ROLE","gates":["setEligibilityPeriod","setEligibilityValidation","setIndexerRetentionPeriod","setOracleUpdateTimeout"]}],"reads":[{"name":"getEligibilityPeriod","sig":"getEligibilityPeriod()","inputs":[],"outputs":[{"name":"","type":"uint256"}],"mut":"view","doc":{"notice":"Get the eligibility period","returns":{"_0":"The current eligibility period in seconds"}}},{"name":"getEligibilityRenewalTime","sig":"getEligibilityRenewalTime(address)","inputs":[{"name":"indexer","type":"address"}],"outputs":[{"name":"","type":"uint256"}],"mut":"view","doc":{"notice":"Get the last eligibility renewal timestamp for an indexer","params":{"indexer":"Address of the indexer"},"returns":{"_0":"The last eligibility renewal timestamp, or 0 if the indexer's eligibility has never been renewed"}}},{"name":"getEligibilityValidation","sig":"getEligibilityValidation()","inputs":[],"outputs":[{"name":"","type":"bool"}],"mut":"view","doc":{"notice":"Get eligibility validation state","returns":{"_0":"True if eligibility validation is enabled, false otherwise"}}},{"name":"getIndexerCount","sig":"getIndexerCount()","inputs":[],"outputs":[{"name":"count","type":"uint256"}],"mut":"view","doc":{"notice":"Get the number of tracked indexers","returns":{"_0":"The number of indexers in the tracked set"}}},{"name":"getIndexerRetentionPeriod","sig":"getIndexerRetentionPeriod()","inputs":[],"outputs":[{"name":"","type":"uint256"}],"mut":"view","doc":{"notice":"Get the indexer retention period for tracked indexer cleanup","returns":{"_0":"The current indexer retention period in seconds"}}},{"name":"getIndexers","sig":"getIndexers(uint256,uint256)","inputs":[{"name":"offset","type":"uint256"},{"name":"count","type":"uint256"}],"outputs":[{"name":"result","type":"address[]"}],"mut":"view","doc":{"notice":"Get a paginated slice of tracked indexer addresses","params":{"count":"Maximum number to return (clamped to available)","offset":"The index to start from"},"returns":{"_0":"Array of tracked indexer addresses"}}},{"name":"getIndexers","sig":"getIndexers()","inputs":[],"outputs":[{"name":"result","type":"address[]"}],"mut":"view","doc":{"notice":"Get all tracked indexer addresses","details":"May be expensive for large sets — prefer the paginated overload for on-chain use.","returns":{"_0":"Array of tracked indexer addresses"}}},{"name":"getLastOracleUpdateTime","sig":"getLastOracleUpdateTime()","inputs":[],"outputs":[{"name":"","type":"uint256"}],"mut":"view","doc":{"notice":"Get the last oracle update time","returns":{"_0":"The timestamp of the last oracle update"}}},{"name":"getOracleUpdateTimeout","sig":"getOracleUpdateTimeout()","inputs":[],"outputs":[{"name":"","type":"uint256"}],"mut":"view","doc":{"notice":"Get the oracle update timeout","returns":{"_0":"The current oracle update timeout in seconds"}}},{"name":"isEligible","sig":"isEligible(address)","inputs":[{"name":"provider","type":"address"}],"outputs":[{"name":"eligible","type":"bool"}],"mut":"view","doc":{"notice":"Check if a service provider is eligible to receive rewards or other payments.","details":"Returns true if any of the following conditions are met: 1. Eligibility validation is disabled globally 2. Oracle timeout has been exceeded (fail-safe to allow all indexers) 3. block.timestamp < indexerEligibilityTimestamps[indexer] + eligibilityPeriod Note on condition 3: For indexers who have never been registered, indexerEligibilityTimestamps[indexer] is 0. If eligibilityPeriod is set to an extremely large value exceeding block.timestamp, the check becomes (block.timestamp < 0 + eligibilityPeriod), which will be true, making all indexers eligible.","params":{"provider":"Address of the service provider"},"returns":{"_0":"True if the provider is eligible, false otherwise"}}}],"writes":[{"name":"removeExpiredIndexer","sig":"removeExpiredIndexer(address)","inputs":[{"name":"indexer","type":"address"}],"outputs":[{"name":"gone","type":"bool"}],"mut":"nonpayable","doc":{"notice":"Remove an expired indexer from the tracked set","details":"Permissionless. An indexer is expired when `block.timestamp >= renewalTimestamp + indexerRetentionPeriod`. Removes the indexer from the enumerable set and deletes its renewal timestamp. No-op (returns true) if the indexer is not in the tracked set.","params":{"indexer":"The indexer address to remove"},"returns":{"gone":"True if the indexer is absent from the tracked set (whether removed by this call or already not tracked); false if the indexer is still tracked (not expired)"}},"emits":["IndexerTrackingUpdated"]},{"name":"renewIndexerEligibility","sig":"renewIndexerEligibility(address[],bytes)","inputs":[{"name":"indexers","type":"address[]"},{"name":"data","type":"bytes"}],"outputs":[{"name":"","type":"uint256"}],"mut":"nonpayable","doc":{"notice":"Renew eligibility for provided indexers to receive rewards","params":{"data":"Arbitrary calldata for future extensions","indexers":"Array of indexer addresses. Zero addresses are ignored."},"returns":{"_0":"Number of indexers whose eligibility renewal timestamp was updated"}},"access":{"roles":["ORACLE_ROLE"],"mods":[]},"emits":["IndexerEligibilityData","IndexerTrackingUpdated","IndexerEligibilityRenewed"]},{"name":"setEligibilityPeriod","sig":"setEligibilityPeriod(uint256)","inputs":[{"name":"eligibilityPeriod","type":"uint256"}],"outputs":[{"name":"","type":"bool"}],"mut":"nonpayable","doc":{"notice":"Set the eligibility period for indexers","details":"Only callable by accounts with the OPERATOR_ROLE","params":{"eligibilityPeriod":"New eligibility period in seconds"},"returns":{"_0":"True if the state is as requested (eligibility period is set to the specified value)"}},"access":{"roles":["OPERATOR_ROLE"],"mods":[]},"emits":["EligibilityPeriodUpdated"]},{"name":"setEligibilityValidation","sig":"setEligibilityValidation(bool)","inputs":[{"name":"enabled","type":"bool"}],"outputs":[{"name":"","type":"bool"}],"mut":"nonpayable","doc":{"notice":"Set eligibility validation state","details":"Only callable by accounts with the OPERATOR_ROLE","params":{"enabled":"True to enable eligibility validation, false to disable"},"returns":{"_0":"True if successfully set (always the case for current code)"}},"access":{"roles":["OPERATOR_ROLE"],"mods":[]},"emits":["EligibilityValidationUpdated"]},{"name":"setIndexerRetentionPeriod","sig":"setIndexerRetentionPeriod(uint256)","inputs":[{"name":"indexerRetentionPeriod","type":"uint256"}],"outputs":[{"name":"","type":"bool"}],"mut":"nonpayable","doc":{"notice":"Set the indexer retention period for tracked indexer cleanup","details":"Only callable by accounts with the OPERATOR_ROLE. Indexers whose last renewal timestamp is older than this period can be permissionlessly removed from the tracked set via {IRewardsEligibilityMaintenance-removeStaleIndexer}.","params":{"indexerRetentionPeriod":"New retention period in seconds"},"returns":{"_0":"True if the state is as requested (retention period is set to the specified value)"}},"access":{"roles":["OPERATOR_ROLE"],"mods":[]},"emits":["IndexerRetentionPeriodSet"]},{"name":"setOracleUpdateTimeout","sig":"setOracleUpdateTimeout(uint256)","inputs":[{"name":"oracleUpdateTimeout","type":"uint256"}],"outputs":[{"name":"","type":"bool"}],"mut":"nonpayable","doc":{"notice":"Set the oracle update timeout","details":"Only callable by accounts with the OPERATOR_ROLE","params":{"oracleUpdateTimeout":"New timeout period in seconds"},"returns":{"_0":"True if the state is as requested (timeout is set to the specified value)"}},"access":{"roles":["OPERATOR_ROLE"],"mods":[]},"emits":["OracleUpdateTimeoutUpdated"]}],"events":[{"name":"EligibilityPeriodUpdated","sig":"EligibilityPeriodUpdated(uint256,uint256)","inputs":[{"name":"oldPeriod","type":"uint256","indexed":true},{"name":"newPeriod","type":"uint256","indexed":true}],"doc":{"notice":"Emitted when the eligibility period is updated","params":{"newPeriod":"The new eligibility period in seconds","oldPeriod":"The previous eligibility period in seconds"}}},{"name":"EligibilityValidationUpdated","sig":"EligibilityValidationUpdated(bool)","inputs":[{"name":"enabled","type":"bool","indexed":true}],"doc":{"notice":"Emitted when eligibility validation is enabled or disabled","params":{"enabled":"True if eligibility validation is enabled, false if disabled"}}},{"name":"IndexerEligibilityData","sig":"IndexerEligibilityData(address,bytes)","inputs":[{"name":"oracle","type":"address","indexed":true},{"name":"data","type":"bytes","indexed":false}],"doc":{"notice":"Emitted when an oracle submits eligibility data","params":{"data":"The eligibility data submitted by the oracle","oracle":"The address of the oracle that submitted the data"}}},{"name":"IndexerEligibilityRenewed","sig":"IndexerEligibilityRenewed(address,address)","inputs":[{"name":"indexer","type":"address","indexed":true},{"name":"oracle","type":"address","indexed":true}],"doc":{"notice":"Emitted when an indexer's eligibility is renewed by an oracle","params":{"indexer":"The address of the indexer whose eligibility was renewed","oracle":"The address of the oracle that renewed the indexer's eligibility"}}},{"name":"IndexerRetentionPeriodSet","sig":"IndexerRetentionPeriodSet(uint256,uint256)","inputs":[{"name":"oldPeriod","type":"uint256","indexed":true},{"name":"newPeriod","type":"uint256","indexed":true}],"doc":{"notice":"Emitted when the indexer retention period is updated","params":{"newPeriod":"The new retention period in seconds","oldPeriod":"The previous retention period in seconds"}}},{"name":"IndexerTrackingUpdated","sig":"IndexerTrackingUpdated(address,bool)","inputs":[{"name":"indexer","type":"address","indexed":true},{"name":"tracked","type":"bool","indexed":true}],"doc":{"notice":"Emitted when an indexer is added to or removed from the tracked set","params":{"indexer":"The indexer address","tracked":"True when added (first renewal), false when removed (stale cleanup)"}}},{"name":"OracleUpdateTimeoutUpdated","sig":"OracleUpdateTimeoutUpdated(uint256,uint256)","inputs":[{"name":"oldTimeout","type":"uint256","indexed":true},{"name":"newTimeout","type":"uint256","indexed":true}],"doc":{"notice":"Emitted when the oracle update timeout is updated","params":{"newTimeout":"The new timeout period in seconds","oldTimeout":"The previous timeout period in seconds"}}}],"counts":{"reads":10,"writes":6,"events":7}},{"id":"RewardsEligibilityHelper","name":"RewardsEligibilityHelper","layer":"issuance","chain":"L2","core":false,"legacy":false,"address":null,"desc":"A stateless, permissionless convenience wrapper around the RewardsEligibilityOracle that bundles common oracle calls. It holds no state of its own.","contractDoc":null,"implements":["IRewardsEligibilityHelper"],"deps":[{"to":"RewardsEligibilityOracle","label":"convenience calls into"}],"roles":[],"reads":[],"writes":[{"name":"removeExpiredIndexers","sig":"removeExpiredIndexers(address[])","inputs":[{"name":"indexers","type":"address[]"}],"outputs":[{"name":"gone","type":"uint256"}],"mut":"nonpayable","doc":{"notice":"Remove expired indexers from the tracked set by explicit address list","details":"Calls {IRewardsEligibilityMaintenance-removeExpiredIndexer} for each address.","params":{"indexers":"Array of indexer addresses to check and remove"},"returns":{"gone":"Number of indexers now absent from the tracked set"}},"calls":["RewardsEligibilityOracle"]},{"name":"removeExpiredIndexers","sig":"removeExpiredIndexers()","inputs":[],"outputs":[{"name":"gone","type":"uint256"}],"mut":"nonpayable","doc":{"notice":"Remove all expired indexers from the tracked set","details":"Snapshots the full tracked set then calls {IRewardsEligibilityMaintenance-removeExpiredIndexer} for each. May be expensive for large sets; prefer the paginated overload for gas-bounded calls.","returns":{"gone":"Number of indexers now absent from the tracked set"}},"calls":["RewardsEligibilityOracle"]},{"name":"removeExpiredIndexers","sig":"removeExpiredIndexers(uint256,uint256)","inputs":[{"name":"offset","type":"uint256"},{"name":"count","type":"uint256"}],"outputs":[{"name":"gone","type":"uint256"}],"mut":"nonpayable","doc":{"notice":"Remove expired indexers from the tracked set by paginated scan","details":"Reads a slice of the tracked set via {IRewardsEligibilityStatus-getIndexers} and calls {IRewardsEligibilityMaintenance-removeExpiredIndexer} for each. Note: removals shift set indices between pages, so some indexers may be skipped across consecutive paginated calls. Use the parameterless overload to process all.","params":{"count":"Maximum number of indexers to process","offset":"Start index into the tracked indexer set"},"returns":{"gone":"Number of indexers now absent from the tracked set"}},"calls":["RewardsEligibilityOracle"]}],"events":[],"counts":{"reads":0,"writes":3,"events":0}},{"id":"Curation","name":"L2Curation","layer":"curation","chain":"L2","core":true,"legacy":false,"address":null,"desc":"Curators deposit GRT to \"signal\" on the subgraph deployments they think indexers should serve, receiving curation shares in return. The amount of signal on a subgraph steers how many indexing rewards it earns, and curators take a small cut of the query fees that flow through it.","contractDoc":{"title":"L2Curation contract","notice":"Allows curators to signal on subgraph deployments that might be relevant to indexers by staking Graph Tokens (GRT). Additionally, curators earn fees from the Query Market related to the subgraph deployment they curate. A curators deposit goes to a curation pool along with the deposits of other curators, only one such pool exists for each subgraph deployment. The contract mints Graph Curation Shares (GCS) according to a (flat) bonding curve for each individual curation pool where GRT is deposited. Holders can burn GCS using this contract to get GRT tokens back according to the bonding curve."},"implements":["IL2Curation","ICuration"],"deps":[{"to":"GraphCurationToken","label":"mints signal shares"},{"to":"L2GraphToken","label":"holds curation reserves"}],"roles":[],"reads":[{"name":"curationTaxPercentage","sig":"curationTaxPercentage()","inputs":[],"outputs":[{"name":"","type":"uint32"}],"mut":"view","doc":{"notice":"Tax charged when curators deposit funds. Parts per million. (Allows for 4 decimal points, 999,999 = 99.9999%)","returns":{"_0":"Curation tax percentage expressed in PPM"}}},{"name":"getCurationPoolSignal","sig":"getCurationPoolSignal(bytes32)","inputs":[{"name":"subgraphDeploymentID","type":"bytes32"}],"outputs":[{"name":"","type":"uint256"}],"mut":"view","doc":{"notice":"Get the amount of signal in a curation pool.","params":{"_subgraphDeploymentID":"Subgraph deployment curation pool"},"returns":{"_0":"Amount of signal minted for the subgraph deployment"}}},{"name":"getCurationPoolTokens","sig":"getCurationPoolTokens(bytes32)","inputs":[{"name":"subgraphDeploymentID","type":"bytes32"}],"outputs":[{"name":"","type":"uint256"}],"mut":"view","doc":{"notice":"Get the amount of token reserves in a curation pool.","params":{"_subgraphDeploymentID":"Subgraph deployment curation pool"},"returns":{"_0":"Amount of token reserves in the curation pool"}}},{"name":"getCuratorSignal","sig":"getCuratorSignal(address,bytes32)","inputs":[{"name":"curator","type":"address"},{"name":"subgraphDeploymentID","type":"bytes32"}],"outputs":[{"name":"","type":"uint256"}],"mut":"view","doc":{"notice":"Get the amount of signal a curator has in a curation pool.","params":{"_curator":"Curator owning the signal tokens","_subgraphDeploymentID":"Subgraph deployment curation pool"},"returns":{"_0":"Amount of signal owned by a curator for the subgraph deployment"}}},{"name":"isCurated","sig":"isCurated(bytes32)","inputs":[{"name":"subgraphDeploymentID","type":"bytes32"}],"outputs":[{"name":"","type":"bool"}],"mut":"view","doc":{"notice":"Check if any GRT tokens are deposited for a SubgraphDeployment.","params":{"_subgraphDeploymentID":"SubgraphDeployment to check if curated"},"returns":{"_0":"True if curated"}}},{"name":"signalToTokens","sig":"signalToTokens(bytes32,uint256)","inputs":[{"name":"subgraphDeploymentID","type":"bytes32"},{"name":"signalIn","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}],"mut":"view","doc":{"notice":"Calculate number of tokens to get when burning signal from a curation pool.","params":{"_signalIn":"Amount of signal to burn","_subgraphDeploymentID":"Subgraph deployment for which to burn signal"},"returns":{"_0":"Amount of tokens to get for an amount of signal"}}},{"name":"tokensToSignal","sig":"tokensToSignal(bytes32,uint256)","inputs":[{"name":"subgraphDeploymentID","type":"bytes32"},{"name":"tokensIn","type":"uint256"}],"outputs":[{"name":"","type":"uint256"},{"name":"","type":"uint256"}],"mut":"view","doc":{"notice":"Calculate amount of signal that can be bought with tokens in a curation pool. This function considers and excludes the deposit tax.","params":{"_subgraphDeploymentID":"Subgraph deployment to mint signal","_tokensIn":"Amount of tokens used to mint signal"},"returns":{"_0":"Amount of signal that can be bought","_1":"Amount of GRT that would be subtracted as curation tax"}}},{"name":"tokensToSignalNoTax","sig":"tokensToSignalNoTax(bytes32,uint256)","inputs":[{"name":"subgraphDeploymentID","type":"bytes32"},{"name":"tokensIn","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}],"mut":"view","doc":{"notice":"Calculate amount of signal that can be bought with tokens in a curation pool, without accounting for curation tax.","params":{"subgraphDeploymentID":"Subgraph deployment for which to mint signal","tokensIn":"Amount of tokens used to mint signal"},"returns":{"_0":"Amount of signal that can be bought"}}},{"name":"tokensToSignalToTokensNoTax","sig":"tokensToSignalToTokensNoTax(bytes32,uint256)","inputs":[{"name":"subgraphDeploymentID","type":"bytes32"},{"name":"tokensIn","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}],"mut":"view","doc":{"notice":"Calculate the amount of tokens that would be recovered if minting signal with the input tokens and then burning it. This can be used to compute rounding error. This function does not account for curation tax.","params":{"subgraphDeploymentID":"Subgraph deployment for which to mint signal","tokensIn":"Amount of tokens used to mint signal"},"returns":{"_0":"Amount of tokens that would be recovered after minting and burning signal"}}}],"writes":[{"name":"burn","sig":"burn(bytes32,uint256,uint256)","inputs":[{"name":"subgraphDeploymentID","type":"bytes32"},{"name":"signalIn","type":"uint256"},{"name":"tokensOutMin","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}],"mut":"nonpayable","doc":{"notice":"Burn _signalIn from the SubgraphDeployment curation pool","details":"Return an amount of signal to get tokens back.","params":{"_signalIn":"Amount of signal to return","_subgraphDeploymentID":"SubgraphDeployment for which the curator is returning signal","_tokensOutMin":"Expected minimum amount of tokens to receive"},"returns":{"_0":"Amount of tokens returned to the sender"}},"calls":["GraphCurationToken"]},{"name":"collect","sig":"collect(bytes32,uint256)","inputs":[{"name":"subgraphDeploymentID","type":"bytes32"},{"name":"tokens","type":"uint256"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Assign Graph Tokens collected as curation fees to the curation pool reserve.","details":"This function can only be called by the Staking contract and will do the Bookkeeping of transferred tokens into this contract.","params":{"_subgraphDeploymentID":"SubgraphDeployment where funds should be allocated as reserves","_tokens":"Amount of Graph Tokens to add to reserves"}}},{"name":"mint","sig":"mint(bytes32,uint256,uint256)","inputs":[{"name":"subgraphDeploymentID","type":"bytes32"},{"name":"tokensIn","type":"uint256"},{"name":"signalOutMin","type":"uint256"}],"outputs":[{"name":"","type":"uint256"},{"name":"","type":"uint256"}],"mut":"nonpayable","doc":{"notice":"Deposit Graph Tokens in exchange for signal of a SubgraphDeployment curation pool.","params":{"_signalOutMin":"Expected minimum amount of signal to receive","_subgraphDeploymentID":"Subgraph deployment pool from where to mint signal","_tokensIn":"Amount of Graph Tokens to deposit"},"returns":{"_0":"Signal minted","_1":"Curation tax paid"}},"calls":["GraphCurationToken"]},{"name":"mintTaxFree","sig":"mintTaxFree(bytes32,uint256)","inputs":[{"name":"subgraphDeploymentID","type":"bytes32"},{"name":"tokensIn","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}],"mut":"nonpayable","doc":{"notice":"Deposit Graph Tokens in exchange for signal of a SubgraphDeployment curation pool.","details":"This function charges no tax and can only be called by GNS in specific scenarios (for now only during an L1-L2 transfer).","params":{"subgraphDeploymentID":"Subgraph deployment pool from where to mint signal","tokensIn":"Amount of Graph Tokens to deposit"},"returns":{"_0":"Signal minted"}},"calls":["GraphCurationToken"]},{"name":"setCurationTaxPercentage","sig":"setCurationTaxPercentage(uint32)","inputs":[{"name":"percentage","type":"uint32"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Set the curation tax percentage to charge when a curator deposits GRT tokens.","params":{"_percentage":"Curation tax percentage charged when depositing GRT tokens"}},"access":{"roles":[],"mods":["onlyGovernor"]}},{"name":"setCurationTokenMaster","sig":"setCurationTokenMaster(address)","inputs":[{"name":"curationTokenMaster","type":"address"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Set the master copy to use as clones for the curation token.","params":{"_curationTokenMaster":"Address of implementation contract to use for curation tokens"}},"access":{"roles":[],"mods":["onlyGovernor"]}},{"name":"setDefaultReserveRatio","sig":"setDefaultReserveRatio(uint32)","inputs":[{"name":"defaultReserveRatio","type":"uint32"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Set the default reserve ratio - not implemented in L2","details":"We only keep this for compatibility with ICuration","params":{"_defaultReserveRatio":"Reserve ratio (in PPM)"}},"access":{"roles":[],"mods":["onlyGovernor"]}},{"name":"setMinimumCurationDeposit","sig":"setMinimumCurationDeposit(uint256)","inputs":[{"name":"minimumCurationDeposit","type":"uint256"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Update the minimum deposit amount to `_minimumCurationDeposit`","details":"Set the minimum deposit amount for curators.","params":{"_minimumCurationDeposit":"Minimum amount of tokens required deposit"}},"access":{"roles":[],"mods":["onlyGovernor"]}},{"name":"setSubgraphService","sig":"setSubgraphService(address)","inputs":[{"name":"subgraphService","type":"address"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Set the subgraph service address","params":{"_subgraphService":"Address of the subgraph service contract"}},"access":{"roles":[],"mods":["onlyGovernor"]}}],"events":[],"counts":{"reads":9,"writes":9,"events":0}},{"id":"GraphCurationToken","name":"GraphCurationToken","layer":"curation","chain":"L2","core":false,"legacy":false,"address":"0x00FBd5D46FFAc54862c1Dd27BE08924BB17f5CDa","desc":"The ERC-20 share token minted by Curation to represent a curator's position on a single subgraph deployment. One token contract is deployed per curation pool; burning shares returns the underlying GRT.","contractDoc":{"title":"GraphCurationToken contract","notice":"This is the implementation of the Curation ERC20 token (GCS). GCS are created for each subgraph deployment curated in the Curation contract. The Curation contract is the owner of GCS tokens and the only one allowed to mint or burn them. GCS tokens are transferrable and their holders can do any action allowed in a standard ERC20 token implementation except for burning them. This contract is meant to be used as the implementation for Minimal Proxy clones for gas-saving purposes."},"implements":["IGraphCurationToken","ERC20"],"deps":[],"roles":[],"reads":[{"name":"allowance","sig":"allowance(address,address)","inputs":[{"name":"owner","type":"address"},{"name":"spender","type":"address"}],"outputs":[{"name":"","type":"uint256"}],"mut":"view","doc":{"details":"See {IERC20-allowance}."}},{"name":"balanceOf","sig":"balanceOf(address)","inputs":[{"name":"account","type":"address"}],"outputs":[{"name":"","type":"uint256"}],"mut":"view","doc":{"details":"See {IERC20-balanceOf}."}},{"name":"totalSupply","sig":"totalSupply()","inputs":[],"outputs":[{"name":"","type":"uint256"}],"mut":"view","doc":{"details":"See {IERC20-totalSupply}."}}],"writes":[{"name":"approve","sig":"approve(address,uint256)","inputs":[{"name":"spender","type":"address"},{"name":"amount","type":"uint256"}],"outputs":[{"name":"","type":"bool"}],"mut":"nonpayable","doc":{"details":"See {IERC20-approve}. Requirements: - `spender` cannot be the zero address."}},{"name":"burnFrom","sig":"burnFrom(address,uint256)","inputs":[{"name":"account","type":"address"},{"name":"amount","type":"uint256"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Burn tokens from an address.","params":{"_account":"Address from where tokens will be burned","_amount":"Amount of tokens to burn"}},"access":{"roles":[],"mods":["onlyGovernor"]}},{"name":"initialize","sig":"initialize(address)","inputs":[{"name":"owner","type":"address"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Graph Curation Token Contract initializer.","params":{"_owner":"Address of the contract issuing this token"}}},{"name":"mint","sig":"mint(address,uint256)","inputs":[{"name":"to","type":"address"},{"name":"amount","type":"uint256"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Mint new tokens.","params":{"_amount":"Amount of tokens to mint","_to":"Address to send the newly minted tokens"}},"access":{"roles":[],"mods":["onlyGovernor"]}},{"name":"transfer","sig":"transfer(address,uint256)","inputs":[{"name":"recipient","type":"address"},{"name":"amount","type":"uint256"}],"outputs":[{"name":"","type":"bool"}],"mut":"nonpayable","doc":{"details":"See {IERC20-transfer}. Requirements: - `recipient` cannot be the zero address. - the caller must have a balance of at least `amount`."}},{"name":"transferFrom","sig":"transferFrom(address,address,uint256)","inputs":[{"name":"sender","type":"address"},{"name":"recipient","type":"address"},{"name":"amount","type":"uint256"}],"outputs":[{"name":"","type":"bool"}],"mut":"nonpayable","doc":{"details":"See {IERC20-transferFrom}. Emits an {Approval} event indicating the updated allowance. This is not required by the EIP. See the note at the beginning of {ERC20}. Requirements: - `sender` and `recipient` cannot be the zero address. - `sender` must have a balance of at least `amount`. - the caller must have allowance for ``sender``'s tokens of at least `amount`."}}],"events":[{"name":"Approval","sig":"Approval(address,address,uint256)","inputs":[{"name":"owner","type":"address","indexed":true},{"name":"spender","type":"address","indexed":true},{"name":"value","type":"uint256","indexed":false}]},{"name":"Transfer","sig":"Transfer(address,address,uint256)","inputs":[{"name":"from","type":"address","indexed":true},{"name":"to","type":"address","indexed":true},{"name":"value","type":"uint256","indexed":false}]}],"counts":{"reads":3,"writes":6,"events":2}},{"id":"L2GNS","name":"L2GNS","layer":"curation","chain":"L2","core":true,"legacy":false,"address":"0x3133948342F35b8699d8F94aeE064AbB76eDe965","desc":"The Graph Name System: the human-facing registry of \"subgraphs\" that developers publish and version. Each published subgraph is an NFT whose owner can point it at different underlying deployments. It also receives subgraphs bridged from L1 and auto-migrates their curation.","contractDoc":{"title":"L2GNS","notice":"The Graph Name System contract provides a decentralized naming system for subgraphs used in the scope of the Graph Network. It translates Subgraphs into Subgraph Versions. Each version is associated with a Subgraph Deployment. The contract has no knowledge of human-readable names. All human readable names emitted in events. The contract implements a multicall behaviour to support batching multiple calls in a single transaction. This particular contract is meant to be deployed in L2, and includes helper functions to receive subgraphs that are transferred from L1."},"implements":["IL2GNS","IGNS"],"deps":[{"to":"SubgraphNFT","label":"mints ownership NFTs"},{"to":"Curation","label":"curates deployments"},{"to":"L2GraphToken","label":"handles signal GRT"}],"roles":[],"reads":[{"name":"getAliasedL2SubgraphID","sig":"getAliasedL2SubgraphID(uint256)","inputs":[{"name":"l1SubgraphID","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}],"mut":"pure","doc":{"notice":"Return the aliased L2 subgraph ID from a transferred L1 subgraph ID","params":{"l1SubgraphID":"L1 subgraph ID"},"returns":{"_0":"L2 subgraph ID"}}},{"name":"getCuratorSignal","sig":"getCuratorSignal(uint256,address)","inputs":[{"name":"subgraphID","type":"uint256"},{"name":"curator","type":"address"}],"outputs":[{"name":"","type":"uint256"}],"mut":"view","doc":{"notice":"Get the amount of subgraph signal a curator has.","params":{"curator":"Curator address","subgraphID":"Subgraph ID"},"returns":{"_0":"Amount of subgraph signal owned by a curator"}}},{"name":"getLegacySubgraphKey","sig":"getLegacySubgraphKey(uint256)","inputs":[{"name":"subgraphID","type":"uint256"}],"outputs":[{"name":"account","type":"address"},{"name":"seqID","type":"uint256"}],"mut":"view","doc":{"notice":"Returns account and sequence ID for a legacy subgraph (created before subgraph NFTs).","params":{"subgraphID":"Subgraph ID"},"returns":{"account":"Account that created the subgraph (or 0 if it's not a legacy subgraph)","seqID":"Sequence number for the subgraph"}}},{"name":"getUnaliasedL1SubgraphID","sig":"getUnaliasedL1SubgraphID(uint256)","inputs":[{"name":"l2SubgraphID","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}],"mut":"pure","doc":{"notice":"Return the unaliased L1 subgraph ID from a transferred L2 subgraph ID","params":{"l2SubgraphID":"L2 subgraph ID"},"returns":{"_0":"L1subgraph ID"}}},{"name":"isLegacySubgraph","sig":"isLegacySubgraph(uint256)","inputs":[{"name":"subgraphID","type":"uint256"}],"outputs":[{"name":"","type":"bool"}],"mut":"view","doc":{"notice":"Return whether a subgraph is a legacy subgraph (created before subgraph NFTs).","params":{"_subgraphID":"Subgraph ID"},"returns":{"_0":"Return true if subgraph is a legacy subgraph"}}},{"name":"isPublished","sig":"isPublished(uint256)","inputs":[{"name":"subgraphID","type":"uint256"}],"outputs":[{"name":"","type":"bool"}],"mut":"view","doc":{"notice":"Return whether a subgraph is published.","params":{"subgraphID":"Subgraph ID"},"returns":{"_0":"Return true if subgraph is currently published"}}},{"name":"nSignalToTokens","sig":"nSignalToTokens(uint256,uint256)","inputs":[{"name":"subgraphID","type":"uint256"},{"name":"nSignalIn","type":"uint256"}],"outputs":[{"name":"","type":"uint256"},{"name":"","type":"uint256"}],"mut":"view","doc":{"notice":"Calculate tokens returned for an amount of subgraph signal.","params":{"_nSignalIn":"Subgraph signal being exchanged for tokens","_subgraphID":"Subgraph ID"},"returns":{"_0":"vSignalOut Amount of version signal burned","_1":"tokensOut Amount of tokens returned"}}},{"name":"nSignalToVSignal","sig":"nSignalToVSignal(uint256,uint256)","inputs":[{"name":"subgraphID","type":"uint256"},{"name":"nSignalIn","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}],"mut":"view","doc":{"notice":"Calculate subgraph deployment signal to be returned for an amount of subgraph signal.","params":{"nSignalIn":"Subgraph signal being exchanged for subgraph deployment signal","subgraphID":"Subgraph ID"},"returns":{"_0":"Amount of subgraph deployment signal that can be returned"}}},{"name":"ownerOf","sig":"ownerOf(uint256)","inputs":[{"name":"tokenID","type":"uint256"}],"outputs":[{"name":"","type":"address"}],"mut":"view","doc":{"notice":"Return the owner of a subgraph.","params":{"tokenID":"Subgraph ID"},"returns":{"_0":"Owner address"}}},{"name":"subgraphSignal","sig":"subgraphSignal(uint256)","inputs":[{"name":"subgraphID","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}],"mut":"view","doc":{"notice":"Return the total signal on the subgraph.","params":{"_subgraphID":"Subgraph ID"},"returns":{"_0":"Total signal on the subgraph"}}},{"name":"subgraphTokens","sig":"subgraphTokens(uint256)","inputs":[{"name":"subgraphID","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}],"mut":"view","doc":{"notice":"Return the total tokens on the subgraph at current value.","params":{"_subgraphID":"Subgraph ID"},"returns":{"_0":"Total tokens on the subgraph"}}},{"name":"tokensToNSignal","sig":"tokensToNSignal(uint256,uint256)","inputs":[{"name":"subgraphID","type":"uint256"},{"name":"tokensIn","type":"uint256"}],"outputs":[{"name":"","type":"uint256"},{"name":"","type":"uint256"},{"name":"","type":"uint256"}],"mut":"view","doc":{"notice":"Calculate subgraph signal to be returned for an amount of tokens.","params":{"_subgraphID":"Subgraph ID","_tokensIn":"Tokens being exchanged for subgraph signal"},"returns":{"_0":"nSignalOut Amount of name signal minted","_1":"curationTax Amount of curation tax charged","_2":"vSignalOut Amount of version signal minted"}}},{"name":"vSignalToNSignal","sig":"vSignalToNSignal(uint256,uint256)","inputs":[{"name":"subgraphID","type":"uint256"},{"name":"vSignalIn","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}],"mut":"view","doc":{"notice":"Calculate subgraph signal to be returned for an amount of subgraph deployment signal.","params":{"subgraphID":"Subgraph ID","vSignalIn":"Amount of subgraph deployment signal to exchange for subgraph signal"},"returns":{"_0":"Amount of subgraph signal that can be bought"}}}],"writes":[{"name":"approveAll","sig":"approveAll()","inputs":[],"outputs":[],"mut":"nonpayable","doc":{"notice":"Approve curation contract to pull funds."}},{"name":"burnSignal","sig":"burnSignal(uint256,uint256,uint256)","inputs":[{"name":"subgraphID","type":"uint256"},{"name":"nSignal","type":"uint256"},{"name":"tokensOutMin","type":"uint256"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Burn signal for a subgraph and return the GRT.","params":{"nSignal":"The amount of nSignal the nameCurator wants to burn","subgraphID":"Subgraph ID","tokensOutMin":"Expected minimum amount of tokens to receive"}}},{"name":"deprecateSubgraph","sig":"deprecateSubgraph(uint256)","inputs":[{"name":"subgraphID","type":"uint256"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"The bonding curve is destroyed, the vSignal is burned, and the GNS contract holds the GRT from burning the vSignal, which all curators can withdraw manually. Can only be done by the subgraph owner.","params":{"subgraphID":"Subgraph ID"}}},{"name":"finishSubgraphTransferFromL1","sig":"finishSubgraphTransferFromL1(uint256,bytes32,bytes32,bytes32)","inputs":[{"name":"l2SubgraphID","type":"uint256"},{"name":"subgraphDeploymentID","type":"bytes32"},{"name":"subgraphMetadata","type":"bytes32"},{"name":"versionMetadata","type":"bytes32"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Finish a subgraph transfer from L1. The subgraph must have been previously sent through the bridge using the sendSubgraphToL2 function on L1GNS.","params":{"l2SubgraphID":"Subgraph ID in L2 (aliased from the L1 subgraph ID)","subgraphDeploymentID":"Latest subgraph deployment to assign to the subgraph","subgraphMetadata":"IPFS hash of the subgraph metadata","versionMetadata":"IPFS hash of the version metadata"}},"calls":["Curation"]},{"name":"mintSignal","sig":"mintSignal(uint256,uint256,uint256)","inputs":[{"name":"subgraphID","type":"uint256"},{"name":"tokensIn","type":"uint256"},{"name":"nSignalOutMin","type":"uint256"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Deposit GRT into a subgraph and mint signal.","params":{"nSignalOutMin":"Expected minimum amount of name signal to receive","subgraphID":"Subgraph ID","tokensIn":"The amount of tokens the nameCurator wants to deposit"}}},{"name":"onTokenTransfer","sig":"onTokenTransfer(address,uint256,bytes)","inputs":[{"name":"from","type":"address"},{"name":"amount","type":"uint256"},{"name":"data","type":"bytes"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Receive tokens with a callhook from the bridge. The callhook will receive a subgraph or a curator's balance from L1. The _data parameter must contain the ABI encoding of: (uint8 code, uint256 subgraphId, address beneficiary) Where `code` is one of the codes defined in IL2GNS.L1MessageCodes. If the code is RECEIVE_SUBGRAPH_CODE, the beneficiary is the address of the owner of the subgraph on L2. If the code is RECEIVE_CURATOR_BALANCE_CODE, then the beneficiary is the address of the curator in L2. In this case, If the subgraph transfer was never finished (or the subgraph doesn't exist), the tokens will be sent to the curator.","details":"This function is called by the L2GraphTokenGateway contract.","params":{"_amount":"Amount of tokens that were transferred","_data":"ABI-encoded callhook data","_from":"Token sender in L1 (must be the L1GNS)"}},"calls":["Curation"]},{"name":"publishNewSubgraph","sig":"publishNewSubgraph(bytes32,bytes32,bytes32)","inputs":[{"name":"subgraphDeploymentID","type":"bytes32"},{"name":"versionMetadata","type":"bytes32"},{"name":"subgraphMetadata","type":"bytes32"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Publish a new subgraph.","params":{"subgraphDeploymentID":"Subgraph deployment for the subgraph","subgraphMetadata":"IPFS hash for the subgraph metadata","versionMetadata":"IPFS hash for the subgraph version metadata"}}},{"name":"publishNewVersion","sig":"publishNewVersion(uint256,bytes32,bytes32)","inputs":[{"name":"subgraphID","type":"uint256"},{"name":"subgraphDeploymentID","type":"bytes32"},{"name":"versionMetadata","type":"bytes32"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Publish a new version of an existing subgraph.","details":"This is the same as the one in the base GNS, but skips the check for a subgraph to not be pre-curated, as the reserve ratio in L2 is set to 1, which prevents the risk of rug-pulling.","params":{"_subgraphDeploymentID":"Subgraph deployment ID of the new version","_subgraphID":"Subgraph ID","_versionMetadata":"IPFS hash for the subgraph version metadata"}},"calls":["Curation"]},{"name":"setDefaultName","sig":"setDefaultName(address,uint8,bytes32,string)","inputs":[{"name":"graphAccount","type":"address"},{"name":"nameSystem","type":"uint8"},{"name":"nameIdentifier","type":"bytes32"},{"name":"name","type":"string"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Allows a graph account to set a default name","params":{"graphAccount":"Account that is setting its name","name":"The name being set as default","nameIdentifier":"The unique identifier that is used to identify the name in the system","nameSystem":"Name system account already has ownership of a name in"}}},{"name":"setOwnerTaxPercentage","sig":"setOwnerTaxPercentage(uint32)","inputs":[{"name":"ownerTaxPercentage","type":"uint32"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Set the owner fee percentage. This is used to prevent a subgraph owner to drain all the name curators tokens while upgrading or deprecating and is configurable in parts per million.","params":{"ownerTaxPercentage":"Owner tax percentage"}}},{"name":"transferSignal","sig":"transferSignal(uint256,address,uint256)","inputs":[{"name":"subgraphID","type":"uint256"},{"name":"recipient","type":"address"},{"name":"amount","type":"uint256"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Move subgraph signal from sender to `_recipient`","params":{"_amount":"The amount of nSignal to transfer","_recipient":"Address to send the signal to","_subgraphID":"Subgraph ID"}}},{"name":"updateSubgraphMetadata","sig":"updateSubgraphMetadata(uint256,bytes32)","inputs":[{"name":"subgraphID","type":"uint256"},{"name":"subgraphMetadata","type":"bytes32"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Allows a subgraph owner to update the metadata of a subgraph they have published","params":{"subgraphID":"Subgraph ID","subgraphMetadata":"IPFS hash for the subgraph metadata"}}},{"name":"withdraw","sig":"withdraw(uint256)","inputs":[{"name":"subgraphID","type":"uint256"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Withdraw tokens from a deprecated subgraph. When the subgraph is deprecated, any curator can call this function and withdraw the GRT they are entitled for its original deposit","params":{"_subgraphID":"Subgraph ID"}}}],"events":[],"counts":{"reads":13,"writes":13,"events":0}},{"id":"SubgraphNFT","name":"SubgraphNFT","layer":"curation","chain":"L2","core":false,"legacy":false,"address":"0xF21Df5BbA7EB9b54D8F60C560aFb9bA63e6aED1A","desc":"The ERC-721 token that represents ownership of a published subgraph in the GNS. Holding the NFT is what lets an account re-point or deprecate that subgraph.","contractDoc":{"title":"NFT that represents ownership of a Subgraph","notice":"NFT that represents ownership of a Subgraph"},"implements":["ISubgraphNFT","ERC721"],"deps":[{"to":"SubgraphNFTDescriptor","label":"renders token metadata"}],"roles":[],"reads":[{"name":"balanceOf","sig":"balanceOf(address)","inputs":[{"name":"owner","type":"address"}],"outputs":[{"name":"balance","type":"uint256"}],"mut":"view","doc":{"details":"See {IERC721-balanceOf}."}},{"name":"getApproved","sig":"getApproved(uint256)","inputs":[{"name":"tokenId","type":"uint256"}],"outputs":[{"name":"operator","type":"address"}],"mut":"view","doc":{"details":"See {IERC721-getApproved}."}},{"name":"isApprovedForAll","sig":"isApprovedForAll(address,address)","inputs":[{"name":"owner","type":"address"},{"name":"operator","type":"address"}],"outputs":[{"name":"","type":"bool"}],"mut":"view","doc":{"details":"See {IERC721-isApprovedForAll}."}},{"name":"ownerOf","sig":"ownerOf(uint256)","inputs":[{"name":"tokenId","type":"uint256"}],"outputs":[{"name":"owner","type":"address"}],"mut":"view","doc":{"details":"See {IERC721-ownerOf}."}},{"name":"supportsInterface","sig":"supportsInterface(bytes4)","inputs":[{"name":"interfaceId","type":"bytes4"}],"outputs":[{"name":"","type":"bool"}],"mut":"view","doc":{"details":"See {IERC165-supportsInterface}. Time complexity O(1), guaranteed to always use less than 30 000 gas."}},{"name":"tokenURI","sig":"tokenURI(uint256)","inputs":[{"name":"tokenId","type":"uint256"}],"outputs":[{"name":"","type":"string"}],"mut":"view","doc":{"notice":"Returns the Uniform Resource Identifier (URI) for `tokenId` token","details":"See {IERC721Metadata-tokenURI}.","params":{"tokenId":"ID of the NFT"},"returns":{"_0":"The URI for the token"}}}],"writes":[{"name":"approve","sig":"approve(address,uint256)","inputs":[{"name":"to","type":"address"},{"name":"tokenId","type":"uint256"}],"outputs":[],"mut":"nonpayable","doc":{"details":"See {IERC721-approve}."}},{"name":"burn","sig":"burn(uint256)","inputs":[{"name":"tokenId","type":"uint256"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Burn `tokenId`","details":"The approval is cleared when the token is burned","params":{"tokenId":"ID of the NFT"}}},{"name":"mint","sig":"mint(address,uint256)","inputs":[{"name":"to","type":"address"},{"name":"tokenId","type":"uint256"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Mint `tokenId` and transfers it to `to`","details":"`tokenId` must not exist and `to` cannot be the zero address","params":{"to":"Address receiving the minted NFT","tokenId":"ID of the NFT"}}},{"name":"safeTransferFrom","sig":"safeTransferFrom(address,address,uint256)","inputs":[{"name":"from","type":"address"},{"name":"to","type":"address"},{"name":"tokenId","type":"uint256"}],"outputs":[],"mut":"nonpayable","doc":{"details":"See {IERC721-safeTransferFrom}."}},{"name":"safeTransferFrom","sig":"safeTransferFrom(address,address,uint256,bytes)","inputs":[{"name":"from","type":"address"},{"name":"to","type":"address"},{"name":"tokenId","type":"uint256"},{"name":"data","type":"bytes"}],"outputs":[],"mut":"nonpayable","doc":{"details":"See {IERC721-safeTransferFrom}."}},{"name":"setApprovalForAll","sig":"setApprovalForAll(address,bool)","inputs":[{"name":"operator","type":"address"},{"name":"_approved","type":"bool"}],"outputs":[],"mut":"nonpayable","doc":{"details":"See {IERC721-setApprovalForAll}."}},{"name":"setBaseURI","sig":"setBaseURI(string)","inputs":[{"name":"baseURI","type":"string"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Set the base URI","details":"Can be set to empty","params":{"baseURI":"Base URI to use to build the token URI"}},"access":{"roles":[],"mods":["onlyGovernor"]}},{"name":"setMinter","sig":"setMinter(address)","inputs":[{"name":"minter","type":"address"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Set the minter allowed to perform actions on the NFT","details":"Minter can mint, burn and update the metadata","params":{"minter":"Address of the allowed minter"}},"access":{"roles":[],"mods":["onlyGovernor"]}},{"name":"setSubgraphMetadata","sig":"setSubgraphMetadata(uint256,bytes32)","inputs":[{"name":"tokenId","type":"uint256"},{"name":"subgraphMetadata","type":"bytes32"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Set the metadata for a subgraph represented by `tokenId`","details":"`tokenId` must exist","params":{"subgraphMetadata":"IPFS hash for the metadata","tokenId":"ID of the NFT"}}},{"name":"setTokenDescriptor","sig":"setTokenDescriptor(address)","inputs":[{"name":"tokenDescriptor","type":"address"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Set the token descriptor contract","details":"Token descriptor can be zero. If set, it must be a contract","params":{"tokenDescriptor":"Address of the contract that creates the NFT token URI"}},"access":{"roles":[],"mods":["onlyGovernor"]}},{"name":"transferFrom","sig":"transferFrom(address,address,uint256)","inputs":[{"name":"from","type":"address"},{"name":"to","type":"address"},{"name":"tokenId","type":"uint256"}],"outputs":[],"mut":"nonpayable","doc":{"details":"See {IERC721-transferFrom}."}}],"events":[{"name":"Approval","sig":"Approval(address,address,uint256)","inputs":[{"name":"owner","type":"address","indexed":true},{"name":"approved","type":"address","indexed":true},{"name":"tokenId","type":"uint256","indexed":true}]},{"name":"ApprovalForAll","sig":"ApprovalForAll(address,address,bool)","inputs":[{"name":"owner","type":"address","indexed":true},{"name":"operator","type":"address","indexed":true},{"name":"approved","type":"bool","indexed":false}]},{"name":"Transfer","sig":"Transfer(address,address,uint256)","inputs":[{"name":"from","type":"address","indexed":true},{"name":"to","type":"address","indexed":true},{"name":"tokenId","type":"uint256","indexed":true}]}],"counts":{"reads":6,"writes":11,"events":3}},{"id":"SubgraphNFTDescriptor","name":"SubgraphNFTDescriptor","layer":"curation","chain":"L2","core":false,"legacy":false,"address":"0x4032F7B6b27FfC9862106f826379DaB1716C71d7","desc":"A pure helper that builds the on-chain metadata (tokenURI) for a SubgraphNFT. It has no state and only produces display data.","contractDoc":{"title":"Describes subgraph NFT tokens via URI","notice":"Describes subgraph NFT tokens via URI"},"implements":["ISubgraphNFTDescriptor"],"deps":[],"roles":[],"reads":[{"name":"tokenURI","sig":"tokenURI(address,uint256,string,bytes32)","inputs":[{"name":"minter","type":"address"},{"name":"tokenId","type":"uint256"},{"name":"baseURI","type":"string"},{"name":"subgraphMetadata","type":"bytes32"}],"outputs":[{"name":"","type":"string"}],"mut":"view","doc":{"notice":"Produces the URI describing a particular token ID for a Subgraph","details":"Note this URI may be data: URI with the JSON contents directly inlined","params":{"baseURI":"The base URI that could be prefixed to the final URI","minter":"Address of the allowed minter","subgraphMetadata":"Subgraph metadata set for the subgraph","tokenId":"The ID of the subgraph NFT for which to produce a description, which may not be valid"},"returns":{"_0":"The URI of the ERC721-compliant metadata"}}}],"writes":[],"events":[],"counts":{"reads":1,"writes":0,"events":0}},{"id":"ServiceRegistry","name":"ServiceRegistry","layer":"curation","chain":"L2","core":false,"legacy":true,"address":"0x888541878CbDDEd880Cd58c728f1Af5C47343F86","desc":"A legacy directory where indexers published the public URL of their query endpoint so gateways could find them. Largely superseded by indexer registration in the Subgraph Service, but still deployed.","contractDoc":{"title":"ServiceRegistry contract","notice":"This contract supports the service discovery process by allowing indexers to register their service url and any other relevant information."},"implements":["IServiceRegistry"],"deps":[],"roles":[],"reads":[{"name":"isRegistered","sig":"isRegistered(address)","inputs":[{"name":"indexer","type":"address"}],"outputs":[{"name":"","type":"bool"}],"mut":"view","doc":{"notice":"Return the registration status of an indexer service","params":{"indexer":"Address of the indexer"},"returns":{"_0":"True if the indexer service is registered"}}}],"writes":[{"name":"register","sig":"register(string,string)","inputs":[{"name":"url","type":"string"},{"name":"geohash","type":"string"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Register an indexer service","params":{"geohash":"Geohash of the indexer service location","url":"URL of the indexer service"}}},{"name":"registerFor","sig":"registerFor(address,string,string)","inputs":[{"name":"indexer","type":"address"},{"name":"url","type":"string"},{"name":"geohash","type":"string"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Register an indexer service","params":{"geohash":"Geohash of the indexer service location","indexer":"Address of the indexer","url":"URL of the indexer service"}}},{"name":"unregister","sig":"unregister()","inputs":[],"outputs":[],"mut":"nonpayable","doc":{"notice":"Unregister an indexer service"}},{"name":"unregisterFor","sig":"unregisterFor(address)","inputs":[{"name":"indexer","type":"address"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Unregister an indexer service","params":{"indexer":"Address of the indexer"}}}],"events":[],"counts":{"reads":1,"writes":4,"events":0}},{"id":"EthereumDIDRegistry","name":"EthereumDIDRegistry","layer":"curation","chain":"L2","core":false,"legacy":true,"address":"0xF5f4cA61481558709AFa94AdEDa7B5F180f4AD59","desc":"A standard ERC-1056 identity registry used to attach off-chain metadata (such as an indexer's profile) to an Ethereum address. Peripheral to the core economic flows.","contractDoc":{"title":"Ethereum DID Registry","notice":"Registry for Ethereum Decentralized Identifiers (DIDs)"},"implements":["IEthereumDIDRegistry (ERC-1056)"],"deps":[],"roles":[],"reads":[{"name":"identityOwner","sig":"identityOwner(address)","inputs":[{"name":"identity","type":"address"}],"outputs":[{"name":"","type":"address"}],"mut":"view","doc":{"notice":"Get the owner of an identity","params":{"identity":"The identity address"},"returns":{"_0":"The address of the identity owner"}}}],"writes":[{"name":"setAttribute","sig":"setAttribute(address,bytes32,bytes,uint256)","inputs":[{"name":"identity","type":"address"},{"name":"name","type":"bytes32"},{"name":"value","type":"bytes"},{"name":"validity","type":"uint256"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Set an attribute for an identity","params":{"identity":"The identity to set an attribute for","name":"The name of the attribute","validity":"The validity period in seconds","value":"The value of the attribute"}}}],"events":[],"counts":{"reads":1,"writes":1,"events":0}},{"id":"Controller","name":"Controller","layer":"governance","chain":"L2","core":true,"legacy":false,"address":"0x9DB3ee191681f092607035d9BDA6e59FbEaCa695","desc":"The protocol's phone book and master switch. Every managed contract looks up its peers by name through the Controller, and it holds the governor address plus a global pause. Change an address here and the whole protocol re-wires to the new contract.","contractDoc":{"title":"Graph Controller contract","notice":"Controller is a registry of contracts for convenience. Inspired by Livepeer: https://github.com/livepeer/protocol/blob/streamflow/contracts/Controller.sol"},"implements":["IController","IManaged"],"deps":[],"roles":[],"reads":[{"name":"getContractProxy","sig":"getContractProxy(bytes32)","inputs":[{"name":"id","type":"bytes32"}],"outputs":[{"name":"","type":"address"}],"mut":"view","doc":{"notice":"Get contract proxy address by its id","params":{"id":"Contract id"},"returns":{"_0":"Address of the proxy contract for the provided id"}}},{"name":"getGovernor","sig":"getGovernor()","inputs":[],"outputs":[{"name":"","type":"address"}],"mut":"view","doc":{"notice":"Return the governor address","returns":{"_0":"The governor address"}}},{"name":"partialPaused","sig":"partialPaused()","inputs":[],"outputs":[{"name":"","type":"bool"}],"mut":"view","doc":{"notice":"Return whether the protocol is partially paused","returns":{"_0":"True if the protocol is partially paused"}}},{"name":"paused","sig":"paused()","inputs":[],"outputs":[{"name":"","type":"bool"}],"mut":"view","doc":{"notice":"Return whether the protocol is paused","returns":{"_0":"True if the protocol is paused"}}}],"writes":[{"name":"setContractProxy","sig":"setContractProxy(bytes32,address)","inputs":[{"name":"id","type":"bytes32"},{"name":"contractAddress","type":"address"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Register contract id and mapped address","params":{"contractAddress":"Contract address","id":"Contract id (keccak256 hash of contract name)"}},"access":{"roles":[],"mods":["onlyGovernor"]}},{"name":"setPartialPaused","sig":"setPartialPaused(bool)","inputs":[{"name":"partialPause","type":"bool"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Change the partial paused state of the contract Partial pause is intended as a partial pause of the protocol","params":{"_toPartialPause":"True if the contracts should be (partially) paused, false otherwise"}}},{"name":"setPaused","sig":"setPaused(bool)","inputs":[{"name":"pause","type":"bool"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Change the paused state of the contract Full pause most of protocol functions","details":"Full pause most of protocol functions","params":{"pause":"True if the contracts should be paused, false otherwise"}}},{"name":"setPauseGuardian","sig":"setPauseGuardian(address)","inputs":[{"name":"newPauseGuardian","type":"address"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Change the Pause Guardian","params":{"newPauseGuardian":"The address of the new Pause Guardian"}},"access":{"roles":[],"mods":["onlyGovernor"]}},{"name":"unsetContractProxy","sig":"unsetContractProxy(bytes32)","inputs":[{"name":"id","type":"bytes32"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Unregister a contract address","params":{"id":"Contract id (keccak256 hash of contract name)"}},"access":{"roles":[],"mods":["onlyGovernor"]}},{"name":"updateController","sig":"updateController(bytes32,address)","inputs":[{"name":"id","type":"bytes32"},{"name":"controller","type":"address"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Update contract's controller","params":{"controller":"Controller address","id":"Contract id (keccak256 hash of contract name)"}},"access":{"roles":[],"mods":["onlyGovernor"]}}],"events":[],"counts":{"reads":4,"writes":6,"events":0}},{"id":"GraphProxyAdmin","name":"GraphProxyAdmin","layer":"governance","chain":"L2","core":false,"legacy":false,"address":"0x7474a6cc5fAeDEc620Db0fa8E4da6eD58477042C","desc":"The owner of the upgradeable proxies. Governance calls it to point a proxy at a new implementation, which is how almost every contract in the protocol gets upgraded.","contractDoc":{"title":"GraphProxyAdmin","notice":"This is the owner of upgradeable proxy contracts. Proxy contracts use a TransparentProxy pattern, any admin related call like upgrading a contract or changing the admin needs to be send through this contract."},"implements":["IGraphProxyAdmin"],"deps":[],"roles":[],"reads":[{"name":"getProxyAdmin","sig":"getProxyAdmin(address)","inputs":[{"name":"proxy","type":"address"}],"outputs":[{"name":"","type":"address"}],"mut":"view","doc":{"notice":"Returns the admin of a proxy. Only the admin can query it.","params":{"_proxy":"Address of the proxy for which to get the admin."},"returns":{"_0":"The address of the current admin of the proxy."}}},{"name":"getProxyImplementation","sig":"getProxyImplementation(address)","inputs":[{"name":"proxy","type":"address"}],"outputs":[{"name":"","type":"address"}],"mut":"view","doc":{"notice":"Returns the current implementation of a proxy.","details":"This is needed because only the proxy admin can query it.","params":{"_proxy":"Address of the proxy for which to get the implementation."},"returns":{"_0":"The address of the current implementation of the proxy."}}},{"name":"getProxyPendingImplementation","sig":"getProxyPendingImplementation(address)","inputs":[{"name":"proxy","type":"address"}],"outputs":[{"name":"","type":"address"}],"mut":"view","doc":{"notice":"Returns the pending implementation of a proxy.","details":"This is needed because only the proxy admin can query it.","params":{"_proxy":"Address of the proxy for which to get the pending implementation."},"returns":{"_0":"The address of the pending implementation of the proxy."}}},{"name":"governor","sig":"governor()","inputs":[],"outputs":[{"name":"","type":"address"}],"mut":"view","doc":{"notice":"Address of the governor","returns":{"_0":"The address of the governor"}}},{"name":"pendingGovernor","sig":"pendingGovernor()","inputs":[],"outputs":[{"name":"","type":"address"}],"mut":"view","doc":{"notice":"Address of the new governor that is pending acceptance","returns":{"_0":"The address of the pending governor"}}}],"writes":[{"name":"acceptOwnership","sig":"acceptOwnership()","inputs":[],"outputs":[],"mut":"nonpayable","doc":{"notice":"Admin function for pending governor to accept role and update governor. This function must called by the pending governor."}},{"name":"acceptProxy","sig":"acceptProxy(address,address)","inputs":[{"name":"implementation","type":"address"},{"name":"proxy","type":"address"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Accepts a proxy.","params":{"_implementation":"Address of the implementation accepting the proxy.","_proxy":"Address of the proxy being accepted."}},"access":{"roles":[],"mods":["onlyGovernor"]}},{"name":"acceptProxyAndCall","sig":"acceptProxyAndCall(address,address,bytes)","inputs":[{"name":"implementation","type":"address"},{"name":"proxy","type":"address"},{"name":"data","type":"bytes"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Accepts a proxy and call a function on the implementation.","params":{"_data":"Encoded function to call on the implementation after accepting the proxy.","_implementation":"Address of the implementation accepting the proxy.","_proxy":"Address of the proxy being accepted."}},"access":{"roles":[],"mods":["onlyGovernor"]}},{"name":"changeProxyAdmin","sig":"changeProxyAdmin(address,address)","inputs":[{"name":"proxy","type":"address"},{"name":"newAdmin","type":"address"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Changes the admin of a proxy.","params":{"_newAdmin":"Address to transfer proxy administration to.","_proxy":"Proxy to change admin."}},"access":{"roles":[],"mods":["onlyGovernor"]}},{"name":"transferOwnership","sig":"transferOwnership(address)","inputs":[{"name":"newGovernor","type":"address"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Admin function to begin change of governor. The `_newGovernor` must call `acceptOwnership` to finalize the transfer.","params":{"_newGovernor":"Address of new `governor`"}}},{"name":"upgrade","sig":"upgrade(address,address)","inputs":[{"name":"proxy","type":"address"},{"name":"implementation","type":"address"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Upgrades a proxy to the newest implementation of a contract.","params":{"_implementation":"the address of the Implementation.","_proxy":"Proxy to be upgraded."}},"access":{"roles":[],"mods":["onlyGovernor"]}},{"name":"upgradeTo","sig":"upgradeTo(address,address)","inputs":[{"name":"proxy","type":"address"},{"name":"implementation","type":"address"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Upgrade a proxy to a new implementation","params":{"implementation":"The new implementation address","proxy":"The proxy contract to upgrade"}}},{"name":"upgradeToAndCall","sig":"upgradeToAndCall(address,address,bytes)","inputs":[{"name":"proxy","type":"address"},{"name":"implementation","type":"address"},{"name":"data","type":"bytes"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Upgrade a proxy to a new implementation and call a function","params":{"data":"The calldata to execute on the new implementation","implementation":"The new implementation address","proxy":"The proxy contract to upgrade"}}}],"events":[{"name":"NewOwnership","sig":"NewOwnership(address,address)","inputs":[{"name":"from","type":"address","indexed":true},{"name":"to","type":"address","indexed":true}],"doc":{"notice":"Emitted when a new owner/governor has accepted their role","params":{"from":"The address of the previous governor","to":"The address of the new governor"}}},{"name":"NewPendingOwnership","sig":"NewPendingOwnership(address,address)","inputs":[{"name":"from","type":"address","indexed":true},{"name":"to","type":"address","indexed":true}],"doc":{"notice":"Emitted when a new owner/governor has been set, but is pending acceptance","params":{"from":"The address of the current governor","to":"The address of the new pending governor"}}}],"counts":{"reads":5,"writes":8,"events":2}},{"id":"EpochManager","name":"EpochManager","layer":"governance","chain":"L2","core":true,"legacy":false,"address":"0x88b3C7f37253bAA1A9b95feAd69bD5320585826D","desc":"Chops time into fixed-length \"epochs\" measured in blocks. Allocations and other time-bounded protocol actions reference epochs so that everyone agrees on when one period ends and the next begins.","contractDoc":{"title":"EpochManager contract","notice":"Produce epochs based on a number of blocks to coordinate contracts in the protocol."},"implements":["IEpochManager"],"deps":[],"roles":[],"reads":[{"name":"blockHash","sig":"blockHash(uint256)","inputs":[{"name":"blockNumber","type":"uint256"}],"outputs":[{"name":"","type":"bytes32"}],"mut":"view","doc":{"notice":"Get the hash of a specific block","params":{"blockNumber":"Block number to get hash for"},"returns":{"_0":"Block hash"}}},{"name":"blockNum","sig":"blockNum()","inputs":[],"outputs":[{"name":"","type":"uint256"}],"mut":"view","doc":{"notice":"Get the current block number","returns":{"_0":"Current block number"}}},{"name":"currentEpoch","sig":"currentEpoch()","inputs":[],"outputs":[{"name":"","type":"uint256"}],"mut":"view","doc":{"notice":"Get the current epoch number","returns":{"_0":"Current epoch number"}}},{"name":"currentEpochBlock","sig":"currentEpochBlock()","inputs":[],"outputs":[{"name":"","type":"uint256"}],"mut":"view","doc":{"notice":"Get the block number when the current epoch started","returns":{"_0":"Block number of current epoch start"}}},{"name":"currentEpochBlockSinceStart","sig":"currentEpochBlockSinceStart()","inputs":[],"outputs":[{"name":"","type":"uint256"}],"mut":"view","doc":{"notice":"Get the number of blocks since the current epoch started","returns":{"_0":"Number of blocks since current epoch start"}}},{"name":"epochsSince","sig":"epochsSince(uint256)","inputs":[{"name":"epoch","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}],"mut":"view","doc":{"notice":"Get the number of epochs since a given epoch","params":{"epoch":"Epoch to calculate from"},"returns":{"_0":"Number of epochs since the given epoch"}}},{"name":"epochsSinceUpdate","sig":"epochsSinceUpdate()","inputs":[],"outputs":[{"name":"","type":"uint256"}],"mut":"view","doc":{"notice":"Get the number of epochs since the last epoch length update","returns":{"_0":"Number of epochs since last update"}}},{"name":"isCurrentEpochRun","sig":"isCurrentEpochRun()","inputs":[],"outputs":[{"name":"","type":"bool"}],"mut":"view","doc":{"notice":"Check if the current epoch has been run","returns":{"_0":"True if current epoch has been run, false otherwise"}}}],"writes":[{"name":"runEpoch","sig":"runEpoch()","inputs":[],"outputs":[],"mut":"nonpayable","doc":{"notice":"Perform state changes for the current epoch","details":"Run a new epoch, should be called once at the start of any epoch."}},{"name":"setEpochLength","sig":"setEpochLength(uint256)","inputs":[{"name":"epochLength","type":"uint256"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Set epoch length to `epochLength` blocks","params":{"epochLength":"Epoch length in blocks"}},"access":{"roles":[],"mods":["onlyGovernor"]}}],"events":[],"counts":{"reads":8,"writes":2,"events":0}},{"id":"SubgraphAvailabilityManager","name":"SubgraphAvailabilityManager","layer":"governance","chain":"L2","core":false,"legacy":false,"address":"0x71D9aE967d1f31fbbD1817150902de78f8f2f73E","desc":"A multi-oracle voting contract that decides which subgraphs are allowed to earn rewards. A quorum of oracles must agree to deny a subgraph, and the RewardsManager reads its verdict before paying out — a safety valve against rewarding harmful content.","contractDoc":{"title":"Subgraph Availability Manager","notice":"Manages the availability of subgraphs by allowing oracles to vote on whether a subgraph should be denied rewards or not. When enough oracles have voted to deny or allow rewards for a subgraph, it calls the RewardsManager Contract to set the correct state. The oracles and the execution threshold are set at deployment time. Only governance can update the oracles and voteTimeLimit. Governor can transfer ownership to a new governor."},"implements":["(no published interface)"],"deps":[{"to":"RewardsManager","label":"sets reward denylist"}],"roles":[],"reads":[{"name":"checkVotes","sig":"checkVotes(bytes32,bool)","inputs":[{"name":"_subgraphDeploymentID","type":"bytes32"},{"name":"_deny","type":"bool"}],"outputs":[{"name":"","type":"bool"}],"mut":"view","doc":{"notice":"Check if the execution threshold has been reached for a subgraph. For a vote to be valid it needs to be within the vote time limit.","params":{"_deny":"True to deny, false to allow","_subgraphDeploymentID":"Subgraph deployment ID"},"returns":{"_0":"True if execution threshold is reached"}}},{"name":"currentNonce","sig":"currentNonce()","inputs":[],"outputs":[{"name":"","type":"uint256"}],"mut":"view","doc":{"notice":"Nonce for generating votes on subgraph deployment IDs"}},{"name":"executionThreshold","sig":"executionThreshold()","inputs":[],"outputs":[{"name":"","type":"uint256"}],"mut":"view","doc":{"notice":"Number of votes required to execute a deny or allow call to the RewardsManager"}},{"name":"governor","sig":"governor()","inputs":[],"outputs":[{"name":"","type":"address"}],"mut":"view","doc":{"notice":"Address of the governor"}},{"name":"lastAllowVote","sig":"lastAllowVote(uint256,bytes32,uint256)","inputs":[{"name":"","type":"uint256"},{"name":"","type":"bytes32"},{"name":"","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}],"mut":"view","doc":{"notice":"Mapping of current nonce to subgraph deployment ID to an array of timestamp of last allow vote"}},{"name":"lastDenyVote","sig":"lastDenyVote(uint256,bytes32,uint256)","inputs":[{"name":"","type":"uint256"},{"name":"","type":"bytes32"},{"name":"","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}],"mut":"view","doc":{"notice":"Mapping of current nonce to subgraph deployment ID to an array of timestamps of last deny vote"}},{"name":"NUM_ORACLES","sig":"NUM_ORACLES()","inputs":[],"outputs":[{"name":"","type":"uint256"}],"mut":"view","doc":{"notice":"Number of oracles"}},{"name":"oracles","sig":"oracles(uint256)","inputs":[{"name":"","type":"uint256"}],"outputs":[{"name":"","type":"address"}],"mut":"view","doc":{"notice":"Array of oracle addresses"}},{"name":"pendingGovernor","sig":"pendingGovernor()","inputs":[],"outputs":[{"name":"","type":"address"}],"mut":"view","doc":{"notice":"Address of the new governor that is pending acceptance"}},{"name":"voteTimeLimit","sig":"voteTimeLimit()","inputs":[],"outputs":[{"name":"","type":"uint256"}],"mut":"view","doc":{"notice":"Time limit for a vote to be valid"}}],"writes":[{"name":"acceptOwnership","sig":"acceptOwnership()","inputs":[],"outputs":[],"mut":"nonpayable","doc":{"notice":"Admin function for pending governor to accept role and update governor. This function must called by the pending governor."}},{"name":"setOracle","sig":"setOracle(uint256,address)","inputs":[{"name":"_index","type":"uint256"},{"name":"_oracle","type":"address"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Set oracle address with index. Refreshes all existing votes by incrementing the current nonce.","params":{"_index":"Index of the oracle","_oracle":"Address of the oracle"}},"access":{"roles":[],"mods":["onlyGovernor"]},"emits":["OracleSet"]},{"name":"setVoteTimeLimit","sig":"setVoteTimeLimit(uint256)","inputs":[{"name":"_voteTimeLimit","type":"uint256"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Set the vote time limit. Refreshes all existing votes by incrementing the current nonce.","params":{"_voteTimeLimit":"Vote time limit in seconds"}},"access":{"roles":[],"mods":["onlyGovernor"]},"emits":["VoteTimeLimitSet"]},{"name":"transferOwnership","sig":"transferOwnership(address)","inputs":[{"name":"_newGovernor","type":"address"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Admin function to begin change of governor. The `_newGovernor` must call `acceptOwnership` to finalize the transfer.","params":{"_newGovernor":"Address of new `governor`"}}},{"name":"vote","sig":"vote(bytes32,bool,uint256)","inputs":[{"name":"_subgraphDeploymentID","type":"bytes32"},{"name":"_deny","type":"bool"},{"name":"_oracleIndex","type":"uint256"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Vote deny or allow for a subgraph. NOTE: Can only be called by an oracle.","params":{"_deny":"True to deny, false to allow","_oracleIndex":"Index of the oracle voting","_subgraphDeploymentID":"Subgraph deployment ID"}},"emits":["OracleVote"],"calls":["RewardsManager"]},{"name":"voteMany","sig":"voteMany(bytes32[],bool[],uint256)","inputs":[{"name":"_subgraphDeploymentID","type":"bytes32[]"},{"name":"_deny","type":"bool[]"},{"name":"_oracleIndex","type":"uint256"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Vote deny or allow for many subgraphs. NOTE: Can only be called by an oracle.","params":{"_deny":"Array of booleans, true to deny, false to allow","_oracleIndex":"Index of the oracle voting","_subgraphDeploymentID":"Array of subgraph deployment IDs"}},"emits":["OracleVote"],"calls":["RewardsManager"]}],"events":[{"name":"NewOwnership","sig":"NewOwnership(address,address)","inputs":[{"name":"from","type":"address","indexed":true},{"name":"to","type":"address","indexed":true}],"doc":{"notice":"Emitted when a new owner/governor has accepted their role"}},{"name":"NewPendingOwnership","sig":"NewPendingOwnership(address,address)","inputs":[{"name":"from","type":"address","indexed":true},{"name":"to","type":"address","indexed":true}],"doc":{"notice":"Emitted when a new owner/governor has been set, but is pending acceptance"}},{"name":"OracleSet","sig":"OracleSet(uint256,address)","inputs":[{"name":"index","type":"uint256","indexed":true},{"name":"oracle","type":"address","indexed":true}],"doc":{"notice":"Emitted when an oracle is set","params":{"index":"Index of the oracle","oracle":"Address of the oracle"}}},{"name":"OracleVote","sig":"OracleVote(bytes32,bool,uint256,uint256)","inputs":[{"name":"subgraphDeploymentID","type":"bytes32","indexed":true},{"name":"deny","type":"bool","indexed":false},{"name":"oracleIndex","type":"uint256","indexed":true},{"name":"timestamp","type":"uint256","indexed":false}],"doc":{"notice":"Emitted when an oracle votes to deny or allow a subgraph","params":{"deny":"True to deny, false to allow","oracleIndex":"Index of the oracle voting","subgraphDeploymentID":"Subgraph deployment ID","timestamp":"Timestamp of the vote"}}},{"name":"VoteTimeLimitSet","sig":"VoteTimeLimitSet(uint256)","inputs":[{"name":"voteTimeLimit","type":"uint256","indexed":false}],"doc":{"notice":"Emitted when the vote time limit is set","params":{"voteTimeLimit":"Vote time limit in seconds"}}}],"counts":{"reads":10,"writes":6,"events":5}},{"id":"L2GraphTokenGateway","name":"L2GraphTokenGateway","layer":"bridge","chain":"L2","core":true,"legacy":false,"address":"0xB24Ce0f8c18c4DdDa584A7EeC132F49C966813bb","desc":"The L2 end of the Ethereum↔Arbitrum GRT bridge. When GRT arrives from L1 it mints the matching amount here; when users bridge back it burns and signals L1. It can also carry a \"callhook\" so bridged tokens land directly in a contract like the GNS.","contractDoc":{"title":"L2 Graph Token Gateway Contract","notice":"Provides the L2 side of the Ethereum-Arbitrum GRT bridge. Receives GRT from the L1 chain and mints them on the L2 side. Sends GRT back to L1 by burning them on the L2 side. Based on Offchain Labs' reference implementation and Livepeer's arbitrum-lpt-bridge (See: https://github.com/OffchainLabs/arbitrum/tree/master/packages/arb-bridge-peripherals/contracts/tokenbridge and https://github.com/livepeer/arbitrum-lpt-bridge)"},"implements":["IL2GraphTokenGateway","ITokenGateway"],"deps":[{"to":"L2GraphToken","label":"mints / burns bridged GRT"}],"roles":[],"reads":[{"name":"calculateL2TokenAddress","sig":"calculateL2TokenAddress(address)","inputs":[{"name":"l1ERC20","type":"address"}],"outputs":[{"name":"","type":"address"}],"mut":"view","doc":{"notice":"Calculate the address used when bridging an ERC20 token","details":"In our case, this would only work for GRT.","params":{"l1ERC20":"address of L1 token"},"returns":{"_0":"L2 address of a bridged ERC20 token"}}},{"name":"getOutboundCalldata","sig":"getOutboundCalldata(address,address,address,uint256,bytes)","inputs":[{"name":"token","type":"address"},{"name":"from","type":"address"},{"name":"to","type":"address"},{"name":"amount","type":"uint256"},{"name":"data","type":"bytes"}],"outputs":[{"name":"","type":"bytes"}],"mut":"pure","doc":{"notice":"Creates calldata required to send tx to L1","details":"encodes the target function with its params which will be called on L1 when the message is received on L1","params":{"_amount":"Amount of GRT to transfer","_data":"Additional calldata for the transaction","_from":"Address of the token sender on L2","_to":"Address to which we're sending tokens on L1","_token":"Address of the token on L1"},"returns":{"_0":"Calldata for a transaction sent to L1"}}}],"writes":[{"name":"finalizeInboundTransfer","sig":"finalizeInboundTransfer(address,address,address,uint256,bytes)","inputs":[{"name":"l1Token","type":"address"},{"name":"from","type":"address"},{"name":"to","type":"address"},{"name":"amount","type":"uint256"},{"name":"data","type":"bytes"}],"outputs":[],"mut":"payable","doc":{"notice":"Finalize an inbound token transfer","details":"Only accepts transactions from the L1 GRT Gateway. The function is payable for ITokenGateway compatibility, but msg.value must be zero. Note that allowlisted senders (some protocol contracts) can include additional calldata for a callhook to be executed on the L2 side when the tokens are received. In this case, the L2 transaction can revert if the callhook reverts, potentially locking the tokens on the bridge if the callhook never succeeds. This requires extra care when adding contracts to the allowlist, but is necessary to ensure that the tickets can be retried in the case of a temporary failure, and to ensure the atomicity of callhooks with token transfers.","params":{"amount":"Amount of tokens being transferred","data":"Additional data for the transfer","from":"Sender address on the source chain","to":"Recipient address on the destination chain","token":"Address of the token being transferred"}},"access":{"roles":[],"mods":["nonReentrant"]},"emits":["DepositFinalized"]},{"name":"initialize","sig":"initialize(address)","inputs":[{"name":"controller","type":"address"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Initialize the L2GraphTokenGateway contract.","details":"The contract will be paused. Note some parameters have to be set separately as they are generally not expected to be available at initialization time: - l2Router using setL2Router - l1GRT using setL1TokenAddress - l1Counterpart using setL1CounterpartAddress - pauseGuardian using setPauseGuardian","params":{"_controller":"Address of the Controller that manages this contract"}}},{"name":"outboundTransfer","sig":"outboundTransfer(address,address,uint256,bytes)","inputs":[{"name":"l1Token","type":"address"},{"name":"to","type":"address"},{"name":"amount","type":"uint256"},{"name":"data","type":"bytes"}],"outputs":[{"name":"","type":"bytes"}],"mut":"nonpayable","doc":{"notice":"Burns L2 tokens and initiates a transfer to L1. The tokens will be received on L1 only after the wait period (7 days) is over, and will require an Outbox.executeTransaction to finalize.","details":"no additional callhook data is allowed","params":{"_amount":"Amount of tokens to burn","_data":"Contains sender and additional data to send to L1","_l1Token":"L1 Address of GRT (needed for compatibility with Arbitrum Gateway Router)","_to":"Recipient address on L1"},"returns":{"_0":"ID of the withdraw tx"}},"access":{"roles":[],"mods":["nonReentrant"]},"emits":["WithdrawalInitiated"]},{"name":"outboundTransfer","sig":"outboundTransfer(address,address,uint256,uint256,uint256,bytes)","inputs":[{"name":"l1Token","type":"address"},{"name":"to","type":"address"},{"name":"amount","type":"uint256"},{"name":"unused1","type":"uint256"},{"name":"unused2","type":"uint256"},{"name":"data","type":"bytes"}],"outputs":[{"name":"","type":"bytes"}],"mut":"payable","doc":{"notice":"Transfer tokens from L1 to L2 or L2 to L1","details":"Burns L2 tokens and initiates a transfer to L1. The tokens will be available on L1 only after the wait period (7 days) is over, and will require an Outbox.executeTransaction to finalize. Note that the caller must previously allow the gateway to spend the specified amount of GRT. No additional callhook data is allowed. The two unused params are needed for compatibility with Arbitrum's gateway router. The function is payable for ITokenGateway compatibility, but msg.value must be zero.","params":{"amount":"Amount of tokens to transfer","data":"Additional data for the transfer","gasPriceBid":"Gas price bid for the transaction","maxGas":"Maximum gas for the transaction","to":"Recipient address on the destination chain","token":"Address of the token being transferred"},"returns":{"_0":"Transaction data"}},"access":{"roles":[],"mods":["nonReentrant"]},"emits":["WithdrawalInitiated"]},{"name":"setL1CounterpartAddress","sig":"setL1CounterpartAddress(address)","inputs":[{"name":"l1Counterpart","type":"address"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Sets the address of the counterpart gateway on L1","params":{"_l1Counterpart":"Address of the L1GraphTokenGateway on L1"}},"access":{"roles":[],"mods":["onlyGovernor"]},"emits":["L1CounterpartAddressSet"]},{"name":"setL1TokenAddress","sig":"setL1TokenAddress(address)","inputs":[{"name":"l1GRT","type":"address"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Sets the address of the Graph Token on L1","params":{"_l1GRT":"L1 address of the Graph Token contract"}},"access":{"roles":[],"mods":["onlyGovernor"]},"emits":["L1TokenAddressSet"]},{"name":"setL2Router","sig":"setL2Router(address)","inputs":[{"name":"l2Router","type":"address"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Sets the address of the Arbitrum Gateway Router on L2","params":{"_l2Router":"Address of the L2 Router (provided by Arbitrum)"}},"access":{"roles":[],"mods":["onlyGovernor"]},"emits":["L2RouterSet"]}],"events":[{"name":"DepositFinalized","sig":"DepositFinalized(address,address,address,uint256)","inputs":[{"name":"l1Token","type":"address","indexed":true},{"name":"from","type":"address","indexed":true},{"name":"to","type":"address","indexed":true},{"name":"amount","type":"uint256","indexed":false}],"doc":{"notice":"Emitted when an incoming transfer is finalized, i.e. tokens were deposited from L1 to L2","params":{"amount":"Amount of tokens transferred","from":"Address sending the tokens on L1","l1Token":"Address of the L1 token","to":"Address receiving the tokens on L2"}}},{"name":"L1CounterpartAddressSet","sig":"L1CounterpartAddressSet(address)","inputs":[{"name":"l1Counterpart","type":"address","indexed":false}],"doc":{"notice":"Emitted when the address of the counterpart gateway on L1 has been updated","params":{"l1Counterpart":"Address of the L1 counterpart gateway"}}},{"name":"L1TokenAddressSet","sig":"L1TokenAddressSet(address)","inputs":[{"name":"l1GRT","type":"address","indexed":false}],"doc":{"notice":"Emitted when the L1 Graph Token address has been updated","params":{"l1GRT":"Address of the L1 GRT contract"}}},{"name":"L2RouterSet","sig":"L2RouterSet(address)","inputs":[{"name":"l2Router","type":"address","indexed":false}],"doc":{"notice":"Emitted when the Arbitrum Gateway Router address on L2 has been updated","params":{"l2Router":"Address of the L2 Gateway Router"}}},{"name":"WithdrawalInitiated","sig":"WithdrawalInitiated(address,address,address,uint256,uint256,uint256)","inputs":[{"name":"l1Token","type":"address","indexed":false},{"name":"from","type":"address","indexed":true},{"name":"to","type":"address","indexed":true},{"name":"l2ToL1Id","type":"uint256","indexed":true},{"name":"exitNum","type":"uint256","indexed":false},{"name":"amount","type":"uint256","indexed":false}],"doc":{"notice":"Emitted when an outbound transfer is initiated, i.e. tokens are being withdrawn from L2 back to L1","params":{"amount":"Amount of tokens transferred","exitNum":"Exit number (always 0 for this contract)","from":"Address sending the tokens on L2","l1Token":"Address of the L1 token","l2ToL1Id":"ID of the L2 to L1 message","to":"Address receiving the tokens on L1"}}}],"counts":{"reads":2,"writes":7,"events":5}},{"id":"L1GraphTokenGateway","name":"L1GraphTokenGateway","layer":"bridge","chain":"L1","core":false,"legacy":false,"address":null,"desc":"The Ethereum (L1) end of the GRT bridge. It escrows GRT in the BridgeEscrow and sends a message to Arbitrum to mint the matching tokens on L2, and releases escrow when tokens come back.","contractDoc":{"title":"L1 Graph Token Gateway Contract","notice":"Provides the L1 side of the Ethereum-Arbitrum GRT bridge. Sends GRT to the L2 chain by escrowing them and sending a message to the L2 gateway, and receives tokens from L2 by releasing them from escrow. Based on Offchain Labs' reference implementation and Livepeer's arbitrum-lpt-bridge (See: https://github.com/OffchainLabs/arbitrum/tree/master/packages/arb-bridge-peripherals/contracts/tokenbridge and https://github.com/livepeer/arbitrum-lpt-bridge)"},"implements":["ITokenGateway","IGraphTokenGateway"],"deps":[{"to":"BridgeEscrow","label":"escrows bridged GRT"},{"to":"GraphToken","label":"moves L1 GRT"}],"roles":[],"reads":[{"name":"accumulatedL2MintAllowanceAtBlock","sig":"accumulatedL2MintAllowanceAtBlock(uint256)","inputs":[{"name":"_blockNum","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}],"mut":"view","doc":{"notice":"Get the accumulated L2 mint allowance at a particular block number","params":{"_blockNum":"Block at which allowance will be computed"},"returns":{"_0":"The accumulated GRT amount that can be minted from L2 at the specified block"}}},{"name":"accumulatedL2MintAllowanceSnapshot","sig":"accumulatedL2MintAllowanceSnapshot()","inputs":[],"outputs":[{"name":"","type":"uint256"}],"mut":"view","doc":{"notice":"Accumulated allowance for tokens minted from L2 at lastL2MintAllowanceUpdateBlock"}},{"name":"calculateL2TokenAddress","sig":"calculateL2TokenAddress(address)","inputs":[{"name":"_l1ERC20","type":"address"}],"outputs":[{"name":"","type":"address"}],"mut":"view","doc":{"notice":"Calculate the address used when bridging an ERC20 token","details":"In our case, this would only work for GRT.","params":{"l1ERC20":"address of L1 token"},"returns":{"_0":"L2 address of a bridged ERC20 token"}}},{"name":"callhookAllowlist","sig":"callhookAllowlist(address)","inputs":[{"name":"","type":"address"}],"outputs":[{"name":"","type":"bool"}],"mut":"view","doc":{"notice":"Addresses for which this mapping is true are allowed to send callhooks in outbound transfers"}},{"name":"controller","sig":"controller()","inputs":[],"outputs":[{"name":"","type":"address"}],"mut":"view","doc":{"notice":"Get the Controller that manages this contract"}},{"name":"counterpartGateway","sig":"counterpartGateway()","inputs":[],"outputs":[{"name":"","type":"address"}],"mut":"view","doc":{"notice":"Get the address of the L2GraphTokenGateway","details":"This is added for compatibility with the Arbitrum Router's gateway registration process.","returns":{"_0":"Address of the L2 gateway connected to this gateway"}}},{"name":"escrow","sig":"escrow()","inputs":[],"outputs":[{"name":"","type":"address"}],"mut":"view","doc":{"notice":"Address of the BridgeEscrow contract that holds the GRT in the bridge"}},{"name":"getOutboundCalldata","sig":"getOutboundCalldata(address,address,address,uint256,bytes)","inputs":[{"name":"_l1Token","type":"address"},{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_amount","type":"uint256"},{"name":"_data","type":"bytes"}],"outputs":[{"name":"","type":"bytes"}],"mut":"pure","doc":{"notice":"Creates calldata required to create a retryable ticket","details":"encodes the target function with its params which will be called on L2 when the retryable ticket is redeemed","params":{"_amount":"Amount of GRT to transfer","_data":"Additional call data for the L2 transaction, which must be empty unless the caller is allowlisted","_from":"Address on L1 from which we're transferring tokens","_l1Token":"Address of the Graph token contract on L1","_to":"Address on L2 to which we're transferring tokens"},"returns":{"_0":"Encoded calldata (including function selector) for the L2 transaction"}}},{"name":"inbox","sig":"inbox()","inputs":[],"outputs":[{"name":"","type":"address"}],"mut":"view","doc":{"notice":"Address of the Arbitrum Inbox"}},{"name":"l1Router","sig":"l1Router()","inputs":[],"outputs":[{"name":"","type":"address"}],"mut":"view","doc":{"notice":"Address of the Arbitrum Gateway Router on L1"}},{"name":"l2Counterpart","sig":"l2Counterpart()","inputs":[],"outputs":[{"name":"","type":"address"}],"mut":"view","doc":{"notice":"Address of the L2GraphTokenGateway on L2 that is the counterpart of this gateway"}},{"name":"l2GRT","sig":"l2GRT()","inputs":[],"outputs":[{"name":"","type":"address"}],"mut":"view","doc":{"notice":"Address of the Graph Token contract on L2"}},{"name":"l2MintAllowancePerBlock","sig":"l2MintAllowancePerBlock()","inputs":[],"outputs":[{"name":"","type":"uint256"}],"mut":"view","doc":{"notice":"New L2 mint allowance per block"}},{"name":"lastL2MintAllowanceUpdateBlock","sig":"lastL2MintAllowanceUpdateBlock()","inputs":[],"outputs":[{"name":"","type":"uint256"}],"mut":"view","doc":{"notice":"Block at which new L2 allowance starts accumulating"}},{"name":"lastPartialPauseTime","sig":"lastPartialPauseTime()","inputs":[],"outputs":[{"name":"","type":"uint256"}],"mut":"view","doc":{"notice":"Timestamp for the last time the partial pause was set"}},{"name":"lastPauseTime","sig":"lastPauseTime()","inputs":[],"outputs":[{"name":"","type":"uint256"}],"mut":"view","doc":{"notice":"Timestamp for the last time the full pause was set"}},{"name":"paused","sig":"paused()","inputs":[],"outputs":[{"name":"","type":"bool"}],"mut":"view","doc":{"notice":"Getter to access paused state of this contract","returns":{"_0":"True if the contract is paused, false otherwise"}}},{"name":"pauseGuardian","sig":"pauseGuardian()","inputs":[],"outputs":[{"name":"","type":"address"}],"mut":"view","doc":{"notice":"Pause guardian is a separate entity from the governor that can pause and unpause the protocol, fully or partially"}},{"name":"totalMintedFromL2","sig":"totalMintedFromL2()","inputs":[],"outputs":[{"name":"","type":"uint256"}],"mut":"view","doc":{"notice":"Total amount minted from L2"}}],"writes":[{"name":"acceptProxy","sig":"acceptProxy(address)","inputs":[{"name":"_proxy","type":"address"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Accept to be an implementation of proxy.","params":{"_proxy":"Proxy to accept"}}},{"name":"acceptProxyAndCall","sig":"acceptProxyAndCall(address,bytes)","inputs":[{"name":"_proxy","type":"address"},{"name":"_data","type":"bytes"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Accept to be an implementation of proxy and then call a function from the new implementation as specified by `_data`, which should be an encoded function call. This is useful to initialize new storage variables in the proxied contract.","params":{"_data":"Calldata for the initialization function call (including selector)","_proxy":"Proxy to accept"}}},{"name":"addToCallhookAllowlist","sig":"addToCallhookAllowlist(address)","inputs":[{"name":"_newAllowlisted","type":"address"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Adds an address to the callhook allowlist. This address will be allowed to include callhooks when transferring tokens.","params":{"_newAllowlisted":"Address to add to the allowlist"}},"access":{"roles":[],"mods":["onlyGovernor"]},"emits":["AddedToCallhookAllowlist"]},{"name":"finalizeInboundTransfer","sig":"finalizeInboundTransfer(address,address,address,uint256,bytes)","inputs":[{"name":"_l1Token","type":"address"},{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_amount","type":"uint256"},{"name":"","type":"bytes"}],"outputs":[],"mut":"payable","doc":{"notice":"Finalize an inbound token transfer","details":"can only accept transactions coming from the L2 GRT Gateway. The last parameter is unused but kept for compatibility with Arbitrum gateways, and the encoded exitNum is assumed to be 0.","params":{"amount":"Amount of tokens being transferred","data":"Additional data for the transfer","from":"Sender address on the source chain","to":"Recipient address on the destination chain","token":"Address of the token being transferred"}},"emits":["WithdrawalFinalized","TokensMintedFromL2"],"calls":["GraphToken"]},{"name":"initialize","sig":"initialize(address)","inputs":[{"name":"_controller","type":"address"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Initialize the L1GraphTokenGateway contract.","details":"The contract will be paused. Note some parameters have to be set separately as they are generally not expected to be available at initialization time: - inbox and l1Router using setArbitrumAddresses - l2GRT using setL2TokenAddress - l2Counterpart using setL2CounterpartAddress - escrow using setEscrowAddress - allowlisted callhook callers using addToCallhookAllowlist - pauseGuardian using setPauseGuardian","params":{"_controller":"Address of the Controller that manages this contract"}}},{"name":"outboundTransfer","sig":"outboundTransfer(address,address,uint256,uint256,uint256,bytes)","inputs":[{"name":"_l1Token","type":"address"},{"name":"_to","type":"address"},{"name":"_amount","type":"uint256"},{"name":"_maxGas","type":"uint256"},{"name":"_gasPriceBid","type":"uint256"},{"name":"_data","type":"bytes"}],"outputs":[{"name":"","type":"bytes"}],"mut":"payable","doc":{"notice":"Transfer tokens from L1 to L2 or L2 to L1","details":"maxGas and gasPriceBid must be set using Arbitrum's NodeInterface.estimateRetryableTicket method. Also note that allowlisted senders (some protocol contracts) can include additional calldata for a callhook to be executed on the L2 side when the tokens are received. In this case, the L2 transaction can revert if the callhook reverts, potentially locking the tokens on the bridge if the callhook never succeeds. This requires extra care when adding contracts to the allowlist, but is necessary to ensure that the tickets can be retried in the case of a temporary failure, and to ensure the atomicity of callhooks with token transfers.","params":{"amount":"Amount of tokens to transfer","data":"Additional data for the transfer","gasPriceBid":"Gas price bid for the transaction","maxGas":"Maximum gas for the transaction","to":"Recipient address on the destination chain","token":"Address of the token being transferred"},"returns":{"_0":"Transaction data"}},"emits":["DepositInitiated"],"calls":["GraphToken"]},{"name":"removeFromCallhookAllowlist","sig":"removeFromCallhookAllowlist(address)","inputs":[{"name":"_notAllowlisted","type":"address"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Removes an address from the callhook allowlist. This address will no longer be allowed to include callhooks when transferring tokens.","params":{"_notAllowlisted":"Address to remove from the allowlist"}},"access":{"roles":[],"mods":["onlyGovernor"]},"emits":["RemovedFromCallhookAllowlist"]},{"name":"setArbitrumAddresses","sig":"setArbitrumAddresses(address,address)","inputs":[{"name":"_inbox","type":"address"},{"name":"_l1Router","type":"address"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Sets the addresses for L1 contracts provided by Arbitrum","params":{"_inbox":"Address of the Inbox that is part of the Arbitrum Bridge","_l1Router":"Address of the Gateway Router"}},"access":{"roles":[],"mods":["onlyGovernor"]},"emits":["ArbitrumAddressesSet"]},{"name":"setController","sig":"setController(address)","inputs":[{"name":"_controller","type":"address"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Set the controller that manages this contract","details":"Only the current controller can set a new controller","params":{"newController":"Address of the new controller"}}},{"name":"setEscrowAddress","sig":"setEscrowAddress(address)","inputs":[{"name":"_escrow","type":"address"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Sets the address of the escrow contract on L1","params":{"_escrow":"Address of the BridgeEscrow"}},"access":{"roles":[],"mods":["onlyGovernor"]},"emits":["EscrowAddressSet"]},{"name":"setL2CounterpartAddress","sig":"setL2CounterpartAddress(address)","inputs":[{"name":"_l2Counterpart","type":"address"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Sets the address of the counterpart gateway on L2","params":{"_l2Counterpart":"Address of the corresponding L2GraphTokenGateway on Arbitrum"}},"access":{"roles":[],"mods":["onlyGovernor"]},"emits":["L2CounterpartAddressSet"]},{"name":"setL2MintAllowanceParametersManual","sig":"setL2MintAllowanceParametersManual(uint256,uint256,uint256)","inputs":[{"name":"_accumulatedL2MintAllowanceSnapshot","type":"uint256"},{"name":"_l2MintAllowancePerBlock","type":"uint256"},{"name":"_lastL2MintAllowanceUpdateBlock","type":"uint256"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Manually sets the parameters used to compute the L2 mint allowance The use of this function is not recommended, use updateL2MintAllowance instead; this one is only meant to be used as a backup recovery if a previous call to updateL2MintAllowance was done with incorrect values.","params":{"_accumulatedL2MintAllowanceSnapshot":"Accumulated L2 mint allowance at L1 block _lastL2MintAllowanceUpdateBlock","_l2MintAllowancePerBlock":"L2 issuance per block since block number _lastL2MintAllowanceUpdateBlock","_lastL2MintAllowanceUpdateBlock":"L1 Block number at which issuancePerBlock was last updated in L2"}},"access":{"roles":[],"mods":["onlyGovernor"]},"emits":["L2MintAllowanceUpdated"]},{"name":"setL2TokenAddress","sig":"setL2TokenAddress(address)","inputs":[{"name":"_l2GRT","type":"address"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Sets the address of the L2 Graph Token","params":{"_l2GRT":"Address of the GRT contract on L2"}},"access":{"roles":[],"mods":["onlyGovernor"]},"emits":["L2TokenAddressSet"]},{"name":"setPaused","sig":"setPaused(bool)","inputs":[{"name":"_newPaused","type":"bool"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Change the paused state of the contract","params":{"_newPaused":"New value for the pause state (true means the transfers will be paused)"}}},{"name":"setPauseGuardian","sig":"setPauseGuardian(address)","inputs":[{"name":"_newPauseGuardian","type":"address"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Change the Pause Guardian for this contract","params":{"_newPauseGuardian":"The address of the new Pause Guardian"}}},{"name":"syncAllContracts","sig":"syncAllContracts()","inputs":[],"outputs":[],"mut":"nonpayable","doc":{"notice":"Sync protocol contract addresses from the Controller registry","details":"This function will cache all the contracts using the latest addresses. Anyone can call the function whenever a Proxy contract change in the controller to ensure the protocol is using the latest version."}},{"name":"updateL2MintAllowance","sig":"updateL2MintAllowance(uint256,uint256)","inputs":[{"name":"_l2IssuancePerBlock","type":"uint256"},{"name":"_updateBlockNum","type":"uint256"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Updates the L2 mint allowance per block It is meant to be called _after_ the issuancePerBlock is updated in L2. The caller should provide the new issuance per block and the block at which it was updated, the function will automatically compute the values so that the bridge's mint allowance correctly tracks the maximum rewards minted in L2.","params":{"_l2IssuancePerBlock":"New issuancePerBlock that has been set in L2","_updateBlockNum":"L1 Block number at which issuancePerBlock was updated in L2"}},"access":{"roles":[],"mods":["onlyGovernor"]},"emits":["L2MintAllowanceUpdated"]}],"events":[{"name":"AddedToCallhookAllowlist","sig":"AddedToCallhookAllowlist(address)","inputs":[{"name":"newAllowlisted","type":"address","indexed":false}],"doc":{"notice":"Emitted when an address is added to the callhook allowlist","params":{"newAllowlisted":"Address added to the allowlist"}}},{"name":"ArbitrumAddressesSet","sig":"ArbitrumAddressesSet(address,address)","inputs":[{"name":"inbox","type":"address","indexed":false},{"name":"l1Router","type":"address","indexed":false}],"doc":{"notice":"Emitted when the Arbitrum Inbox and Gateway Router addresses have been updated","params":{"inbox":"Address of the Arbitrum Inbox","l1Router":"Address of the L1 Gateway Router"}}},{"name":"ContractSynced","sig":"ContractSynced(bytes32,address)","inputs":[{"name":"nameHash","type":"bytes32","indexed":true},{"name":"contractAddress","type":"address","indexed":false}],"doc":{"notice":"Emitted when contract with `nameHash` is synced to `contractAddress`."}},{"name":"DepositInitiated","sig":"DepositInitiated(address,address,address,uint256,uint256)","inputs":[{"name":"l1Token","type":"address","indexed":false},{"name":"from","type":"address","indexed":true},{"name":"to","type":"address","indexed":true},{"name":"sequenceNumber","type":"uint256","indexed":true},{"name":"amount","type":"uint256","indexed":false}],"doc":{"notice":"Emitted when an outbound transfer is initiated, i.e. tokens are deposited from L1 to L2","params":{"amount":"Amount of tokens transferred","from":"Address sending the tokens on L1","l1Token":"Address of the L1 token being transferred","sequenceNumber":"Sequence number of the retryable ticket","to":"Address receiving the tokens on L2"}}},{"name":"EscrowAddressSet","sig":"EscrowAddressSet(address)","inputs":[{"name":"escrow","type":"address","indexed":false}],"doc":{"notice":"Emitted when the escrow address has been updated","params":{"escrow":"Address of the escrow contract"}}},{"name":"L2CounterpartAddressSet","sig":"L2CounterpartAddressSet(address)","inputs":[{"name":"l2Counterpart","type":"address","indexed":false}],"doc":{"notice":"Emitted when the counterpart L2GraphTokenGateway address has been updated","params":{"l2Counterpart":"Address of the L2 counterpart gateway"}}},{"name":"L2MintAllowanceUpdated","sig":"L2MintAllowanceUpdated(uint256,uint256,uint256)","inputs":[{"name":"accumulatedL2MintAllowanceSnapshot","type":"uint256","indexed":false},{"name":"l2MintAllowancePerBlock","type":"uint256","indexed":false},{"name":"lastL2MintAllowanceUpdateBlock","type":"uint256","indexed":false}],"doc":{"notice":"Emitted when the L2 mint allowance per block is updated","params":{"accumulatedL2MintAllowanceSnapshot":"Accumulated allowance snapshot at update block","l2MintAllowancePerBlock":"New allowance per block","lastL2MintAllowanceUpdateBlock":"Block number when allowance was updated"}}},{"name":"L2TokenAddressSet","sig":"L2TokenAddressSet(address)","inputs":[{"name":"l2GRT","type":"address","indexed":false}],"doc":{"notice":"Emitted when the L2 GRT address has been updated","params":{"l2GRT":"Address of the L2 GRT contract"}}},{"name":"NewPauseGuardian","sig":"NewPauseGuardian(address,address)","inputs":[{"name":"oldPauseGuardian","type":"address","indexed":true},{"name":"pauseGuardian","type":"address","indexed":true}],"doc":{"notice":"Emitted when the pause guardian is changed"}},{"name":"ParameterUpdated","sig":"ParameterUpdated(string)","inputs":[{"name":"param","type":"string","indexed":false}],"doc":{"notice":"Emitted when a contract parameter has been updated"}},{"name":"PartialPauseChanged","sig":"PartialPauseChanged(bool)","inputs":[{"name":"isPaused","type":"bool","indexed":false}],"doc":{"notice":"Emitted when the partial pause state changed"}},{"name":"PauseChanged","sig":"PauseChanged(bool)","inputs":[{"name":"isPaused","type":"bool","indexed":false}],"doc":{"notice":"Emitted when the full pause state changed"}},{"name":"RemovedFromCallhookAllowlist","sig":"RemovedFromCallhookAllowlist(address)","inputs":[{"name":"notAllowlisted","type":"address","indexed":false}],"doc":{"notice":"Emitted when an address is removed from the callhook allowlist","params":{"notAllowlisted":"Address removed from the allowlist"}}},{"name":"SetController","sig":"SetController(address)","inputs":[{"name":"controller","type":"address","indexed":false}],"doc":{"notice":"Emitted when the controller address has been set"}},{"name":"TokensMintedFromL2","sig":"TokensMintedFromL2(uint256)","inputs":[{"name":"amount","type":"uint256","indexed":false}],"doc":{"notice":"Emitted when tokens are minted due to an incoming transfer from L2","params":{"amount":"Amount of tokens minted"}}},{"name":"TxToL2","sig":"TxToL2(address,address,uint256,bytes)","inputs":[{"name":"_from","type":"address","indexed":true},{"name":"_to","type":"address","indexed":true},{"name":"_seqNum","type":"uint256","indexed":true},{"name":"_data","type":"bytes","indexed":false}],"doc":{"notice":"Emitted when a transaction is sent to L2"}},{"name":"WithdrawalFinalized","sig":"WithdrawalFinalized(address,address,address,uint256,uint256)","inputs":[{"name":"l1Token","type":"address","indexed":false},{"name":"from","type":"address","indexed":true},{"name":"to","type":"address","indexed":true},{"name":"exitNum","type":"uint256","indexed":true},{"name":"amount","type":"uint256","indexed":false}],"doc":{"notice":"Emitted when an incoming transfer is finalized, i.e tokens are withdrawn from L2 to L1","params":{"amount":"Amount of tokens transferred","exitNum":"Exit number (always 0 for this contract)","from":"Address sending the tokens on L2","l1Token":"Address of the L1 token being transferred","to":"Address receiving the tokens on L1"}}}],"counts":{"reads":19,"writes":17,"events":17}},{"id":"BridgeEscrow","name":"BridgeEscrow","layer":"bridge","chain":"L1","core":false,"legacy":false,"address":null,"desc":"A vault on L1 that simply holds the GRT backing every token bridged to L2. The L1 gateway is approved to move funds in and out as users bridge across.","contractDoc":{"title":"Bridge Escrow","notice":"This contracts acts as a gateway for an L2 bridge (or several). It simply holds GRT and has a set of spenders that can transfer the tokens; the L1 side of each L2 bridge has to be approved as a spender."},"implements":["(simple escrow)"],"deps":[],"roles":[],"reads":[{"name":"controller","sig":"controller()","inputs":[],"outputs":[{"name":"","type":"address"}],"mut":"view","doc":{"notice":"Get the Controller that manages this contract"}}],"writes":[{"name":"acceptProxy","sig":"acceptProxy(address)","inputs":[{"name":"_proxy","type":"address"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Accept to be an implementation of proxy.","params":{"_proxy":"Proxy to accept"}}},{"name":"acceptProxyAndCall","sig":"acceptProxyAndCall(address,bytes)","inputs":[{"name":"_proxy","type":"address"},{"name":"_data","type":"bytes"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Accept to be an implementation of proxy and then call a function from the new implementation as specified by `_data`, which should be an encoded function call. This is useful to initialize new storage variables in the proxied contract.","params":{"_data":"Calldata for the initialization function call (including selector)","_proxy":"Proxy to accept"}}},{"name":"approveAll","sig":"approveAll(address)","inputs":[{"name":"_spender","type":"address"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Approve a spender (i.e. a bridge that manages the GRT funds held by the escrow)","params":{"_spender":"Address of the spender that will be approved"}},"access":{"roles":[],"mods":["onlyGovernor"]}},{"name":"initialize","sig":"initialize(address)","inputs":[{"name":"_controller","type":"address"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Initialize the BridgeEscrow contract.","params":{"_controller":"Address of the Controller that manages this contract"}}},{"name":"revokeAll","sig":"revokeAll(address)","inputs":[{"name":"_spender","type":"address"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Revoke a spender (i.e. a bridge that will no longer manage the GRT funds held by the escrow)","params":{"_spender":"Address of the spender that will be revoked"}},"access":{"roles":[],"mods":["onlyGovernor"]}},{"name":"setController","sig":"setController(address)","inputs":[{"name":"_controller","type":"address"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Set the controller that manages this contract","details":"Only the current controller can set a new controller","params":{"newController":"Address of the new controller"}}},{"name":"syncAllContracts","sig":"syncAllContracts()","inputs":[],"outputs":[],"mut":"nonpayable","doc":{"notice":"Sync protocol contract addresses from the Controller registry","details":"This function will cache all the contracts using the latest addresses. Anyone can call the function whenever a Proxy contract change in the controller to ensure the protocol is using the latest version."}}],"events":[{"name":"ContractSynced","sig":"ContractSynced(bytes32,address)","inputs":[{"name":"nameHash","type":"bytes32","indexed":true},{"name":"contractAddress","type":"address","indexed":false}],"doc":{"notice":"Emitted when contract with `nameHash` is synced to `contractAddress`."}},{"name":"ParameterUpdated","sig":"ParameterUpdated(string)","inputs":[{"name":"param","type":"string","indexed":false}],"doc":{"notice":"Emitted when a contract parameter has been updated"}},{"name":"SetController","sig":"SetController(address)","inputs":[{"name":"controller","type":"address","indexed":false}],"doc":{"notice":"Emitted when the controller address has been set"}}],"counts":{"reads":1,"writes":7,"events":3}},{"id":"GraphToken","name":"GraphToken (L1 GRT)","layer":"legacy","chain":"L1","core":false,"legacy":false,"address":null,"desc":"The original GRT ERC-20 on Ethereum mainnet. It is the canonical supply that the L1 gateway escrows when bridging to L2, where L2GraphToken mirrors it.","contractDoc":{"title":"GraphToken contract","notice":"This is the implementation of the ERC20 Graph Token. The implementation exposes a Permit() function to allow for a spender to send a signed message and approve funds to a spender following EIP2612 to make integration with other contracts easier. The token is initially owned by the deployer address that can mint tokens to create the initial distribution. For convenience, an initial supply can be passed in the constructor that will be assigned to the deployer. The governor can add the RewardsManager contract to mint indexing rewards."},"implements":["IGraphToken","ERC20"],"deps":[],"roles":[],"reads":[{"name":"allowance","sig":"allowance(address,address)","inputs":[{"name":"owner","type":"address"},{"name":"spender","type":"address"}],"outputs":[{"name":"","type":"uint256"}],"mut":"view","doc":{"details":"See {IERC20-allowance}."}},{"name":"balanceOf","sig":"balanceOf(address)","inputs":[{"name":"account","type":"address"}],"outputs":[{"name":"","type":"uint256"}],"mut":"view","doc":{"details":"See {IERC20-balanceOf}."}},{"name":"isMinter","sig":"isMinter(address)","inputs":[{"name":"account","type":"address"}],"outputs":[{"name":"","type":"bool"}],"mut":"view","doc":{"notice":"Return if the `_account` is a minter or not.","params":{"_account":"Address to check"},"returns":{"_0":"True if the `_account` is minter"}}},{"name":"totalSupply","sig":"totalSupply()","inputs":[],"outputs":[{"name":"","type":"uint256"}],"mut":"view","doc":{"details":"See {IERC20-totalSupply}."}}],"writes":[{"name":"addMinter","sig":"addMinter(address)","inputs":[{"name":"account","type":"address"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Add a new minter.","details":"Only callable by accounts with appropriate permissions","params":{"_account":"Address of the minter"}},"access":{"roles":[],"mods":["onlyGovernor"]}},{"name":"approve","sig":"approve(address,uint256)","inputs":[{"name":"spender","type":"address"},{"name":"amount","type":"uint256"}],"outputs":[{"name":"","type":"bool"}],"mut":"nonpayable","doc":{"details":"See {IERC20-approve}. Requirements: - `spender` cannot be the zero address."}},{"name":"burn","sig":"burn(uint256)","inputs":[{"name":"amount","type":"uint256"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Burns tokens from the caller's account","details":"Destroys `amount` tokens from the caller. See {ERC20-_burn}.","params":{"amount":"The amount of tokens to burn"}}},{"name":"burnFrom","sig":"burnFrom(address,uint256)","inputs":[{"name":"from","type":"address"},{"name":"amount","type":"uint256"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Burns tokens from a specified account (requires allowance)","details":"Destroys `amount` tokens from `account`, deducting from the caller's allowance. See {ERC20-_burn} and {ERC20-allowance}. Requirements: - the caller must have allowance for ``accounts``'s tokens of at least `amount`.","params":{"amount":"The amount of tokens to burn","from":"The account to burn tokens from"}}},{"name":"decreaseAllowance","sig":"decreaseAllowance(address,uint256)","inputs":[{"name":"spender","type":"address"},{"name":"subtractedValue","type":"uint256"}],"outputs":[{"name":"","type":"bool"}],"mut":"nonpayable","doc":{"notice":"Decreases the allowance granted to a spender","details":"Atomically decreases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address. - `spender` must have allowance for the caller of at least `subtractedValue`.","params":{"spender":"The account whose allowance will be decreased","subtractedValue":"The amount to decrease the allowance by"},"returns":{"_0":"True if the operation succeeded"}}},{"name":"increaseAllowance","sig":"increaseAllowance(address,uint256)","inputs":[{"name":"spender","type":"address"},{"name":"addedValue","type":"uint256"}],"outputs":[{"name":"","type":"bool"}],"mut":"nonpayable","doc":{"notice":"Increases the allowance granted to a spender","details":"Atomically increases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address.","params":{"addedValue":"The amount to increase the allowance by","spender":"The account whose allowance will be increased"},"returns":{"_0":"True if the operation succeeded"}}},{"name":"mint","sig":"mint(address,uint256)","inputs":[{"name":"to","type":"address"},{"name":"amount","type":"uint256"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Mint new tokens.","details":"Only callable by accounts with minter role","params":{"_amount":"Amount of tokens to mint","_to":"Address to send the newly minted tokens"}}},{"name":"permit","sig":"permit(address,address,uint256,uint256,uint8,bytes32,bytes32)","inputs":[{"name":"owner","type":"address"},{"name":"spender","type":"address"},{"name":"value","type":"uint256"},{"name":"deadline","type":"uint256"},{"name":"v","type":"uint8"},{"name":"r","type":"bytes32"},{"name":"s","type":"bytes32"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Approve token allowance by validating a message signed by the holder.","params":{"_deadline":"Expiration time of the signed permit","_owner":"Address of the token holder","_r":"Signature r value","_s":"Signature s value","_spender":"Address of the approved spender","_v":"Signature version","_value":"Amount of tokens to approve the spender"}}},{"name":"removeMinter","sig":"removeMinter(address)","inputs":[{"name":"account","type":"address"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Remove a minter.","details":"Only callable by accounts with appropriate permissions","params":{"_account":"Address of the minter"}},"access":{"roles":[],"mods":["onlyGovernor"]}},{"name":"renounceMinter","sig":"renounceMinter()","inputs":[],"outputs":[],"mut":"nonpayable","doc":{"notice":"Renounce to be a minter.","details":"Allows a minter to voluntarily give up their minting privileges"}},{"name":"transfer","sig":"transfer(address,uint256)","inputs":[{"name":"recipient","type":"address"},{"name":"amount","type":"uint256"}],"outputs":[{"name":"","type":"bool"}],"mut":"nonpayable","doc":{"details":"See {IERC20-transfer}. Requirements: - `recipient` cannot be the zero address. - the caller must have a balance of at least `amount`."}},{"name":"transferFrom","sig":"transferFrom(address,address,uint256)","inputs":[{"name":"sender","type":"address"},{"name":"recipient","type":"address"},{"name":"amount","type":"uint256"}],"outputs":[{"name":"","type":"bool"}],"mut":"nonpayable","doc":{"details":"See {IERC20-transferFrom}. Emits an {Approval} event indicating the updated allowance. This is not required by the EIP. See the note at the beginning of {ERC20}. Requirements: - `sender` and `recipient` cannot be the zero address. - `sender` must have a balance of at least `amount`. - the caller must have allowance for ``sender``'s tokens of at least `amount`."}}],"events":[{"name":"Approval","sig":"Approval(address,address,uint256)","inputs":[{"name":"owner","type":"address","indexed":true},{"name":"spender","type":"address","indexed":true},{"name":"value","type":"uint256","indexed":false}],"doc":{"details":"Emitted when the allowance of a `spender` for an `owner` is set by a call to {approve}. `value` is the new allowance."}},{"name":"Transfer","sig":"Transfer(address,address,uint256)","inputs":[{"name":"from","type":"address","indexed":true},{"name":"to","type":"address","indexed":true},{"name":"value","type":"uint256","indexed":false}],"doc":{"details":"Emitted when `value` tokens are moved from one account (`from`) to another (`to`). Note that `value` may be zero."}}],"counts":{"reads":4,"writes":12,"events":2}},{"id":"L2Staking","name":"L2Staking (legacy)","layer":"legacy","chain":"L2","core":false,"legacy":true,"address":"0x865365C425f3A593Ffe698D9c4E6707D14d51e08","desc":"The pre-Horizon staking contract, where indexers allocated stake directly to subgraphs and earned rewards and query fees. On this branch its proxy has been upgraded to HorizonStaking, so this ABI is the legacy surface of the same address that the migration is moving away from.","contractDoc":{"title":"L2Staking contract","notice":"This contract is the L2 variant of the Staking contract. It adds a function to receive an indexer's stake or delegation from L1. Note that this contract inherits Staking, which uses a StakingExtension contract to implement the full IStaking interface through delegatecalls."},"implements":["IL2Staking","IStaking","IStakingExtension"],"deps":[{"to":"L2GraphToken","label":"held staked GRT"},{"to":"RewardsManager","label":"claimed rewards"}],"roles":[],"reads":[{"name":"allocations","sig":"allocations(address)","inputs":[{"name":"_allocationID","type":"address"}],"outputs":[{"name":"","type":"(address,bytes32,uint256,uint256,uint256,uint256,uint256,uint256,uint256)"}],"mut":"view","doc":{"notice":"Getter for allocations[_allocationID]: gets an allocation's information as an IStakingData.Allocation struct.","params":{"allocationID":"Allocation ID for which to query the allocation information"},"returns":{"_0":"The specified allocation, as an IStakingData.Allocation struct"}}},{"name":"alphaDenominator","sig":"alphaDenominator()","inputs":[],"outputs":[{"name":"","type":"uint32"}],"mut":"view","doc":{"notice":"Getter for the denominator of the rebates alpha parameter","returns":{"_0":"Alpha denominator"}}},{"name":"alphaNumerator","sig":"alphaNumerator()","inputs":[],"outputs":[{"name":"","type":"uint32"}],"mut":"view","doc":{"notice":"Getter for the numerator of the rebates alpha parameter","returns":{"_0":"Alpha numerator"}}},{"name":"controller","sig":"controller()","inputs":[],"outputs":[{"name":"","type":"address"}],"mut":"view","doc":{"notice":"Get the Controller that manages this contract","returns":{"_0":"The Controller as an IController interface"}}},{"name":"curationPercentage","sig":"curationPercentage()","inputs":[],"outputs":[{"name":"","type":"uint32"}],"mut":"view","doc":{"notice":"Getter for curationPercentage: the percentage of query fees that are distributed to curators.","returns":{"_0":"Curation percentage in parts per million"}}},{"name":"delegationPools","sig":"delegationPools(address)","inputs":[{"name":"_indexer","type":"address"}],"outputs":[{"name":"","type":"(uint32,uint32,uint32,uint256,uint256,uint256)"}],"mut":"view","doc":{"notice":"Getter for delegationPools[_indexer]: gets the delegation pool structure for a particular indexer.","params":{"indexer":"Address of the indexer for which to query the delegation pool"},"returns":{"_0":"Delegation pool as a DelegationPoolReturn struct"}}},{"name":"delegationRatio","sig":"delegationRatio()","inputs":[],"outputs":[{"name":"","type":"uint32"}],"mut":"view","doc":{"notice":"Getter for the delegationRatio, i.e. the delegation capacity multiplier: If delegation ratio is 100, and an Indexer has staked 5 GRT, then they can use up to 500 GRT from the delegated stake","returns":{"_0":"Delegation ratio"}}},{"name":"delegationTaxPercentage","sig":"delegationTaxPercentage()","inputs":[],"outputs":[{"name":"","type":"uint32"}],"mut":"view","doc":{"notice":"Getter for delegationTaxPercentage: Percentage of tokens to tax a delegation deposit, expressed in parts per million","returns":{"_0":"Delegation tax percentage in parts per million"}}},{"name":"delegationUnbondingPeriod","sig":"delegationUnbondingPeriod()","inputs":[],"outputs":[{"name":"","type":"uint32"}],"mut":"view","doc":{"notice":"Getter for delegationUnbondingPeriod: Time in epochs a delegator needs to wait to withdraw delegated stake","returns":{"_0":"Delegation unbonding period in epochs"}}},{"name":"getAllocation","sig":"getAllocation(address)","inputs":[{"name":"_allocationID","type":"address"}],"outputs":[{"name":"","type":"(address,bytes32,uint256,uint256,uint256,uint256,uint256,uint256,uint256)"}],"mut":"view","doc":{"notice":"Return the allocation by ID.","params":{"allocationID":"Address used as allocation identifier"},"returns":{"_0":"Allocation data"}}},{"name":"getAllocationData","sig":"getAllocationData(address)","inputs":[{"name":"_allocationID","type":"address"}],"outputs":[{"name":"","type":"bool"},{"name":"","type":"address"},{"name":"","type":"bytes32"},{"name":"","type":"uint256"},{"name":"","type":"uint256"},{"name":"","type":"uint256"}],"mut":"view","doc":{"notice":"Get the allocation data for the rewards manager","details":"New function to get the allocation data for the rewards managerNote that this is only to make tests pass, as the staking contract with this changes will never get deployed. HorizonStaking is taking it's place.","params":{"allocationID":"The allocation ID"},"returns":{"_0":"active Whether the allocation is active","_1":"indexer The indexer address","_2":"subgraphDeploymentID The subgraph deployment ID","_3":"tokens The allocated tokens","_4":"createdAtEpoch The epoch when allocation was created","_5":"closedAtEpoch The epoch when allocation was closed"}}},{"name":"getAllocationState","sig":"getAllocationState(address)","inputs":[{"name":"_allocationID","type":"address"}],"outputs":[{"name":"","type":"uint8"}],"mut":"view","doc":{"notice":"Return the current state of an allocation","params":{"allocationID":"Allocation identifier"},"returns":{"_0":"AllocationState enum with the state of the allocation"}}},{"name":"getDelegation","sig":"getDelegation(address,address)","inputs":[{"name":"_indexer","type":"address"},{"name":"_delegator","type":"address"}],"outputs":[{"name":"","type":"(uint256,uint256,uint256)"}],"mut":"view","doc":{"notice":"Return the delegation from a delegator to an indexer.","params":{"delegator":"Address of the delegator","indexer":"Address of the indexer where funds have been delegated"},"returns":{"_0":"Delegation data"}}},{"name":"getIndexerCapacity","sig":"getIndexerCapacity(address)","inputs":[{"name":"_indexer","type":"address"}],"outputs":[{"name":"","type":"uint256"}],"mut":"view","doc":{"notice":"Get the total amount of tokens available to use in allocations. This considers the indexer stake and delegated tokens according to delegation ratio","params":{"indexer":"Address of the indexer"},"returns":{"_0":"Amount of tokens available to allocate including delegation"}}},{"name":"getIndexerStakedTokens","sig":"getIndexerStakedTokens(address)","inputs":[{"name":"_indexer","type":"address"}],"outputs":[{"name":"","type":"uint256"}],"mut":"view","doc":{"notice":"Get the total amount of tokens staked by the indexer.","params":{"indexer":"Address of the indexer"},"returns":{"_0":"Amount of tokens staked by the indexer"}}},{"name":"getSubgraphAllocatedTokens","sig":"getSubgraphAllocatedTokens(bytes32)","inputs":[{"name":"_subgraphDeploymentID","type":"bytes32"}],"outputs":[{"name":"","type":"uint256"}],"mut":"view","doc":{"notice":"Return the total amount of tokens allocated to subgraph.","params":{"subgraphDeploymentID":"Deployment ID for the subgraph"},"returns":{"_0":"Total tokens allocated to subgraph"}}},{"name":"getWithdraweableDelegatedTokens","sig":"getWithdraweableDelegatedTokens((uint256,uint256,uint256))","inputs":[{"name":"_delegation","type":"(uint256,uint256,uint256)"}],"outputs":[{"name":"","type":"uint256"}],"mut":"view","doc":{"notice":"Returns amount of delegated tokens ready to be withdrawn after unbonding period.","params":{"delegation":"Delegation of tokens from delegator to indexer"},"returns":{"_0":"Amount of tokens to withdraw"}}},{"name":"hasStake","sig":"hasStake(address)","inputs":[{"name":"_indexer","type":"address"}],"outputs":[{"name":"","type":"bool"}],"mut":"view","doc":{"notice":"Getter that returns if an indexer has any stake.","params":{"indexer":"Address of the indexer"},"returns":{"_0":"True if indexer has staked tokens"}}},{"name":"isActiveAllocation","sig":"isActiveAllocation(address)","inputs":[{"name":"_allocationID","type":"address"}],"outputs":[{"name":"","type":"bool"}],"mut":"view","doc":{"notice":"Get the allocation active status for the rewards manager","details":"New function to get the allocation active status for the rewards managerNote that this is only to make tests pass, as the staking contract with this changes will never get deployed. HorizonStaking is taking it's place.","params":{"allocationID":"The allocation identifier"},"returns":{"_0":"True if the allocation is active, false otherwise"}}},{"name":"isAllocation","sig":"isAllocation(address)","inputs":[{"name":"_allocationID","type":"address"}],"outputs":[{"name":"","type":"bool"}],"mut":"view","doc":{"notice":"Return if allocationID is used.","params":{"allocationID":"Address used as signer by the indexer for an allocation"},"returns":{"_0":"True if allocationID already used"}}},{"name":"isDelegator","sig":"isDelegator(address,address)","inputs":[{"name":"_indexer","type":"address"},{"name":"_delegator","type":"address"}],"outputs":[{"name":"","type":"bool"}],"mut":"view","doc":{"notice":"Return whether the delegator has delegated to the indexer.","params":{"delegator":"Address of the delegator","indexer":"Address of the indexer where funds have been delegated"},"returns":{"_0":"True if delegator has tokens delegated to the indexer"}}},{"name":"isOperator","sig":"isOperator(address,address)","inputs":[{"name":"_operator","type":"address"},{"name":"_indexer","type":"address"}],"outputs":[{"name":"","type":"bool"}],"mut":"view","doc":{"notice":"Return true if operator is allowed for indexer.","params":{"indexer":"Address of the indexer","operator":"Address of the operator"},"returns":{"_0":"True if operator is allowed for indexer, false otherwise"}}},{"name":"lambdaDenominator","sig":"lambdaDenominator()","inputs":[],"outputs":[{"name":"","type":"uint32"}],"mut":"view","doc":{"notice":"Getter for the denominator of the rebates lambda parameter","returns":{"_0":"Lambda denominator"}}},{"name":"lambdaNumerator","sig":"lambdaNumerator()","inputs":[],"outputs":[{"name":"","type":"uint32"}],"mut":"view","doc":{"notice":"Getter for the numerator of the rebates lambda parameter","returns":{"_0":"Lambda numerator"}}},{"name":"maxAllocationEpochs","sig":"maxAllocationEpochs()","inputs":[],"outputs":[{"name":"","type":"uint32"}],"mut":"view","doc":{"notice":"Getter for maxAllocationEpochs: the maximum time in epochs that an allocation can be open before anyone is allowed to close it. This also caps the effective allocation when sending the allocation's query fees to the rebate pool.","returns":{"_0":"Maximum allocation period in epochs"}}},{"name":"minimumIndexerStake","sig":"minimumIndexerStake()","inputs":[],"outputs":[{"name":"","type":"uint256"}],"mut":"view","doc":{"notice":"Getter for minimumIndexerStake: the minimum amount of GRT that an indexer needs to stake.","returns":{"_0":"Minimum indexer stake in GRT"}}},{"name":"operatorAuth","sig":"operatorAuth(address,address)","inputs":[{"name":"_indexer","type":"address"},{"name":"_maybeOperator","type":"address"}],"outputs":[{"name":"","type":"bool"}],"mut":"view","doc":{"notice":"Getter for operatorAuth[_indexer][_maybeOperator]: returns true if the operator is authorized to operate on behalf of the indexer.","params":{"indexer":"The indexer address for which to query authorization","maybeOperator":"The address that may or may not be an operator"},"returns":{"_0":"True if the operator is authorized to operate on behalf of the indexer"}}},{"name":"protocolPercentage","sig":"protocolPercentage()","inputs":[],"outputs":[{"name":"","type":"uint32"}],"mut":"view","doc":{"notice":"Getter for protocolPercentage: the percentage of query fees that are burned as protocol fees.","returns":{"_0":"Protocol percentage in parts per million"}}},{"name":"rewardsDestination","sig":"rewardsDestination(address)","inputs":[{"name":"_indexer","type":"address"}],"outputs":[{"name":"","type":"address"}],"mut":"view","doc":{"notice":"Getter for rewardsDestination[_indexer]: returns the address where the indexer's rewards are sent.","params":{"indexer":"The indexer address for which to query the rewards destination"},"returns":{"_0":"The address where the indexer's rewards are sent, zero if none is set in which case rewards are re-staked"}}},{"name":"slashers","sig":"slashers(address)","inputs":[{"name":"_maybeSlasher","type":"address"}],"outputs":[{"name":"","type":"bool"}],"mut":"view","doc":{"notice":"Getter for slashers[_maybeSlasher]: returns true if the address is a slasher, i.e. an entity that can slash indexers","params":{"maybeSlasher":"Address for which to check the slasher role"},"returns":{"_0":"True if the address is a slasher"}}},{"name":"stakes","sig":"stakes(address)","inputs":[{"name":"_indexer","type":"address"}],"outputs":[{"name":"","type":"(uint256,uint256,uint256,uint256)"}],"mut":"view","doc":{"notice":"Getter for stakes[_indexer]: gets the stake information for an indexer as an IStakes.Indexer struct.","params":{"_indexer":"Indexer address for which to query the stake information"},"returns":{"_0":"Stake information for the specified indexer, as an IStakes.Indexer struct"}}},{"name":"subgraphAllocations","sig":"subgraphAllocations(bytes32)","inputs":[{"name":"_subgraphDeploymentId","type":"bytes32"}],"outputs":[{"name":"","type":"uint256"}],"mut":"view","doc":{"notice":"Getter for subgraphAllocations[_subgraphDeploymentId]: returns the amount of tokens allocated to a subgraph deployment.","params":{"subgraphDeploymentId":"The subgraph deployment for which to query the allocations"},"returns":{"_0":"The amount of tokens allocated to the subgraph deployment"}}},{"name":"thawingPeriod","sig":"thawingPeriod()","inputs":[],"outputs":[{"name":"","type":"uint32"}],"mut":"view","doc":{"notice":"Getter for thawingPeriod: the time in blocks an indexer needs to wait to unstake tokens.","returns":{"_0":"Thawing period in blocks"}}}],"writes":[{"name":"acceptProxy","sig":"acceptProxy(address)","inputs":[{"name":"_proxy","type":"address"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Accept to be an implementation of proxy.","params":{"_proxy":"Proxy to accept"}}},{"name":"acceptProxyAndCall","sig":"acceptProxyAndCall(address,bytes)","inputs":[{"name":"_proxy","type":"address"},{"name":"_data","type":"bytes"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Accept to be an implementation of proxy and then call a function from the new implementation as specified by `_data`, which should be an encoded function call. This is useful to initialize new storage variables in the proxied contract.","params":{"_data":"Calldata for the initialization function call (including selector)","_proxy":"Proxy to accept"}}},{"name":"allocate","sig":"allocate(bytes32,uint256,address,bytes32,bytes)","inputs":[{"name":"_subgraphDeploymentID","type":"bytes32"},{"name":"_tokens","type":"uint256"},{"name":"_allocationID","type":"address"},{"name":"_metadata","type":"bytes32"},{"name":"_proof","type":"bytes"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Allocate available tokens to a subgraph deployment.","params":{"allocationID":"The allocation identifier","metadata":"IPFS hash for additional information about the allocation","proof":"A 65-bytes Ethereum signed message of `keccak256(indexerAddress,allocationID)`","subgraphDeploymentID":"ID of the SubgraphDeployment where tokens will be allocated","tokens":"Amount of tokens to allocate"}}},{"name":"allocateFrom","sig":"allocateFrom(address,bytes32,uint256,address,bytes32,bytes)","inputs":[{"name":"_indexer","type":"address"},{"name":"_subgraphDeploymentID","type":"bytes32"},{"name":"_tokens","type":"uint256"},{"name":"_allocationID","type":"address"},{"name":"_metadata","type":"bytes32"},{"name":"_proof","type":"bytes"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Allocate available tokens to a subgraph deployment from and indexer's stake. The caller must be the indexer or the indexer's operator.","params":{"allocationID":"The allocation identifier","indexer":"Indexer address to allocate funds from.","metadata":"IPFS hash for additional information about the allocation","proof":"A 65-bytes Ethereum signed message of `keccak256(indexerAddress,allocationID)`","subgraphDeploymentID":"ID of the SubgraphDeployment where tokens will be allocated","tokens":"Amount of tokens to allocate"}}},{"name":"closeAllocation","sig":"closeAllocation(address,bytes32)","inputs":[{"name":"_allocationID","type":"address"},{"name":"_poi","type":"bytes32"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Close an allocation and free the staked tokens. To be eligible for rewards a proof of indexing must be presented. Presenting a bad proof is subject to slashable condition. To opt out of rewards set poi to 0x0","details":"To be eligible for rewards a proof of indexing must be presented. Presenting a bad proof is subject to slashable condition. To opt out of rewards set _poi to 0x0","params":{"allocationID":"The allocation identifier","poi":"Proof of indexing submitted for the allocated period"}}},{"name":"collect","sig":"collect(uint256,address)","inputs":[{"name":"_tokens","type":"uint256"},{"name":"_allocationID","type":"address"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Collect query fees from state channels and assign them to an allocation. Funds received are only accepted from a valid sender.","details":"We use an exponential rebate formula to calculate the amount of tokens to rebate to the indexer. This implementation allows collecting multiple times on the same allocation, keeping track of the total amount rebated, the total amount collected and compensating the indexer for the difference.","params":{"allocationID":"Allocation where the tokens will be assigned","tokens":"Amount of tokens to collect"}}},{"name":"delegate","sig":"delegate(address,uint256)","inputs":[{"name":"_indexer","type":"address"},{"name":"_tokens","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}],"mut":"nonpayable","doc":{"notice":"Delegate tokens to an indexer.","params":{"indexer":"Address of the indexer to which tokens are delegated","tokens":"Amount of tokens to delegate"},"returns":{"_0":"Amount of shares issued from the delegation pool"}}},{"name":"initialize","sig":"initialize(address,uint256,uint32,uint32,uint32,uint32,uint32,uint32,(uint32,uint32,uint32,uint32),address)","inputs":[{"name":"_controller","type":"address"},{"name":"_minimumIndexerStake","type":"uint256"},{"name":"_thawingPeriod","type":"uint32"},{"name":"_protocolPercentage","type":"uint32"},{"name":"_curationPercentage","type":"uint32"},{"name":"_maxAllocationEpochs","type":"uint32"},{"name":"_delegationUnbondingPeriod","type":"uint32"},{"name":"_delegationRatio","type":"uint32"},{"name":"_rebatesParameters","type":"(uint32,uint32,uint32,uint32)"},{"name":"_extensionImpl","type":"address"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Initialize this contract.","params":{"controller":"Address of the controller that manages this contract","curationPercentage":"Percentage of query fees that are given to curators (in PPM)","delegationRatio":"The ratio between an indexer's own stake and the delegation they can use","delegationUnbondingPeriod":"The period in epochs that tokens get locked after undelegating","extensionImpl":"Address of the StakingExtension implementation","maxAllocationEpochs":"The maximum number of epochs that an allocation can be active","minimumIndexerStake":"Minimum amount of tokens that an indexer must stake","protocolPercentage":"Percentage of query fees that are burned as protocol fee (in PPM)","rebatesParameters":"Alpha and lambda parameters for rebates function","thawingPeriod":"Number of blocks that tokens get locked after unstaking"}}},{"name":"initialize","sig":"initialize(uint32,uint32,uint32,uint32)","inputs":[{"name":"_delegationUnbondingPeriod","type":"uint32"},{"name":"_cooldownBlocks","type":"uint32"},{"name":"_delegationRatio","type":"uint32"},{"name":"_delegationTaxPercentage","type":"uint32"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Initialize the StakingExtension contract","details":"This function is meant to be delegatecalled from the Staking contract's initialize() function, so it uses the same access control check to ensure it is being called by the Staking implementation as part of the proxy upgrade process.","params":{"_cooldownBlocks":"Deprecated parameter (no longer used)","_delegationRatio":"Delegation capacity multiplier (e.g. 10 means 10x the indexer stake)","_delegationTaxPercentage":"Percentage of delegated tokens to burn as delegation tax, expressed in parts per million","_delegationUnbondingPeriod":"Delegation unbonding period in blocks"}}},{"name":"multicall","sig":"multicall(bytes[])","inputs":[{"name":"data","type":"bytes[]"}],"outputs":[{"name":"results","type":"bytes[]"}],"mut":"nonpayable","doc":{"notice":"Call multiple functions in the current contract and return the data from all of them if they all succeed","params":{"data":"The encoded function data for each of the calls to make to this contract"},"returns":{"results":"The results from each of the calls passed in via data"}}},{"name":"onTokenTransfer","sig":"onTokenTransfer(address,uint256,bytes)","inputs":[{"name":"_from","type":"address"},{"name":"_amount","type":"uint256"},{"name":"_data","type":"bytes"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Receive tokens with a callhook from the bridge","details":"The encoded _data can contain information about an indexer's stake or a delegator's delegation. See L1MessageCodes in IL2Staking for the supported messages.","params":{"_amount":"Amount of tokens that were transferred","_data":"ABI-encoded callhook data which must include a uint8 code and either a ReceiveIndexerStakeData or ReceiveDelegationData struct.","_from":"Token sender in L1"}},"emits":["TransferredDelegationReturnedToDelegator","StakeDelegated","StakeDeposited"]},{"name":"setController","sig":"setController(address)","inputs":[{"name":"_controller","type":"address"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Set the controller that manages this contract","details":"Only the current controller can set a new controller","params":{"newController":"Address of the new controller"}}},{"name":"setCounterpartStakingAddress","sig":"setCounterpartStakingAddress(address)","inputs":[{"name":"_counterpart","type":"address"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Set the address of the counterpart (L1 or L2) staking contract.","details":"This function can only be called by the governor.","params":{"counterpart":"Address of the counterpart staking contract in the other chain, without any aliasing."}}},{"name":"setCurationPercentage","sig":"setCurationPercentage(uint32)","inputs":[{"name":"_percentage","type":"uint32"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Set the curation percentage of query fees sent to curators.","details":"This function can only be called by the governor.","params":{"percentage":"Percentage of query fees sent to curators"}}},{"name":"setDelegationParameters","sig":"setDelegationParameters(uint32,uint32,uint32)","inputs":[{"name":"_indexingRewardCut","type":"uint32"},{"name":"_queryFeeCut","type":"uint32"},{"name":"","type":"uint32"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Set the delegation parameters for the caller.","params":{"cooldownBlocks":"Deprecated cooldown blocks parameter (no longer used)","indexingRewardCut":"Percentage of indexing rewards left for the indexer","queryFeeCut":"Percentage of query fees left for the indexer"}}},{"name":"setDelegationRatio","sig":"setDelegationRatio(uint32)","inputs":[{"name":"_delegationRatio","type":"uint32"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Set the delegation ratio. If set to 10 it means the indexer can use up to 10x the indexer staked amount from their delegated tokens","details":"This function is only callable by the governor","params":{"newDelegationRatio":"Delegation capacity multiplier"}}},{"name":"setDelegationTaxPercentage","sig":"setDelegationTaxPercentage(uint32)","inputs":[{"name":"_percentage","type":"uint32"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Set a delegation tax percentage to burn when delegated funds are deposited.","details":"This function is only callable by the governor","params":{"percentage":"Percentage of delegated tokens to burn as delegation tax, expressed in parts per million"}}},{"name":"setDelegationUnbondingPeriod","sig":"setDelegationUnbondingPeriod(uint32)","inputs":[{"name":"_delegationUnbondingPeriod","type":"uint32"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Set the time, in epochs, a Delegator needs to wait to withdraw tokens after undelegating.","details":"This function is only callable by the governor","params":{"newDelegationUnbondingPeriod":"Period in epochs to wait for token withdrawals after undelegating"}}},{"name":"setExtensionImpl","sig":"setExtensionImpl(address)","inputs":[{"name":"_extensionImpl","type":"address"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Set the address of the StakingExtension implementation.","details":"This function can only be called by the governor.","params":{"extensionImpl":"Address of the StakingExtension implementation"}}},{"name":"setMaxAllocationEpochs","sig":"setMaxAllocationEpochs(uint32)","inputs":[{"name":"_maxAllocationEpochs","type":"uint32"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Set the max time allowed for indexers to allocate on a subgraph before others are allowed to close the allocation.","details":"This function can only be called by the governor.","params":{"maxAllocationEpochs":"Allocation duration limit in epochs"}}},{"name":"setMinimumIndexerStake","sig":"setMinimumIndexerStake(uint256)","inputs":[{"name":"_minimumIndexerStake","type":"uint256"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Set the minimum stake needed to be an Indexer","details":"This function can only be called by the governor.","params":{"minimumIndexerStake":"Minimum amount of tokens that an indexer must stake"}}},{"name":"setOperator","sig":"setOperator(address,bool)","inputs":[{"name":"_operator","type":"address"},{"name":"_allowed","type":"bool"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Authorize or unauthorize an address to be an operator for the caller.","params":{"allowed":"Whether the operator is authorized or not","operator":"Address to authorize or unauthorize"}}},{"name":"setProtocolPercentage","sig":"setProtocolPercentage(uint32)","inputs":[{"name":"_percentage","type":"uint32"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Set a protocol percentage to burn when collecting query fees.","details":"This function can only be called by the governor.","params":{"percentage":"Percentage of query fees to burn as protocol fee"}}},{"name":"setRebateParameters","sig":"setRebateParameters(uint32,uint32,uint32,uint32)","inputs":[{"name":"_alphaNumerator","type":"uint32"},{"name":"_alphaDenominator","type":"uint32"},{"name":"_lambdaNumerator","type":"uint32"},{"name":"_lambdaDenominator","type":"uint32"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Set the rebate parameters","details":"This function can only be called by the governor.","params":{"alphaDenominator":"Denominator of `alpha`","alphaNumerator":"Numerator of `alpha`","lambdaDenominator":"Denominator of `lambda`","lambdaNumerator":"Numerator of `lambda`"}}},{"name":"setRewardsDestination","sig":"setRewardsDestination(address)","inputs":[{"name":"_destination","type":"address"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Set the destination where to send rewards for an indexer.","params":{"destination":"Rewards destination address. If set to zero, rewards will be restaked"}}},{"name":"setSlasher","sig":"setSlasher(address,bool)","inputs":[{"name":"_slasher","type":"address"},{"name":"_allowed","type":"bool"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Set or unset an address as allowed slasher.","details":"This function can only be called by the governor.","params":{"allowed":"True if slasher is allowed","slasher":"Address of the party allowed to slash indexers"}}},{"name":"setThawingPeriod","sig":"setThawingPeriod(uint32)","inputs":[{"name":"_thawingPeriod","type":"uint32"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Set the number of blocks that tokens get locked after unstaking","details":"This function can only be called by the governor.","params":{"thawingPeriod":"Number of blocks that tokens get locked after unstaking"}}},{"name":"slash","sig":"slash(address,uint256,uint256,address)","inputs":[{"name":"_indexer","type":"address"},{"name":"_tokens","type":"uint256"},{"name":"_reward","type":"uint256"},{"name":"_beneficiary","type":"address"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Slash the indexer stake. Delegated tokens are not subject to slashing.","details":"Can only be called by the slasher role.","params":{"beneficiary":"Address of a beneficiary to receive a reward for the slashing","indexer":"Address of indexer to slash","reward":"Amount of reward tokens to send to a beneficiary","tokens":"Amount of tokens to slash from the indexer stake"}}},{"name":"stake","sig":"stake(uint256)","inputs":[{"name":"_tokens","type":"uint256"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Deposit tokens on the indexer's stake. The amount staked must be over the minimumIndexerStake.","params":{"tokens":"Amount of tokens to stake"}}},{"name":"stakeTo","sig":"stakeTo(address,uint256)","inputs":[{"name":"_indexer","type":"address"},{"name":"_tokens","type":"uint256"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Deposit tokens on the Indexer stake, on behalf of the Indexer. The amount staked must be over the minimumIndexerStake.","params":{"indexer":"Address of the indexer","tokens":"Amount of tokens to stake"}}},{"name":"syncAllContracts","sig":"syncAllContracts()","inputs":[],"outputs":[],"mut":"nonpayable","doc":{"notice":"Sync protocol contract addresses from the Controller registry","details":"This function will cache all the contracts using the latest addresses. Anyone can call the function whenever a Proxy contract change in the controller to ensure the protocol is using the latest version."}},{"name":"undelegate","sig":"undelegate(address,uint256)","inputs":[{"name":"_indexer","type":"address"},{"name":"_shares","type":"uint256"}],"outputs":[{"name":"","type":"uint256"}],"mut":"nonpayable","doc":{"notice":"Undelegate tokens from an indexer. Tokens will be locked for the unbonding period.","params":{"indexer":"Address of the indexer to which tokens had been delegated","shares":"Amount of shares to return and undelegate tokens"},"returns":{"_0":"Amount of tokens returned for the shares of the delegation pool"}}},{"name":"unstake","sig":"unstake(uint256)","inputs":[{"name":"_tokens","type":"uint256"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Unstake tokens from the indexer stake, lock them until the thawing period expires.","details":"NOTE: The function accepts an amount greater than the currently staked tokens. If that happens, it will try to unstake the max amount of tokens it can. The reason for this behaviour is to avoid time conditions while the transaction is in flight.","params":{"tokens":"Amount of tokens to unstake"}}},{"name":"withdraw","sig":"withdraw()","inputs":[],"outputs":[],"mut":"nonpayable","doc":{"notice":"Withdraw indexer tokens once the thawing period has passed."}},{"name":"withdrawDelegated","sig":"withdrawDelegated(address,address)","inputs":[{"name":"_indexer","type":"address"},{"name":"_newIndexer","type":"address"}],"outputs":[{"name":"","type":"uint256"}],"mut":"nonpayable","doc":{"notice":"Withdraw undelegated tokens once the unbonding period has passed, and optionally re-delegate to a new indexer.","params":{"indexer":"Withdraw available tokens delegated to indexer","newIndexer":"Re-delegate to indexer address if non-zero, withdraw if zero address"},"returns":{"_0":"Amount of tokens withdrawn"}}}],"events":[{"name":"AllocationClosed","sig":"AllocationClosed(address,bytes32,uint256,uint256,address,address,bytes32,bool)","inputs":[{"name":"indexer","type":"address","indexed":true},{"name":"subgraphDeploymentID","type":"bytes32","indexed":true},{"name":"epoch","type":"uint256","indexed":false},{"name":"tokens","type":"uint256","indexed":false},{"name":"allocationID","type":"address","indexed":true},{"name":"sender","type":"address","indexed":false},{"name":"poi","type":"bytes32","indexed":false},{"name":"isPublic","type":"bool","indexed":false}],"doc":{"notice":"Emitted when `indexer` close an allocation in `epoch` for `allocationID`. An amount of `tokens` get unallocated from `subgraphDeploymentID`. This event also emits the POI (proof of indexing) submitted by the indexer. `isPublic` is true if the sender was someone other than the indexer.","params":{"allocationID":"Allocation identifier","epoch":"Epoch when allocation was closed","indexer":"Address of the indexer","isPublic":"True if closed by someone other than the indexer","poi":"Proof of indexing submitted","sender":"Address that closed the allocation","subgraphDeploymentID":"Subgraph deployment ID","tokens":"Amount of tokens unallocated"}}},{"name":"AllocationCreated","sig":"AllocationCreated(address,bytes32,uint256,uint256,address,bytes32)","inputs":[{"name":"indexer","type":"address","indexed":true},{"name":"subgraphDeploymentID","type":"bytes32","indexed":true},{"name":"epoch","type":"uint256","indexed":false},{"name":"tokens","type":"uint256","indexed":false},{"name":"allocationID","type":"address","indexed":true},{"name":"metadata","type":"bytes32","indexed":false}],"doc":{"notice":"Emitted when `indexer` allocated `tokens` amount to `subgraphDeploymentID` during `epoch`. `allocationID` indexer derived address used to identify the allocation. `metadata` additional information related to the allocation.","params":{"allocationID":"Allocation identifier","epoch":"Epoch when allocation was created","indexer":"Address of the indexer","metadata":"IPFS hash for additional allocation information","subgraphDeploymentID":"Subgraph deployment ID","tokens":"Amount of tokens allocated"}}},{"name":"ContractSynced","sig":"ContractSynced(bytes32,address)","inputs":[{"name":"nameHash","type":"bytes32","indexed":true},{"name":"contractAddress","type":"address","indexed":false}],"doc":{"notice":"Emitted when contract with `nameHash` is synced to `contractAddress`."}},{"name":"DelegationParametersUpdated","sig":"DelegationParametersUpdated(address,uint32,uint32,uint32)","inputs":[{"name":"indexer","type":"address","indexed":true},{"name":"indexingRewardCut","type":"uint32","indexed":false},{"name":"queryFeeCut","type":"uint32","indexed":false},{"name":"__DEPRECATED_cooldownBlocks","type":"uint32","indexed":false}],"doc":{"notice":"Emitted when `indexer` update the delegation parameters for its delegation pool.","params":{"__DEPRECATED_cooldownBlocks":"Deprecated parameter (no longer used)","indexer":"Address of the indexer","indexingRewardCut":"Percentage of indexing rewards left for the indexer","queryFeeCut":"Percentage of query fees left for the indexer"}}},{"name":"ExtensionImplementationSet","sig":"ExtensionImplementationSet(address)","inputs":[{"name":"extensionImpl","type":"address","indexed":true}],"doc":{"notice":"Emitted when `extensionImpl` was set as the address of the StakingExtension contract to which extended functionality is delegated.","params":{"extensionImpl":"Address of the StakingExtension implementation"}}},{"name":"ParameterUpdated","sig":"ParameterUpdated(string)","inputs":[{"name":"param","type":"string","indexed":false}],"doc":{"notice":"Emitted when a contract parameter has been updated"}},{"name":"RebateCollected","sig":"RebateCollected(address,address,bytes32,address,uint256,uint256,uint256,uint256,uint256,uint256,uint256)","inputs":[{"name":"assetHolder","type":"address","indexed":false},{"name":"indexer","type":"address","indexed":true},{"name":"subgraphDeploymentID","type":"bytes32","indexed":true},{"name":"allocationID","type":"address","indexed":true},{"name":"epoch","type":"uint256","indexed":false},{"name":"tokens","type":"uint256","indexed":false},{"name":"protocolTax","type":"uint256","indexed":false},{"name":"curationFees","type":"uint256","indexed":false},{"name":"queryFees","type":"uint256","indexed":false},{"name":"queryRebates","type":"uint256","indexed":false},{"name":"delegationRewards","type":"uint256","indexed":false}],"doc":{"notice":"Emitted when `indexer` collects a rebate on `subgraphDeploymentID` for `allocationID`. `epoch` is the protocol epoch the rebate was collected on The rebate is for `tokens` amount which are being provided by `assetHolder`; `queryFees` is the amount up for rebate after `curationFees` are distributed and `protocolTax` is burnt. `queryRebates` is the amount distributed to the `indexer` with `delegationFees` collected and sent to the delegation pool.","params":{"allocationID":"Allocation identifier","assetHolder":"Address providing the rebate tokens","curationFees":"Amount distributed to curators","delegationRewards":"Amount distributed to delegators","epoch":"Epoch when rebate was collected","indexer":"Address of the indexer collecting the rebate","protocolTax":"Amount burned as protocol tax","queryFees":"Amount available for rebate after fees","queryRebates":"Amount distributed to the indexer","subgraphDeploymentID":"Subgraph deployment ID","tokens":"Total amount of tokens in the rebate"}}},{"name":"SetController","sig":"SetController(address)","inputs":[{"name":"controller","type":"address","indexed":false}],"doc":{"notice":"Emitted when the controller address has been set"}},{"name":"SetOperator","sig":"SetOperator(address,address,bool)","inputs":[{"name":"indexer","type":"address","indexed":true},{"name":"operator","type":"address","indexed":true},{"name":"allowed","type":"bool","indexed":false}],"doc":{"notice":"Emitted when `indexer` set `operator` access.","params":{"allowed":"Whether the operator is authorized","indexer":"Address of the indexer","operator":"Address of the operator"}}},{"name":"SetRewardsDestination","sig":"SetRewardsDestination(address,address)","inputs":[{"name":"indexer","type":"address","indexed":true},{"name":"destination","type":"address","indexed":true}],"doc":{"notice":"Emitted when `indexer` set an address to receive rewards.","params":{"destination":"Address to receive rewards","indexer":"Address of the indexer"}}},{"name":"SlasherUpdate","sig":"SlasherUpdate(address,address,bool)","inputs":[{"name":"caller","type":"address","indexed":true},{"name":"slasher","type":"address","indexed":true},{"name":"allowed","type":"bool","indexed":false}],"doc":{"notice":"Emitted when `caller` set `slasher` address as `allowed` to slash stakes.","params":{"allowed":"Whether the slasher is allowed to slash","caller":"Address that updated the slasher status","slasher":"Address of the slasher"}}},{"name":"StakeDelegated","sig":"StakeDelegated(address,address,uint256,uint256)","inputs":[{"name":"indexer","type":"address","indexed":true},{"name":"delegator","type":"address","indexed":true},{"name":"tokens","type":"uint256","indexed":false},{"name":"shares","type":"uint256","indexed":false}],"doc":{"notice":"Emitted when `delegator` delegated `tokens` to the `indexer`, the delegator gets `shares` for the delegation pool proportionally to the tokens staked. This is copied from IStakingExtension, but we can't inherit from it because we don't implement the full interface here.","params":{"delegator":"Address of the delegator","indexer":"Address of the indexer receiving the delegation","shares":"Amount of shares issued to the delegator","tokens":"Amount of tokens delegated"}}},{"name":"StakeDelegatedLocked","sig":"StakeDelegatedLocked(address,address,uint256,uint256,uint256)","inputs":[{"name":"indexer","type":"address","indexed":true},{"name":"delegator","type":"address","indexed":true},{"name":"tokens","type":"uint256","indexed":false},{"name":"shares","type":"uint256","indexed":false},{"name":"until","type":"uint256","indexed":false}],"doc":{"notice":"Emitted when `delegator` undelegated `tokens` from `indexer`. Tokens get locked for withdrawal after a period of time.","params":{"delegator":"Address of the delegator","indexer":"Address of the indexer from which tokens are undelegated","shares":"Amount of shares returned","tokens":"Amount of tokens undelegated","until":"Epoch until which tokens are locked"}}},{"name":"StakeDelegatedWithdrawn","sig":"StakeDelegatedWithdrawn(address,address,uint256)","inputs":[{"name":"indexer","type":"address","indexed":true},{"name":"delegator","type":"address","indexed":true},{"name":"tokens","type":"uint256","indexed":false}],"doc":{"notice":"Emitted when `delegator` withdrew delegated `tokens` from `indexer`.","params":{"delegator":"Address of the delegator","indexer":"Address of the indexer from which tokens are withdrawn","tokens":"Amount of tokens withdrawn"}}},{"name":"StakeDeposited","sig":"StakeDeposited(address,uint256)","inputs":[{"name":"indexer","type":"address","indexed":true},{"name":"tokens","type":"uint256","indexed":false}],"doc":{"notice":"Emitted when `indexer` stakes `tokens` amount.","params":{"indexer":"Address of the indexer","tokens":"Amount of tokens staked"}}},{"name":"StakeLocked","sig":"StakeLocked(address,uint256,uint256)","inputs":[{"name":"indexer","type":"address","indexed":true},{"name":"tokens","type":"uint256","indexed":false},{"name":"until","type":"uint256","indexed":false}],"doc":{"notice":"Emitted when `indexer` unstaked and locked `tokens` amount until `until` block.","params":{"indexer":"Address of the indexer","tokens":"Amount of tokens locked","until":"Block number until which tokens are locked"}}},{"name":"StakeSlashed","sig":"StakeSlashed(address,uint256,uint256,address)","inputs":[{"name":"indexer","type":"address","indexed":true},{"name":"tokens","type":"uint256","indexed":false},{"name":"reward","type":"uint256","indexed":false},{"name":"beneficiary","type":"address","indexed":false}],"doc":{"notice":"Emitted when `indexer` was slashed for a total of `tokens` amount. Tracks `reward` amount of tokens given to `beneficiary`.","params":{"beneficiary":"Address receiving the reward","indexer":"Address of the indexer that was slashed","reward":"Amount of tokens given as reward","tokens":"Total amount of tokens slashed"}}},{"name":"StakeWithdrawn","sig":"StakeWithdrawn(address,uint256)","inputs":[{"name":"indexer","type":"address","indexed":true},{"name":"tokens","type":"uint256","indexed":false}],"doc":{"notice":"Emitted when `indexer` withdrew `tokens` staked.","params":{"indexer":"Address of the indexer","tokens":"Amount of tokens withdrawn"}}},{"name":"TransferredDelegationReturnedToDelegator","sig":"TransferredDelegationReturnedToDelegator(address,address,uint256)","inputs":[{"name":"indexer","type":"address","indexed":true},{"name":"delegator","type":"address","indexed":true},{"name":"amount","type":"uint256","indexed":false}],"doc":{"notice":"Emitted when transferred delegation is returned to a delegator","params":{"amount":"Amount of delegation returned","delegator":"Address of the delegator","indexer":"Address of the indexer"}}}],"counts":{"reads":33,"writes":35,"events":19}},{"id":"AllocationExchange","name":"AllocationExchange","layer":"legacy","chain":"L2","core":false,"legacy":true,"address":"0x9BD4FBDa981D628AbA16F261f810dD59E5bAf9eA","desc":"A legacy helper that held query-fee funds and let indexers redeem them against vouchers signed by an authority, settling into the old Staking contract. Part of the pre-Horizon query-fee path.","contractDoc":{"title":"Allocation Exchange","notice":"This contract holds tokens that anyone with a voucher signed by the authority can redeem. The contract validates if the voucher presented is valid and then sends tokens to the Staking contract by calling the collect() function passing the voucher allocationID. The contract enforces that only one voucher for an allocationID can be redeemed. Only governance can change the authority."},"implements":["(voucher redeemer)"],"deps":[{"to":"L2Staking","label":"settled query fees into"}],"roles":[],"reads":[{"name":"allocationsRedeemed","sig":"allocationsRedeemed(address)","inputs":[{"name":"","type":"address"}],"outputs":[{"name":"","type":"bool"}],"mut":"view","doc":{"notice":"Mapping of allocations that have been redeemed"}},{"name":"authority","sig":"authority(address)","inputs":[{"name":"","type":"address"}],"outputs":[{"name":"","type":"bool"}],"mut":"view","doc":{"notice":"Mapping of authorized accounts that can redeem allocations"}},{"name":"governor","sig":"governor()","inputs":[],"outputs":[{"name":"","type":"address"}],"mut":"view","doc":{"notice":"Address of the governor"}},{"name":"pendingGovernor","sig":"pendingGovernor()","inputs":[],"outputs":[{"name":"","type":"address"}],"mut":"view","doc":{"notice":"Address of the new governor that is pending acceptance"}}],"writes":[{"name":"acceptOwnership","sig":"acceptOwnership()","inputs":[],"outputs":[],"mut":"nonpayable","doc":{"notice":"Admin function for pending governor to accept role and update governor. This function must called by the pending governor."}},{"name":"approveAll","sig":"approveAll()","inputs":[],"outputs":[],"mut":"nonpayable","doc":{"notice":"Approve the staking contract to pull any amount of tokens from this contract.","details":"Increased gas efficiency instead of approving on each voucher redeem"}},{"name":"redeem","sig":"redeem((address,uint256,bytes))","inputs":[{"name":"_voucher","type":"(address,uint256,bytes)"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Redeem a voucher signed by the authority. No voucher double spending is allowed.","details":"The voucher must be signed using an Ethereum signed message","params":{"_voucher":"Voucher data"}},"emits":["AllocationRedeemed"],"calls":["L2Staking"]},{"name":"redeemMany","sig":"redeemMany((address,uint256,bytes)[])","inputs":[{"name":"_vouchers","type":"(address,uint256,bytes)[]"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Redeem multiple vouchers.","details":"Each voucher must be signed using an Ethereum signed message","params":{"_vouchers":"An array of vouchers"}},"emits":["AllocationRedeemed"],"calls":["L2Staking"]},{"name":"setAuthority","sig":"setAuthority(address,bool)","inputs":[{"name":"_authority","type":"address"},{"name":"_authorized","type":"bool"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Set the authority allowed to sign vouchers.","details":"Only the governor can set the authority","params":{"_authority":"Address of the signing authority","_authorized":"True if the authority is authorized to sign vouchers, false to unset"}},"access":{"roles":[],"mods":["onlyGovernor"]},"emits":["AuthoritySet"]},{"name":"transferOwnership","sig":"transferOwnership(address)","inputs":[{"name":"_newGovernor","type":"address"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Admin function to begin change of governor. The `_newGovernor` must call `acceptOwnership` to finalize the transfer.","params":{"_newGovernor":"Address of new `governor`"}}},{"name":"withdraw","sig":"withdraw(address,uint256)","inputs":[{"name":"_to","type":"address"},{"name":"_amount","type":"uint256"}],"outputs":[],"mut":"nonpayable","doc":{"notice":"Withdraw tokens held in the contract.","details":"Only the governor can withdraw","params":{"_amount":"Amount of tokens to withdraw","_to":"Destination to send the tokens"}},"access":{"roles":[],"mods":["onlyGovernor"]},"emits":["TokensWithdrawn"]}],"events":[{"name":"AllocationRedeemed","sig":"AllocationRedeemed(address,uint256)","inputs":[{"name":"allocationID","type":"address","indexed":true},{"name":"amount","type":"uint256","indexed":false}],"doc":{"notice":"Emitted when an allocation voucher is redeemed","params":{"allocationID":"Address of the allocation","amount":"Amount of tokens redeemed"}}},{"name":"AuthoritySet","sig":"AuthoritySet(address,bool)","inputs":[{"name":"account","type":"address","indexed":true},{"name":"authorized","type":"bool","indexed":false}],"doc":{"notice":"Emitted when an authority is set or unset","params":{"account":"Address of the authority","authorized":"Whether the authority is authorized"}}},{"name":"NewOwnership","sig":"NewOwnership(address,address)","inputs":[{"name":"from","type":"address","indexed":true},{"name":"to","type":"address","indexed":true}],"doc":{"notice":"Emitted when a new owner/governor has accepted their role"}},{"name":"NewPendingOwnership","sig":"NewPendingOwnership(address,address)","inputs":[{"name":"from","type":"address","indexed":true},{"name":"to","type":"address","indexed":true}],"doc":{"notice":"Emitted when a new owner/governor has been set, but is pending acceptance"}},{"name":"TokensWithdrawn","sig":"TokensWithdrawn(address,uint256)","inputs":[{"name":"to","type":"address","indexed":true},{"name":"amount","type":"uint256","indexed":false}],"doc":{"notice":"Emitted when tokens are withdrawn from the contract","params":{"amount":"Amount of tokens withdrawn","to":"Address that received the tokens"}}}],"counts":{"reads":4,"writes":7,"events":5}}],"edges":[{"from":"HorizonStaking","to":"L2GraphToken","label":"locks / moves staked GRT","kind":"flow"},{"from":"HorizonStaking","to":"Controller","label":"reads protocol registry","kind":"registry"},{"from":"GraphPayments","to":"HorizonStaking","label":"pays providers & delegators","kind":"flow"},{"from":"GraphPayments","to":"L2GraphToken","label":"burns protocol cut","kind":"flow"},{"from":"PaymentsEscrow","to":"GraphPayments","label":"forwards collected funds","kind":"flow"},{"from":"PaymentsEscrow","to":"L2GraphToken","label":"custodies GRT","kind":"flow"},{"from":"GraphTallyCollector","to":"PaymentsEscrow","label":"draws owed query fees","kind":"flow"},{"from":"GraphTallyCollector","to":"GraphPayments","label":"triggers settlement","kind":"flow"},{"from":"RecurringCollector","to":"PaymentsEscrow","label":"draws scheduled payments","kind":"flow"},{"from":"RecurringCollector","to":"GraphPayments","label":"triggers settlement","kind":"flow"},{"from":"SubgraphService","to":"HorizonStaking","label":"reads provisions, slashes","kind":"flow"},{"from":"SubgraphService","to":"GraphTallyCollector","label":"collects query fees","kind":"flow"},{"from":"SubgraphService","to":"RecurringCollector","label":"collects indexing fees","kind":"flow"},{"from":"SubgraphService","to":"Curation","label":"pays curation cut","kind":"flow"},{"from":"SubgraphService","to":"RewardsManager","label":"claims indexing rewards","kind":"flow"},{"from":"SubgraphService","to":"GraphPayments","label":"defines payment types","kind":"registry"},{"from":"DisputeManager","to":"SubgraphService","label":"slashes via the service","kind":"flow"},{"from":"DisputeManager","to":"HorizonStaking","label":"reads provisioned stake","kind":"flow"},{"from":"RewardsManager","to":"L2GraphToken","label":"mints rewards","kind":"flow"},{"from":"RewardsManager","to":"Curation","label":"reads signal per subgraph","kind":"flow"},{"from":"RewardsManager","to":"SubgraphService","label":"reads allocations","kind":"registry"},{"from":"RewardsManager","to":"RewardsEligibilityOracle","label":"checks indexer eligibility","kind":"flow"},{"from":"RewardsManager","to":"IssuanceAllocator","label":"pulls issuance budget","kind":"flow"},{"from":"IssuanceAllocator","to":"L2GraphToken","label":"mints issuance","kind":"flow"},{"from":"IssuanceAllocator","to":"RewardsManager","label":"allocates issuance to","kind":"flow"},{"from":"IssuanceAllocator","to":"DirectAllocation","label":"allocates issuance to","kind":"flow"},{"from":"IssuanceAllocator","to":"RecurringAgreementManager","label":"allocates issuance to","kind":"flow"},{"from":"DirectAllocation","to":"L2GraphToken","label":"receives / sends GRT","kind":"flow"},{"from":"RecurringAgreementManager","to":"IssuanceAllocator","label":"receives issuance from","kind":"flow"},{"from":"RecurringAgreementManager","to":"RecurringCollector","label":"owns agreements on","kind":"flow"},{"from":"RecurringAgreementManager","to":"PaymentsEscrow","label":"funds escrow","kind":"flow"},{"from":"RecurringAgreementManager","to":"L2GraphToken","label":"holds GRT","kind":"flow"},{"from":"RecurringAgreementHelper","to":"RecurringAgreementManager","label":"convenience calls into","kind":"flow"},{"from":"RewardsEligibilityHelper","to":"RewardsEligibilityOracle","label":"convenience calls into","kind":"flow"},{"from":"Curation","to":"GraphCurationToken","label":"mints signal shares","kind":"flow"},{"from":"Curation","to":"L2GraphToken","label":"holds curation reserves","kind":"flow"},{"from":"L2GNS","to":"SubgraphNFT","label":"mints ownership NFTs","kind":"flow"},{"from":"L2GNS","to":"Curation","label":"curates deployments","kind":"flow"},{"from":"L2GNS","to":"L2GraphToken","label":"handles signal GRT","kind":"flow"},{"from":"SubgraphNFT","to":"SubgraphNFTDescriptor","label":"renders token metadata","kind":"flow"},{"from":"SubgraphAvailabilityManager","to":"RewardsManager","label":"sets reward denylist","kind":"flow"},{"from":"L2GraphTokenGateway","to":"L2GraphToken","label":"mints / burns bridged GRT","kind":"flow"},{"from":"L1GraphTokenGateway","to":"BridgeEscrow","label":"escrows bridged GRT","kind":"flow"},{"from":"L1GraphTokenGateway","to":"GraphToken","label":"moves L1 GRT","kind":"flow"},{"from":"L2Staking","to":"L2GraphToken","label":"held staked GRT","kind":"flow"},{"from":"L2Staking","to":"RewardsManager","label":"claimed rewards","kind":"flow"},{"from":"AllocationExchange","to":"L2Staking","label":"settled query fees into","kind":"flow"}]};