-
Notifications
You must be signed in to change notification settings - Fork 20
wip: buy with stable/cusd #291
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
base: master
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey - I've found 3 issues, and left some high level feedback:
- In
BuyGDCloneV2.swap, theBoughtevent emitted in the cUSD/stable branch still usesceloas the token address, which will mislead consumers of the event and should be updated to emit the correct token (likelyCUSDorstable). - In
swapCusd,gasCostsare carved out from the contract’sCUSDbalance but the refund is paid instable, which will fail or behave unexpectedly whenstable != CUSD; consider refunding from the same token the gas was reserved in or explicitly ensuring sufficientstablebalance for the refund.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- In `BuyGDCloneV2.swap`, the `Bought` event emitted in the cUSD/stable branch still uses `celo` as the token address, which will mislead consumers of the event and should be updated to emit the correct token (likely `CUSD` or `stable`).
- In `swapCusd`, `gasCosts` are carved out from the contract’s `CUSD` balance but the refund is paid in `stable`, which will fail or behave unexpectedly when `stable != CUSD`; consider refunding from the same token the gas was reserved in or explicitly ensuring sufficient `stable` balance for the refund.
## Individual Comments
### Comment 1
<location> `contracts/utils/BuyGDClone.sol:93-101` </location>
<code_context>
uint256 gasCosts;
+ uint24[] memory fees = new uint24[](1);
+ fees[0] = 100;
if (refundGas != owner) {
- (gasCosts, ) = oracle.quoteAllAvailablePoolsWithTimePeriod(
+ (gasCosts, ) = oracle.quoteSpecificFeeTiersWithTimePeriod(
</code_context>
<issue_to_address>
**issue (bug_risk):** Gas refund is taken from CUSD balance but paid out in `stable`, which can mis-account funds when `stable != CUSD`.
`swapCusd` subtracts `gasCosts` from the CUSD balance (`amountIn = ERC20(CUSD).balanceOf(address(this)) - gasCosts;`) but sends the refund in `stable` (`ERC20(stable).transfer(refundGas, gasCosts)`). When `stable != CUSD`, this reduces CUSD while spending an unreserved amount of `stable`, which can desync balances and underfund future swaps. Consider either refunding in CUSD or charging gas costs from `stable` consistently.
</issue_to_address>
### Comment 2
<location> `contracts/utils/BuyGDClone.sol:72` </location>
<code_context>
return bought;
}
- balance = ERC20(cusd).balanceOf(address(this));
+ balance = ERC20(CUSD).balanceOf(address(this));
if (balance > 0) {
bought = swapCusd(_minAmount, refundGas);
</code_context>
<issue_to_address>
**issue (bug_risk):** `swap` only checks CUSD balance, even though the contract now supports a generic `stable` token.
The second branch still checks `ERC20(CUSD).balanceOf(address(this))` and calls `swapCusd`, so if `stable` is set to a different token and only that token is funded, this path never runs and those funds are never swapped. Either restrict the docstring to CUSD only, or update this branch to work off `stable` (and a corresponding `swapStable`) when `stable != CUSD`.
</issue_to_address>
### Comment 3
<location> `contracts/utils/BuyGDClone.sol:34` </location>
<code_context>
constructor(
ISwapRouter _router,
- address _cusd,
+ address _stable,
address _gd,
</code_context>
<issue_to_address>
**nitpick:** Constructor parameter name `_cusd` in `DonateGDClone` is now misleading since it represents a generic stable token.
The parameter is still named `_cusd` in `DonateGDClone` while it now represents a generic stable token and is passed through to `BuyGDCloneV2`. Please rename it to `_stable` to align with `BuyGDCloneV2` and avoid confusion when deploying with non-cUSD stablecoins.
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
wip: buy with stable/cusd
🚨 Report Summary
For more details view the full report in OpenZeppelin Code Inspector |
… in BuyGDClone tests
…etwork mismatch in BuyGDClone tests
|
@sirpy |
test/utils/BuyGDClone.test.ts
Outdated
| console.log("✓ Factory stable token verified:", factoryStable); | ||
|
|
||
| // Impersonate a whale account to get cUSD | ||
| await ethers.provider.send("hardhat_impersonateAccount", [CUSD_WHALE]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
use ethers.getImpersonatedAccount
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
still not done
test/utils/BuyGDClone.test.ts
Outdated
| console.log("✓ Received amount >= minAmount"); | ||
| }); | ||
|
|
||
| it("Should verify swap path: cUSD -> stable -> G$", async function () { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
there's no swap test here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's not required
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
then it shuold be called "verify swap" if it doesnt swap
| console.log("✓ Clone created successfully at:", cloneAddress); | ||
| }); | ||
|
|
||
| it("Should swap cUSD -> GLOUSD -> G$ via clone", async function () { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- add test for celo -> glousd -> G$
- add a test to compare quote from oracle (mintwap) vs actual pool price
- you dont need minamount = 95% in tests, since mintwap is 98%
- add a test with minamount > 98%
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- Hardhat forking tests cannot verify this behavior because the CELO native token relies on the precompiled TRANSFER contract on Celo, and Hardhat’s forked EVM does not support or execute that precompile.
- added
- fixed it to use mintwap as minAmount
- added
…ap methods and error handling
…ds and tests for expected return and error handling
…ional scenarios for expected returns and error handling
…ew methods for expected returns and enhanced error handling in tests
test/utils/BuyGDClone.test.ts
Outdated
| console.log("✓ Factory stable token verified:", factoryStable); | ||
|
|
||
| // Impersonate a whale account to get cUSD | ||
| await ethers.provider.send("hardhat_impersonateAccount", [CUSD_WHALE]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
still not done
|
|
||
| // Min TWAP should be less than or equal to actual (98% buffer) | ||
| // But allow some tolerance for price movement | ||
| expect(minTwap).to.be.lte(actualPrice.mul(105).div(100)); // Allow 5% tolerance |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you need to check both gt/lt to verify it is in an acceptable range, what if it is close to 0?
| const whaleBalance = await cusdToken.balanceOf(whale.address); | ||
|
|
||
| if (whaleBalance.lt(swapAmount)) { | ||
| console.log("⚠ Whale doesn't have enough cUSD, skipping test"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it should throw an error meaning we cant use the whale account
Description
about: #290