VTVL contest - Dravee's results

Building no-code token management tools to empower web3 founders and investors, starting with token vesting.

General Information

Platform: Code4rena

Start Date: 20/09/2022

Pot Size: $30,000 USDC

Total HM: 12

Participants: 198

Period: 3 days

Judge: 0xean

Total Solo HM: 2

Id: 164

League: ETH

VTVL

Findings Distribution

Researcher Performance

Rank: 143/198

Findings: 1

Award: $18.87

🌟 Selected for report: 0

🚀 Solo Findings: 0

Lines of code

https://github.com/code-423n4/2022-09-vtvl/blob/f68b7f3e61dad0d873b5b5a1e8126b839afeab5f/contracts/AccessProtected.sol#L11 https://github.com/code-423n4/2022-09-vtvl/blob/f68b7f3e61dad0d873b5b5a1e8126b839afeab5f/contracts/AccessProtected.sol#L25

Vulnerability details

Impact

The owner won't be able to pass the AccessProtected mechanism. Only admins can.

Proof of Concept

  • AccessProtected imports OZ's Ownable:
File: AccessProtected.sol
5: import "@openzeppelin/contracts/access/Ownable.sol";
  • Several comments suggest that admin and owner roles are different and should both be checked:
File: AccessProtected.sol
8: @title Access Limiter to multiple owner-specified accounts.
9: @dev Exposes the onlyAdmin modifier, which will revert (ADMIN_ACCESS_REQUIRED) if the caller is not the owner nor the admin.
21:     /**
22:      * Throws if called by any account that isn't an admin or an owner.
23:      */
24:     modifier onlyAdmin() {
25:         require(_admins[_msgSender()], "ADMIN_ACCESS_REQUIRED");
26:         _;
27:     }
  • However, the owner role is never checked. It's not even inherited by AccessProtected while the library is imported:
File: AccessProtected.sol
11: abstract contract AccessProtected is Context {

Consider inheriting Ownable and checking the owner:

File: AccessProtected.sol
- 11: abstract contract AccessProtected is Context {
+ 11: abstract contract AccessProtected is Context, Ownable {
...
24:     modifier onlyAdmin() {
- 25:         require(_admins[_msgSender()], "ADMIN_ACCESS_REQUIRED");
+ 25:         require(_admins[_msgSender()] || owner() == _msgSender(), "ADMIN_ACCESS_REQUIRED");
26:         _;
27:     }

Alternatively, if the owner here isn't relevant, consider adding an array of _owners which would be checked the same way as the array of _admins and remove the unused library import.

Alternatively, if admins and owners are the same role, just remove the confusing comments

#0 - 0xean

2022-09-24T21:00:28Z

downgrading to QA as this seems very much like Low risk (e.g. assets are not at risk: state handling, function incorrect as to spec, issues with comments).

AuditHub

A portfolio for auditors, a security profile for protocols, a hub for web3 security.

Built bymalatrax © 2024

Auditors

Browse

Contests

Browse

Get in touch

ContactTwitter