Skip to content

Commit

Permalink
chore: increase coverage
Browse files Browse the repository at this point in the history
  • Loading branch information
fedealconada committed Jan 24, 2024
1 parent 925aa3b commit 4f4b7b3
Show file tree
Hide file tree
Showing 20 changed files with 406 additions and 142 deletions.
2 changes: 0 additions & 2 deletions script/test.sol
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,6 @@ contract KintoDeployTestCounter is AASetup, KYCSignature, UserOp {
);
UserOperation[] memory userOps = new UserOperation[](1);
userOps[0] = userOp;
// Execute the transaction via the entry point
_entryPoint.handleOps(userOps, payable(deployerPublicKey));
console.log("After UserOp. Counter:", counter.count());
vm.stopBroadcast();
Expand Down Expand Up @@ -234,7 +233,6 @@ contract KintoDeployETHPriceIsRight is AASetup, KYCSignature, UserOp {
);
UserOperation[] memory userOps = new UserOperation[](1);
userOps[0] = userOp;
// Execute the transaction via the entry point
_entryPoint.handleOps(userOps, payable(deployerPublicKey));
console.log("After UserOp. ETHPriceIsRight guess count", ethpriceisright.guessCount());
console.log("After UserOp. ETHPriceIsRight avg guess", ethpriceisright.avgGuess());
Expand Down
21 changes: 18 additions & 3 deletions src/wallet/KintoWallet.sol
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ contract KintoWallet is Initializable, BaseAccount, TokenCallbackHandler, IKinto
for (uint256 i = 0; i < dest.length; i++) {
_executeInner(dest[i], values[i], func[i]);
}
// If can transact, cancel recovery
// if can transact, cancel recovery
inRecovery = 0;
}

Expand Down Expand Up @@ -282,8 +282,8 @@ contract KintoWallet is Initializable, BaseAccount, TokenCallbackHandler, IKinto
// if app key is not set or signature is not valid, verify signer policy
if (
(
signerPolicy == SINGLE_SIGNER && owners.length == 1
&& _verifySingleSignature(owners[0], hashData, userOp.signature) == SIG_VALIDATION_SUCCESS
signerPolicy == SINGLE_SIGNER
&& _verifySingleSignature(hashData, userOp.signature) == SIG_VALIDATION_SUCCESS
)
|| (
signerPolicy != SINGLE_SIGNER
Expand Down Expand Up @@ -335,6 +335,20 @@ contract KintoWallet is Initializable, BaseAccount, TokenCallbackHandler, IKinto
return appRegistry.isSponsored(sponsor, target) || appRegistry.childToParentContract(target) == sponsor;
}

// @notice ensures at least 1 signer has signed the hash
// @dev useful when owners.length > 1
function _verifySingleSignature(bytes32 hashData, bytes memory signature) private view returns (uint256) {
// ensure at least one signer has signed
address recovered = hashData.recover(signature);
for (uint256 i = 0; i < owners.length; i++) {
if (owners[i] == recovered) {
return _packValidationData(false, 0, 0);
}
}
return SIG_VALIDATION_FAILED;
}

// @notice ensures signer has signed the hash
function _verifySingleSignature(address signer, bytes32 hashData, bytes memory signature)
private
pure
Expand All @@ -346,6 +360,7 @@ contract KintoWallet is Initializable, BaseAccount, TokenCallbackHandler, IKinto
return _packValidationData(false, 0, 0);
}

