Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WOETH: Withdraw OETH in surplus. #2119

Open
wants to merge 11 commits into
base: sparrowDom/woeth_hack_proof
Choose a base branch
from
10 changes: 7 additions & 3 deletions contracts/contracts/token/WOETH.sol
Original file line number Diff line number Diff line change
Expand Up @@ -80,9 +80,12 @@ contract WOETH is ERC4626, Governable, Initializable {
external
onlyGovernor
{
//@dev TODO: we could implement a feature where if anyone sends OETH direclty to
// the contract, that we can let the governor transfer the excess of the token.
require(asset_ != address(asset()), "Cannot collect OETH");
if (asset_ == address(asset())) {
uint256 surplus = OETH(asset()).balanceOf(address(this)) -
totalAssets();
require(amount_ <= surplus, "Can only collect surplus");
}

IERC20(asset_).safeTransfer(governor(), amount_);
}

Expand All @@ -96,6 +99,7 @@ contract WOETH is ERC4626, Governable, Initializable {
*/
function _creditsPerAsset(uint256 oethAmount)
internal
view
returns (uint256)
{
(, uint256 creditsPerTokenHighres, ) = OETH(asset())
Expand Down
45 changes: 41 additions & 4 deletions contracts/test/token/woeth.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
const { loadDefaultFixture } = require("../_fixture");
const { oethUnits, daiUnits, isFork } = require("../helpers");
const { hardhatSetBalance } = require("../_fund");
const { impersonateAndFund } = require("../../utils/signers");

Check failure on line 6 in contracts/test/token/woeth.js

View workflow job for this annotation

GitHub Actions / Contracts Linter

'impersonateAndFund' is assigned a value but never used

describe("WOETH", function () {
if (isFork) {
Expand Down Expand Up @@ -105,7 +106,6 @@
await expect(woeth).to.have.approxBalanceOf("150", oeth);
await expect(woeth).to.have.a.totalSupply("50");
});

it("should not increase exchange rate when OETH is transferred to the contract", async () => {
await expect(woeth).to.have.a.totalSupply("50");
await expect(woeth).to.have.approxBalanceOf("100", oeth);
Expand Down Expand Up @@ -144,10 +144,47 @@
await expect(woeth).to.have.a.balanceOf("0", dai);
await expect(governor).to.have.a.balanceOf("1002", dai);
});
it("should not allow a governor to collect OETH", async () => {
it("should allow a governor to collect less than OETH surplus", async () => {
await oeth.connect(josh).transfer(woeth.address, oethUnits("2"));
await expect(woeth).to.have.a.balanceOf("102", oeth);
await woeth.connect(governor).transferToken(oeth.address, oethUnits("1"));
await expect(woeth).to.have.a.balanceOf("101", oeth);
await expect(governor).to.have.a.balanceOf("1", oeth);
await expect(await woeth.totalAssets()).to.equal(oethUnits("100"));
});
it("should allow a governor to collect exact OETH surplus", async () => {
await oeth.connect(josh).transfer(woeth.address, oethUnits("2"));
await expect(woeth).to.have.a.balanceOf("102", oeth);
await woeth.connect(governor).transferToken(oeth.address, oethUnits("2"));
await expect(woeth).to.have.a.balanceOf("100", oeth);
await expect(governor).to.have.a.balanceOf("2", oeth);
await expect(await woeth.totalAssets()).to.equal(oethUnits("100"));
});
it("should not a allow governor to collect more than OETH surplus before rebase", async () => {
await oeth.connect(josh).transfer(woeth.address, oethUnits("2"));
await expect(woeth).to.have.a.balanceOf("102", oeth);
await expect(
woeth.connect(governor).transferToken(oeth.address, oethUnits("3"))
).to.be.revertedWith("Can only collect surplus");
});
it("should not a allow governor to collect more than OETH surplus after rebase", async () => {
await oeth.connect(josh).transfer(woeth.address, oethUnits("2"));
await expect(woeth).to.have.a.balanceOf("102", oeth);

// OETH rebase to increase the worth of WOETH by x2.
const oethSupply = await oeth.totalSupply();
await hardhatSetBalance(josh.address, (oethSupply * 1.1).toString());
await weth.connect(josh).deposit({ value: oethSupply });
await weth.connect(josh).transfer(oethVault.address, oethSupply);
await oethVault.rebase();
await expect(woeth).to.have.a.balanceOf("204", oeth);

// Governor cannot collect more than 4 OETH (2x the original 2 OETH transferred)
await expect(
woeth.connect(governor).transferToken(oeth.address, oethUnits("2"))
).to.be.revertedWith("Cannot collect OETH");
woeth.connect(governor).transferToken(oeth.address, oethUnits("4") + 1)
).to.be.revertedWith("Can only collect surplus");
await woeth.connect(governor).transferToken(oeth.address, oethUnits("4"));
await expect(woeth).to.have.a.balanceOf("200", oeth);
});
it("should not allow a non governor to recover tokens ", async () => {
await expect(
Expand Down
Loading