-
Notifications
You must be signed in to change notification settings - Fork 23
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
Erc20flash mint #407
base: main
Are you sure you want to change the base?
Erc20flash mint #407
Conversation
✅ Deploy Preview for contracts-stylus canceled.
|
✅ Deploy Preview for contracts-stylus ready!
To edit notification comments on pull requests, go to your Netlify site configuration. |
This is my initial draft |
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.
Hi @Ifechukwudaniel!
Thanks for the contribution!
The PR overall looks good, let's polish it a bit
contracts/src/flashloan/borrower.rs
Outdated
|
||
use stylus_sdk::stylus_proc::sol_interface; | ||
|
||
sol_interface! { |
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.
@bidzyyys @qalisander @ggonzalez94 on the one hand this should be defined inside contracts/src/token/erc20/extensions/flashmint.rs, similar to how IERC721Receiver
is defined inside contracts/src/token/erc721/mod.rs
But on the other hand, Solidity version treats this trait (interface) as a standalone file within contracts/interfaces, similar to how we've done by placing Erc1155Receiver in the same folder as Erc1155
.
What is the convention we want to use here?
EDIT: actually both examples I linked to (IERC721Receiver and Erc1155Receiver) technically use a similar convention, the difference being the latter's module is just placed in a separate file.
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.
Making a whole file is not necessary and is not the way it has been done in the codebase. Instead, what I did was add it to the utility of ERC-20, as it is isolated to ERC-20
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.
To follow the existing convention, place IERC3156FlashBorrower
inside contracts/src/token/erc20/extensions/flashmint.rs (see the EDIT in my previous message).
pub fn _flash_fee_receiver(&self) -> Address { | ||
Address::ZERO | ||
} | ||
} |
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.
Missing unit tests
pub fn _flash_fee_receiver(&self) -> Address { | ||
Address::ZERO | ||
} | ||
} |
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.
Missing integration tests
pub fn _flash_fee_receiver(&self) -> Address { | ||
Address::ZERO | ||
} | ||
} |
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.
Update CHANGELOG
pub fn _flash_fee_receiver(&self) -> Address { | ||
Address::ZERO | ||
} | ||
} |
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.
Update antora docs docs/modules/ROOT/pages/erc20.adoc
Co-authored-by: Nenad <[email protected]>
Co-authored-by: Nenad <[email protected]>
chore: fixed tab
Create erc20-flashloan.adoc
chore: fixes
@0xNeshi what do you think about the new implementation for the extension |
cargo build --release --target wasm32-unknown-unknown -Z build-std=std,panic_abort -Z build-std-features=panic_immediate_abort | ||
|
||
export RPC_URL=http://localhost:8547 | ||
|
||
cargo test --features std,e2e --test "*" | ||
cargo test --features std,e2e --test "erc20-flashloan" -- --nocapture |
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.
revert changes to this file
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.
yeah will do that
examples/erc20/src/lib.rs
Outdated
@@ -6,7 +6,10 @@ use alloc::vec::Vec; | |||
use alloy_primitives::{Address, FixedBytes, U256}; | |||
use openzeppelin_stylus::{ | |||
token::erc20::{ | |||
extensions::{capped, Capped, Erc20Metadata, IErc20Burnable}, | |||
extensions::{ | |||
capped, flashmint::IERC3156FlashLender, Capped, Erc20Metadata, |
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.
What purpose does the trait import serve here?
uint256 private _totalSupply; | ||
uint256 private _flash_fee_amount; | ||
address private _flash_fee_receiver_address; | ||
constructor(address flash_fee_receiver_address_, uint256 flash_fee_amount_) { |
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.
Format the contract to make it a bit more readable, you can use Remix to do that
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.1.0/contracts/interfaces/IERC3156FlashBorrower.sol"; | ||
|
||
|
||
contract ERC3156FlashBorrowerMock is IERC3156FlashBorrower { |
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.
Format the contract
|
||
if (data.length > 0) { | ||
// WARNING: This code is for testing purposes only! Do not use. | ||
Address.functionCall(token, data); |
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 you may be missing some imports (Address, IERC20), did you verify the tests pass?
) -> Result<bool, Self::Error>; | ||
} | ||
|
||
/// A Permit error. |
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 wrong docs, please resolve a comment only after it's been fully addressed
|
||
} | ||
|
||
const RETURN_VALUE: B256 = |
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.
Actually, let's make the const clearer by default:
const RETURN_VALUE: [u8; 32] = keccak_const::Keccak256::new()
.update("ERC3156FlashBorrower.onFlashLoan".as_bytes())
.finalize();
@@ -0,0 +1,326 @@ | |||
//! Optional Flashloan extension of the ERC-20 standard. |
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.
Copy/paste docs from the Solidity contract version, and update as appropriate for Stylus (follow the convention set in other contracts)
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.
|
||
sol_storage! { | ||
pub struct Erc20Flashmint { | ||
uint256 _flash_fee_amount; |
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.
Why do you need this contract state?
} | ||
|
||
sol_storage! { | ||
pub struct Erc20Flashmint { |
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 a different (and arguably simpler) approach is warranted for implementing the flash mint contract.
The ERC20FlashMint contract extends ERC20 with 3 new functions, and by the spec, it does not introduce any new state nor override existing ERC20 functions (see Solidity version).
In other words, this means that this contract (extension) should inherit and include all ERC20 functionality, and just add these 3 new functions.
In short, it should be enough to simply implement the IERC3156FlashLender
trait for Erc20
(similar to IErc20Burnable).
- Implement the
IERC3156FlashLender
trait forErc20
. - Copy/paste the logic from the Solidity version linked above.
- Create meaningful unit and integration tests (use Solidity version tests as inspiration).
- Remove redundant code/comments that are spread throughout the PR.
- Update comment docs to follow already set conventions, e.g. use SafeErc20 as inspiration (some may consider comments as overly detailed, but it is better to be clear when building potentially widely used OS code). You can generally copy/paste Solidity contract docs, and update where necessary.
- Add missing ADOC content for the contract, e.g. see Erc20Permit docs.
- Format Solidity code according to conventions set in other contracts.
- Format Rust code and markdown according to GUIDELINES.md.
- (optional) add benchmarks (see ./benches)
What do you think about this?
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 does implement the internal functions _flash_fee and _flash_fee_receiver so they can be overridden and support extensibility, any suggestion of an approach I can use for that
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.
The reason why i went with that current approach is because of those internal functions @0xNeshi
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.
_flash_fee
and _flash_fee_receiver
are not part of the spec (see EIP-3156), so they are not required to exist.
Also, since inheritance is still limited in Stylus, overriding does not work as you might expect in other more object-oriented languages.
In short, _flash_fee
and _flash_fee_receiver
don't make as much sense in Stylus as they do in Solidity.
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.
Thanks for your contribution @Ifechukwudaniel!
I left some comments. Do you want to solve them by yourself or should we handle them?
@@ -0,0 +1,326 @@ | |||
//! Optional Flashloan extension of the ERC-20 standard. |
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 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 believe there should be module erc20::extensions::flashmint
with borrower.rs
file.
examples/erc20-flashmint/src/lib.rs
Outdated
} | ||
} | ||
|
||
impl Erc20FlashMintExample { |
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.
Why do we need additional logic in the example? Is it possible to include this logic in FlashMint Extension code?
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.
for cases where we users would like to implement custom borrower and receiver functions
let Erc20Flashmint::totalSupplyReturn { totalSupply } = | ||
contract.totalSupply().call().await?; | ||
|
||
// let Erc20Flashmint::maxFlashLoanReturn { maxLoan: testMaxLoan } = |
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.
Unused logic, please make it work.
Ok(()) | ||
} | ||
|
||
// #[e2e::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.
Unused test, please make it work.
I can handle them |
Resolves #355
PR Checklist