Skip to content

Commit

Permalink
Merge pull request #5 from Tenderize/nv/uups
Browse files Browse the repository at this point in the history
feat: UUPS upgradeable
  • Loading branch information
kyriediculous authored Mar 29, 2024
2 parents 92d6693 + 5b30988 commit 4419669
Show file tree
Hide file tree
Showing 8 changed files with 125 additions and 4 deletions.
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,6 @@
[submodule "lib/staking"]
path = lib/staking
url = https://github.com/tenderize/staking
[submodule "lib/openzeppelin-contracts-upgradeable"]
path = lib/openzeppelin-contracts-upgradeable
url = https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable
1 change: 1 addition & 0 deletions lib/openzeppelin-contracts-upgradeable
2 changes: 1 addition & 1 deletion script/Add_Liquidity.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ contract Add_Liquidity is Script {

function run() public {
vm.startBroadcast(deployerPrivateKey);
TenderSwap swap = TenderSwap(0x4ec6faD51A1957cAb7E8a62e43f0A0a0c2143d3f);
TenderSwap swap = TenderSwap(0x2C7b29B0d07276bA2DF4abE02E9A38b5693af9c6);
ERC20(underlying).approve(address(swap), 500_000 ether);
swap.deposit(500_000 ether);
console2.log("liabilities", swap.liabilities());
Expand Down
38 changes: 38 additions & 0 deletions script/Stats.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;

import { Script, console2 } from "forge-std/Script.sol";
import { ERC20 } from "solmate/tokens/ERC20.sol";
import { TenderSwap, Config } from "@tenderize/swap/Swap.sol";
import { SD59x18 } from "@prb/math/SD59x18.sol";
import { Tenderizer } from "@tenderize/stake/tenderizer/Tenderizer.sol";
import { StakingXYZ } from "lib/staking/test/helpers/StakingXYZ.sol";

contract Stats is Script {
function run() public {
address tenderswap = vm.envAddress("TENDERSWAP");
TenderSwap swap = TenderSwap(tenderswap);
console2.log(
"staking xyz %s",
StakingXYZ(0xd6d72408586887E37Cf299dbb50181892D3b184e).staked(0xE3350e66D3850B4f4C97b6737E9e8Ff78CFC1b00)
);
console2.log("tenderizer asset %s", Tenderizer(0xE3350e66D3850B4f4C97b6737E9e8Ff78CFC1b00).asset());
console2.log("tenderizer validator %s", Tenderizer(0xE3350e66D3850B4f4C97b6737E9e8Ff78CFC1b00).validator());

console2.log(
"tenderizer bal %s",
Tenderizer(0xE3350e66D3850B4f4C97b6737E9e8Ff78CFC1b00).balanceOf(0xF569CE1f749f073D6B85166141544288b3e24c2B)
);

console2.log("tenderizer supply %s", ERC20(address(0xE3350e66D3850B4f4C97b6737E9e8Ff78CFC1b00)).totalSupply());
ERC20(address(0xE3350e66D3850B4f4C97b6737E9e8Ff78CFC1b00)).approve(tenderswap, 1 ether);
swap.swap(address(0xE3350e66D3850B4f4C97b6737E9e8Ff78CFC1b00), 1 ether, 0);
uint256 liabilities = swap.liabilities();
uint256 liquidity = swap.liquidity();
SD59x18 utilisation = swap.utilisation();

console2.log("liabilities %s", liabilities);
console2.log("liquidity %s", liquidity);
console2.log("utilisation %s", utilisation.unwrap());
}
}
4 changes: 2 additions & 2 deletions src/LPToken.sol
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,10 @@ contract LPToken is ERC20 {
}

function _encodeName(string memory _name) internal pure returns (string memory) {
return string(abi.encodePacked("TenderSwap", " ", _name));
return string.concat("TenderSwap", " ", _name);
}

function _encodeSymbol(string memory _symbol) internal pure returns (string memory) {
return string(abi.encodePacked("tSWAP", " ", _symbol));
return string.concat("tSWAP", " ", _symbol);
}
}
18 changes: 17 additions & 1 deletion src/Swap.sol
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ import { Tenderizer, TenderizerImmutableArgs } from "@tenderize/stake/tenderizer
import { Unlocks } from "@tenderize/stake/unlocks/Unlocks.sol";
import { SafeCastLib } from "solmate/utils/SafeCastLib.sol";

import { OwnableUpgradeable } from "openzeppelin-contracts-upgradeable/access/OwnableUpgradeable.sol";
import { Initializable } from "openzeppelin-contracts-upgradeable/proxy/utils/Initializable.sol";
import { UUPSUpgradeable } from "openzeppelin-contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";

import { Multicall } from "@tenderize/swap/util/Multicall.sol";
import { SelfPermit } from "@tenderize/swap/util/SelfPermit.sol";
import { ERC721Receiver } from "@tenderize/swap/util/ERC721Receiver.sol";
Expand All @@ -29,6 +33,7 @@ import { UnlockQueue } from "@tenderize/swap/UnlockQueue.sol";
pragma solidity >=0.8.19;

// TODO: UUPS upgradeable
// TODO: fix '_utilisation' to use UD60x18

SD59x18 constant BASE_FEE = SD59x18.wrap(0.0005e18);
UD60x18 constant RELAYER_CUT = UD60x18.wrap(0.1e18);
Expand Down Expand Up @@ -80,7 +85,7 @@ abstract contract SwapStorage {
}
}

