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

Sdai adapter and substream #102

Open
wants to merge 75 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 69 commits
Commits
Show all changes
75 commits
Select commit Hold shift + click to select a range
53ef2a0
repo setup
mp-web3 Apr 24, 2024
b64b4fd
Initialized tests
mp-web3 May 6, 2024
c51a089
feat: getTokens function
mp-web3 May 7, 2024
25bb3ef
feat: implemented getPoolIds function
mp-web3 May 7, 2024
f31ccc0
feat: implemented getLimits function
mp-web3 May 7, 2024
ee40c1a
feat: implemented checkInputTokens modifier, swap function, sell func…
mp-web3 May 9, 2024
de19314
test and fix: implemented testSwapFuzzDaiForSDai and fixed sell and b…
mp-web3 May 9, 2024
55a2668
test and fix: implemented testSwapFuzzSDaiForDai, fixed sell and buy …
mp-web3 May 9, 2024
d95f31a
feat: implementing getPriceSwapAt function
mp-web3 May 13, 2024
b496753
tests: implemented new tests
mp-web3 May 13, 2024
3057903
tests: ready for review
mp-web3 May 14, 2024
f7e94a6
fix: fixed functions order, entered comments, updated manifest.yaml file
mp-web3 May 14, 2024
956f969
review and fix
mp-web3 May 14, 2024
2ddf310
chore: Removed unused comments
mp-web3 May 15, 2024
6aa6a5b
fix: fixed getPriceAt(buyToken)
mp-web3 May 16, 2024
cd6e75e
fix of fix: deleted getPriceAt(buyToken), only need sellToken for the…
mp-web3 May 16, 2024
79486a9
fix: propeller review fixes
mp-web3 May 17, 2024
8bf2274
feat: Initial Setup
May 22, 2024
1f4fac5
chore: Initial tokens addition
May 27, 2024
28eaf8e
feat: Integrated sDAI substream
May 28, 2024
acee96c
fix: Fixed naming in deposit event
May 30, 2024
7f25064
feat: Updated modules with configurable params
Jun 3, 2024
b68a8a4
feat: Added sdai into cargo files
Jun 3, 2024
16b4311
fix: Fixed CI/CD errors
Jun 5, 2024
9eded50
fix: Fixed balancer error
Jun 5, 2024
9134f73
chore: Updated toml dependencies
Jun 5, 2024
1201499
fix: Fixed CI checks
Jun 25, 2024
6aa9c40
alignment with propeller main
mp-web3 Oct 16, 2024
e700fff
Update forge-std submodule reference to include ds-test
mp-web3 Oct 16, 2024
089a4c8
repo setup
mp-web3 Apr 24, 2024
0bce026
Initialized tests
mp-web3 May 6, 2024
5b0204c
feat: getTokens function
mp-web3 May 7, 2024
3e62843
feat: implemented getPoolIds function
mp-web3 May 7, 2024
c222887
feat: implemented getLimits function
mp-web3 May 7, 2024
7b04a72
feat: implemented checkInputTokens modifier, swap function, sell func…
mp-web3 May 9, 2024
144f7d3
test and fix: implemented testSwapFuzzDaiForSDai and fixed sell and b…
mp-web3 May 9, 2024
c7aaa59
test and fix: implemented testSwapFuzzSDaiForDai, fixed sell and buy …
mp-web3 May 9, 2024
6dc5eae
feat: implementing getPriceSwapAt function
mp-web3 May 13, 2024
d70ce84
tests: implemented new tests
mp-web3 May 13, 2024
5499156
tests: ready for review
mp-web3 May 14, 2024
a84cf6e
fix: fixed functions order, entered comments, updated manifest.yaml file
mp-web3 May 14, 2024
1edf12e
review and fix
mp-web3 May 14, 2024
3bd4584
chore: Removed unused comments
mp-web3 May 15, 2024
37eca48
fix: fixed getPriceAt(buyToken)
mp-web3 May 16, 2024
bdb8368
fix of fix: deleted getPriceAt(buyToken), only need sellToken for the…
mp-web3 May 16, 2024
cb21eb0
fix: propeller review fixes
mp-web3 May 17, 2024
2e49ad9
rebased propeller/main
mp-web3 Oct 16, 2024
d519a4e
Merge propeller/main into origin/main to include the latest updates
mp-web3 Oct 17, 2024
33abc5f
align with propeller main
mp-web3 Oct 23, 2024
c1e8c5f
Merge remote-tracking branch 'origin/main' into feature/MakerDAO-sDAI…
mp-web3 Oct 23, 2024
1db1509
mod
mp-web3 Oct 23, 2024
6bdee6a
aligned
mp-web3 Oct 23, 2024
92fb797
integration: integrated with adapter sdk
mp-web3 Oct 23, 2024
fec555c
Merge branch 'main' into sdai-adapter-sdk-integration
mp-web3 Oct 25, 2024
8edc192
Merge branch 'main' into feature/sdai-substream
mp-web3 Oct 25, 2024
ebf51fa
deleted cargo.lock because of conflicts
mp-web3 Oct 25, 2024
7d8ab1c
Merge pull request #3 from ShadowyCreators/sdai-adapter-sdk-integration
mp-web3 Oct 25, 2024
76755eb
commented testPoolBehaviourSDAI() because the test is currently broke…
mp-web3 Oct 25, 2024
be3ab7f
starting sdk integration
mp-web3 Oct 25, 2024
67a3d84
fix: fixed map_components
mp-web3 Oct 25, 2024
048a846
fix: sdai substream
mp-web3 Oct 28, 2024
d0caec1
update substream.yaml and creation integration_test
mp-web3 Oct 28, 2024
c7048ac
cargo.toml and rust-toolchain.toml update
mp-web3 Oct 28, 2024
b9d25f3
chore: working on integration test
mp-web3 Oct 28, 2024
0ec28ec
change stop_block
mp-web3 Oct 28, 2024
628cd92
clean up
mp-web3 Oct 29, 2024
629ca7d
fix component vault creation !call.call.state_reverted && is_deployme…
mp-web3 Oct 29, 2024
3880c6e
fixed map_components module as for comments in pull request
mp-web3 Oct 30, 2024
29fb2e1
fix: fix getLimits sDai
mp-web3 Oct 30, 2024
a1784b0
fix: fixed stop block integration test
mp-web3 Oct 30, 2024
b758f64
Merge pull request #4 from ShadowyCreators/sdk-implementation/sdai-ad…
mp-web3 Oct 30, 2024
8a04998
Merge remote-tracking branch 'shadowy/main' into sdai-adapter-and-sub…
mp-web3 Oct 30, 2024
17145cd
forge format
mp-web3 Oct 30, 2024
be7803b
cargo fmt
mp-web3 Oct 30, 2024
a8128bb
nightly build
mp-web3 Oct 30, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,6 @@ tycho-indexer
substreams/my_substream
testing/tycho-client/build/*
testing/tycho-client/*.egg-info

# Substreans
substreams/ethereum-sfrax/
5 changes: 5 additions & 0 deletions evm/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,8 @@ docs/
# Others
.DS_STORE
lcov.info

# lib
lib/

InternalFunctions.sol
37 changes: 37 additions & 0 deletions evm/src/sDai/manifest.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# information about the author helps us reach out in case of issues.
author:
name: shadowycoders.dev
email: [email protected]

# Protocol Constants
constants:
protocol_gas: 30000
# minimum capabilities we can expect, individual pools may extend these
capabilities:
- SellSide
- BuySide
- PriceFunction

# The file containing the adapter contract
contract: sDaiSwapAdapter.sol

# Deployment instances used to generate chain specific bytecode.
instances:
- chain:
name: mainnet
id: 1
arguments:
- "0x83F20F44975D03b1b09e64809B757c47f942BEeA"
- "0x6B175474E89094C44Da98b954EedeAC495271d0F"

# Specify some automatic test cases in case getPoolIds and
# getTokens are not implemented.
tests:
instances:
- pool_id: "0x83F20F44975D03b1b09e64809B757c47f942BEeA"
sell_token: "0x6B175474E89094C44Da98b954EedeAC495271d0F"
buy_token: "0x83F20F44975D03b1b09e64809B757c47f942BEeA"
block: 19866715
chain:
id: 1
name: mainnet
236 changes: 236 additions & 0 deletions evm/src/sDai/sDaiSwapAdapter.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,236 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
pragma solidity ^0.8.13;

import {ISwapAdapter} from "src/interfaces/ISwapAdapter.sol";
import {IERC20Metadata} from "openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol";
import {IERC20, SafeERC20} from "openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol";

/// @title sDaiSwapAdapter

contract sDaiSwapAdapter is ISwapAdapter {
using SafeERC20 for IERC20;
using SafeERC20 for ISavingsDai;

uint256 constant PRECISE_UNIT = 10 ** 18;

ISavingsDai immutable savingsDai;
IERC20 immutable dai;

constructor(address savingsDai_, address dai_) {
savingsDai = ISavingsDai(savingsDai_);
dai = IERC20(dai_);
}

/// @dev Check if swap between provided sellToken and buyToken are supported
/// by this adapter
modifier checkInputTokens(address sellToken, address buyToken) {
if (
(sellToken == address(dai) && buyToken == address(savingsDai)) ||
(sellToken == address(savingsDai) && buyToken == address(dai))
) {} else {
revert Unavailable("This pool only supports DAI<->sDAI swaps");
}

_;
}

/// @inheritdoc ISwapAdapter
/// @notice price doesn't change in the same block after swap for any given quantity
function price(
bytes32,
address sellToken,
address buyToken,
uint256[] memory specifiedAmounts
)
external
view
override
checkInputTokens(sellToken, buyToken)
returns (Fraction[] memory prices)
{
prices = new Fraction[](specifiedAmounts.length);

Fraction memory outputPrice = getPriceAt(sellToken);

for (uint256 i = 0; i < specifiedAmounts.length; i++) {
prices[i] = outputPrice;
}
}

/// @inheritdoc ISwapAdapter
function swap(
bytes32,
address sellToken,
address buyToken,
OrderSide side,
uint256 specifiedAmount
)
external
override
checkInputTokens(sellToken, buyToken)
returns (Trade memory trade)
{
if (specifiedAmount == 0) {
return trade;
}
uint256 gasBefore = gasleft();
if (side == OrderSide.Sell) {
trade.calculatedAmount = sell(IERC20(sellToken), specifiedAmount);
} else {
trade.calculatedAmount = buy(IERC20(buyToken), specifiedAmount);
}

trade.gasUsed = gasBefore - gasleft();

trade.price = getPriceAt(sellToken);
}

/// @inheritdoc ISwapAdapter
function getLimits(
bytes32,
address sellToken,
address
) external view override returns (uint256[] memory limits) {
limits = new uint256[](2);

if (sellToken == address(dai)) {
limits[0] = 3 * (10 ** 24);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you explain this value it seems very arbitrary.

Copy link
Contributor

@domenicodev domenicodev Nov 4, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kayibal It is the DAI total supply value approx., and we need to use static values due to the incompatibility issue between substreams and external calls

Copy link
Contributor

@tvinagre tvinagre Feb 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can overwrite the token's totalSupply so ideally we should track this via attributes
Currently, DAI supply is 1000 times bigger than this number.

limits[1] = limits[0];
} else {
uint256 totalAssets = savingsDai.totalAssets();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kayibal I think this is not possible with the current Simulation module, as we override the tokens, right?
Maybe we can change it to ignore the token overrides when executing functions that are not price and swap - but that would still require us to track this token's storage.

limits[0] = savingsDai.previewWithdraw(totalAssets);
limits[1] = totalAssets;
}
}

/// @inheritdoc ISwapAdapter
function getCapabilities(
bytes32,
address,
address
) external pure override returns (Capability[] memory capabilities) {
capabilities = new Capability[](4);
capabilities[0] = Capability.SellOrder;
capabilities[1] = Capability.BuyOrder;
capabilities[2] = Capability.PriceFunction;
capabilities[3] = Capability.ConstantPrice;
}

/// @inheritdoc ISwapAdapter
function getTokens(
bytes32
) external view override returns (address[] memory tokens) {
tokens = new address[](2);
tokens[0] = address(dai);
tokens[1] = address(savingsDai);
}

/// @inheritdoc ISwapAdapter
function getPoolIds(
uint256,
uint256
) external view override returns (bytes32[] memory ids) {
ids = new bytes32[](1);
ids[0] = bytes20(address(savingsDai));
}

/// @notice Executes a sell order on the contract.
/// @param sellToken The token being sold.
/// @param amount The amount to be traded.
/// @return calculatedAmount The amount of tokens received.
function sell(
IERC20 sellToken,
uint256 amount
) internal returns (uint256 calculatedAmount) {
sellToken.safeTransferFrom(msg.sender, address(this), amount);

if (address(sellToken) == address(dai)) {
sellToken.safeIncreaseAllowance(address(savingsDai), amount);
}

return
address(sellToken) == address(dai)
? savingsDai.deposit(amount, msg.sender)
: savingsDai.redeem(amount, msg.sender, address(this));
}

/// @notice Executes a buy order on the contract.
/// @param buyToken The token being bought.
/// @param amount The amount of buyToken to receive.
/// @return calculatedAmount The amount of sellToken sold.
function buy(
IERC20 buyToken,
uint256 amount
) internal returns (uint256 calculatedAmount) {
if (address(buyToken) == address(savingsDai)) {
// DAI-sDAI
uint256 amountIn = savingsDai.previewMint(amount);
dai.safeTransferFrom(msg.sender, address(this), amountIn);
dai.safeIncreaseAllowance(address(savingsDai), amountIn);
return savingsDai.mint(amount, msg.sender);
} else {
// sDAI-DAI
uint256 amountIn = savingsDai.previewWithdraw(amount);
savingsDai.safeTransferFrom(msg.sender, address(this), amountIn);
return savingsDai.withdraw(amount, msg.sender, address(this));
}
}

/// @notice Get swap price
/// @param sellToken token to sell
function getPriceAt(
address sellToken
) internal view returns (Fraction memory) {
if (sellToken == address(dai)) {
return
Fraction(savingsDai.previewDeposit(PRECISE_UNIT), PRECISE_UNIT);
} else {
return
Fraction(savingsDai.previewRedeem(PRECISE_UNIT), PRECISE_UNIT);
}
}
}

interface ISavingsDai is IERC20 {
function asset() external view returns (address);

function decimals() external view returns (uint8);

function maxMint(address) external pure returns (uint256);

function maxRedeem(address) external view returns (uint256);

function previewMint(uint256 shares) external view returns (uint256);

function previewWithdraw(uint256 assets) external view returns (uint256);

function previewDeposit(uint256 assets) external view returns (uint256);

function previewRedeem(uint256 shares) external view returns (uint256);

function totalAssets() external view returns (uint256);

function totalSupply() external pure returns (uint256);

function deposit(
uint256 assets,
address receiver
) external returns (uint256 shares);

function mint(
uint256 shares,
address receiver
) external returns (uint256 assets);

function withdraw(
uint256 assets,
address receiver,
address owner
) external returns (uint256 shares);

function redeem(
uint256 shares,
address receiver,
address owner
) external returns (uint256 assets);
}
Loading