-
Notifications
You must be signed in to change notification settings - Fork 11
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
erc20<->cosmos coin amount conversion #19
Conversation
} | ||
} | ||
|
||
contract ERC20CosmosCoinAmountConversionTest is 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.
Might be worth using both fuzz and invariants testing here: https://book.getfoundry.sh/forge/advanced-testing
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's absolutely a great Idea! Only wonder, do we want to address this now? or later on? If you guys needs this lib asap to complete your workflows, I can address this in a later on PR and refactor the testing file. My primary goal was to ensure it works properly :)
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.
Let's address this now. We don't require this lib asap since our mock ERC20's size doesn't cause issues. So it is ok to take time to make sure we design and test this properly.
uint256 factor; | ||
// Case ERC20 decimals are bigger than cosmos decimals | ||
if (tokenDecimals > DEFAULT_COSMOS_DECIMALS) { | ||
factor = 10 ** (tokenDecimals - DEFAULT_COSMOS_DECIMALS); |
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.
Are there any scenarios where this can cause any overflows?
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.
Solidity version starting from 0.8 supports built-in underflows and overflows checks for arithmetic operations with automatic reverting. We should be good!
// Case ERC20 decimals < DEFAULT_COSMOS_DECIMALS | ||
// Note we need to amplify the decimals | ||
factor = 10 ** (DEFAULT_COSMOS_DECIMALS - tokenDecimals); | ||
temp_convertedAmount = amount * factor; |
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.
Same here, could there be an overflow 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.
As Above
import { ERC20CosmosCoinAmountConversion } from "../src/utils/ERC20CosmosCoinAmountConversion.sol"; | ||
import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; | ||
|
||
// Discuss - Do we want to move mock contract to a mock folder? |
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 are already some mocks, might make sense to keep mocks separate, yes.
Maybe we can also reuse the ERC20 mocks that exist there to some extent also.
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.
Yes, please move or reuse the other ERC20 mock if possible.
* - Converted Amount: 1000000000000000001 / 10^12 = 1000000 (Cosmos coins). | ||
* - Remainder: 1000000000000000001 % 10^12 = 1 (Wei remaining). | ||
*/ | ||
function testConvertMockERC20TokenAmountToCosmosCoin_1() public view { |
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 might change a bit if you decide upon using the fuzzing framework as many of these tests could be written as a single test, but just a general comment: I personally prefer the test functions to be more clearly named what scenario/sub-scenario they are testing, rather than 1, 2, 3 etc.
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.
Definitely agree. Reasons for this naming are 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.
Yes, please rename the tests. It'd be good to refactor these to use table test pattern if possible. You can see me do this 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.
Does the fuzz tests with fixtures do the same @srdtrk?
https://book.getfoundry.sh/forge/fuzz-testing#fuzz-test-fixtures
assertEq(convertedAmount, expectedAmount, "Conversion mismatch for higher decimals"); | ||
} | ||
|
||
function testConvertCosmosCoinAmountToERC20_LessThanSixDecimals() public { |
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 would be good to try to cover a few more failure scenarios: ideally triggering all the reverts we have if possible :)
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.
Addressed 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 we can add more failure scenarios. But we don't need to hit everything as long as we add a TODO
for this and address it in the future
Co-authored-by: Gjermund Garaba <[email protected]>
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.
Looks amazing @sangier, thanks for the superb work. And don't worry, we have enough time to address the PR reviews since this is not required for e2es to pass or be written.
This PR would be needed to deploy this to a testnet and use WETH.
function _getERC20TokenDecimals(address tokenAddress) internal view returns (uint8) { | ||
// Input validation | ||
// TODO Add custom error? | ||
require(tokenAddress != address(0), "Address cannot be the zero address"); |
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.
Introduce custom errors. For now, we will use reverts but we can change to require in the next version of solidity. Do this for all require please
require(tokenAddress != address(0), "Address cannot be the zero address"); | ||
// TODO Reason about this check - Remember it as a good practice but what real protections give us? | ||
// TODO Add custom error? | ||
require(tokenAddress != address(this), "Address cannot be the contract itself"); |
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.
probably we can remove this for now
// Note if we want to allow different cosmos decimals, we need to handle that here too | ||
// Note that tokenAddress input validations are executed in the _getERC20TokenDecimals function | ||
uint8 tokenDecimals = _getERC20TokenDecimals(tokenAddress); | ||
// TODO write an ADR for 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.
Repo is not mature enough for ADRs yet. So we can remove this.
import { ERC20CosmosCoinAmountConversion } from "../src/utils/ERC20CosmosCoinAmountConversion.sol"; | ||
import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; | ||
|
||
// Discuss - Do we want to move mock contract to a mock folder? |
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.
Yes, please move or reuse the other ERC20 mock if possible.
} | ||
} | ||
|
||
contract ERC20CosmosCoinAmountConversionTest is 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.
Let's address this now. We don't require this lib asap since our mock ERC20's size doesn't cause issues. So it is ok to take time to make sure we design and test this properly.
* - Converted Amount: 1000000000000000001 / 10^12 = 1000000 (Cosmos coins). | ||
* - Remainder: 1000000000000000001 % 10^12 = 1 (Wei remaining). | ||
*/ | ||
function testConvertMockERC20TokenAmountToCosmosCoin_1() public view { |
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.
Yes, please rename the tests. It'd be good to refactor these to use table test pattern if possible. You can see me do this here.
assertEq(convertedAmount, expectedAmount, "Conversion mismatch for higher decimals"); | ||
} | ||
|
||
function testConvertCosmosCoinAmountToERC20_LessThanSixDecimals() public { |
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 we can add more failure scenarios. But we don't need to hit everything as long as we add a TODO
for this and address it in the future
src/errors/IIErrors.sol
Outdated
// SPDX-License-Identifier: MIT | ||
pragma solidity >=0.8.25; | ||
|
||
interface IIErrors { |
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.
Created this file to manage errors that are common for all the contracts. Is the name ok or shall we call it IICommonErrors?
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 don't know if we need this yet, I'd prefer not to have it yet. So maybe just use errors specific to your library
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.
Looks good. Please address my comments, and then we can merge this
test/sdkCoinTest.t.sol
Outdated
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.
Rename this file to use capital letters SdkCoinTest.t.sol
import { SafeCast } from "@openzeppelin/contracts/utils/math/SafeCast.sol"; | ||
import { IISdkCoinErrors } from "../errors/IISdkCoinErrors.sol"; | ||
|
||
library SdkCoin { |
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.
library SdkCoin { | |
library SdkCoin is IISdkCoinErrors { |
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.
Co-authored-by: srdtrk <[email protected]>
Implements a library for the conversion of ERC20 amounts to cosmos coin amounts.
closes #5