Tally x Lido DAO Research Grant

Tally x Lido DAO Research Grant

Authors: Frisson (Tally), Dennison Bertram (Tally), Raf Solari (Tally)
Contributors: Raphael Spannocchi (StableLab), Nneoma (StableLab)

Background

Lido DAO is currently looking for ways to increase voter participation and decision quality by introducing delegation. Further down the road are exciting governance experiments in line with Lido’s Dual Governance research, opening the possibility for stETH holders to potentially veto DAO governance motions.

Tally believes we can help improve participation and overall engagement with our best-in-class governance platform. We are particularly excited to enable on-chain delegation. The current implementation of the LDO token and Lido DAO governance structure does not allow for a straightforward integration with Tally, however.

Tally has deep expertise integrating on-chain governance.

  • We work closely with Open Zeppelin on the
    Governor standard and closely with the Scopelift team on the Flexible Voting module.
  • We work with the Uniswap DAO as part of the Uniswap Deployments Accountability Committee.
  • Tally is leading the way in the world of crosschain governance with our recent deep dive into crosschain governance designs for the Optimism Collective.

The Tally team is qualified to thoroughly analyze and evaluate the implementation solutions available to the Lido DAO. We are excited to partner with Lido’s operations team and bring in governance expertise from StableLab to identify the best path forward!

Research Deliverable

We propose a research project focused on adding delegation to LDO voting power and supporting the Lido DAO on Tally. The project will sketch out different ways to implement each of the following four options. We’ll also provide a thorough analysis of each option along with pros and cons for the Lido DAO operations team to consider.

The research deliverable will contain an analysis of the following options:

  1. Fully support delegation built on top of the existing Lido DAO Aragon governance system on Tally
  2. Build smart contract interface that makes the LDO token compatible to Tally’s interface
  3. Build a proxy contract to make the LDO token look like an ERC20Votes token, then add a Governor as a module to the existing Aragon contracts
  4. Migrate the whole Lido DAO to a Governor that works natively with Tally. This option is unlikely to be preferred by the Lido community. As a result, our analysis may be less detailed for the option (e.g. we may not include a scope of work required to implement).

For each option, we will include the following components in the deliverable:

  • Time and cost required to deliver
  • Ongoing maintenance costs
  • User experience benefits and challenges
  • Security implications and key risks
  • Detailed explanation of our research process with links to source material
  • Detailed scope of work required to implement (this will only be included for options that are promising according to our analysis)

Implementation Cost and Timeline

We anticipate that it will require about two full work weeks of one researcher’s time to complete this research deliverable. We plan to spread that work out across a longer period following this timeline:

  • Week of December 4th: Begin research
  • Week of December 18th: Share project update with Lido DAO operations team for feedback and direction. Mid-project update to include key learnings about each implementation option and a preview of the final deliverable format
  • Week of December 25th: Pause for holidays
  • Week of January 15th: Share final draft of research deliverable with Lido DAO operations team for feedback and direction
  • Week of January 22nd: Complete research deliverable and move to implementation phase

Cost: 10,000 DAI/USDC
Tally Multisig Address for payment: eth:0x7E90E03654732ABedF89Faf87f05BcD03ACEeFdC

14 Likes

Thank you for the proposal! The LEGO approved the Pebble grant, the payment will be made shortly.

6 Likes

Thank you, kadmil! We are excited to deliver this research to the Lido DAO.

6 Likes

Grant payment sent =))

4 Likes

Hello Lido community! I’m back with an update on our Lido x Tally research grant. We’ve made great progress on our evaluation of each of the implementation options for supporting the Lido DAO on Tally and enabling delegation. Below, I share a brief summary of what we’ve learned. I will also highlight the solution we think is most promising and then conclude by previewing our deliverable.

I’d like to give a huge shout out to @ rspa_StableLab and @Nneoma_StableLab from StableLab as well as @kadmil from Lido DAO Operations, who have all made fantastic contributions to this research project.

In the research grant proposal, we highlight four options:

  • Option One: Fully support delegation on top of the existing Lido DAO Aragon governance system on Tally.
  • Option Two: Build a smart contract interface that makes the LDO token compatible with Tally’s interface.
  • Option Three: Build a proxy contract to make the LDO token look like an ERC20Votes token, then add a Governor as a module to the existing Aragon contracts.
  • Option Four: Migrate the whole Lido DAO to a Governor which works natively with Tally.

