diff --git a/.env.sample b/.env.sample index bea8b21f..d58599a7 100644 --- a/.env.sample +++ b/.env.sample @@ -4,3 +4,4 @@ KINTO_RPC_URL="https://kinto-mainnet.calderachain.xyz/http" MAINNET_NETWORK_ID="7887" TESTNET_NETWORK_ID="7887000" KINTO_EXPLORER_URL="https://kinto-mainnet.calderaexplorer.xyz/" +LEDGER_ADMIN="" diff --git a/script/migrations/07-deploy_kinto_app.sol b/script/migrations/07-deploy_kinto_app.sol new file mode 100644 index 00000000..d3844e59 --- /dev/null +++ b/script/migrations/07-deploy_kinto_app.sol @@ -0,0 +1,61 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.13; + +import "forge-std/Script.sol"; +import "../../src/apps/KintoAppRegistry.sol"; +import "../../src/paymasters/SponsorPaymaster.sol"; +import "../../src/interfaces/IKintoWalletFactory.sol"; +import {Create2Helper} from "../../test/helpers/Create2Helper.sol"; +import {ArtifactsReader} from "../../test/helpers/ArtifactsReader.sol"; +import {UUPSProxy} from "../../test/helpers/UUPSProxy.sol"; +import "@openzeppelin/contracts-upgradeable/utils/cryptography/ECDSAUpgradeable.sol"; +import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; +import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol"; +import "forge-std/console.sol"; + +contract KintoMigration7DeployScript is Create2Helper, ArtifactsReader { + using ECDSAUpgradeable for bytes32; + + KintoAppRegistry _kintoApp; + + function setUp() public {} + + // solhint-disable code-complexity + function run() public { + console.log("RUNNING ON CHAIN WITH ID", vm.toString(block.chainid)); + // Execute this script with the hot wallet, not with ledger + uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY"); + address admin = vm.envAddress("LEGER_ADMIN"); + if (admin == address(0)) { + console.log("Admin key not set", admin); + return; + } + vm.startBroadcast(deployerPrivateKey); + console.log("Executing with address", msg.sender); + vm.startBroadcast(); + address appAddr = _getChainDeployment("KintoAppRegistry"); + if (appAddr != address(0)) { + console.log("KintoAppRegistry already deployed", appAddr); + return; + } + address walletFactoryAddr = _getChainDeployment("KintoWalletFactory"); + IKintoWalletFactory _walletFactory = IKintoWalletFactory(walletFactoryAddr); + _kintoApp = KintoAppRegistry( + _walletFactory.deployContract( + msg.sender, 0, abi.encodePacked(type(KintoAppRegistry).creationCode), bytes32(0) + ) + ); + // Give ownership to admin + _kintoApp.transferOwnership(admin); + address credits = _getChainDeployment("EngenCredits"); + // Create Engen App + _kintoApp.registerApp("Engen", credits, new address[](0), [uint256(0), uint256(0), uint256(0), uint256(0)]); + // Fund in the paymaster + SponsorPaymaster _paymaster = SponsorPaymaster(payable(_getChainDeployment("SponsorPaymaster"))); + _paymaster.addDepositFor{value: 1e17}(credits); + vm.stopBroadcast(); + // Writes the addresses to a file + console.log("Add these new addresses to the artifacts file"); + console.log(string.concat('"KintoAppRegistry": "', vm.toString(address(_kintoApp)), '"')); + } +} diff --git a/script/migrations/08-upgrade_wallet_v3.sol b/script/migrations/08-upgrade_wallet_v3.sol new file mode 100644 index 00000000..d42c2cff --- /dev/null +++ b/script/migrations/08-upgrade_wallet_v3.sol @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.13; + +import "forge-std/Script.sol"; +import "../../src/wallet/KintoWalletFactory.sol"; +import {KintoWallet} from "../../src/wallet/KintoWallet.sol"; +import {Create2Helper} from "../../test/helpers/Create2Helper.sol"; +import {ArtifactsReader} from "../../test/helpers/ArtifactsReader.sol"; +import {UUPSProxy} from "../../test/helpers/UUPSProxy.sol"; +import "@openzeppelin/contracts-upgradeable/utils/cryptography/ECDSAUpgradeable.sol"; +import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; +import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol"; +import "forge-std/console.sol"; + +contract KintoMigration8DeployScript is Create2Helper, ArtifactsReader { + using ECDSAUpgradeable for bytes32; + + KintoWalletFactory _walletFactory; + KintoWalletV3 _kintoWalletImpl; + UUPSProxy _proxy; + + function setUp() public {} + + // solhint-disable code-complexity + function run() public { + console.log("RUNNING ON CHAIN WITH ID", vm.toString(block.chainid)); + // Execute this script with the ledger admin + console.log("Executing with address", msg.sender); + vm.startBroadcast(); + address walletFactoryAddr = _getChainDeployment("KintoWalletFactory"); + if (walletFactoryAddr == address(0)) { + console.log("Need to execute main deploy script first", walletFactoryAddr); + return; + } + address kintoAppAddr = _getChainDeployment("KintoAppRegistry"); + if (kintoAppAddr == address(0)) { + console.log("Need to deploy kinto app registry first", kintoAppAddr); + return; + } + _walletFactory = KintoWalletFactory(payable(walletFactoryAddr)); + + bytes memory bytecode = abi.encodePacked( + abi.encodePacked(type(KintoWalletV3).creationCode), + abi.encode( + _getChainDeployment("EntryPoint"), + IKintoID(_getChainDeployment("KintoID")), + IKintoAppRegistry(_getChainDeployment("KintoAppRegistry")) + ) // Encoded constructor arguments + ); + + // Deploy new wallet implementation + _kintoWalletImpl = KintoWalletV3(payable(_walletFactory.deployContract(msg.sender, 0, bytecode, bytes32(0)))); + // Upgrade all implementations + _walletFactory.upgradeAllWalletImplementations(_kintoWalletImpl); + vm.stopBroadcast(); + // Writes the addresses to a file + console.log("Add these new addresses to the artifacts file"); + console.log(string.concat('"KintoWalletV3-impl": "', vm.toString(address(_kintoWalletImpl)), '"')); + } +} diff --git a/script/migrations/09-upgrade_paymasterv2.sol b/script/migrations/09-upgrade_paymasterv2.sol new file mode 100644 index 00000000..cce96654 --- /dev/null +++ b/script/migrations/09-upgrade_paymasterv2.sol @@ -0,0 +1,54 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.13; + +import "forge-std/Script.sol"; +import "../../src/wallet/KintoWalletFactory.sol"; +import "../../src/paymasters/SponsorPaymaster.sol"; +import {KintoWallet} from "../../src/wallet/KintoWallet.sol"; +import {Create2Helper} from "../../test/helpers/Create2Helper.sol"; +import {ArtifactsReader} from "../../test/helpers/ArtifactsReader.sol"; +import {UUPSProxy} from "../../test/helpers/UUPSProxy.sol"; +import "@openzeppelin/contracts-upgradeable/utils/cryptography/ECDSAUpgradeable.sol"; +import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; +import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol"; +import "forge-std/console.sol"; + +contract KintoMigration9DeployScript is Create2Helper, ArtifactsReader { + using ECDSAUpgradeable for bytes32; + + SponsorPaymaster _paymaster; + KintoWalletFactory _walletFactory; + SponsorPaymasterV2 _paymasterImpl; + UUPSProxy _proxy; + + function setUp() public {} + + // solhint-disable code-complexity + function run() public { + console.log("RUNNING ON CHAIN WITH ID", vm.toString(block.chainid)); + // Execute this script with the ledger admin + console.log("Executing with address", msg.sender); + vm.startBroadcast(); + address sponsorAddr = _getChainDeployment("SponsorPaymaster"); + if (sponsorAddr == address(0)) { + console.log("Need to execute main deploy script first", sponsorAddr); + return; + } + _paymaster = SponsorPaymaster(payable(sponsorAddr)); + + _walletFactory = KintoWalletFactory(payable(_getChainDeployment("KintoWalletFactory"))); + bytes memory bytecode = abi.encodePacked( + abi.encodePacked(type(SponsorPaymasterV2).creationCode), + abi.encode(_getChainDeployment("EntryPoint")) // Encoded constructor arguments + ); + + // Deploy new paymaster implementation + _paymasterImpl = SponsorPaymasterV2(payable(_walletFactory.deployContract(msg.sender, 0, bytecode, bytes32(0)))); + // Upgrade + _paymaster.upgradeTo(address(_paymasterImpl)); + vm.stopBroadcast(); + // Writes the addresses to a file + console.log("Add these new addresses to the artifacts file"); + console.log(string.concat('"SponsorPaymasterV2-impl": "', vm.toString(address(_paymasterImpl)), '"')); + } +} diff --git a/script/migrations/10-upgrade_wallet_factoryv2.sol b/script/migrations/10-upgrade_wallet_factoryv2.sol new file mode 100644 index 00000000..e4b07470 --- /dev/null +++ b/script/migrations/10-upgrade_wallet_factoryv2.sol @@ -0,0 +1,56 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.13; + +import "forge-std/Script.sol"; +import "../../src/wallet/KintoWalletFactory.sol"; +import {KintoWallet} from "../../src/wallet/KintoWallet.sol"; +import {Create2Helper} from "../../test/helpers/Create2Helper.sol"; +import {ArtifactsReader} from "../../test/helpers/ArtifactsReader.sol"; +import {UUPSProxy} from "../../test/helpers/UUPSProxy.sol"; +import "@openzeppelin/contracts-upgradeable/utils/cryptography/ECDSAUpgradeable.sol"; +import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; +import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol"; +import "forge-std/console.sol"; + +contract KintoMigration9DeployScript is Create2Helper, ArtifactsReader { + using ECDSAUpgradeable for bytes32; + + KintoWalletFactory _walletFactory; + KintoWalletFactoryV2 _factoryImpl; + UUPSProxy _proxy; + + function setUp() public {} + + // solhint-disable code-complexity + function run() public { + console.log("RUNNING ON CHAIN WITH ID", vm.toString(block.chainid)); + // Execute this script with the ledger admin + console.log("Executing with address", msg.sender); + vm.startBroadcast(); + address factoryAddr = _getChainDeployment("KintoWalletFactory"); + if (factoryAddr == address(0)) { + console.log("Need to execute main deploy script first", factoryAddr); + return; + } + _walletFactory = KintoWalletFactory(payable(_getChainDeployment("KintoWalletFactory"))); + + address newImpl = _getChainDeployment("KintoWalletV3-impl"); + if (newImpl == address(0)) { + console.log("Need to deploy the new wallet first", newImpl); + return; + } + bytes memory bytecode = abi.encodePacked( + abi.encodePacked(type(KintoWalletFactoryV2).creationCode), + abi.encode(_getChainDeployment("KintoWalletV3-impl")) // Encoded constructor arguments + ); + + // Deploy new paymaster implementation + _factoryImpl = KintoWalletFactoryV2(payable(_walletFactory.deployContract(msg.sender, 0, bytecode, bytes32(0)))); + // Upgrade + _walletFactory.upgradeTo(address(_factoryImpl)); + vm.stopBroadcast(); + // Writes the addresses to a file + console.log("Add these new addresses to the artifacts file"); + console.log(string.concat('"KintoWalletFactoryV2-impl": "', vm.toString(address(_factoryImpl)), '"')); + } +} diff --git a/script/upgrade.sol b/script/upgrade.sol index 0b979ecb..f411a381 100644 --- a/script/upgrade.sol +++ b/script/upgrade.sol @@ -22,7 +22,7 @@ import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol"; import "forge-std/console.sol"; -contract KintoWalletFactoryV2 is KintoWalletFactory { +contract KintoWalletFactoryV999 is KintoWalletFactory { constructor(KintoWallet _impl) KintoWalletFactory(_impl) {} } @@ -39,10 +39,10 @@ contract KintoWalletFactoryUpgradeScript is ArtifactsReader { uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY"); vm.startBroadcast(deployerPrivateKey); _oldKintoWalletFactory = KintoWalletFactory(payable(_getChainDeployment("KintoWalletFactory"))); - KintoWalletFactoryV2 _implementationV2 = - new KintoWalletFactoryV2(KintoWallet(payable(_getChainDeployment("KintoWallet-impl")))); - _oldKintoWalletFactory.upgradeTo(address(_implementationV2)); - console.log("KintoWalletFactory Upgraded to implementation", address(_implementationV2)); + KintoWalletFactoryV999 _implementationV999 = + new KintoWalletFactoryV999(KintoWallet(payable(_getChainDeployment("KintoWallet-impl")))); + _oldKintoWalletFactory.upgradeTo(address(_implementationV999)); + console.log("KintoWalletFactory Upgraded to implementation", address(_implementationV999)); vm.stopBroadcast(); } } diff --git a/src/paymasters/SponsorPaymaster.sol b/src/paymasters/SponsorPaymaster.sol index 72735370..2f160db6 100644 --- a/src/paymasters/SponsorPaymaster.sol +++ b/src/paymasters/SponsorPaymaster.sol @@ -298,3 +298,7 @@ contract SponsorPaymaster is Initializable, BasePaymaster, UUPSUpgradeable, Reen } } } + +contract SponsorPaymasterV2 is SponsorPaymaster { + constructor(IEntryPoint __entryPoint) SponsorPaymaster(__entryPoint) {} +} diff --git a/src/wallet/KintoWalletFactory.sol b/src/wallet/KintoWalletFactory.sol index 49cdec46..2f65f09d 100644 --- a/src/wallet/KintoWalletFactory.sol +++ b/src/wallet/KintoWalletFactory.sol @@ -266,3 +266,7 @@ contract KintoWalletFactory is Initializable, UUPSUpgradeable, OwnableUpgradeabl return created; } } + +contract KintoWalletFactoryV2 is KintoWalletFactory { + constructor(KintoWallet _implAddressP) KintoWalletFactory(_implAddressP) {} +} diff --git a/test/KintoWalletFactory.t.sol b/test/KintoWalletFactory.t.sol index f775fe71..8237214a 100644 --- a/test/KintoWalletFactory.t.sol +++ b/test/KintoWalletFactory.t.sol @@ -45,7 +45,7 @@ contract Counter { } } -contract KintoWalletFactoryV2 is KintoWalletFactory { +contract KintoWalletFactoryV999 is KintoWalletFactory { constructor(KintoWallet _impl) KintoWalletFactory(_impl) {} function newFunction() public pure returns (uint256) { @@ -57,7 +57,7 @@ contract KintoWalletFactoryTest is Create2Helper, UserOp, AATestScaffolding { using ECDSAUpgradeable for bytes32; using SignatureChecker for address; - KintoWalletFactoryV2 _walletFactoryv2; + KintoWalletFactoryV999 _walletFactoryv2; KintoWalletV999 _kintoWalletv2; uint256 _chainID = 1; @@ -79,18 +79,18 @@ contract KintoWalletFactoryTest is Create2Helper, UserOp, AATestScaffolding { function testOwnerCanUpgradeFactory() public { vm.startPrank(_owner); - KintoWalletFactoryV2 _implementationV2 = new KintoWalletFactoryV2(_kintoWalletImpl); - _walletFactory.upgradeTo(address(_implementationV2)); + KintoWalletFactoryV999 _implementationV999 = new KintoWalletFactoryV999(_kintoWalletImpl); + _walletFactory.upgradeTo(address(_implementationV999)); // re-wrap the _proxy - _walletFactoryv2 = KintoWalletFactoryV2(address(_walletFactory)); + _walletFactoryv2 = KintoWalletFactoryV999(address(_walletFactory)); assertEq(_walletFactoryv2.newFunction(), 1); vm.stopPrank(); } function test_RevertWhen_OthersCannotUpgradeFactory() public { - KintoWalletFactoryV2 _implementationV2 = new KintoWalletFactoryV2(_kintoWalletImpl); + KintoWalletFactoryV999 _implementationV999 = new KintoWalletFactoryV999(_kintoWalletImpl); vm.expectRevert("Ownable: caller is not the owner"); - _walletFactory.upgradeTo(address(_implementationV2)); + _walletFactory.upgradeTo(address(_implementationV999)); } function testAllWalletsUpgrade() public { diff --git a/test/SponsorPaymaster.t.sol b/test/SponsorPaymaster.t.sol index 8b52a6cd..124f7e36 100644 --- a/test/SponsorPaymaster.t.sol +++ b/test/SponsorPaymaster.t.sol @@ -15,7 +15,7 @@ import "@aa/core/EntryPoint.sol"; import "forge-std/Test.sol"; import "forge-std/console.sol"; -contract SponsorPaymasterV2 is SponsorPaymaster { +contract SponsorPaymasterV999 is SponsorPaymaster { constructor(IEntryPoint __entryPoint, address _owner) SponsorPaymaster(__entryPoint) { _disableInitializers(); _transferOwnership(_owner); @@ -32,7 +32,7 @@ contract SponsorPaymasterTest is KYCSignature { EntryPoint _entryPoint; SponsorPaymaster _paymaster; - SponsorPaymasterV2 _paymasterv2; + SponsorPaymasterV999 _paymasterv999; UUPSProxy _proxy; address _owner = address(1); @@ -66,18 +66,18 @@ contract SponsorPaymasterTest is KYCSignature { function testOwnerCanUpgrade() public { vm.startPrank(_owner); - SponsorPaymasterV2 _implementationV2 = new SponsorPaymasterV2(_entryPoint, _owner); - _paymaster.upgradeTo(address(_implementationV2)); + SponsorPaymasterV999 _implementationV999 = new SponsorPaymasterV999(_entryPoint, _owner); + _paymaster.upgradeTo(address(_implementationV999)); // re-wrap the _proxy - _paymasterv2 = SponsorPaymasterV2(address(_proxy)); - assertEq(_paymasterv2.newFunction(), 1); + _paymasterv999 = SponsorPaymasterV999(address(_proxy)); + assertEq(_paymasterv999.newFunction(), 1); vm.stopPrank(); } function testUpgrade_RevertWhen_CallerIsNotOwner() public { - SponsorPaymasterV2 _implementationV2 = new SponsorPaymasterV2(_entryPoint, _owner); + SponsorPaymasterV999 _implementationV999 = new SponsorPaymasterV999(_entryPoint, _owner); vm.expectRevert("SP: not owner"); - _paymaster.upgradeTo(address(_implementationV2)); + _paymaster.upgradeTo(address(_implementationV999)); } // Deposit & Stake