The contract doesn't have the ability to revoke, but you can add it via inheritance. Here's some untested code that can work as a start:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/finance/VestingWallet.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
contract RevocableVestingWallet is VestingWallet, Ownable {
uint256 returned;
mapping (address => uint256) erc20Returned;
constructor(address beneficiaryAddress, uint64 startTimestamp, uint64 durationSeconds)
VestingWallet(beneficiaryAddress, startTimestamp, durationSeconds)
{}
function revoke() public onlyOwner {
uint256 balance = address(this).balance;
uint256 returnable = balance - releasable();
Address.sendValue(payable(msg.sender), returnable);
returned += returnable;
}
function revoke(address token) public onlyOwner {
uint256 balance = IERC20(token).balanceOf(address(this));
uint256 returnable = balance - releasable(token);
SafeERC20.safeTransfer(IERC20(token), msg.sender, returnable);
erc20Returned[token] += returnable;
}
function released() public view override returns (uint256) {
return super.released() + returned;
}
function released(address token) public view override returns (uint256) {
return super.released(token) + erc20Returned[token];
}
}
The one downside here is that through the released getters it will appear as though the funds returned to the owner have been released. I could not find a way around this.