0006-gip-withdraw-helper
Abstract
Consumers in the Graph Network set up state channels for sending query fees to Indexers using Vector. Vector is an ultra-simple, flexible state channel protocol implementation. This proposal introduces a contract required to encode custom logic in the process of withdrawing query fees from Vector state channels. The GRTWithdrawHelper contract receives query fees from a Vector state channel, then it forwards them to the Staking contract where they are distributed according to the protocol economics.
Motivation
Vector state channels are contracts that hold funds used as collateral for consumer-to-indexer payments. When an Indexer closes an allocation, both parties sign a withdrawal commitment to transfer the query fees accumulated for the allocation back to the network. Vector, by default, supports plain transfers from the channel to any destination defined in the withdrawal commitment. In the case of the Graph Network, all funds should be collected by calling the collect() function in the Staking contract. For the purpose of calling custom logic when transferring from channels, Vector supports using a WithdrawHelper contract. In this proposal, we describe the implementation of such a contract for connecting a Vector withdrawal transfer to The Graph smart contracts.
Detailed Specification
We created a contract called GRTWithdrawHelper that extends the base WithdrawHelper provided by the Vector framework. This contract has a function execute(WithdrawData _wd, uint256 _actualAmount) external
that is called in the same transaction when the indexer withdraw funds from the channel. The execute function evaluates the validity of the WithdrawData
struct, and then approve and transfer the received funds to the Staking contract by calling collect()
.
Transaction Flow
Features
The GRTWithdrawHelper is deployed with the token address that will be used for transfers, in our case it is the GRT token address. It can't be changed at later stage but this can easily be solved deploying a new contract if needed.
The contract expects to have available tokens in balance when
execute(WithdrawData calldata wd, uint256 actualAmount)
is called by the Channel. For that to happen the Channel needs to transfer funds to the GRTWithdrawHelper before execute is called.On execute, the GRTWithdrawHelper will approve the funds to send to the Staking contract and then execute
collect()
passing the proper allocationID and amount. The Staking contract will then pull the tokens.If the call to
collect()
fails, the funds are returned to a return address. This is important for Vector accounting of funds.
Requirements
Set the GRTWithdrawHelper contract as AssetHolder in the Staking contract. This way we allow the network contracts to accept funds from this contract.
The cooperative withdrawal commitments must have the following data (indicated with arrows):
The parties must agree and sign the WithdrawalCommitment with that information to achieve proper execution of the withdrawals.
Exceptions
The following conditions will result in reverts of the execution:
assetId
inWithdrawData
not matching the token address configured in the GRTWithdrawHelper.GRTWithdrawHelper not having enough balance to transfer the Staking contract as stated in
actualAmount
.Setting an invalid staking contract address.
Note: To avoid unexpected conditions in the Vector off-chain logic, it is encouraged that the parties verify the WithdrawData does not revert by doing a call/estimateGas.
Handled Exceptions
These reverts are handled and will make the contract to return the funds to the return address.
Doing a withdrawal for a non-existing
allocationID
as defined inCollectData
when callingcollect()
.
Assumptions
This contract does not know if a
WithdrawalCommitment
is correct, it just accepts a transfer andWithdrawData
that defines a proper destination.A properly formatted
WithdrawData
can be crafted to send outside funds to the Staking contract. In that case, the person will get those funds distributed with Curators + Delegators + taxed a protocol percentage. There is no rational economic incentive to do so.
Backwards Compatibility
The contract in this proposal is new and peripheral to the rest of the network contracts. No breaking change is introduced. The Graph Council will need to set the GRTWithdrawHelper as an AssetHolder in the Staking contract.
Validation
Audits
An audit of the changes described in this document was performed by ChainSafe (see assets/gip-0006/TheGraph-GRTWithdrawHelper-Audit.pdf
).
Testnet
The implementation was deployed and tested on Rinkeby testnet. https://rinkeby.etherscan.io/address/0xe5fa88135c992a385aaa1c65a0c1b8ff3fde1fd4
Copyright Waiver
Copyright and related rights waived via CC0.
Last updated