We’ve learned that Option Two is the most efficient and secure way to achieve Options One and Three, so I’ve combined those options into one update below.

Options One, Two and Three: Build a smart contract interface that makes the LDO token compatible with Tally’s interface.

  • Solution description: There is a hook that notifies the LDO token manager contract when LDO is transferred. The LDO token manager contract is upgradeable (unlike the LDO token itself), so this solution involves adding a function call on this hook that adds to a registry of delegations to keep voting power in sync with token balances. This registry would be deployed as a parallel smart contract to the LDO token. A Governor (which is natively compatible with Tally) would be deployed that uses the registry to track voting power. This solution would then require the permissions of the DAO to be passed from the current Aragon system to the newly deployed Governor.
  • Analysis: Based on our research to date, option two is the preferable solution. It enables delegation without requiring LDO token holders to lock their tokens in a governance escrow or wrap their tokens. The architecture of this solution is compatible with Tally today, so it wouldn’t require Tally to support Lido as a one-off design on an ongoing basis (though it will require some customization to support).

Option Four: Migrate the whole Lido DAO to a Governor, which works natively with Tally.

  • Solution description 1: Raph from StableLab explored an implementation similar to MakerDAO’s delegation system. MakerDAO’s MKR token is an ERC20 implementation with mint and burn functionality and some smaller technical differences, but no delegation functionality. If MKR holders want to vote on executive proposals and move the hat (the current set of active smart contracts) to a new spell, as the set of smart contracts that executes the latest bundle of approved proposals is called, they need to lock their MKR into the governance escrow of their delegate (or their own).
  • Solution description 2: Another option would be to deploy a wrapped Lido governance token (LDO) that implements the ERC-5805 standard, which includes the token interfaces for voting with delegation. A new Lido DAO Governor contract would also need to be deployed. Once live, the DAO’s onchain assets, presently with Aragon, including the treasury, protocol, and any associated administrative permissions, will transition to this Governor contract. A detailed view of impacted contracts can be found in Lido’s GitHub repository.
  • Analysis: These solutions require LDO token holders to either lock their tokens in a governance escrow or wrap their tokens. While both implementations are elegant and proven, we prefer a solution that does not require LDO token holders to lock or migrate their tokens.

In our final deliverable, we will include the following components in our analysis of each option:

  • Time and cost required to deliver
  • Ongoing maintenance costs
  • User experience benefits and challenges
  • Security implications and key risks
  • Detailed explanation of our research process with links to source material

For option two, we will include a detailed scope of work for implementation.

Cheers,

Frisson

4 Likes

Thank you for the update!

2 Likes

You might also consider Tao Voting as option 5. It is an old school Aragon app that is compatible with the LDO token we have today. Aragon was just about to start using it for their DAO (but instead got rid of their token) and the TEC just deployed it on Optimism a couple weeks ago.

It has delegation built in as well as other nice features.

5 Likes

Thank you for the suggestion, Griff! We’ll look into TAO voting.

Do you by any chance have a pointer to some of the technical implementation details of TAO voting?

1 Like

Hello, Lido community! I’m back with the final deliverable on our Lido x Tally research grant.

Authors: Frisson (Tally), Dennison Bertram (Tally), Raphael Spannocchi (StableLab), Nneoma (StableLab), Dulguun (StableLab)

Contributors: Kadmil (Lido)

Background

Lido DAO would like to increase voter participation and decision quality by introducing delegation.
Tally believes we can help introduce delegation to the Lido DAO while improving participation and overall engagement with Tally’s best-in-class governance platform. The current implementation of the LDO token and Lido DAO governance structure does not allow for a straightforward integration with Tally, however. With this research deliverable, we evaluate implementation solutions available to the Lido DAO and recommend a path forward.

Analysis and Conclusion

