Managing Deposits
This guide covers topics around creating and managing staking deposit positions in the UniStaker contract. It is intended for developers and integrators. It is not intended for everyday users, who would be expected to interact with the project via a client.
Overview
In the UniStaker system, staking positions are managed on a per-deposit basis. A given deposit is owned by the account that creates it, and can be managed and modified independent of other deposits, including ones that might be owned by the same account.
Each deposit has a unique DepositIdentifier
, i.e. an integer that uniquely identifies a single deposit position.
The data of a deposit is defined by the following struct:
struct Deposit {
uint256 balance;
address owner;
address delegatee;
address beneficiary;
}
In addition to the deposit's balance and owner, which are self explanatory, each deposit includes the following parameters which warrant some explanation:
delegatee
- The governance delegate who receives the voting weight for this deposit.beneficiary
- The address that accrues staking rewards earned by this deposit.
Creating a Deposit
In the UniStaker.sol contract, a user stakes UNI tokens by calling one of the stake
family of methods:
function stake(uint256 _amount, address _delegatee)
external
returns (DepositIdentifier _depositId);
function stake(uint256 _amount, address _delegatee, address _beneficiary)
external
returns (DepositIdentifier _depositId);
function permitAndStake(
uint256 _amount,
address _delegatee,
address _beneficiary,
uint256 _deadline,
uint8 _v,
bytes32 _r,
bytes32 _s
) external returns (DepositIdentifier _depositId);
function stakeOnBehalf(
uint256 _amount,
address _delegatee,
address _beneficiary,
address _depositor,
bytes memory _signature
) external returns (DepositIdentifier _depositId);
The DepositId returned by this method will be used to reference this deposit during future interactions with the UniStaker contract.
Each method also emits the following event:
event StakeDeposited(
address owner, DepositIdentifier indexed depositId, uint256 amount, uint256 depositBalance
);
The various stake methods include the following assumptions about the caller and about token approvals:
- The
stake/2
andstake/3
methods will make the caller the owner of the new deposit. The owner account must pre-approve the UniStaker contract to spend at least the amount of UNI being deposited. - The
permitAndStake
method also makes the caller the owner of the new deposit. Rather than require a pre-approval, this method takes the signature parameters associated with the UNI permit (opens in a new tab) method and forwards them ahead to create the approval. This is a convenience method that allows staking with one transaction instead of two. - The
stakeOnBehalf
method will make the_depositor
the owner of the new deposit. It can be submitted by any account, such as a relayer, as long as a valid signature from the_depositor
authorizes the deposit. The_depositor
must pre-approve the UniStaker contract to spend at least the amount of UNI being deposited.
Modifying a Deposit
To modify a deposit, you must have the unique DepositIdentifier
that was returned by whichever stake method was used to create it originally. The identifier is also emitted in the StakeDeposited
event, as documented above. Once you have the DepositIdentifier
, the account that owns it may perform the following actions.
Adding UNI
Adding UNI to a staking position is done through the stakeMore
family of methods:
function stakeMore(DepositIdentifier _depositId, uint256 _amount) external;
function permitAndStakeMore(
DepositIdentifier _depositId,
uint256 _amount,
uint256 _deadline,
uint8 _v,
bytes32 _r,
bytes32 _s
) external;
function stakeMoreOnBehalf(
DepositIdentifier _depositId,
uint256 _amount,
address _depositor,
bytes memory _signature
) external;
The stakeMore
family of methods follow a pattern similar to the stake
methods as it relates to ownership and token approvals:
- The
stakeMore
method must be called by theowner
of the deposit, and the owner must have pre-approved the UniStaker contract for the_amount
. - The
permitAndStakeMore
method must be called by theowner
of the deposit, and the owner must provide a permit signature which will be forwarded to UNI to approve the_amount
- The
stakeMoreOnBehalf
method may be called by anyone, but the_depositor
must be theowner
of the deposit, and must provide a valid signature.
Changing the Governance Delegatee
Updating the governance delegatee, that is, the account that can vote in Uniswap Governance on behalf of the token weight that is staked as part of this deposit, can be done with the alterDelegatee
and the alterDelegateeOnBehalf
methods. As the name suggests, the latter may be called by a relayer, as long as valid signature is provided by the deposit owner
.
Changing the Reward Beneficiary
Updating the reward beneficiary, that is, the account that earns rewards on behalf of the UNI that is staked in this deposit, can be done with the alterBeneficiary
and alterBeneficiaryOnBehalf
methods. As the name suggests, the latter may be called by a relayer, as long as valid signature is provided by the deposit owner
.
Rewards stop accruing the old beneficiary, and begin accruing to the new beneficiary, as soon as the transaction that changes it completes. Note that rewards which have already accrued are not impacted by calling this method. The old beneficiary is still eligible to claim those rewards at any point in the future.
Withdrawing a Deposit
Withdrawing UNI from the UniStaker contract can be done with the withdraw
and withdrawOnBehalf
methods. As the name suggests, the latter may be called by a relayer, as long as valid signature is provided by the deposit owner
. The UNI that is withdrawn is transferred to the deposit owner
account.
Batching Stake Operations
The UniStaker contract supports multicall (opens in a new tab), allowing users to batch multiple calls to the contract's methods in a single atomic transaction. This can be useful if, for example, a depositor wanted to add to their staking position and update the beneficiary address at the same time.