contract TenderSwap is SwapStorage, Multicall, SelfPermit, ERC721Receiver {
contract TenderSwap is Initializable, UUPSUpgradeable, OwnableUpgradeable, SwapStorage, Multicall, SelfPermit, ERC721Receiver {
using SafeTransferLib for ERC20;
using SafeCastLib for uint256;
using UnlockQueue for UnlockQueue.Data;
Expand All @@ -104,11 +109,18 @@ contract TenderSwap is SwapStorage, Multicall, SelfPermit, ERC721Receiver {
address private immutable registry;
address private immutable unlocks;

function intialize() public initializer {
__Ownable_init();
__UUPSUpgradeable_init();
}

/// @custom:oz-upgrades-unsafe-allow constructor
constructor(Config memory config) {
lpToken = new LPToken(config.underlying.name(), config.underlying.symbol());
underlying = config.underlying;
registry = config.registry;
unlocks = config.unlocks;
_disableInitializers();
}

modifier supplyUpdateHook(address asset) {
Expand Down Expand Up @@ -545,6 +557,10 @@ contract TenderSwap is SwapStorage, Multicall, SelfPermit, ERC721Receiver {

return amount * supply / $.liabilities;
}

///@dev required by the OZ UUPS module
// solhint-disable-next-line no-empty-blocks
function _authorizeUpgrade(address) internal override onlyOwner { }
}

function _encodeTokenId(address tenderizer, uint96 id) pure returns (uint256) {
Expand Down
15 changes: 15 additions & 0 deletions test/z3/quote.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
UNIT = 1e18
BASE_FEE = 0.005


def quote(x, u, U, s, S, L, K):
sumA = ((u + x) * K - U + u) * ((U + x) / L)**K

sumB = (U - u - K * u) * (U / L)**K

nom = (sumA + sumB) * (S + U)
denom = K * (UNIT + K) * (s + u)

fee = BASE_FEE * x + nom / denom
out = x - fee
return (out, fee)
48 changes: 48 additions & 0 deletions test/z3/quote_solver.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
from z3 import Solver, Int, sat
import quote

# Define Z3 variables corresponding to Solidity function inputs and parameters
amount = Int('amount')
L = Int('L') # Liability
U = Int('U') # Example parameter from SwapParams
x = Int('x') # Corresponds to 'amount' in Solidity
K = Int('K') # Some constant from your function
BASE_FEE = Int('BASE_FEE') # Base fee constant
UNIT = Int('1')

# SwapParams in Z3 (simplified)
p_u = Int('p_u')
p_U = Int('p_U')
p_s = Int('p_s')
p_S = Int('p_S')

s = Solver()

# Generate random values (as an example)
# random_amount = random.uniform(0, 1000) # Random value between 0 and 1000
# ... generate other random values as needed

# Add random values as constraints
# s.add(amount == random_amount)

# Define bounds (as an example)
# lower_bound = 10
# upper_bound = 500

# Add constraints for bounds
# s.add(amount >= lower_bound, amount <= upper_bound)

# Simplified representation of the fee calculation logic
# Note: This is highly simplified and should be replaced with the actual logic
(out, fee) = quote.quote(amount, p_u, p_U, p_s, p_S, L, K)

# Define invariants

s.add(out <= amount, fee <= amount, out + fee ==
amount, out <= L - U, amount <= p_s)

# Check if the invariants are satisfiable
if s.check() == sat:
print("Invariants are satisfiable. Function behaves as expected under these conditions.")
else:
print("Invariants are not satisfiable. Function may have an issue or the model may need refinement.")

0 comments on commit 4419669

Please sign in to comment.