Overt Alabaster Cottonmouth
Medium
As soon as an author sees in the mempool that the slasher has chosen to call slash() on his profileId, they can front-run it and call unvouch() on all their vouches. This immediately returns all the balance to the author. The slash()
function anyway doesn't consider archived vouches while slashing since they wouldn't have any balance:
File: ethos/packages/contracts/contracts/EthosVouch.sol
520: function slash(
521: uint256 authorProfileId,
522: uint256 slashBasisPoints
523: ) external onlySlasher whenNotPaused nonReentrant returns (uint256) {
524: if (slashBasisPoints > MAX_SLASH_PERCENTAGE) {
525: revert InvalidSlashPercentage();
526: }
527:
528: uint256 totalSlashed;
529: uint256[] storage vouchIds = vouchIdsByAuthor[authorProfileId];
530:
531: for (uint256 i = 0; i < vouchIds.length; i++) {
532: Vouch storage vouch = vouches[vouchIds[i]];
533:@---> // Only slash active vouches
534:@---> if (!vouch.archived) {
535: uint256 slashAmount = vouch.balance.mulDiv(
536: slashBasisPoints,
537: BASIS_POINT_SCALE,
538: Math.Rounding.Floor
539: );
540: if (slashAmount > 0) {
541: vouch.balance -= slashAmount;
542: totalSlashed += slashAmount;
543: }
544: }
545: }
This may effect the author's reputation but the immediate loss of ETH which would probably be of greater value, is avoided.
- Thr protocol could consider adding a time delay between the call to
unvouch()
and funds being returned to the author. The author should be required to call a new function to pull these funds into their address once the time period has expired. - Then, the
slash()
logic can be modified to exclude only the vouches which are archived and have zero withdrawable funds in them. We may need to add another element instruct Vouch
nameduint256 fundsNotYetPulledByAuthor
to track this.