diff --git a/README.md b/README.md
index 768ea51e..9a64775a 100644
--- a/README.md
+++ b/README.md
@@ -30,15 +30,27 @@ Read the local [docs](./docs/src/), hosted docs [docs.primitive.xyz](https://doc
| Contract | Canonical cross-chain address |
| -------------------- | -------------------------------------------- |
| Portfolio 1.3.0-beta | `0x82360b9a2076a09ea8abe2b3e11aed89de3a02d1` |
-| Portfolio 1.4.0-beta | `todo` |
+| Portfolio 1.4.0-beta | `n/a` |
+| Portfolio 1.5.0-beta | `0x0000a37Fd680Ab248119b448545eF72C51Bf7530` |
### Deployments by Chain
-| Network | Portfolio 1.3.0-beta | Portfolio v1.4.0-beta |
-| -------- | ----------------------------------------------------------------------------------------------------------------------------- | --------------------- |
-| Ethereum | [0x82360b9a2076a09ea8abe2b3e11aed89de3a02d1](https://etherscan.io/address/0x82360b9a2076a09ea8abe2b3e11aed89de3a02d1 ) | todo |
-| Base | n/a | todo |
-| Sepolia | [0x82360b9a2076a09ea8abe2b3e11aed89de3a02d1](https://sepolia.etherscan.io/address/0x82360b9a2076a09ea8abe2b3e11aed89de3a02d1) | todo |
+| Network | Portfolio 1.3.0-beta | Portfolio v1.4.0-beta | Portfolio v1.5.0-beta |
+| -------- | ----------------------------------------------------------------------------------------------------------------------------- | --------------------- | --------------------------------------------------------------------------------------------------------------------- |
+| Ethereum | [0x82360b9a2076a09ea8abe2b3e11aed89de3a02d1](https://etherscan.io/address/0x82360b9a2076a09ea8abe2b3e11aed89de3a02d1 ) | n/a | [0x0000a37Fd680Ab248119b448545eF72C51Bf7530](https://etherscan.io/address/0x0000a37fd680ab248119b448545ef72c51bf7530) |
+| Base | n/a | n/a | n/a |
+| Sepolia | [0x82360b9a2076a09ea8abe2b3e11aed89de3a02d1](https://sepolia.etherscan.io/address/0x82360b9a2076a09ea8abe2b3e11aed89de3a02d1) | n/a | n/a |
+
+| Network | PortfolioRegistry v1.5.0-beta |
+| -------- | --------------------------------------------------------------------------------------------------------------------- |
+| Ethereum | [0x42776F58b6BC63492E0b7A7a937D1138DF716670](https://etherscan.io/address/0x42776f58b6bc63492e0b7a7a937d1138df716670) |
+
+| Network | PositionRenderer v1.5.0-beta |
+| -------- | --------------------------------------------------------------------------------------------------------------------- |
+| Ethereum | [0xdDA01E1d7684Cc35e6a3A5803736D32d012B8C99](https://etherscan.io/address/0xdDA01E1d7684Cc35e6a3A5803736D32d012B8C99) |
+
+
+
# Security
diff --git a/contracts/Portfolio.sol b/contracts/Portfolio.sol
index 13c298f7..850bf0a7 100644
--- a/contracts/Portfolio.sol
+++ b/contracts/Portfolio.sol
@@ -7,7 +7,6 @@ import "./interfaces/IERC20.sol";
import "./interfaces/IPortfolio.sol";
import "./interfaces/IPortfolioRegistry.sol";
import "./interfaces/IStrategy.sol";
-import "./strategies/NormalStrategy.sol";
import "./PositionRenderer.sol";
/**
@@ -35,11 +34,11 @@ contract Portfolio is ERC1155, IPortfolio {
mstore(0x00, 0x20)
// We load the length of our string (11 bytes, 0x0b in hex) and its
- // actual hex value (0x76312e342e302d62657461) using the offset 0x2b.
+ // actual hex value (0x76312e352e302d62657461) using the offset 0x2b.
// Using this particular offset value will right pad the length at
// the end of the slot and left pad the string at the beginning of
// the next slot, assuring the right ABI format to return a string.
- mstore(0x2b, 0x0b76312e342e302d62657461) // "v1.4.0-beta"
+ mstore(0x2b, 0x0b76312e352e302d62657461) // "v1.5.0-beta"
// Return all the 96 bytes (0x60) of data that was loaded into
// the memory.
@@ -56,9 +55,6 @@ contract Portfolio is ERC1155, IPortfolio {
/// @inheritdoc IPortfolioState
address public immutable REGISTRY;
- /// @inheritdoc IPortfolioState
- address public immutable DEFAULT_STRATEGY;
-
/// @inheritdoc IPortfolioState
address public immutable POSITION_RENDERER;
@@ -206,7 +202,6 @@ contract Portfolio is ERC1155, IPortfolio {
) ERC1155() {
WETH = weth;
REGISTRY = registry;
- DEFAULT_STRATEGY = address(new NormalStrategy(address(this)));
POSITION_RENDERER = positionRenderer;
__account__.settled = true;
}
@@ -729,12 +724,9 @@ contract Portfolio is ERC1155, IPortfolio {
// Increment the pool nonce.
uint32 poolNonce = ++getPoolNonce[pairNonce];
- // Zero address strtaegy is a magic value to use the default strategy.
- strategy = strategy == address(0) ? DEFAULT_STRATEGY : strategy;
-
// Compute the poolId, which is a packed 64-bit integer.
poolId = PoolIdLib.encode(
- strategy != DEFAULT_STRATEGY, // Flips the "altered" flag in the upper 4 bits: "0x10..."
+ false, // Flips the "altered" flag in the upper 4 bits: "0x10..."
controller != address(0), // Flips the "controlled" flag in the lower 4 bits: "0x01..."
pairNonce,
poolNonce
diff --git a/contracts/PositionRenderer.sol b/contracts/PositionRenderer.sol
index ec0e1674..6cf66048 100644
--- a/contracts/PositionRenderer.sol
+++ b/contracts/PositionRenderer.sol
@@ -45,7 +45,6 @@ contract PositionRenderer {
address controller;
address strategy;
uint256 spotPriceWad;
- bool hasDefaultStrategy;
}
struct Config {
@@ -157,9 +156,7 @@ contract PositionRenderer {
priorityFeeBasisPoints: priorityFeeBasisPoints,
controller: controller,
strategy: strategy,
- spotPriceWad: spotPriceWad,
- hasDefaultStrategy: strategy
- == IPortfolio(msg.sender).DEFAULT_STRATEGY()
+ spotPriceWad: spotPriceWad
});
}
@@ -598,9 +595,7 @@ contract PositionRenderer {
'
',
controlledLabel,
" and uses ",
- properties.pool.hasDefaultStrategy
- ? "the default strategy."
- : "a custom strategy.",
+ "a custom strategy.",
"
"
)
);
diff --git a/contracts/interfaces/IPortfolio.sol b/contracts/interfaces/IPortfolio.sol
index 5a34929b..a776e19d 100644
--- a/contracts/interfaces/IPortfolio.sol
+++ b/contracts/interfaces/IPortfolio.sol
@@ -216,9 +216,6 @@ interface IPortfolioState {
/// @notice Contract for rendering position tokens.
function POSITION_RENDERER() external view returns (address);
- /// @notice Default strategy contract used in pool creation.
- function DEFAULT_STRATEGY() external view returns (address);
-
/// @notice Proportion of swap fee allocated to the Registry controller.
function protocolFee() external view returns (uint256);
diff --git a/lib/nugu b/lib/nugu
index 71fbe1e7..4c456d07 160000
--- a/lib/nugu
+++ b/lib/nugu
@@ -1 +1 @@
-Subproject commit 71fbe1e7e1441147886e70425cbb4f6b645ee286
+Subproject commit 4c456d0745a88c7507977574fd5a037d6d5c10e1
diff --git a/package.json b/package.json
index b02b842c..3f921d0c 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
"name": "@primitivexyz/portfolio",
"license": "AGPL-3.0-only",
- "version": "v1.4.0-beta",
+ "version": "v1.5.0-beta",
"description": "Portfolio is an automated market making protocol for implementing custom liquidity distribution strategies at the lowest cost possible. ",
"publishConfig": {
"access": "public"
diff --git a/scripts/Prepare.s.sol b/scripts/Prepare.s.sol
index 1920ee32..f0947c0d 100644
--- a/scripts/Prepare.s.sol
+++ b/scripts/Prepare.s.sol
@@ -35,13 +35,14 @@ import "../contracts/PositionRenderer.sol";
// data that was generated and send the transaction.
// 5. Repeat step 4 for all the data generated by this script (3 in total).
-address constant MULTISIG_WALLET = 0x8cDb0095ceddb092aD592aCE2971e4f364b5E8eE;
+address constant MULTISIG_WALLET = 0xD86872c94484abf03EA8F98ED8E91E9D943781CE;
address constant NUGU_ADDRESS = 0xe50ea0e9849cb17829907Acaf764af8F37d4938E;
-address constant WETH_ADDRESS = 0xB4FBF271143F4FBf7B91A5ded31805e42b2208d6;
+address constant WETH_ADDRESS = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
bytes32 constant REGISTRY_SALT = keccak256("REGISTRY0");
bytes32 constant POSITION_RENDERER_SALT = keccak256("POSITION_RENDERER0");
-bytes32 constant PORTFOLIO_SALT = keccak256("PORTFOLIO0");
+bytes32 constant PORTFOLIO_SALT =
+ bytes32(0x0EB4AB9B29D4F1CFBCDB500D936BCD61BC941EFDBCD3141738F68F972CC15ED4);
contract Deploy is Script {
bytes internal constant PROXY_BYTECODE =
@@ -56,14 +57,13 @@ contract Deploy is Script {
abi.encodePacked(
type(PortfolioRegistry).creationCode,
abi.encode(MULTISIG_WALLET)
- ),
- 0
+ )
)
);
bytes memory positionRendererDeployData = abi.encodeCall(
NuguFactory.deploy,
- (POSITION_RENDERER_SALT, type(PositionRenderer).creationCode, 0)
+ (POSITION_RENDERER_SALT, type(PositionRenderer).creationCode)
);
address predictedRegistryAddress =
@@ -83,8 +83,7 @@ contract Deploy is Script {
predictedRegistryAddress,
predictedPositionRendererAddress
)
- ),
- 0
+ )
)
);
@@ -96,6 +95,8 @@ contract Deploy is Script {
console.log("\nPortfolio deploy data:");
console.logBytes(portfolioDeployData);
+ console.log("\n Portfolio address:");
+ console.log(getDeployed(NUGU_ADDRESS, MULTISIG_WALLET, PORTFOLIO_SALT));
}
function getDeployed(
diff --git a/test/ETHSP.t.sol b/test/ETHSP.t.sol
index 029420a1..cb08c10e 100644
--- a/test/ETHSP.t.sol
+++ b/test/ETHSP.t.sol
@@ -235,10 +235,12 @@ contract ETHSP is Setup {
Configuration memory TRANCHE_A_CONFIG = CONFIG.edit(
"asset", abi.encode(TOKEN_0)
).edit("quote", abi.encode(TOKEN_1));
+ TRANCHE_A_CONFIG.strategy = normalStrategy();
Configuration memory TRANCHE_B_CONFIG = CONFIG.edit(
"asset", abi.encode(TOKEN_2)
).edit("quote", abi.encode(TOKEN_3));
+ TRANCHE_B_CONFIG.strategy = normalStrategy();
// Creates the pools with the configs.
TRANCHE_A_POOL = TRANCHE_A_CONFIG.activate(
address(subject()), NormalConfiguration.validateNormalStrategy
diff --git a/test/Setup.sol b/test/Setup.sol
index c0a850ab..c325935a 100644
--- a/test/Setup.sol
+++ b/test/Setup.sol
@@ -34,6 +34,7 @@ struct SubjectsType {
address weth;
address portfolio;
address positionRenderer;
+ address normalStrategy;
}
// Interfaces
@@ -70,6 +71,9 @@ interface ISetup {
/// @dev Returns the position renderer contract used in the subject.
function positionRenderer() external view returns (address);
+
+ /// @dev Returns the normal strategy address.
+ function normalStrategy() external view returns (address);
}
contract Setup is ISetup, Test, ERC1155TokenReceiver {
@@ -115,13 +119,17 @@ contract Setup is ISetup, Test, ERC1155TokenReceiver {
);
vm.label(_subjects.portfolio, "portfolio");
+ _subjects.normalStrategy =
+ address(new NormalStrategy(_subjects.portfolio));
+ vm.label(_subjects.normalStrategy, "normal-strategy");
+
_ghost_state = GhostType({
actor: address(this),
subject: _subjects.portfolio,
poolId: 0
});
- assertEq(subject().VERSION(), "v1.4.0-beta", "version-not-equal");
+ assertEq(subject().VERSION(), "v1.5.0-beta", "version-not-equal");
}
// ============= Edit Test Environment ============= //
@@ -136,6 +144,7 @@ contract Setup is ISetup, Test, ERC1155TokenReceiver {
(address asset, address quote) = deployDefaultTokenPair();
if (config.asset == address(0)) config.asset = asset;
if (config.quote == address(0)) config.quote = quote;
+ config.strategy = normalStrategy();
// Makes it accessible for debugging via `Setup.global_config()`.
_global_config = config;
@@ -501,5 +510,10 @@ contract Setup is ISetup, Test, ERC1155TokenReceiver {
return _subjects.positionRenderer;
}
+ /// @inheritdoc ISetup
+ function normalStrategy() public view override returns (address) {
+ return _subjects.normalStrategy;
+ }
+
receive() external payable { }
}
diff --git a/test/TestGas.t.sol b/test/TestGas.t.sol
index 77c91c2b..c0bf2e5a 100644
--- a/test/TestGas.t.sol
+++ b/test/TestGas.t.sol
@@ -148,7 +148,7 @@ contract TestGas is Setup {
hundred, // fee
0, // prior fee
address(0), // controller
- subject().DEFAULT_STRATEGY(),
+ normalStrategy(),
testConfig.strategyArgs
)
);
@@ -271,7 +271,7 @@ contract TestGas is Setup {
hundred, // fee
0, // prior fee
address(0), // controller
- address(0), // default strategy
+ normalStrategy(),
testConfig.strategyArgs
)
);
@@ -559,7 +559,7 @@ contract TestGas is Setup {
uint16(100 + 100 / i), // fee
0, // prior fee
controller,
- subject().DEFAULT_STRATEGY(),
+ normalStrategy(),
testConfig.strategyArgs
)
);
@@ -692,7 +692,7 @@ contract TestGas is Setup {
uint16(100), // fee
uint16(10), // prior fee
address(0), // controller
- subject().DEFAULT_STRATEGY(),
+ normalStrategy(),
testConfig.strategyArgs
)
);
diff --git a/test/TestPortfolioAllocate.t.sol b/test/TestPortfolioAllocate.t.sol
index bd94382b..5782d893 100644
--- a/test/TestPortfolioAllocate.t.sol
+++ b/test/TestPortfolioAllocate.t.sol
@@ -37,7 +37,7 @@ contract TestPortfolioAllocate is Setup {
100, // fee
0, // prior fee
address(0), // controller
- subject().DEFAULT_STRATEGY(),
+ normalStrategy(),
testConfig.strategyArgs
)
);
@@ -610,7 +610,7 @@ contract TestPortfolioAllocate is Setup {
30, // fee
0, // priority fee
address(0),
- subject().DEFAULT_STRATEGY(),
+ normalStrategy(),
testConfig.strategyArgs
);
diff --git a/test/TestPortfolioCreatePool.t.sol b/test/TestPortfolioCreatePool.t.sol
index c6dabe02..5b2a9d48 100644
--- a/test/TestPortfolioCreatePool.t.sol
+++ b/test/TestPortfolioCreatePool.t.sol
@@ -61,27 +61,6 @@ contract TestPortfolioCreatePool is Setup {
);
}
- function test_createPool_no_strategy_defaults() public defaultConfig {
- Configuration memory testConfig = configureNormalStrategy();
-
- testConfig.reserveXPerWad++; // Avoid the reserve error
- testConfig.reserveYPerWad++; // Avoid the reserve error
-
- uint64 poolId = subject().createPool(
- 0,
- testConfig.reserveXPerWad,
- testConfig.reserveYPerWad,
- 100, // fee
- 0, // prior fee
- address(0), // controller
- address(0), // strategy
- testConfig.strategyArgs
- );
-
- (,,,,,,, address strategy) = subject().pools(poolId);
- assertEq(strategy, subject().DEFAULT_STRATEGY());
- }
-
function test_revert_createPool_invalid_priority_fee() public {
bytes[] memory data = new bytes[](1);
@@ -101,7 +80,7 @@ contract TestPortfolioCreatePool is Setup {
1, // fee
testConfig.priorityFeeBasisPoints.safeCastTo16(), // prior fee
address(this), // controller
- subject().DEFAULT_STRATEGY(),
+ normalStrategy(),
testConfig.strategyArgs
)
);
@@ -184,7 +163,7 @@ contract TestPortfolioCreatePool is Setup {
100,
1,
address(0),
- subject().DEFAULT_STRATEGY(),
+ normalStrategy(),
abi.encode(
PortfolioConfig(
100,
diff --git a/test/TestPositionRendererUri.t.sol b/test/TestPositionRendererUri.t.sol
index cf3346d7..b79cac18 100644
--- a/test/TestPositionRendererUri.t.sol
+++ b/test/TestPositionRendererUri.t.sol
@@ -31,7 +31,7 @@ contract TestPositionRendererUri is Setup {
}
(bytes memory strategyData, uint256 initialX, uint256 initialY) =
- INormalStrategy(subject().DEFAULT_STRATEGY()).getStrategyData(
+ INormalStrategy(normalStrategy()).getStrategyData(
ctx.strikePriceWad,
1_00, // volatilityBasisPoints
ctx.durationSeconds,
@@ -83,7 +83,7 @@ contract TestPositionRendererUri is Setup {
isPerpetual: false,
priceWad: AssemblyLib.scaleToWad(1666 * 10 ** 6, 6),
controller: address(0),
- strategy: address(0),
+ strategy: normalStrategy(),
prioritySwapFee: 0
});
@@ -102,7 +102,7 @@ contract TestPositionRendererUri is Setup {
isPerpetual: false,
priceWad: AssemblyLib.scaleToWad(1666 * 10 ** 6, 6),
controller: address(this),
- strategy: address(0),
+ strategy: normalStrategy(),
prioritySwapFee: 200
});
@@ -121,7 +121,7 @@ contract TestPositionRendererUri is Setup {
isPerpetual: true,
priceWad: AssemblyLib.scaleToWad(1666 * 10 ** 6, 6),
controller: address(0),
- strategy: address(0),
+ strategy: normalStrategy(),
prioritySwapFee: 0
});
@@ -178,7 +178,7 @@ contract TestPositionRendererUri is Setup {
isPerpetual: false,
priceWad: AssemblyLib.scaleToWad(1666 * 10 ** 6, 6),
controller: address(0),
- strategy: address(0),
+ strategy: normalStrategy(),
prioritySwapFee: 0
});