The four options for supporting Lido on Tally and enabling delegation we will discuss are:

  • Option One: Fully support delegation on top of the existing Lido DAO Aragon governance system on Tally. We only discuss this option briefly, because it is not technically viable.
  • Option Two: Build a smart contract interface that makes the LDO token compatible with Tally’s interface.
  • Option Three: Build an IOU voting proxy contract that enables delegation of the LDO token, then add the voting proxy contract as a module to the existing Aragon contracts. We adjusted the nature of option three from the original research proposal to reflect the most viable implementation path.
  • Option Four: Migrate the whole Lido DAO to a Governor that works natively with Tally.

This deliverable includes an evaluation of each implementation option. It also includes a detailed spec for implementing our recommended solution, Option Two: Build a smart contract interface that makes the LDO token compatible with Tally’s interface. We’re excited to gather feedback from the Lido community on our analysis and make progress towards implementation.

We put together a visual matrix below that highlights the performance of each option on each factor of our analysis. Option one is not technically viable from our point of view. Option three is technically challenging and would require high maintenance. Option four requires almost uniform user participation and represents a major technical change to the current governance system. Option two stands out as the only path that is viable across all dimensions of our analysis. We’ve identified an elegant path to implementing option two that requires minimal change to the Lido governance system, is straightforward for Tally to support, and provides a smooth, non-disruptive user experience for Lido token holders.

Option One: Fully support delegation on top of the existing Lido DAO Aragon governance system on Tally.

We were not able to determine a technically viable path to supporting delegation on top of the existing Lido DAO Aragon governance system. All viable solutions involve either building a smart contract interface (option two), building a proxy contract (option three), or migrating to a Governor (option four).

One option we explored thanks to Griff’s helpful recommendation in this forum thread is TAO voting. The TAO system is a kind of implementation of liquid democracy which includes a system for delegated voting. To the best of our understanding however, the Aragon implementation of this system is not compatible with the demands or scale of an organization such as Lido.

Aragon TAO Voting unfortunately hits the same constraints as the Lido DAO when seeking an implementation of delegation for the token. That is: there is no native way to track delegated voting power onchain. In the TAO Voting implementation, ‘voteOnbehalfOf’ implements the ability to “vote on behalf” of someone, or delegation. The implementation requires that the user pass in at vote time an array containing all of the voters that they are voting on behalf of. This is non-scalable, as the smart contract function loops through each individual delegate to calculate their voting power at voting time. For a delegate such as Linda Xie in Optimism, this would require passing in a list of over 80,000 delegates and executing the loop 80,000 times. This is prohibitive in terms of gas cost (even on L2), potentially impossible to execute, and might lead to operational inefficiency (to save gas costs, perhaps Linda would only vote with a subset of her delegated voting power, meaning the smaller delegates’ votes would essentially be wasted).

Option Two: Build a smart contract interface that makes the LDO token compatible with Tally’s interface.

Solution summary
To implement option two, we propose creating an interface contract which mimics the interface of a standard OpenZeppelin ERC20Votes smart contract. This interface would be connected to the Aragon Token Manager contract and its state updated as part of the internal “doTransfer” call, which is made on each LDO token transfer. In this way, we can implement delegation that tracks the delegated token balance at any point in time without requiring any changes to the LDO token or requiring some sort of wrapper.

Implementation cost
The architecture of option two is generally compatible with Tally today. With option two, Tally could and probably should make a product investment to support some aspects of the legacy Aragon system alongside the new system so that users can see old proposals and interact with the old system as needed.

Option two requires the creation of an interface contract which mimics the interface of a standard OpenZeppelin ERC20Votes smart contract. This interface would be connected to the Aragon Token Manager contract, and its state updated as part of the internal “doTransfer” call, which is made on each LDO token transfer. Adding the new interface to the Lido DAO is a relatively straightforward process and would involve packaging a Governor that inherits the Aragons forwarder and ACL controls, essentially making it a module.

Maintenance cost
The architecture of this solution is generally compatible with Tally today. As a result, the majority of the ongoing maintenance cost of this solution is already captured by the work Tally does to support its platform as a whole across all clients. If Tally makes incremental product investments to support some aspects of the legacy Aragon system alongside the new system, this will entail ongoing maintenance costs specific to Lido.

User experience
Option two enables delegation and Tally support without requiring LDO token holders to lock their tokens in a governance escrow or wrap their tokens.

Option two also enables Lido token holders to participate via the legacy system by over voting (voting with their own voting power on a proposal that their delegate has already voted on), if desired. The new system interface provides the logic for returning an individual addresses token power as well as their delegated voting power.

