Closed sherlock-admin2 closed 9 months ago
Invalid. Governance tokens holders can always choose to delegate to the same address if they like.
But it incresing the voting power by which the delagatee win any vote, is not it unexpected??? The code allowing me to delegate multiple time so I can vest as many time I want and increase the voting power as much as I want, that is what I shown in test, are you sure this behaviour is expected??
The organization that grants the tokens is the one that deposits them into escrow. Regardless, whoever has initial access to the tokens can delegate the full balance to anyone, with or without the vesting contracts.
The organization that grants the tokens is the one that deposits them into escrow. Regardless, whoever has initial access to the tokens can delegate the full balance to anyone, with or without the vesting contracts.
No sir, As per current implementation of contracts organisation does not deposits tokens into escrow, the recipient, who opened vesting position, is the one who deposits token in escrow contract, you can see it here:
FOR User 1
├─ [0] VM::startPrank(0x6813Eb9362372EEF6200f3b1dbC3f819671cBA69)
│ └─ ← ()
├─ [96778] OZVotingToken::mint(0x6813Eb9362372EEF6200f3b1dbC3f819671cBA69, 1000000000000000000 [1e18])
│ ├─ emit Transfer(from: 0x0000000000000000000000000000000000000000, to: 0x6813Eb9362372EEF6200f3b1dbC3f819671cBA69, value: 1000000000000000000 [1e18])
│ └─ ← ()
├─ [24605] OZVotingToken::approve(VestingEscrowFactory: [0xc7183455a4C133Ae270771860664b6B7ec320bB1], 115792089237316195423570985008687907853269984665640564039457584007913129639935 [1.157e77])
│ ├─ emit Approval(owner: 0x6813Eb9362372EEF6200f3b1dbC3f819671cBA69, spender: VestingEscrowFactory: [0xc7183455a4C133Ae270771860664b6B7ec320bB1], value: 115792089237316195423570985008687907853269984665640564039457584007913129639935 [1.157e77])
│ └─ ← true
├─ [119023] VestingEscrowFactory::deployVestingContract(1000000000000000000 [1e18], 0x6813Eb9362372EEF6200f3b1dbC3f819671cBA69, 864000 [8.64e5], 1, 432000 [4.32e5], true, 0x)
│ ├─ [41458] → new <unknown>@0xa38D17ef017A314cCD72b8F199C0e108EF7Ca04c
│ │ └─ ← 207 bytes of code
│ ├─ [22516] OZVotingToken::transferFrom(0x6813Eb9362372EEF6200f3b1dbC3f819671cBA69, 0xa38D17ef017A314cCD72b8F199C0e108EF7Ca04c, 1000000000000000000 [1e18])
│ │ ├─ emit Transfer(from: 0x6813Eb9362372EEF6200f3b1dbC3f819671cBA69, to: 0xa38D17ef017A314cCD72b8F199C0e108EF7Ca04c, value: 1000000000000000000 [1e18])
│ │ └─ ← true
│ ├─ [31321] 0xa38D17ef017A314cCD72b8F199C0e108EF7Ca04c::initialize(true, 0x)
│ │ ├─ [28590] VestingEscrow::initialize(true, 0x) [delegatecall]
│ │ │ ├─ [816] OZVotingToken::balanceOf(0xa38D17ef017A314cCD72b8F199C0e108EF7Ca04c) [staticcall]
│ │ │ │ └─ ← 1000000000000000000 [1e18]
│ │ │ ├─ emit VestingEscrowInitialized(factory: VestingEscrowFactory: [0xc7183455a4C133Ae270771860664b6B7ec320bB1], recipient: 0x6813Eb9362372EEF6200f3b1dbC3f819671cBA69, token: OZVotingToken: [0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f], amount: 1000000000000000000 [1e18], startTime: 1, endTime: 864001 [8.64e5], cliffLength: 432000 [4.32e5], isFullyRevokable: true)
│ │ │ └─ ← ()
│ │ └─ ← ()
│ ├─ emit VestingEscrowCreated(creator: 0x6813Eb9362372EEF6200f3b1dbC3f819671cBA69, recipient: 0x6813Eb9362372EEF6200f3b1dbC3f819671cBA69, escrow: 0xa38D17ef017A314cCD72b8F199C0e108EF7Ca04c)
│ └─ ← 0xa38D17ef017A314cCD72b8F199C0e108EF7Ca04c
├─ [0] VM::stopPrank()
*/
Now see this line:
│ ├─ [41458] → new <unknown>@0xa38D17ef017A314cCD72b8F199C0e108EF7Ca04c
│ │ └─ ← 207 bytes of code
│ ├─ [22516] OZVotingToken::transferFrom(0x6813Eb9362372EEF6200f3b1dbC3f819671cBA69, 0xa38D17ef017A314cCD72b8F199C0e108EF7Ca04c, 1000000000000000000 [1e18])
│ │ ├─ emit Transfer(from: 0x6813Eb9362372EEF6200f3b1dbC3f819671cBA69, to: 0xa38D17ef017A314cCD72b8F199C0e108EF7Ca04c, value: 1000000000000000000 [1e18])
│ │ └─ ← true
0xa38D17ef017A314cCD72b8F199C0e108EF7Ca04c
is the escrow contract address, 0x6813Eb9362372EEF6200f3b1dbC3f819671cBA69
is the recipient address.
No sir, As per current implementation of contracts organisation does not deposits tokens into escrow, the recipient, who opened vesting position, is the one who deposits token in escrow contract, you can see it here...
The setup script doesn't make the call as the owner because it's not necessary as there is no access control for convenience, though all deployed vesting escrows are controlled by the owner. These contracts are designed for token grants (like stock grants), which allows the recipient to use their full governance power immediately.
Even if the user wanted to create a vesting escrow using their tokens, they would not gain anything. They'd only lose the ability to transfer the tokens for the vesting period. They already have full control over the voting power of the tokens they hold and could delegate them if they want. The vesting escrow delegate function does not give them any special ability.
Invalid, in this test you are assuming admin deployed 5 different escrows contract for the same user1, so it is intended that delegatee assigned by recipient have 5e18 voting power.
1 comment(s) were left on this issue during the judging contest.
pratraut commented:
'invalid due to deployer or recipient is a TRUSTED entity'
itsabinashb
high
VestingEscrow::user can maliciously increase voting power of delegatee
Summary
An user can call
delegate()
ofVestingEscrow.sol
contract and increase voting power of a delegatee as much as they want.Vulnerability Detail
The
deployVestingContract()
ofVestingEscrowFactory.sol
contract allows a user to call it multiple time, but the thing is each time the data will be updated with latest data which is passed as argument indeployVestingContract()
. Thedelegate()
also allows same user to call it multiple times, it has no check whether the same delegatee is passed, whether the same user calling it etc. As a result any user can start vesting as many as possible by calling thedeployVestingContract()
and then call thedelegate()
to increase voting power of a particular delegatee. We can verify this case by a test, to conduct the test we need to comment out 2 lines fromTestUtil.sol
contract - this one and this one. Now create a test file inside test folder and paste this test:The result of the test is:
You can see how a user could manage to increase voting power of the delegatee.
Impact
User can increase voting power of a delegatee as much as he want.
Code Snippet
Tool used
Manual Review, Foundry
Recommendation
An user should not delegate a delegatee more than 1 time.