// @notice ensures required signers have signed the hash
function _verifyMultipleSignatures(bytes32 hashData, bytes memory signature) private view returns (uint256) {
// calculate required signers
uint256 requiredSigners =
Expand Down
3 changes: 0 additions & 3 deletions test/EngenCredits.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,6 @@ contract EngenCreditsTest is UserOp, AATestScaffolding {
privateKeys, address(_kintoWallet), _kintoWallet.getNonce(), address(_engenCredits), address(_paymaster)
);
userOps[1] = userOp;
// Execute the transaction via the entry point
_entryPoint.handleOps(userOps, payable(_owner));
assertEq(_engenCredits.balanceOf(address(_kintoWallet)), 15);
vm.stopPrank();
Expand Down Expand Up @@ -171,7 +170,6 @@ contract EngenCreditsTest is UserOp, AATestScaffolding {
privateKeys, address(_kintoWallet), _kintoWallet.getNonce(), address(_engenCredits), address(_paymaster)
);
userOps[1] = userOp;
// Execute the transaction via the entry point
_entryPoint.handleOps(userOps, payable(_owner));
assertEq(_engenCredits.balanceOf(address(_kintoWallet)), 20);
vm.stopPrank();
Expand All @@ -198,7 +196,6 @@ contract EngenCreditsTest is UserOp, AATestScaffolding {
privateKeys, address(_kintoWallet), _kintoWallet.getNonce(), address(_engenCredits), address(_paymaster)
);
userOps[1] = userOp;
// Execute the transaction via the entry point
_entryPoint.handleOps(userOps, payable(_owner));
assertEq(_engenCredits.balanceOf(address(_kintoWallet)), 15);
// call again
Expand Down
52 changes: 13 additions & 39 deletions test/KYCViewer.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,8 @@ import "../src/wallet/KintoWalletFactory.sol";
import "../src/KintoID.sol";
import "../src/viewers/KYCViewer.sol";

import "./helpers/UserOp.sol";
import "./SharedSetup.t.sol";
import "./helpers/UUPSProxy.sol";
import {AATestScaffolding} from "./helpers/AATestScaffolding.sol";

contract KYCViewerUpgraded is KYCViewer {
function newFunction() external pure returns (uint256) {
Expand All @@ -21,55 +20,28 @@ contract KYCViewerUpgraded is KYCViewer {
constructor(address _kintoWalletFactory) KYCViewer(_kintoWalletFactory) {}
}

contract KYCViewerTest is UserOp, AATestScaffolding {
uint256 _chainID = 1;

UUPSProxy _proxyViewer;
KYCViewer _implkycViewer;
KYCViewerUpgraded _implKYCViewerUpgraded;
KYCViewer _kycViewer;
KYCViewerUpgraded _kycViewer2;

function setUp() public {
vm.chainId(_chainID);
vm.startPrank(address(1));
_owner.transfer(1e18);
vm.stopPrank();
deployAAScaffolding(_owner, 1, _kycProvider, _recoverer);
vm.startPrank(_owner);
_implkycViewer = new KYCViewer{salt: 0}(address(_walletFactory));
// deploy _proxy contract and point it to _implementation
_proxyViewer = new UUPSProxy{salt: 0}(address(_implkycViewer), "");
// wrap in ABI to support easier calls
_kycViewer = KYCViewer(address(_proxyViewer));
// Initialize kyc viewer _proxy
_kycViewer.initialize();
vm.stopPrank();
}

function testUp() public {
console.log("address owner", address(_owner));
contract KYCViewerTest is SharedSetup {
function testUp() public override {
super.testUp();
assertEq(_kycViewer.owner(), _owner);
assertEq(address(_entryPoint.walletFactory()), address(_kycViewer.walletFactory()));
address kintoID = address(_kycViewer.kintoID());
assertEq(address(_walletFactory.kintoID()), kintoID);
assertEq(address(_walletFactory.kintoID()), address(_kycViewer.kintoID()));
}

/* ============ Upgrade Tests ============ */

function testOwnerCanUpgradeViewer() public {
vm.startPrank(_owner);
function testUpgradeTo_WhenCallerIsOwner() public {
KYCViewerUpgraded _implementationV2 = new KYCViewerUpgraded(address(_walletFactory));
vm.prank(_owner);
_kycViewer.upgradeTo(address(_implementationV2));
// re-wrap the _proxy
_kycViewer2 = KYCViewerUpgraded(address(_kycViewer));
assertEq(_kycViewer2.newFunction(), 1);
vm.stopPrank();
assertEq(KYCViewerUpgraded(address(_kycViewer)).newFunction(), 1);
}

function test_RevertWhen_OthersCannotUpgradeFactory() public {
function testUpgradeTo_RevertWhen_CallerIsNotOwner(address someone) public {
vm.assume(someone != _owner);
KYCViewerUpgraded _implementationV2 = new KYCViewerUpgraded(address(_walletFactory));
vm.expectRevert("only owner");
vm.prank(someone);
_kycViewer.upgradeTo(address(_implementationV2));
}

Expand All @@ -80,5 +52,7 @@ contract KYCViewerTest is UserOp, AATestScaffolding {
assertEq(_kycViewer.isIndividual(address(_kintoWallet)), _kycViewer.isIndividual(_owner));
assertEq(_kycViewer.isCompany(address(_kintoWallet)), false);
assertEq(_kycViewer.hasTrait(address(_kintoWallet), 6), false);
assertEq(_kycViewer.isSanctionsSafe(address(_kintoWallet)), true);
assertEq(_kycViewer.isSanctionsSafeIn(address(_kintoWallet), 1), true);
}
}
4 changes: 2 additions & 2 deletions test/KintoAppRegistry.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import "forge-std/console.sol";

import "../src/apps/KintoAppRegistry.sol";

import "./KintoWallet.t.sol";
import "./SharedSetup.t.sol";

contract KintoAppRegistryV2 is KintoAppRegistry {
function newFunction() external pure returns (uint256) {
Expand All @@ -16,7 +16,7 @@ contract KintoAppRegistryV2 is KintoAppRegistry {
constructor(IKintoWalletFactory _walletFactory) KintoAppRegistry(_walletFactory) {}
}

contract KintoAppRegistryTest is KintoWalletTest {
contract KintoAppRegistryTest is SharedSetup {
function testUp() public override {
super.testUp();

Expand Down
4 changes: 2 additions & 2 deletions test/KintoEntryPoint.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ pragma solidity ^0.8.18;
import "forge-std/Test.sol";
import "forge-std/console.sol";

import "./KintoWallet.t.sol";
import "./SharedSetup.t.sol";

contract KintoEntryPointTest is KintoWalletTest {
contract KintoEntryPointTest is SharedSetup {
function testUp() public override {
assertEq(_entryPoint.walletFactory(), address(_walletFactory));
}
Expand Down
98 changes: 91 additions & 7 deletions test/KintoWalletFactory.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import "../src/sample/Counter.sol";
import "../src/interfaces/IKintoWallet.sol";
import "../src/wallet/KintoWallet.sol";

import "./KintoWallet.t.sol";
import "./SharedSetup.t.sol";

contract KintoWalletUpgrade is KintoWallet {
constructor(IEntryPoint _entryPoint, IKintoID _kintoID, IKintoAppRegistry _kintoAppRegistry)
Expand All @@ -33,7 +33,7 @@ contract KintoWalletFactoryUpgrade is KintoWalletFactory {
}
}

contract KintoWalletFactoryTest is KintoWalletTest {
contract KintoWalletFactoryTest is SharedSetup {
using ECDSAUpgradeable for bytes32;
using SignatureChecker for address;

Expand All @@ -46,9 +46,26 @@ contract KintoWalletFactoryTest is KintoWalletTest {
assertEq(_entryPoint.walletFactory(), address(_walletFactory));
}

/* ============ Create Account Tests ============ */

function testCreateAccount() public {
vm.prank(address(_owner));
_kintoWallet = _walletFactory.createAccount(_owner, _owner, 0);
assertEq(_kintoWallet.owners(0), _owner);
}

function testCreateAccount_WhenAlreadyExists() public {
vm.prank(address(_owner));
_kintoWallet = _walletFactory.createAccount(_owner, _owner, 0);

vm.prank(address(_owner));
IKintoWallet _kintoWalletAfter = _walletFactory.createAccount(_owner, _owner, 0);
assertEq(address(_kintoWallet), address(_kintoWalletAfter));
}

/* ============ Upgrade Tests ============ */

function testOwnerCanUpgradeFactory() public {
function testUpgradeTo_WhenCallerIsOwner() public {
vm.startPrank(_owner);
KintoWalletFactoryUpgrade _newImplementation = new KintoWalletFactoryUpgrade(_kintoWalletImpl);
_walletFactory.upgradeTo(address(_newImplementation));
Expand All @@ -58,9 +75,12 @@ contract KintoWalletFactoryTest is KintoWalletTest {
vm.stopPrank();
}

function test_RevertWhen_OthersCannotUpgradeFactory() public {
function testUpgradeTo_RevertWhen_CallerIsNotOwner(address someone) public {
vm.assume(someone != _owner);
KintoWalletFactoryUpgrade _newImplementation = new KintoWalletFactoryUpgrade(_kintoWalletImpl);

vm.expectRevert("Ownable: caller is not the owner");
vm.prank(someone);
_walletFactory.upgradeTo(address(_newImplementation));
}

Expand Down Expand Up @@ -147,7 +167,6 @@ contract KintoWalletFactoryTest is KintoWalletTest {
);
UserOperation[] memory userOps = new UserOperation[](1);
userOps[0] = userOp;
// Execute the transaction via the entry point
_entryPoint.handleOps(userOps, payable(_owner));
vm.deal(_funder, 1e17);
vm.startPrank(_funder);
Expand Down Expand Up @@ -176,13 +195,78 @@ contract KintoWalletFactoryTest is KintoWalletTest {

/* ============ Recovery Tests ============ */

function testStart_RevertWhen_RecoverNotRecoverer(address someone) public {
vm.assume(someone != address(_walletFactory));
function testStartWalletRecovery_WhenCallerIsRecoverer() public {
vm.prank(address(_kintoWallet.recoverer()));
_walletFactory.startWalletRecovery(payable(address(_kintoWallet)));
}

function testStartWalletRecovery_WhenCallerIsRecoverer_RevertWhen_WalletNotExists() public {
vm.prank(address(_kintoWallet.recoverer()));
vm.expectRevert("invalid wallet");
_walletFactory.startWalletRecovery(payable(address(123)));
}

function testStartWalletRecovery_RevertWhen_CallerIsNotRecoverer(address someone) public {
vm.assume(someone != address(_kintoWallet.recoverer()));
vm.prank(someone);
vm.expectRevert("only recoverer");
_walletFactory.startWalletRecovery(payable(address(_kintoWallet)));
}

function testCompleteWalletRecovery_WhenCallerIsRecoverer() public {
vm.prank(address(_kintoWallet.recoverer()));
_walletFactory.startWalletRecovery(payable(address(_kintoWallet)));

vm.warp(block.timestamp + _kintoWallet.RECOVERY_TIME() + 1);

// approve KYC for _user burn KYC for _owner
revokeKYC(_kycProvider, _owner, _ownerPk);
approveKYC(_kycProvider, _user, _userPk);

// run monitor
address[] memory users = new address[](1);
users[0] = _user;
IKintoID.MonitorUpdateData[][] memory updates = new IKintoID.MonitorUpdateData[][](1);
updates[0] = new IKintoID.MonitorUpdateData[](1);
updates[0][0] = IKintoID.MonitorUpdateData(true, true, 5);
vm.prank(_kycProvider);
_kintoIDv1.monitor(users, updates);

vm.prank(address(_kintoWallet.recoverer()));
_walletFactory.completeWalletRecovery(payable(address(_kintoWallet)), users);
}

function testCompleteWalletRecovery_RevertWhen_WhenCallerIsRecoverer_WalletNotExists() public {
vm.prank(address(_kintoWallet.recoverer()));
vm.expectRevert("invalid wallet");
_walletFactory.completeWalletRecovery(payable(address(123)), new address[](0));
}

function testCompleteWalletRecovery_RevertWhen_CallerIsNotRecoverer(address someone) public {
vm.assume(someone != address(_kintoWallet.recoverer()));
vm.prank(someone);
vm.expectRevert("only recoverer");
_walletFactory.completeWalletRecovery(payable(address(_kintoWallet)), new address[](0));
}

function testChangeWalletRecoverer_WhenCallerIsRecoverer() public {
vm.prank(address(_kintoWallet.recoverer()));
_walletFactory.changeWalletRecoverer(payable(address(_kintoWallet)), payable(address(123)));
}

function testChangeWalletRecoverer_RevertWhen_CallerIsRecoverer_WhenWalletNotExists() public {
vm.prank(address(_kintoWallet.recoverer()));
vm.expectRevert("invalid wallet");
_walletFactory.changeWalletRecoverer(payable(address(123)), payable(address(123)));
}

function testChangeWalletRecoverer_RevertWhen_CallerIsNotRecoverer(address someone) public {
vm.assume(someone != address(_kintoWallet.recoverer()));
vm.prank(someone);
vm.expectRevert("only recoverer");
_walletFactory.changeWalletRecoverer(payable(address(_kintoWallet)), payable(address(123)));
}

/* ============ Send Money Tests ============ */

function testSendMoneyToAccount_WhenCallerIsKYCd() public {
Expand Down
3 changes: 2 additions & 1 deletion test/KintoWallet.t.sol → test/SharedSetup.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import "./harness/SponsorPaymasterHarness.sol";
import {UserOp} from "./helpers/UserOp.sol";
import {AATestScaffolding} from "./helpers/AATestScaffolding.sol";

contract KintoWalletTest is UserOp, AATestScaffolding {
contract SharedSetup is UserOp, AATestScaffolding {
uint256[] privateKeys;
Counter counter;

Expand All @@ -27,6 +27,7 @@ contract KintoWalletTest is UserOp, AATestScaffolding {
event KintoWalletInitialized(IEntryPoint indexed entryPoint, address indexed owner);
event WalletPolicyChanged(uint256 newPolicy, uint256 oldPolicy);
event RecovererChanged(address indexed newRecoverer, address indexed recoverer);
event PostOpRevertReason(bytes32 indexed userOpHash, address indexed sender, uint256 nonce, bytes revertReason);

function setUp() public virtual {
deployAAScaffolding(_owner, 1, _kycProvider, _recoverer);
Expand Down
1 change: 0 additions & 1 deletion test/SponsorPaymastExploit.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,6 @@ contract SponsorPaymasterExploitTest is MyOpCreator, AATestScaffolding {
);
UserOperation[] memory userOps = new UserOperation[](1);
userOps[0] = userOp;
// Execute the transaction via the entry point
uint256 balanceBefore = _owner.balance;
console.log("HACKER BALANCE BEFORE", balanceBefore);
vm.expectRevert();
Expand Down
Loading

0 comments on commit 4f4b7b3

Please sign in to comment.