Option two enables partial voting: the ability for an address to delegate to multiple addresses. This is frequently useful for very large token holders looking to spread out their voting power between various addresses. This is a feature that would be straightforward to implement in the interface contract.

Security implications
This is a generally safe implementation, because it only requires a small change to the LDO token manager. We only need to make the token manager contract tell the new ERC20Votes interface contract when a balance changes. This is only a one-way integration. The token manager does not need to read from the ERC20Votes interface contract. With this implementation, we minimize the need for any changes on the existing Lido DAO smart contracts. We use the existing Aragon design and system to add a new smart contract to the system, which is within the scope and design of the original implementation/intention of the Aragon system.

We would recommend an audit of the smart contract code to ensure that there is no way for the ERC20Votes interface contract to change the state of the LDO token manager. We would also recommend an audit of the new Governor module that would be added to the Aragon system.

Implementation spec
Delegation can be thought of as a two-part system: a delegate registry that tracks who is delegating to whom, and a counter which tracks the amount of voting power that is delegated from one address to another. The delegate registry is relatively simple. The ERC20Votes OpenZeppelin contract already contains logic that manages a registry of delegations. There are other off-the shelf solutions that also exist, such as Delegate.xyz and Safe’s Delegate Registry. In its simplest form, the registry is a mapping of address → address.The complexity comes from implementing a counter system that tracks the delegated voting balance of an address at any time point, so that at any point in time the delegated voting power of an address can be determined onchain. The challenge that we have overcome in this implementation is updating the delegated token balance in a way that automatically stays in sync with a user’s token transfers.

While the LDO token does have a built-in checkpointing system that allows one to get the token balance of an address at any point in time, the token does not have a way to do delegation or track delegated token balances. The LDO token is also not upgradable, meaning it is not possible to add this functionality to the LDO token itself. Fortunately, the LDO token does have an internal hook function that calls to the Aragon Token Manager contract. There is an internal function called ‘doTransfer’, which informs the Aragon Token Manager contract of token transfers for implementing functionality around blocking transferability or transfer caps. The Aragon Token Manager contract is a proxy contract, and thus is designed to be upgradable. This offers us the opportunity to build a delegate registry and voting balance checkpointing as a function of the Aragon Token Manager contract.

To implement delegation for the LDO token, we propose the creation of an interface contract which mimics the interface of a standard OpenZeppelin ERC20Votes smart contract. This interface would be connected to the Aragon Token Manager contract and its state updated as part of the internal “doTransfer” call, which is made on each LDO token transfer. In this way, we can implement delegation that tracks the delegated token balance at any point in time without requiring any changes to the LDO token or requiring some sort of wrapper.

Logical flow of execution when a user transfers an LDO token today

The interface contract would exist to implement an ERC20Votes interface for contracts such as OpenZeppelin Governor, but would not actually be a token. The majority of the functional logic such as “balanceOf” or “name” would be removed and instead directly reference the LDO implementation. Public functions such as transfer, or approve would simply revert when called, as the ERC20Votes contract would exist as an interface to the LDO contract.

Users holding LDO would continue to use their LDO token contract in the normal way, they would have no need to interact with the interface contract, except for delegation. The interface would exist to simply interpret the LDO token with delegation added. Users would transfer and use their LDO tokens like before. For delegation, they would be required to call the LDO Interface contract to select their delegate. On the first delegation, the interface contract would check the LDO tokens balanceOof and set the first delegate along with the delegators token balance for voting power.

On each subsequent token transfer to or from the delegators addresses, the TokenManager would update the interface contract with the new balances to correctly represent the delegated voting power of the user.

Implementation of a Delegate Registry Interface

The Lido DAO is built upon a legacy version of Aragon DAO software. This system was developed as a kind of “operating system” where users could create unique programs which could be ‘attached’ to the DAO. The design envisioned a freeform flexible structure that users could customize to their needs. The system, while powerful, is also complicated and hard for 3rd parties to reason about without understanding its design system. At its core, the legacy Aragon system is essentially a permissions system controlled by a module called the “ACL” (Access Control List) which intermediates the permissions between various smart contracts. The structure of the Lido permission system can be loosely understood from the Aragon Lido DAO page.

