From 5260c9a959b8146d585caf9473c024da6661f498 Mon Sep 17 00:00:00 2001 From: Philippe Dumonet Date: Wed, 14 Feb 2024 19:08:08 +0000 Subject: [PATCH 1/4] =?UTF-8?q?=F0=9F=90=9B=20Update=20allowance=20target?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/AfEthRelayer.sol | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/AfEthRelayer.sol b/src/AfEthRelayer.sol index 3ea6ef1..fb8fb81 100644 --- a/src/AfEthRelayer.sol +++ b/src/AfEthRelayer.sol @@ -17,7 +17,6 @@ contract AfEthRelayer is Initializable { address internal immutable THIS_ = address(this); address internal constant ZERO_X_EXCHANGE = 0xDef1C0ded9bec7F1a1670819833240f027b25EfF; - address internal constant ZERO_X_ERC20_PROXY = 0x95E6F48254609A6ee006F7D493c8e5fB97094ceF; struct SwapParams { address sellToken; @@ -82,7 +81,7 @@ contract AfEthRelayer is Initializable { * allows for an optional nested call to an actual deposit transaction. */ function enableNewSellToken(address sellToken, bytes calldata innerCall) external payable { - sellToken.safeApproveWithRetry(ZERO_X_ERC20_PROXY, type(uint256).max); + sellToken.safeApproveWithRetry(ZERO_X_EXCHANGE, type(uint256).max); if (innerCall.length > 0) { // Delegate to `THIS_` (implementation address) to avoid proxy overhead, functionally // equivalent to calling address(this). From d3cd5560f3078a0eec93dacf071f64f58b6c0ea3 Mon Sep 17 00:00:00 2001 From: Philippe Dumonet Date: Mon, 19 Feb 2024 02:43:48 +0000 Subject: [PATCH 2/4] =?UTF-8?q?=E2=9C=A8=20Use=20verifiable=20proxy?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- script/DeployMainnet.s.sol | 31 +++++++++++++----------- src/AfEth.sol | 9 ++++++- src/interfaces/IProxySource.sol | 7 ++++++ src/strategies/VotiumStrategy.sol | 10 ++++++-- src/utils/SimpleProxy.sol | 19 +++++++++++++++ src/utils/SimpleProxyFactory.sol | 39 +++++++++++++++++++++++++++++++ test/AfEth.t.sol | 30 ++++++++++++++++++++++++ test/mocks/MockUpgrade.huff | 20 ++++++++++++++++ test/utils/BaseTest.sol | 18 ++++++++------ 9 files changed, 160 insertions(+), 23 deletions(-) create mode 100644 src/interfaces/IProxySource.sol create mode 100644 src/utils/SimpleProxy.sol create mode 100644 src/utils/SimpleProxyFactory.sol create mode 100644 test/mocks/MockUpgrade.huff diff --git a/script/DeployMainnet.s.sol b/script/DeployMainnet.s.sol index dc06bd6..a64e5a0 100644 --- a/script/DeployMainnet.s.sol +++ b/script/DeployMainnet.s.sol @@ -4,28 +4,36 @@ pragma solidity 0.8.20; import {Script} from "forge-std/Script.sol"; import {Test} from "forge-std/Test.sol"; import {console2 as console} from "forge-std/console2.sol"; -import {ERC1967FactoryConstants} from "solady/src/utils/ERC1967FactoryConstants.sol"; -import {ERC1967Factory} from "solady/src/utils/ERC1967Factory.sol"; +import {SimpleProxyFactory} from "../src/utils/SimpleProxyFactory.sol"; import {VotiumStrategy} from "../src/strategies/VotiumStrategy.sol"; import {AfEth} from "../src/AfEth.sol"; import {console2 as console} from "forge-std/console2.sol"; /// @author philogy contract DeployMainnetScript is Test, Script { - bytes32 internal constant AF_ETH_VANITY_SALT = 0x67b80ff33e5937b58b2a46870a912cb11d231efbec654a8355b46947ec1a0010; - bytes32 internal constant VOTIUM_VANITY_SALT = 0x67b80ff33e5937b58b2a46870a912cb11d231efbf13066ae7fad3ff30a060010; + bytes32 internal constant AF_ETH_VANITY_SALT = 0x67b80ff33e5937b58b2a46870a912cb11d231efb29d74144d35ec0000fcd3cd6; + bytes32 internal constant VOTIUM_VANITY_SALT = 0x67b80ff33e5937b58b2a46870a912cb11d231efb29d74144d35e200008cc162e; function run() public { - ERC1967Factory factory = ERC1967Factory(ERC1967FactoryConstants.ADDRESS); - address OWNER = 0x263b03BbA0BbbC320928B6026f5eAAFAD9F1ddeb; address REWARDER = 0xa927c81CC214cc991613cB695751Bc932F042501; // TODO: Not the recommended way of loading private key. uint256 pk = vm.envUint("PRIV_KEY"); + address me = vm.addr(pk); vm.startBroadcast(pk); + (bool success, bytes memory addr) = + CREATE2_FACTORY.call(abi.encodePacked(bytes32(0), type(SimpleProxyFactory).creationCode)); + require(success, "failed to deploy factory"); + + SimpleProxyFactory factory = SimpleProxyFactory(address(bytes20(addr))); + + console.log("deployer: %s", me); + console.log("factory: %s", address(factory)); + console.log("proxy inithash: %x", uint256(factory.PROXY_INIT_HASH())); + address votiumImplementation; address afEthImplementation; { @@ -35,15 +43,12 @@ contract DeployMainnetScript is Test, Script { votiumImplementation = address(new VotiumStrategy(afEthProxyAddr)); afEthImplementation = address(new AfEth(votiumProxyAddr)); } - address votium = factory.deployDeterministicAndCall( - votiumImplementation, - OWNER, - VOTIUM_VANITY_SALT, - abi.encodeCall(VotiumStrategy.initialize, (OWNER, REWARDER)) + address votium = factory.deployDeterministic( + VOTIUM_VANITY_SALT, votiumImplementation, abi.encodeCall(VotiumStrategy.initialize, (OWNER, REWARDER)) ); - address afEth = factory.deployDeterministicAndCall{value: 1 gwei}( - afEthImplementation, OWNER, AF_ETH_VANITY_SALT, abi.encodeCall(AfEth.initialize, (OWNER, REWARDER)) + address afEth = factory.deployDeterministic{value: 1 gwei}( + AF_ETH_VANITY_SALT, afEthImplementation, abi.encodeCall(AfEth.initialize, (OWNER, REWARDER)) ); console.log("afEth successfuly deployed at %s", afEth); diff --git a/src/AfEth.sol b/src/AfEth.sol index b24745b..ae78131 100644 --- a/src/AfEth.sol +++ b/src/AfEth.sol @@ -3,6 +3,7 @@ pragma solidity 0.8.20; import {ERC20PermitUpgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20PermitUpgradeable.sol"; +import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; import {IAfEth} from "./interfaces/afeth/IAfEth.sol"; import {Ownable} from "solady/src/auth/Ownable.sol"; import {FixedPointMathLib} from "solady/src/utils/FixedPointMathLib.sol"; @@ -12,7 +13,7 @@ import {IVotiumStrategy} from "./interfaces/afeth/IVotiumStrategy.sol"; import {SfrxEthStrategy} from "./strategies/SfrxEthStrategy.sol"; /// @dev AfEth is the strategy manager for the sfrxETH and votium strategies -contract AfEth is IAfEth, Ownable, ERC20PermitUpgradeable { +contract AfEth is IAfEth, Ownable, ERC20PermitUpgradeable, UUPSUpgradeable { using FixedPointMathLib for uint256; using SafeTransferLib for address; using SafeCastLib for uint256; @@ -64,6 +65,7 @@ contract AfEth is IAfEth, Ownable, ERC20PermitUpgradeable { string memory name_ = "Asymmetry Finance afETH"; __ERC20_init(name_, "afETH"); __ERC20Permit_init(name_); + __UUPSUpgradeable_init(); _initializeOwner(initialOwner); emit SetRewarder(rewarder = initialRewarder); @@ -87,6 +89,11 @@ contract AfEth is IAfEth, Ownable, ERC20PermitUpgradeable { _mint(address(0xdead), recognizedValue); } + /** + * @dev Allows the owner of the contract to upgrade to *any* new address. + */ + function _authorizeUpgrade(address /* newImplementation */ ) internal view override onlyOwner {} + modifier latestAt(uint256 deadline) { if (block.timestamp > deadline) revert StaleAction(); _; diff --git a/src/interfaces/IProxySource.sol b/src/interfaces/IProxySource.sol new file mode 100644 index 0000000..bad68b4 --- /dev/null +++ b/src/interfaces/IProxySource.sol @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.20; + +/// @author philogy +interface IProxySource { + function implementation() external view returns (address); +} diff --git a/src/strategies/VotiumStrategy.sol b/src/strategies/VotiumStrategy.sol index 4a35532..28c6b11 100644 --- a/src/strategies/VotiumStrategy.sol +++ b/src/strategies/VotiumStrategy.sol @@ -2,7 +2,7 @@ pragma solidity 0.8.20; import {Ownable} from "solady/src/auth/Ownable.sol"; -import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; +import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; import {TrackedAllowances, Allowance} from "../utils/TrackedAllowances.sol"; import {FixedPointMathLib} from "solady/src/utils/FixedPointMathLib.sol"; import {SafeTransferLib} from "solady/src/utils/SafeTransferLib.sol"; @@ -22,7 +22,7 @@ import {IAfEth} from "../interfaces/afeth/IAfEth.sol"; /// @title Votium Strategy Token /// @author Asymmetry Finance -contract VotiumStrategy is IVotiumStrategy, Ownable, TrackedAllowances, Initializable { +contract VotiumStrategy is IVotiumStrategy, Ownable, TrackedAllowances, UUPSUpgradeable { using FixedPointMathLib for uint256; using SafeTransferLib for address; using SafeCastLib for uint256; @@ -87,6 +87,7 @@ contract VotiumStrategy is IVotiumStrategy, Ownable, TrackedAllowances, Initiali ISnapshotDelegationRegistry(SNAPSHOT_DELEGATE_REGISTRY).setDelegate(VOTE_DELEGATION_ID, VOTE_PROXY); rewarder = initialRewarder; _initializeOwner(initialOwner); + __UUPSUpgradeable_init(); // Approve once to save gas later by avoiding having to re-approve every time. _grantAndTrackInfiniteAllowance(Allowance({spender: address(LOCKED_CVX), token: CVX})); @@ -95,6 +96,11 @@ contract VotiumStrategy is IVotiumStrategy, Ownable, TrackedAllowances, Initiali emit RewarderSet(initialRewarder); } + /** + * @dev Allows the owner of the contract to upgrade to *any* new address. + */ + function _authorizeUpgrade(address /* newImplementation */ ) internal view override onlyOwner {} + /** * @notice - Function to set the address of the rewarder account that periodically claims rewards * @param newRewarder Address of the rewarder account diff --git a/src/utils/SimpleProxy.sol b/src/utils/SimpleProxy.sol new file mode 100644 index 0000000..d71a6f9 --- /dev/null +++ b/src/utils/SimpleProxy.sol @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.20; + +import {Proxy} from "@openzeppelin/contracts/proxy/Proxy.sol"; +import {ERC1967Utils} from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Utils.sol"; +import {IProxySource} from "../interfaces/IProxySource.sol"; + +/// @author philogy +/// @dev ERC1967 Proxy that has no initcall or implementation factor in its deploy bytecode. +contract SimpleProxy is Proxy { + constructor() { + address implementation = IProxySource(msg.sender).implementation(); + ERC1967Utils.upgradeToAndCall(implementation, new bytes(0)); + } + + function _implementation() internal view override returns (address) { + return ERC1967Utils.getImplementation(); + } +} diff --git a/src/utils/SimpleProxyFactory.sol b/src/utils/SimpleProxyFactory.sol new file mode 100644 index 0000000..09c29a4 --- /dev/null +++ b/src/utils/SimpleProxyFactory.sol @@ -0,0 +1,39 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.20; + +import {IProxySource} from "../interfaces/IProxySource.sol"; +import {SimpleProxy} from "./SimpleProxy.sol"; + +/// @author philogy +contract SimpleProxyFactory is IProxySource { + address internal constant NO_IMPLEMENTATION = address(1); + + bytes32 public immutable PROXY_INIT_HASH = keccak256(type(SimpleProxy).creationCode); + + address public implementation = NO_IMPLEMENTATION; + + error NotSaltOwner(); + error InitCallFailed(); + + function deployDeterministic(bytes32 salt, address initialImplementation, bytes memory initCall) + external + payable + returns (address proxy) + { + address saltOwner = address(bytes20(salt)); + if (saltOwner != address(0) && saltOwner != msg.sender) revert NotSaltOwner(); + implementation = initialImplementation; + proxy = address(new SimpleProxy{salt: salt}()); + implementation = NO_IMPLEMENTATION; + + if (msg.value > 0 || initCall.length > 0) { + (bool success,) = proxy.call{value: msg.value}(initCall); + if (!success) revert InitCallFailed(); + } + } + + function predictDeterministicAddress(bytes32 salt) external view returns (address addr) { + return + address(uint160(uint256(keccak256(abi.encodePacked(bytes1(0xff), address(this), salt, PROXY_INIT_HASH))))); + } +} diff --git a/test/AfEth.t.sol b/test/AfEth.t.sol index ef2488b..dc0a183 100644 --- a/test/AfEth.t.sol +++ b/test/AfEth.t.sol @@ -232,6 +232,36 @@ contract AfEthTest is BaseTest { assertApproxEqRel(ethOut, amount, 0.005e18, "unlocked ETH not equal to amount"); } + function testOwnerCanUpgrade() public { + address newImpl = makeAddr("new_impl"); + vm.etch( + newImpl, + hex"7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc3d52593d3d3560e01c6352d1902d0361003557f35bfd" + ); + + vm.prank(owner); + afEth.upgradeToAndCall(newImpl, new bytes(0)); + + (bool success, bytes memory errorData) = address(afEth).call(hex"01020304"); + assertFalse(success); + assertEq(abi.decode(errorData, (bytes32)), 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc); + } + + function testOnlyOwnerCanUpgrade() public { + address newImpl = makeAddr("new_impl"); + vm.etch( + newImpl, + hex"7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc3d52593d3d3560e01c6352d1902d0361003557f35bfd" + ); + + vm.prank(owner); + afEth.upgradeToAndCall(newImpl, new bytes(0)); + + (bool success, bytes memory errorData) = address(afEth).call(hex"01020304"); + assertFalse(success); + assertEq(abi.decode(errorData, (bytes32)), 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc); + } + function _deposit(string memory label, uint256 amount) internal returns (uint256 amountOut) { hoax(makeAddr(label), amount); amountOut = afEth.deposit{value: amount}(0, block.timestamp); diff --git a/test/mocks/MockUpgrade.huff b/test/mocks/MockUpgrade.huff new file mode 100644 index 0000000..839defd --- /dev/null +++ b/test/mocks/MockUpgrade.huff @@ -0,0 +1,20 @@ +#define constant SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc + +#define function proxiableUUID() view returns (bytes32) + + +#define macro _MAIN(z0) = takes(0) returns(0) { + [SLOT] mstore + + msize + + calldataload 0xe0 shr + __FUNC_SIG(proxiableUUID) sub error jumpi + return + error: + revert +} + +#define macro MAIN() = takes(0) returns(0) { + _MAIN(returndatasize) +} diff --git a/test/utils/BaseTest.sol b/test/utils/BaseTest.sol index 631fcaa..10a2dea 100644 --- a/test/utils/BaseTest.sol +++ b/test/utils/BaseTest.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.0; import {Test} from "forge-std/Test.sol"; -import {ERC1967Factory} from "solady/src/utils/ERC1967Factory.sol"; +import {SimpleProxyFactory} from "../../src/utils/SimpleProxyFactory.sol"; import {VotiumStrategy} from "../../src/strategies/VotiumStrategy.sol"; import {AfEth} from "../../src/AfEth.sol"; import {MockOracle} from "../mocks/MockOracle.sol"; @@ -10,6 +10,9 @@ import {AggregatorV3Interface} from "@chainlink/contracts/src/v0.8/interfaces/Ag /// @author philogy abstract contract BaseTest is Test { + bytes private constant CREATE2_FACTORY_CODE = + hex"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe03601600081602082378035828234f58015156039578182fd5b8082525050506014600cf3"; + uint256 internal constant USE_MAX = 1 << 255; address internal immutable deployer = makeAddr("DEPLOYER"); @@ -17,7 +20,7 @@ abstract contract BaseTest is Test { address internal immutable rewarder = makeAddr("REWARDER"); MockOracle internal immutable baseOracle = new MockOracle(); - ERC1967Factory internal immutable factory = new ERC1967Factory(); + SimpleProxyFactory internal immutable factory = new SimpleProxyFactory(); VotiumStrategy private _votiumImplementation; VotiumStrategy internal votium; @@ -39,21 +42,22 @@ abstract contract BaseTest is Test { startHoax(deployer, 1 ether); votium = VotiumStrategy( payable( - factory.deployDeterministicAndCall( - address(_votiumImplementation), - owner, + factory.deployDeterministic( votiumSalt, + address(_votiumImplementation), abi.encodeCall(VotiumStrategy.initialize, (owner, rewarder)) ) ) ); + assertEq(address(votium), votiumProxyAddr, "predicted wrong votium proxy address"); afEth = AfEth( payable( - factory.deployDeterministicAndCall{value: 1 gwei}( - address(_afEthImplementation), owner, afEthSalt, abi.encodeCall(AfEth.initialize, (owner, rewarder)) + factory.deployDeterministic{value: 1 gwei}( + afEthSalt, address(_afEthImplementation), abi.encodeCall(AfEth.initialize, (owner, rewarder)) ) ) ); + assertEq(address(afEth), afEthProxyAddr, "predicted wrong afETH proxy address"); vm.stopPrank(); } From 98dc426fe54ee82c18366623f6a143cfb92fa621 Mon Sep 17 00:00:00 2001 From: Philippe Dumonet Date: Mon, 19 Feb 2024 03:40:53 +0000 Subject: [PATCH 3/4] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Redeploy=20verifiable?= =?UTF-8?q?=20relay?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 10 +++++----- script/DeployRelay.s.sol | 18 +++++------------- src/AfEthRelayer.sol | 17 +++++++++++++---- 3 files changed, 23 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index 2a5c5dc..4a88276 100644 --- a/README.md +++ b/README.md @@ -8,9 +8,9 @@ technical details on internal works view ["AfEth"](./docs/AfEth.md). |Description|Address + Link| |-----------|--------------| -|The AfEth ERC1967 proxy, deployed using Solady's [ERC1967 Factory](https://etherscan.io/address/0x0000000000006396FF2a80c067f99B3d2Ab4Df24#readContract).| [`0x00000000fbAA96B36A2AcD4B7B36385c426B119D`](https://etherscan.io/address/0x00000000fbAA96B36A2AcD4B7B36385c426B119D)| -|The Votium ERC1967 proxy, also deployed using Solady's [ERC1967 Factory](https://etherscan.io/address/0x0000000000006396FF2a80c067f99B3d2Ab4Df24#readContract)|[`0x000000004c4bb6e0a169FE3A9228cd0F70873CdE`](https://etherscan.io/address/0x000000004c4bb6e0a169FE3A9228cd0F70873CdE)| -|Votium Implementation Contract|[`0xCf687792a1e65bB41793cc938Cf8e27E5D1B678b`](https://etherscan.io/address/0xCf687792a1e65bB41793cc938Cf8e27E5D1B678b)| -|AfEth Implementation Contract|[`0x1a0A62AA8A9471a6a726B5cDc24192Be3a3DBc7B`](https://etherscan.io/address/0x1a0A62AA8A9471a6a726B5cDc24192Be3a3DBc7B)| -|AfEthRelayer, also deployed using Solady's [ERC1967 Factory](https://etherscan.io/address/0x0000000000006396FF2a80c067f99B3d2Ab4Df24#readContract)|[`0x00000000b8791985c4bd2cbc4584cee89c4e95ef`](https://etherscan.io/address/0x00000000b8791985c4bd2cbc4584cee89c4e95ef)| +|The AfEth ERC1967 proxy| [`0x0000000016E6Cb3038203c1129c8B4aEE7af7a11`](https://etherscan.io/address/0x0000000016e6cb3038203c1129c8b4aee7af7a11)| +|The Votium ERC1967 proxy|[`0x00000069aBbB0B1Ad6975bcF753eEe15D318A0BF`](https://etherscan.io/address/0x00000069abbb0b1ad6975bcf753eee15d318a0bf)| +|Votium Implementation Contract|[`0x01e111D815261c8ad6A1271861970E804E4282E4`](https://etherscan.io/address/0x01e111d815261c8ad6a1271861970e804e4282e4)| +|AfEth Implementation Contract|[`0x0A36224486D4E49dEB27b489233c6B64e0241D6A`](https://etherscan.io/address/0x0a36224486d4e49deb27b489233c6b64e0241d6a)| +|AfEthRelayer|[`0x0000005aC28De2cbda005a8500A9578921FDB7da`](https://etherscan.io/address/0x0000005aC28De2cbda005a8500A9578921FDB7da)| diff --git a/script/DeployRelay.s.sol b/script/DeployRelay.s.sol index 92caec5..074f6d6 100644 --- a/script/DeployRelay.s.sol +++ b/script/DeployRelay.s.sol @@ -3,20 +3,16 @@ pragma solidity 0.8.20; import {Script} from "forge-std/Script.sol"; import {Test} from "forge-std/Test.sol"; -import {ERC1967FactoryConstants} from "solady/src/utils/ERC1967FactoryConstants.sol"; -import {ERC1967Factory} from "solady/src/utils/ERC1967Factory.sol"; import {AfEthRelayer} from "../src/AfEthRelayer.sol"; +import {SimpleProxyFactory} from "../src/utils/SimpleProxyFactory.sol"; import {console2 as console} from "forge-std/console2.sol"; /// @author philogy contract DeployRelayScript is Test, Script { - bytes32 internal constant AF_ETH_VANITY_SALT = 0x67b80ff33e5937b58b2a46870a912cb11d231efbec654a8355b46947ec1a0010; - bytes32 internal constant VOTIUM_VANITY_SALT = 0x67b80ff33e5937b58b2a46870a912cb11d231efbf13066ae7fad3ff30a060010; - - bytes32 internal constant RELAY_VANITY_SALT = 0x67b80ff33e5937b58b2a46870a912cb11d231efbbab440b5457a1800089dc6c5; + bytes32 internal constant RELAY_VANITY_SALT = 0x67b80ff33e5937b58b2a46870a912cb11d231efb29d74144d35e2000083bf82a; function run() public { - ERC1967Factory factory = ERC1967Factory(ERC1967FactoryConstants.ADDRESS); + SimpleProxyFactory factory = SimpleProxyFactory(0x51fBA11386fb26Ae017D539624435137a25d7CE9); address OWNER = 0x263b03BbA0BbbC320928B6026f5eAAFAD9F1ddeb; @@ -27,14 +23,10 @@ contract DeployRelayScript is Test, Script { address relayImplementation = address(new AfEthRelayer()); - address relay = factory.deployDeterministicAndCall( - relayImplementation, - OWNER, - RELAY_VANITY_SALT, - abi.encodeCall(AfEthRelayer.initialize, ()) + address relay = factory.deployDeterministic( + RELAY_VANITY_SALT, relayImplementation, abi.encodeCall(AfEthRelayer.initialize, (OWNER)) ); - console.log("relay successfuly deployed at %s", relay); vm.stopBroadcast(); diff --git a/src/AfEthRelayer.sol b/src/AfEthRelayer.sol index fb8fb81..d586e35 100644 --- a/src/AfEthRelayer.sol +++ b/src/AfEthRelayer.sol @@ -1,18 +1,19 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.20; -import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; +import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; +import {Ownable} from "solady/src/auth/Ownable.sol"; import {SafeTransferLib} from "solady/src/utils/SafeTransferLib.sol"; import {IAfEth} from "./interfaces/afeth/IAfEth.sol"; import {ISafEth} from "./interfaces/safeth/ISafEth.sol"; import {IWETH, WETH} from "./interfaces/IWETH.sol"; // AfEth is the strategy manager for safEth and votium strategies -contract AfEthRelayer is Initializable { +contract AfEthRelayer is Ownable, UUPSUpgradeable { using SafeTransferLib for address; ISafEth public constant SAF_ETH = ISafEth(0x6732Efaf6f39926346BeF8b821a04B6361C4F3e5); - IAfEth public constant AF_ETH = IAfEth(0x00000000fbAA96B36A2AcD4B7B36385c426B119D); + IAfEth public constant AF_ETH = IAfEth(0x0000000016E6Cb3038203c1129c8B4aEE7af7a11); address internal immutable THIS_ = address(this); @@ -40,7 +41,15 @@ contract AfEthRelayer is Initializable { * @notice - Initialize values for the contracts * @dev - This replaces the constructor for upgradeable contracts */ - function initialize() external initializer {} + function initialize(address initialOwner) external initializer { + __UUPSUpgradeable_init(); + _initializeOwner(initialOwner); + } + + /** + * @dev Allows the owner of the contract to upgrade to *any* new address. + */ + function _authorizeUpgrade(address /* newImplementation */ ) internal view override onlyOwner {} /** * @notice Deposits into the SafEth contract and relay to owner address From fe463f719f6856cc2cec493f546be3b1b614f63a Mon Sep 17 00:00:00 2001 From: Philippe Dumonet Date: Mon, 19 Feb 2024 11:20:34 +0000 Subject: [PATCH 4/4] =?UTF-8?q?=F0=9F=93=9D=20Update=20descriptions?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 4a88276..2c82190 100644 --- a/README.md +++ b/README.md @@ -8,9 +8,10 @@ technical details on internal works view ["AfEth"](./docs/AfEth.md). |Description|Address + Link| |-----------|--------------| -|The AfEth ERC1967 proxy| [`0x0000000016E6Cb3038203c1129c8B4aEE7af7a11`](https://etherscan.io/address/0x0000000016e6cb3038203c1129c8b4aee7af7a11)| -|The Votium ERC1967 proxy|[`0x00000069aBbB0B1Ad6975bcF753eEe15D318A0BF`](https://etherscan.io/address/0x00000069abbb0b1ad6975bcf753eee15d318a0bf)| +|The Main AfEth Contract (ERC1967 proxy)| [`0x0000000016E6Cb3038203c1129c8B4aEE7af7a11`](https://etherscan.io/address/0x0000000016e6cb3038203c1129c8b4aee7af7a11)| +|The Votium Strategy Contract (ERC1967 proxy)|[`0x00000069aBbB0B1Ad6975bcF753eEe15D318A0BF`](https://etherscan.io/address/0x00000069abbb0b1ad6975bcf753eee15d318a0bf)| |Votium Implementation Contract|[`0x01e111D815261c8ad6A1271861970E804E4282E4`](https://etherscan.io/address/0x01e111d815261c8ad6a1271861970e804e4282e4)| |AfEth Implementation Contract|[`0x0A36224486D4E49dEB27b489233c6B64e0241D6A`](https://etherscan.io/address/0x0a36224486d4e49deb27b489233c6b64e0241d6a)| |AfEthRelayer|[`0x0000005aC28De2cbda005a8500A9578921FDB7da`](https://etherscan.io/address/0x0000005aC28De2cbda005a8500A9578921FDB7da)| +|AfEthRelayer Contract Implementation|[`0x47c212ddebcad886d0e7b8482bd13f8a27eb0b72`](https://etherscan.io/address/0x47c212ddebcad886d0e7b8482bd13f8a27eb0b72)|