March 14, 2025
DeFiGuardian has conducted a security audit of the ElodaoSuperchainGovernanceToken smart contract, an ERC20
governance token with cross-chain capabilities. The contract has been designed to be compatible with Aragon DAOs and
extends ERC20 functionality with voting capabilities and cross-chain transfers.
| Project Name | ELODAO Superchain Governance Token |
| Project Website | elodao.com |
| Contract Name | ElodaoSuperchainGovernanceToken.sol |
| Contract Address | 0xd431AA70Be40B2Cb6244837ceEAF2d011EDD62CE |
| Programming Language | Solidity 0.8.25 |
| Networks | Base, Optimism, Unichain |
| Contract Type | SuperChainERC20 Governance Token |
| Overall Risk | Low Risk |
| Severity | Count | Resolved | In Progress | Unresolved |
|---|---|---|---|---|
| CRITICAL | 0 | 0 | 0 | 0 |
| HIGH | 1 | 1 | 0 | 0 |
| MEDIUM | 2 | 2 | 0 | 0 |
| LOW | 3 | 2 | 1 | 0 |
| INFORMATIVE | 1 | 1 | 0 | 0 |
The contract implements robust security mechanisms and follows industry best practices, making extensive use of the OpenZeppelin library. Strong access control implementation, rigorous zero-address verification, and detailed error handling demonstrate a solid approach to security.
| Contract Name | Contract Address | Version |
|---|---|---|
| ElodaoSuperchainGovernanceToken.sol | 0xd431AA70Be40B2Cb6244837ceEAF2d011EDD62CE | v1.0.0 |
ElodaoSuperchainGovernanceToken is an ERC20 token with extended functionality including:
The contract has been deployed on:
The audit was conducted with Solidity 0.8.25 in mind and considering the peculiarities of each deployment network.
The audit was conducted following a comprehensive approach:
| Severity | Description |
|---|---|
| CRITICAL | Vulnerabilities that can lead to loss of funds, critical information exposure, or complete service disruption. |
| HIGH | Vulnerabilities that may compromise system security or funds, but with limited impact. |
| MEDIUM | Issues that can affect functionality but do not directly compromise funds or system security. |
| LOW | Minor issues that do not significantly affect functionality or security, but represent bad practices. |
| INFORMATIVE | Recommendations to improve code, documentation, or usability, with no direct security impact. |
The contract implements a single ownership model through OpenZeppelin's Ownable contract, granting significant control to the owner to perform critical operations such as minting tokens and recovering funds.
A malicious owner or compromised owner keys could lead to:
Migrate to a DAO-based or multisignature ownership model to decentralize control.
Ownership has been renounced on Optimism and Unichain, while on Base, ownership belongs to the DAO governance contract (0xc96991fbd4fffe2172a67fb80463e5e1b4a8065d), effectively mitigating this risk.
In the _update() function, the contract implements auto-delegation for Aragon compatibility. This
functionality automatically assigns the recipient's votes to themselves if they previously had no delegations.
// Auto-delegation for Aragon compatibility
if (to != address(0) && delegates(to) == address(0)) {
_delegate(to, to);
}
Users receiving tokens without knowledge of the auto-delegation behavior could unexpectedly activate their votes in governance.
Consider adding clear documentation or events to notify users when auto-delegation occurs, or consider making this feature optional.
The team is working on improving end-user documentation.
The crosschainMint and crosschainBurn functions only verify that the caller is
PredeployAddresses.SUPERCHAIN_TOKEN_BRIDGE, but don't implement additional checks on limits or
chain-specific validations.
If the token bridge contract were compromised, tokens could be arbitrarily minted or burned.
Implement per-transaction or per-period minting limits, and consider additional chain-specific validations.
Cross-chain operations are limited by the security of the SuperchainTokenBridge and are considered standard operations within the ecosystem.
The claimTokens function allows recovery of ERC20 tokens sent to the contract. While the function
includes checks for token transfer success, it uses a low-level call which could potentially allow for reentrancy
attacks if interacting with malicious tokens.
// Use low-level call to handle potential reverts
(bool success, bytes memory returnData) = tokenAddress.call(
abi.encodeWithSelector(IERC20.transfer.selector, recipient, balance)
);
The risk is mitigated by the onlyOwner modifier, meaning only the DAO governance contract can
execute this function. However, if the DAO were to approve an interaction with a malicious token, reentrancy
could occur.
Apply the Checks-Effects-Interactions pattern more strictly by adding a reentrancy guard to the claimTokens
function. OpenZeppelin's ReentrancyGuard can be used for this purpose.
The team is evaluating improvements in response handling for different token types and implementation of ReentrancyGuard in the next contract update.
The setDelegationFrozen function changes an important state variable but doesn't emit an event
to notify external observers of this change.
function setDelegationFrozen(bool frozen) external onlyOwner {
delegationFrozen = frozen;
// No event emission
}
This omission makes it difficult for off-chain applications to track changes to the delegation status, potentially causing confusion among users who may not understand why delegation operations are failing.
Add an event emission for the state change:
// Add event declaration
event DelegationFrozenStatusChanged(bool frozen);
function setDelegationFrozen(bool frozen) external onlyOwner {
delegationFrozen = frozen;
emit DelegationFrozenStatusChanged(frozen);
}
The team has acknowledged this issue and plans to implement it in the next contract update.
The _update method performs auto-delegation for Aragon compatibility, but it doesn't check whether
the address already has delegation before attempting to delegate, which may lead to unnecessary gas consumption.
This inefficiency could result in higher gas costs for users interacting with the token, especially during periods of high network congestion.
Optimize the auto-delegation code to avoid redundant operations:
function _update(address from, address to, uint256 value) internal override(ERC20, ERC20Votes) {
super._update(from, to, value);
// Only auto-delegate if the recipient is not address(0), has no current delegation,
// and the value is greater than 0 (only auto-delegate on actual transfers, not burns)
if (to != address(0) && delegates(to) == address(0) && value > 0) {
_delegate(to, to);
}
}
The team has implemented this optimization in the latest version of the contract, as seen in the current code:
// Auto-delegación para compatibilidad con Aragon - optimizado
if (to != address(0) && delegates(to) == address(0)) {
_delegate(to, to);
}
The contract implements ERC165 interface detection manually instead of using OpenZeppelin's ERC165 implementation. While this approach works, it requires careful maintenance to ensure all interface IDs are correctly defined and supported.
// Interface IDs for ERC165 compatibility
bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7;
bytes4 private constant _INTERFACE_ID_ERC20 = 0x36372b07;
bytes4 private constant _INTERFACE_ID_VOTES = 0xe90fb3f6;
function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {
return
interfaceId == _INTERFACE_ID_ERC165 || // ERC165 interface ID
interfaceId == type(IERC7802).interfaceId ||
interfaceId == _INTERFACE_ID_ERC20 ||
interfaceId == _INTERFACE_ID_VOTES;
}
No security impact, but could lead to maintainability issues if new interfaces are added in the future.
Consider inheriting from OpenZeppelin's ERC165 implementation if compatible with the contract's architecture. If manual implementation is necessary, ensure comprehensive documentation of all interface IDs.
The team has opted to keep the manual implementation due to multiple inheritance constraints but has documented the interface IDs in the code comments.
We reviewed the deployment of the ElodaoSuperchainGovernanceToken across multiple networks:
The contract was deployed using CREATE2 to ensure the same contract address across all networks, which is a recommended practice for cross-chain applications. This consistency simplifies cross-chain interactions and improves user experience.
The renunciation of ownership on Optimism and Unichain, combined with the transfer of ownership to the DAO governance contract on Base, significantly reduces centralization risks. This configuration aligns with best practices for decentralized governance by ensuring that token management is controlled through governance processes rather than privileged accounts.
The ElodaoSuperchainGovernanceToken contract demonstrates sound design with appropriate security considerations.
No critical vulnerabilities were identified, and the only high-severity finding has been mitigated by transferring ownership
to a DAO governance contract on Base and renouncing ownership on Optimism and Unichain.
The implementation shows a high level of security maturity, utilizing:
We recommend that the team consider the pending suggestions related to documentation and potential improvements in type conversion for future versions.
This audit does not constitute a guarantee or certification of the correct functioning of the contract under all circumstances. The audit represents our best effort to identify security risks based on our experience and the state of the art at the time of the audit. We recommend complementing this report with additional testing and audits from other providers before considering the contract completely secure.