Screenshot from the Aragon Lido DAO Page

In the above table, we can see four columns: “Action”, “On App”, “Assigned to Entity”, and “Managed By” describing the permission. Walking through the first line of this table, we have the first action which is the RadSpec definition of what a specific function on the “App” smart contract is supposed to do. So in this first row example, the entity (smart contract) called “Finance” has the permission to “Transfer Agent’s tokens” on the smart contract App called “Agent”, and this permission is managed by the smart contract called “Voting”.

In the Lido DAO system the smart contract “Voting” controls the permissions for all the smart contracts in the organization. Authorized users create proposals as “evmscript” and the Voting smart contract is able to forward and execute these scripts when a proposal passes and the vote is executed.

Adding Governor to the Lido DAO is a relatively straightforward process and would involve packaging a Governor that inherits the Aragon forwarder and ACL controls, essentially making it a module. Thanks to the flexibility of the Aragon permissions system, the governor smart contracts can be added with the appropriate permissions required to operate the Lido system. Topologically, this is replacing the Aragon “Voting” module with a governor module and giving it the correct permissions. The functionality and operation of the Lido DAO would be effectively the same.

References

The ‘doTransfer’ function of interest:

function doTransfer(address _from, address _to, uint _amount) internal returns(bool) 
[....removed for brevity]
        // Alerts the token controller of the transfer
[....removed for brevity]
 require(ITokenController(controller).onTransfer(_from, _to, _amount) == true);
        }
[....removed for brevity]
    }

Explanation of flow

  1. Transfer Function Call (function transfer(address _to, uint256 _amount) public returns (bool success)):
  • This is the initial entry point for a token transfer.
  • It checks if transfers are enabled via require(transfersEnabled);.
  • Calls the doTransfer function with msg.sender, _to, and _amount.
  1. doTransfer Function Logic (function doTransfer(address _from, address _to, uint _amount) internal returns(bool)):
  • Checks if the amount to be transferred is zero (in which case it just returns true).
  • Ensures that the transfer is not to address 0 or the token contract itself.
  • Retrieves the balance of the sender at the current block (balanceOfAt(_from, block.number)) and checks if the sender has enough balance to transfer the amount.
  • If the contract has a controller, it calls ITokenController(controller).onTransfer(_from, _to, _amount) to notify the controller about the transfer. The controller can potentially reject the transfer by returning false.
  • Updates the sender’s balance by reducing the amount (updateValueAtNow(balances[_from], previousBalanceFrom - _amount)).
  • Similarly, updates the recipient’s balance by adding the amount.
  • Emits a Transfer event.
  1. Other Notes
  • balanceOfAt and updateValueAtNow are used to manage balances at different block numbers, allowing the token to effectively handle balance snapshots.
  • The contract includes checks for overflows and ensures that the transfer does not result in erroneous values (e.g., ensuring previousBalanceTo + _amount >= previousBalanceTo).
  • The controller plays a significant role in this contract. It has the authority to enable or disable transfers, and it can intervene in the transfer process.
  • The transferFrom function allows a third party to transfer tokens on behalf of the owner, provided that it’s approved by the owner. It has similar logic to transfer but with additional checks on allowances.

Change Required

  • Current
function onTransfer(address _from, address _to, uint256 _amount) external onlyToken returns (bool) {
return _isBalanceIncreaseAllowed(_to,_amount) && _transferableBalance(_from, getTimestamp()) >= _amount;}
  • Future
Interface IDelegateRegistryInterface {
function trackBalance(address _from, address _to, uint256 _amount) external;
}
….
IDelegateRegistryInterface IDelegateRegistry = “address Registery”


function onTransfer(address _from, address _to, uint256 _amount) external onlyToken returns (bool) {
 IDelegateRegistry.trackBalance(_from, _to, _amount);
        return _isBalanceIncreaseAllowed(_to, _amount) && _transferableBalance(_from, getTimestamp()) >= _amount;}

Option Three: Build an IOU voting proxy contract that enables delegation of the LDO token, then add the voting proxy contract as a module to the existing Aragon contracts.

