Skip to content

Commit

Permalink
Merge branch 'develop' into feat/config-5-phase-2
Browse files Browse the repository at this point in the history
  • Loading branch information
fxp3 authored Apr 22, 2024
2 parents 199b748 + 49fe36d commit 40dbaf6
Show file tree
Hide file tree
Showing 25 changed files with 841 additions and 613 deletions.
4 changes: 2 additions & 2 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@
},
"editor.formatOnSave": true,
"solidity.linter.type": "solhint",
"solidity.test.executeOnSave": true,
"solidity.compiler.version.remote": "v0.8.23+commit.f704f362",
"solidity.test.executeOnSave": false,
"solidity.compiler.version.remote": "v0.8.25+commit.b61c2a91",
"solidity.compiler.outDir": "build/vsc",
"solidity.compiler.location": "Extension",
"solidity.project.monorepo": false,
Expand Down
2 changes: 1 addition & 1 deletion foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ solc = '0.8.23'
evm_version = 'paris'
via_ir = false
optimizer = true
optimizer_runs = 1000
optimizer_runs = 10000
remappings = [
'@openzeppelin/=lib/kresko-foundry-helpers/lib/openzeppelin-contracts/',
'@oz-upgradeable/=lib/kresko-foundry-helpers/lib/openzeppelin-contracts-upgradeable/contracts/',
Expand Down
17 changes: 14 additions & 3 deletions justfile
Original file line number Diff line number Diff line change
Expand Up @@ -172,11 +172,11 @@ verify-proxy-contract:
--constructor-args "0x"

verify-contract:
forge verify-contract 0x \
DataV1 \
forge verify-contract 0xC35A7648B434f0A161c12BD144866bdf93c4a4FC \
KrMulticall \
--chain arbitrum \
--watch \
--constructor-args "0x"
--constructor-args "0x0000000000000000000000000000000000177abd99485dcaea3efaa91db3fe720000000000000000000000006a1d6d2f4af6915e6bba8f2db46f442d18db5c9b00000000000000000000000068b3465833fb72a70ecdf485e0e4c7bd8665fc4500000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab1000000000000000000000000ff1a0f4744e8582df1ae09d5611b887b6a12925c000000000000000000000000266489bde85ff0dfe1ebf9f0a7e6fed3a973cec3"


set positional-arguments
Expand All @@ -198,6 +198,17 @@ set positional-arguments
bun utils/ffi.ts deleteBatch $1 && \
echo "-> Deleted $1"

@frun script func:
forge script $1 --sig "$2()" --ffi -vvv && \
echo "-> $1.$2() ran successfully"

@fbcast script func:
forge script $1 --sig "$2()" --ffi --broadcast --skip-simulation -vvv && \
echo "-> $1.$2() ran successfully"

@ftest func:
forge test --mt ".*$1.*" --ffi -vvv && \
echo "-> $1.$2() ran successfully"


@setup:
Expand Down
2 changes: 1 addition & 1 deletion lib/forge-std
2 changes: 1 addition & 1 deletion lib/kresko-foundry-helpers
4 changes: 2 additions & 2 deletions out/foundry/deploy/42161/arbitrum-latest.json

Large diffs are not rendered by default.

14 changes: 13 additions & 1 deletion out/foundry/deploy/42161/krSOL-latest.json
Original file line number Diff line number Diff line change
@@ -1 +1,13 @@
{"akrSOL":{"address":"0x362cB60d235Cf8258042DAfB2a3Cdb14302D9D0f","ctor":"0x00000000000000000000000096084d2e3389b85f2dc89e321aaa3692aed05ed2","implementation":"0xb153bFeb5b7E40de4a7056E04c24113142B9327a","initializer":"0x000000000000000000000000b153bfeb5b7e40de4a7056e04c24113142b9327a000000000000000000000000000000000070ab95211e32fda3b706589d3482d500000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000104613d25bb00000000000000000000000096084d2e3389b85f2dc89e321aaa3692aed05ed2000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000266489bde85ff0dfe1ebf9f0a7e6fed3a973cec3000000000000000000000000000000000000000000000000000000000000001b4b7265736b6f20417373657420416e63686f723a20536f6c616e6100000000000000000000000000000000000000000000000000000000000000000000000006616b72534f4c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"},"krSOL":{"address":"0x96084d2E3389B85f2Dc89E321Aaa3692Aed05eD2","implementation":"0x77Bd7E52F2445FcFc8F2700Db8d122f33896F14e","initializer":"0x00000000000000000000000077bd7e52f2445fcfc8f2700db8d122f33896f14e000000000000000000000000000000000070ab95211e32fda3b706589d3482d5000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000001a471206626000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000001600000000000000000000000000000000000000000000000000000000000000012000000000000000000000000266489bde85ff0dfe1ebf9f0a7e6fed3a973cec30000000000000000000000000000000000177abd99485dcaea3efaa91db3fe720000000000000000000000000000000000000000000000000000000000000000000000000000000000000000266489bde85ff0dfe1ebf9f0a7e6fed3a973cec300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e4b7265736b6f3a20536f6c616e6100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000056b72534f4c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"}}
{
"akrSOL": {
"address": "0x362cB60d235Cf8258042DAfB2a3Cdb14302D9D0f",
"ctor": "0x00000000000000000000000096084d2e3389b85f2dc89e321aaa3692aed05ed2",
"implementation": "0xb153bFeb5b7E40de4a7056E04c24113142B9327a",
"initializer": "0x000000000000000000000000b153bfeb5b7e40de4a7056e04c24113142b9327a000000000000000000000000000000000070ab95211e32fda3b706589d3482d500000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000104613d25bb00000000000000000000000096084d2e3389b85f2dc89e321aaa3692aed05ed2000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000266489bde85ff0dfe1ebf9f0a7e6fed3a973cec3000000000000000000000000000000000000000000000000000000000000001b4b7265736b6f20417373657420416e63686f723a20536f6c616e6100000000000000000000000000000000000000000000000000000000000000000000000006616b72534f4c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
},
"krSOL": {
"address": "0x96084d2E3389B85f2Dc89E321Aaa3692Aed05eD2",
"implementation": "0x77Bd7E52F2445FcFc8F2700Db8d122f33896F14e",
"initializer": "0x00000000000000000000000077bd7e52f2445fcfc8f2700db8d122f33896f14e000000000000000000000000000000000070ab95211e32fda3b706589d3482d5000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000001a471206626000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000001600000000000000000000000000000000000000000000000000000000000000012000000000000000000000000266489bde85ff0dfe1ebf9f0a7e6fed3a973cec30000000000000000000000000000000000177abd99485dcaea3efaa91db3fe720000000000000000000000000000000000000000000000000000000000000000000000000000000000000000266489bde85ff0dfe1ebf9f0a7e6fed3a973cec300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e4b7265736b6f3a20536f6c616e6100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000056b72534f4c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
}
}
13 changes: 13 additions & 0 deletions src/contracts/core/libs/Arrays.sol
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,19 @@ library Arrays {
return _oracles[0] == Enums.OracleType.Empty && _oracles[1] == Enums.OracleType.Empty;
}

function findIndex(address[] memory _elements, address _elementToFind) internal pure returns (int256 idx) {
for (uint256 i; i < _elements.length; ) {
if (_elements[i] == _elementToFind) {
return int256(i);
}
unchecked {
++i;
}
}

return -1;
}

function find(address[] storage _elements, address _elementToFind) internal pure returns (FindResult memory result) {
address[] memory elements = _elements;
for (uint256 i; i < elements.length; ) {
Expand Down
85 changes: 80 additions & 5 deletions src/contracts/core/periphery/DataV1.sol
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,18 @@ import {WadRay} from "libs/WadRay.sol";
import {IViewDataFacet} from "periphery/interfaces/IViewDataFacet.sol";
import {PythView} from "vendor/pyth/PythScript.sol";
import {ISwapRouter} from "periphery/IKrMulticall.sol";
import {ISCDPSwapFacet} from "scdp/interfaces/ISCDPSwapFacet.sol";
import {IAssetStateFacet} from "common/interfaces/IAssetStateFacet.sol";
import {PercentageMath} from "libs/PercentageMath.sol";
import {IPyth} from "vendor/pyth/IPyth.sol";
import {IBatchFacet} from "common/interfaces/IBatchFacet.sol";
import {IKresko} from "periphery/IKresko.sol";
import {Arrays} from "libs/Arrays.sol";

// solhint-disable avoid-low-level-calls, var-name-mixedcase

contract DataV1 is IDataV1 {
using WadRay for uint256;
using PercentageMath for uint256;
using Arrays for address[];

address public immutable VAULT;
IViewDataFacet public immutable DIAMOND;
Expand All @@ -47,7 +48,7 @@ contract DataV1 is IDataV1 {
address _questForKresk
) {
VAULT = _vault;
DIAMOND = IViewDataFacet(address(_diamond));
DIAMOND = IViewDataFacet(_diamond);
KISS = _KISS;
KRESKIAN_COLLECTION = _kreskian;
QUEST_FOR_KRESK_COLLECTION = _questForKresk;
Expand Down Expand Up @@ -76,11 +77,41 @@ contract DataV1 is IDataV1 {
(withdrawAmount, fee) = IVault(VAULT).previewWithdraw(args.vaultAsset, vaultAssetAmount);
}

function getGlobals(PythView calldata _prices) external view returns (DGlobal memory result) {
function getGlobals(PythView calldata _prices) external view returns (DGlobal memory result, DWrap[] memory wraps) {
result.chainId = block.chainid;
result.protocol = DIAMOND.viewProtocolData(_prices);
result.vault = getVault();
result.collections = getCollectionData(address(1));
wraps = getWraps(result);
}

function getWraps(DGlobal memory _globals) internal view returns (DWrap[] memory result) {
uint256 count;
for (uint256 i; i < _globals.protocol.assets.length; i++) {
View.AssetView memory asset = _globals.protocol.assets[i];
if (asset.config.kFactor > 0 && asset.synthwrap.underlying != address(0)) ++count;
}
result = new DWrap[](count);
count = 0;
for (uint256 i; i < _globals.protocol.assets.length; i++) {
View.AssetView memory asset = _globals.protocol.assets[i];
if (asset.config.kFactor > 0 && asset.synthwrap.underlying != address(0)) {
uint256 nativeAmount = asset.synthwrap.nativeUnderlyingEnabled ? asset.synthwrap.underlying.balance : 0;
uint256 amount = IERC20(asset.synthwrap.underlying).balanceOf(asset.addr);
result[count] = DWrap({
addr: asset.addr,
underlying: asset.synthwrap.underlying,
symbol: asset.symbol,
price: asset.price,
decimals: asset.config.decimals,
val: toWad(amount, asset.synthwrap.underlyingDecimals).wadMul(asset.price),
amount: amount,
nativeAmount: nativeAmount,
nativeVal: nativeAmount.wadMul(asset.price)
});
++count;
}
}
}

function getExternalTokens(
Expand Down Expand Up @@ -134,7 +165,7 @@ contract DataV1 is IDataV1 {

function getAccount(PythView calldata _prices, address _account) external view returns (DAccount memory result) {
result.protocol = DIAMOND.viewAccountData(_prices, _account);

result.protocol.minter.debts = kissFix(_account, _prices);
result.vault.addr = VAULT;
result.vault.name = IERC20(VAULT).name();
result.vault.amount = IERC20(VAULT).balanceOf(_account);
Expand All @@ -148,6 +179,50 @@ contract DataV1 is IDataV1 {
result.chainId = block.chainid;
}

function kissFix(address _account, PythView calldata _prices) internal view returns (View.Position[] memory result) {
IKresko kr = IKresko(address(DIAMOND));

View.AssetView[] memory assets = DIAMOND.viewProtocolData(_prices).assets;
address[] memory mintedAssets = kr.getAccountMintedAssets(_account);

View.Position[] memory found = new View.Position[](assets.length);
uint256 count;
for (uint256 i; i < assets.length; i++) {
View.AssetView memory asset = assets[i];
if (asset.config.isMinterMintable) {
found[i] = _getMinterPos(_account, asset, kr, mintedAssets);
++count;
}
}

result = new View.Position[](count);
for (uint256 j; j < found.length; j++) {
if (found[j].addr != address(0)) result[--count] = found[j];
}
}

function _getMinterPos(
address _account,
View.AssetView memory _asset,
IKresko _kr,
address[] memory _mintedAssets
) internal view returns (View.Position memory) {
uint256 debtAmount = _kr.getAccountDebtAmount(_account, _asset.addr);
uint256 val = debtAmount.wadMul(_asset.price);
return
View.Position({
addr: _asset.addr,
symbol: _asset.symbol,
amount: debtAmount,
amountAdj: 0,
val: val,
valAdj: val.percentMul(_asset.config.kFactor),
index: _mintedAssets.findIndex(_asset.addr),
price: _asset.price,
config: _asset.config
});
}

function getBalances(
PythView calldata _prices,
address _account,
Expand Down
5 changes: 4 additions & 1 deletion src/contracts/core/periphery/IKrMulticall.sol
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,10 @@ interface IKrMulticall {
Native,
PullFromSender,
UseContractBalance,
UseContractBalanceExactAmountIn
UseContractBalanceExactAmountIn,
UseContractBalanceUnwrapNative,
UseContractBalanceWrapNative,
UseContractBalanceNative
}

/**
Expand Down
52 changes: 44 additions & 8 deletions src/contracts/core/periphery/KrMulticall.sol
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {IWETH9} from "kresko-lib/token/IWETH9.sol";
import {ISwapRouter, IKrMulticall} from "periphery/IKrMulticall.sol";
import {IPyth} from "vendor/pyth/IPyth.sol";
import {BurnArgs, MintArgs, SCDPWithdrawArgs, SwapArgs, WithdrawArgs} from "common/Args.sol";
import {fromWad} from "common/funcs/Math.sol";

// solhint-disable avoid-low-level-calls, code-complexity

Expand All @@ -29,6 +30,7 @@ contract KrMulticall is IKrMulticall, Ownable {
IPyth public pythEp;
ISwapRouter public v3Router;
IWETH9 public wNative;
event MulticallExecuted(address _sender, Operation[] ops, Result[] results);

constructor(
address _kresko,
Expand All @@ -47,7 +49,7 @@ contract KrMulticall is IKrMulticall, Ownable {

function rescue(address _token, uint256 _amount, address _receiver) external onlyOwner {
if (_token == address(0)) payable(_receiver).transfer(_amount);
IERC20(_token).transfer(_receiver, _amount);
else IERC20(_token).transfer(_receiver, _amount);
}

function execute(
Expand Down Expand Up @@ -115,9 +117,15 @@ contract KrMulticall is IKrMulticall, Ownable {
results[i].amountOut = balanceAfter - results[i].amountOut;
}
}

if (i > 0 && results[i - 1].amountOut == 0) {
results[i - 1].amountOut = results[i].amountIn;
}
}

_handleFinished(ops);

emit MulticallExecuted(msg.sender, ops, results);
}
}

Expand Down Expand Up @@ -150,6 +158,25 @@ contract KrMulticall is IKrMulticall, Ownable {
if (_op.data.tokensInMode == TokensInMode.UseContractBalance) {
return token.balanceOf(address(this));
}
if (_op.data.tokensInMode == TokensInMode.UseContractBalanceNative) {
return address(this).balance;
}

if (_op.data.tokensInMode == TokensInMode.UseContractBalanceUnwrapNative) {
if (_op.data.tokenIn != address(wNative)) {
revert INVALID_NATIVE_TOKEN_IN(_op.action, _op.data.tokenIn, wNative.symbol());
}
wNative.withdraw(wNative.balanceOf(address(this)));
return address(this).balance;
}

if (_op.data.tokensInMode == TokensInMode.UseContractBalanceWrapNative) {
if (_op.data.tokenIn != address(wNative)) {
revert INVALID_NATIVE_TOKEN_IN(_op.action, _op.data.tokenIn, wNative.symbol());
}
wNative.deposit{value: address(this).balance}();
return wNative.balanceOf(address(this));
}

// Use amountIn for tokens in, eg. MinterRepay allows this.
if (_op.data.tokensInMode == TokensInMode.UseContractBalanceExactAmountIn) return _op.data.amountIn;
Expand All @@ -160,7 +187,7 @@ contract KrMulticall is IKrMulticall, Ownable {
function _handleTokensOut(Operation memory _op, uint256 balance) internal {
if (_op.data.tokensOutMode == TokensOutMode.ReturnToSenderNative) {
wNative.withdraw(balance);
payable(msg.sender).transfer(balance);
payable(msg.sender).transfer(address(this).balance);
return;
}

Expand Down Expand Up @@ -196,7 +223,7 @@ contract KrMulticall is IKrMulticall, Ownable {
}

// Transfer native to sender
if (address(this).balance > 0) payable(msg.sender).transfer(address(this).balance);
if (address(this).balance != 0) payable(msg.sender).transfer(address(this).balance);
}

function _approve(address _token, uint256 _amount, address spender) internal {
Expand Down Expand Up @@ -301,13 +328,22 @@ contract KrMulticall is IKrMulticall, Ownable {
revert NATIVE_SYNTH_WRAP_NOT_ALLOWED(_op.action, _op.data.tokenOut, IKreskoAsset(_op.data.tokenOut).symbol());
}

return address(_op.data.tokenOut).call{value: _op.data.amountIn}("");
uint256 wBal = wNative.balanceOf(address(this));
if (wBal != 0) wNative.withdraw(wBal);

return address(_op.data.tokenOut).call{value: address(this).balance}("");
} else if (_op.action == Action.SynthUnwrap) {
_approve(_op.data.tokenIn, _op.data.amountIn, _op.data.tokenIn);
return _op.data.tokenIn.call(abi.encodeCall(IKreskoAsset.unwrap, (receiver, _op.data.amountIn, false)));
IKreskoAsset krAsset = IKreskoAsset(_op.data.tokenIn);
IKreskoAsset.Wrapping memory info = krAsset.wrappingInfo();
return
_op.data.tokenIn.call(
abi.encodeCall(
IKreskoAsset.unwrap,
(receiver, fromWad(krAsset.balanceOf(address(this)), info.underlyingDecimals), false)
)
);
} else if (_op.action == Action.SynthUnwrapNative) {
_approve(_op.data.tokenIn, _op.data.amountIn, _op.data.tokenIn);
return _op.data.tokenIn.call(abi.encodeCall(IKreskoAsset.unwrap, (receiver, _op.data.amountIn, false)));
return _op.data.tokenIn.call(abi.encodeCall(IKreskoAsset.unwrap, (receiver, _op.data.amountIn, true)));
} else if (_op.action == Action.VaultDeposit) {
_approve(_op.data.tokenIn, _op.data.amountIn, kiss);
return kiss.call(abi.encodeCall(IVaultExtender.vaultDeposit, (_op.data.tokenIn, _op.data.amountIn, receiver)));
Expand Down
Loading

0 comments on commit 40dbaf6

Please sign in to comment.