Solution summary
To execute on option three, we would propose creating an LDO IOU voting proxy contract similar to the one used in MakerDAO. The MKR token is an ERC20 implementation with mint and burn functionality and some smaller technical differences, but no delegation functionality. If MKR holders want to vote on executive proposals and move the hat (the current set of active smart contracts) to a new spell, as the set of smart contracts that executes the latest bundle of approved proposals is called, they need to lock their MKR into the governance escrow. When token holders lock their MKR in the voting proxy or dss-chief smart contract, they receive IOU tokens in return for the amount of MKR they send into the escrow on a one-to-one basis.

Implementation cost
The architecture of option three is not compatible with Tally today. With option three, Tally would need to make a very large investment to integrate a MakerDAO-like system with our API and front end. The cost of this could potentially be offset to some extent by the fact that Tally would then likely be able to support MakerDAO governance.

Option three requires the creation of an LDO IOU voting proxy contract similar to the MKR voting proxy. Adding the new IOU voting proxy contract to the Lido DAO is a relatively straightforward process and would involve packaging it in a way that inherits the Aragons forwarder and ACL controls, essentially making it a module.

Maintenance cost
The architecture in option three is not compatible with Tally today. As a result, this solution would require significant ongoing additional maintenance cost for Tally.

User experience
Option three avoids some of the need to actively manage another LDO token. While the IOU tokens are transferable, they can only be redeemed by the same address that executed the lock transaction. Token holders can lock up their LDO tokens from their main wallet, but then use a less secure hot wallet for voting, since IOUs are worthless to anyone but the address that locked the tokens. Users can free their tokens at any time by triggering a transaction in the opposite direction. (free instead of lock).

IOU tokens can be engineered to support any kind of behavior, which would open the door to future governance innovations like dual token voting and partial voting/delegation.

Option three enables Lido token holders to participate via the legacy system by voting with their own voting power on a proposal that their delegate has already voted on, if desired. The new system interface provides the logic for returning an individual addresses token power as well as their delegated voting power.

Security implications
IOU tokens can be used to vote on executive proposals, and can be delegated. Delegations can be changed at any time, also during ongoing votes. This can lead to dramatic changes in voting outcomes, if large delegations get moved around during a contested vote. See the following link for a particular example. # 42 | Valkyrie: MakerDAO and Our Side of History (substack.com)

MakerDAO’s implementation of an IOU token doesn’t have a delegate function itself. Instead IOU tokens can come from different governance contracts. MKR holders can deposit their MKRs into their own vote proxy contract and vote directly, or into a delegates’ vote proxy contract, and receive IOUs from them. The delegates do not have the ability to access or transfer the tokens in their vote proxy, so user funds are SAFU at all times. The schema below visualizes the flow of tokens.

While it may seem that the delegate could have influence over whether or not the MKR get deposited into the governance contract, this is not the case, but part of the delegate’s smart contract functionality.

Option Four: Migrate the whole Lido DAO to a Governor that works natively with Tally

Solution Summary
To execute option four, we would deploy a wrapped Lido governance token (LDO) that implements the ERC-5805 standard, which includes the token interfaces for voting with delegation. A new Lido DAO Governor contract would also need to be deployed. Once live, the DAO’s onchain assets, presently with Aragon, including the treasury, protocol, and any associated administrative permissions, will transition to this Governor contract. A detailed view of impacted contracts can be found in Lido’s GitHub repository.

Implementation cost
The architecture of this solution is generally compatible with Tally today. As a result, the majority of the implementation cost of this solution is already captured by the work Tally does to support its platform as a whole across all clients.

Maintenance cost
The architecture of this solution is generally compatible with Tally today. As a result, the majority of the ongoing maintenance cost of this solution is already captured by the work Tally does to support its platform as a whole across all clients.

User experience
Option four requires LDO token holders to wrap their tokens into a new, liquid governance token that needs to be managed in parallel with the existing LDO token. In our opinion, this is a blocker for implementation.

Security implications
Option four requires migration to an entirely new governance token, which is a level of change that is likely unacceptable to the Lido DAO from a security perspective.

6 Likes

I’m so impressed by your research, @frisson! This was awesome to read, not only because you made this so accessible (I learned a ton) but it was a more than sufficient analysis.

I love the approach Tally took here too, from one governance professional to the next. Hats off!

1 Like

Thank you for your kind words @ValerieSpina!